diff options
| author | Jabier Arraiza <jabier.arraiza@marker.es> | 2017-11-03 00:10:02 +0000 |
|---|---|---|
| committer | Jabier Arraiza <jabier.arraiza@marker.es> | 2017-11-03 00:10:02 +0000 |
| commit | d2df0412f728dd5bb54537dfdfe7c35b34d40e0e (patch) | |
| tree | e2703384779e83312c456399999997fcc289c5cf /src | |
| parent | Merge branch 'master' into powerpencil (diff) | |
| parent | change assignment to equality (diff) | |
| download | inkscape-d2df0412f728dd5bb54537dfdfe7c35b34d40e0e.tar.gz inkscape-d2df0412f728dd5bb54537dfdfe7c35b34d40e0e.zip | |
Merge branch 'master' into powerpencil
Diffstat (limited to 'src')
397 files changed, 6728 insertions, 5732 deletions
diff --git a/src/2geom/makefile.in b/src/2geom/makefile.in deleted file mode 100644 index ca7943377..000000000 --- a/src/2geom/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) 2geom/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) 2geom/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7437f12ae..4c56b211d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,7 @@ set(sp_SRC sp-cursor.cpp sp-defs.cpp sp-desc.cpp + sp-dimensions.cpp sp-ellipse.cpp sp-factory.cpp sp-filter-primitive.cpp @@ -97,6 +98,7 @@ set(sp_SRC sp-cursor.h sp-defs.h sp-desc.h + sp-dimensions.h sp-ellipse.h sp-factory.h sp-filter-primitive.h @@ -323,7 +325,6 @@ set(inkscape_SRC guide-snapper.h help.h helper-fns.h - icon-size.h id-clash.h inkscape-version.h inkscape.h @@ -479,7 +480,6 @@ if(WIN32) list(APPEND main_SRC registrytool.h registrytool.cpp - winmain.cpp ) # Configure and add the platform specific resource files (enabling the app icon). @@ -540,7 +540,7 @@ set(INKSCAPE_TARGET_LIBS ) # Build everything except main and inkview.c in a shared library. -add_library(inkscape_base SHARED ${inkscape_SRC} ${sp_SRC}) +add_library(inkscape_base ${inkscape_SRC} ${sp_SRC}) if(WITH_DBUS) add_dependencies(inkscape_base inkscape_dbus) diff --git a/src/attributes.cpp b/src/attributes.cpp index 9ba646ab4..6522563af 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -507,9 +507,10 @@ static SPStyleProp const props[] = { /* SVG 2 Text Wrapping */ {SP_PROP_SHAPE_INSIDE, "shape-inside"}, - {SP_PROP_SHAPE_OUTSIDE, "shape-outside"}, + {SP_PROP_SHAPE_SUBTRACT,"shape-subtract"}, {SP_PROP_SHAPE_PADDING, "shape-padding"}, {SP_PROP_SHAPE_MARGIN, "shape-margin"}, + {SP_PROP_INLINE_SIZE, "inline-size"}, /* Text Decoration */ {SP_PROP_TEXT_DECORATION, "text-decoration"}, // CSS 2/CSS3-Shorthand diff --git a/src/attributes.h b/src/attributes.h index 3fee14133..a2c1c30f5 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -515,9 +515,10 @@ enum SPAttributeEnum { /* SVG 2 Text Wrapping */ SP_PROP_SHAPE_INSIDE, - SP_PROP_SHAPE_OUTSIDE, + SP_PROP_SHAPE_SUBTRACT, SP_PROP_SHAPE_PADDING, SP_PROP_SHAPE_MARGIN, + SP_PROP_INLINE_SIZE, /* Text Decoration */ SP_PROP_TEXT_DECORATION, // CSS 2/CSS3-Shorthand diff --git a/src/axis-manip.cpp b/src/axis-manip.cpp index 8955202c8..2332bc0a3 100644 --- a/src/axis-manip.cpp +++ b/src/axis-manip.cpp @@ -32,12 +32,12 @@ get_remaining_axes (Axis axis) { return std::make_pair (extract_first_axis_direction (plane), extract_second_axis_direction (plane)); } -char * string_from_axes (Box3D::Axis axis) { - GString *pstring = g_string_new(""); - if (axis & Box3D::X) g_string_append_printf (pstring, "X"); - if (axis & Box3D::Y) g_string_append_printf (pstring, "Y"); - if (axis & Box3D::Z) g_string_append_printf (pstring, "Z"); - return pstring->str; +Glib::ustring string_from_axes (Box3D::Axis axis) { + Glib::ustring result; + if (axis & Box3D::X) result += "X"; + if (axis & Box3D::Y) result += "Y"; + if (axis & Box3D::Z) result += "Z"; + return result; } } // namespace Box3D diff --git a/src/axis-manip.h b/src/axis-manip.h index 5e245939e..28875b2f5 100644 --- a/src/axis-manip.h +++ b/src/axis-manip.h @@ -15,6 +15,7 @@ #include <cassert> #include <string> #include <utility> +#include <glibmm/ustring.h> namespace Proj { @@ -238,7 +239,7 @@ inline Box3D::Axis get_perpendicular_axis_direction (Box3D::Axis dirs) { return Box3D::NONE; } -char * string_from_axes (Box3D::Axis axis); +Glib::ustring string_from_axes (Box3D::Axis axis); std::pair <Axis, Axis> get_remaining_axes (Axis axis); } // namespace Box3D diff --git a/src/box3d-side.cpp b/src/box3d-side.cpp index 14b457ea6..3eea8855c 100644 --- a/src/box3d-side.cpp +++ b/src/box3d-side.cpp @@ -210,29 +210,28 @@ void Box3DSide::set_shape() { c->unref(); } -gchar *box3d_side_axes_string(Box3DSide *side) +Glib::ustring box3d_side_axes_string(Box3DSide *side) { - GString *pstring = g_string_new(""); - g_string_printf (pstring, "%s", Box3D::string_from_axes ((Box3D::Axis) (side->dir1 ^ side->dir2))); + Glib::ustring result(Box3D::string_from_axes((Box3D::Axis) (side->dir1 ^ side->dir2))); switch ((Box3D::Axis) (side->dir1 ^ side->dir2)) { case Box3D::XY: - g_string_append_printf (pstring, (side->front_or_rear == Box3D::FRONT) ? "front" : "rear"); + result += ((side->front_or_rear == Box3D::FRONT) ? "front" : "rear"); break; case Box3D::XZ: - g_string_append_printf (pstring, (side->front_or_rear == Box3D::FRONT) ? "top" : "bottom"); + result += ((side->front_or_rear == Box3D::FRONT) ? "top" : "bottom"); break; case Box3D::YZ: - g_string_append_printf (pstring, (side->front_or_rear == Box3D::FRONT) ? "right" : "left"); + result += ((side->front_or_rear == Box3D::FRONT) ? "right" : "left"); break; default: break; } - return pstring->str; + return result; } static void diff --git a/src/box3d-side.h b/src/box3d-side.h index 4783a5f24..29f17b8f3 100644 --- a/src/box3d-side.h +++ b/src/box3d-side.h @@ -43,7 +43,7 @@ public: void box3d_side_position_set (Box3DSide *side); // FIXME: Replace this by box3d_side_set_shape?? -char *box3d_side_axes_string(Box3DSide *side); +Glib::ustring box3d_side_axes_string(Box3DSide *side); Persp3D *box3d_side_perspective(Box3DSide *side); diff --git a/src/box3d.cpp b/src/box3d.cpp index 23766895a..98f49e52a 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -192,7 +192,7 @@ void SPBox3D::update(SPCtx *ctx, guint flags) { /* FIXME?: Perhaps the display updates of box sides should be instantiated from here, but this causes evil update loops so it's all done from box3d_position_set, which is called from - various other places (like the handlers in object-edit.cpp, vanishing-point.cpp, etc. */ + various other places (like the handlers in shape-editor-knotholders.cpp, vanishing-point.cpp, etc. */ } diff --git a/src/check-header-compile.in b/src/check-header-compile.in deleted file mode 100755 index 2295dcf91..000000000 --- a/src/check-header-compile.in +++ /dev/null @@ -1,47 +0,0 @@ -#! /bin/sh -# Check that each .h file has all the includes it needs. - -# Probably requires gnu find (for -printf '%P\n'). - -# This script hereby placed into the public domain. - -set -e -mydir=`dirname "$0"` -cd "$mydir" -srcdir="@srcdir@" -CXX="@CXX@" -INCLUDES="@GNOME_VFS_CFLAGS@ @POPPLER_GLIB_CFLAGS@ @INKSCAPE_CFLAGS@" -OBJEXT="@OBJEXT@" -config_h_dir=.. - -check_compile () { - (echo "#include <config.h>"; echo "#include <$1>"; echo "int header_tst_dummy;") > header-tst.cpp - $CXX -c -I. -I"$srcdir" -I$config_h_dir $INCLUDES header-tst.cpp -} - -if [ $# = 0 ]; then - for i in `find "$srcdir" \ - -name bonobo -prune \ - -o -name dom -prune \ - -o -name ecma -prune \ - -o -name render -prune \ - -o -name xpath -prune \ - -o -name '*.h' \ - \! -name gnome.h \! -name nr-type-gnome.h \! -name Livarot.h \! -name radial.h \ - \! -name '*-test.h' \ - \! -name test-helpers.h \ - \! -name PylogFormatter.h \ - \! -name TRPIFormatter.h \ - \! -name win32.h \ - \! -name '*-w32.h' \ - \! -name '*-win32.h' \ - -printf '%P\n'` - do - check_compile "$i" - done -else - for i in "$@"; do - check_compile "$i" - done -fi -rm header-tst.cpp header-tst.$OBJEXT diff --git a/src/color-profile.cpp b/src/color-profile.cpp index 1552c38e7..7bdde9b6d 100644 --- a/src/color-profile.cpp +++ b/src/color-profile.cpp @@ -755,6 +755,22 @@ std::set<ColorProfile::FilePlusHome> ColorProfile::getBaseProfileDirs() { sources.insert(FilePlusHome(path, true)); g_free(path); + // search colord ICC store paths + // (see https://github.com/hughsie/colord/blob/fe10f76536bb27614ced04e0ff944dc6fb4625c0/lib/colord/cd-icc-store.c#L590) + + // user store + path = g_build_filename(g_get_user_data_dir(), "icc", NULL); + sources.insert(FilePlusHome(path, true)); + g_free(path); + + path = g_build_filename(g_get_home_dir(), ".color", "icc", NULL); + sources.insert(FilePlusHome(path, true)); + g_free(path); + + // machine store + sources.insert(FilePlusHome("/var/lib/color/icc", false)); + sources.insert(FilePlusHome("/var/lib/colord/icc", false)); + const gchar* const * dataDirs = g_get_system_data_dirs(); for ( int i = 0; dataDirs[i]; i++ ) { gchar* path = g_build_filename(dataDirs[i], "color", "icc", NULL); diff --git a/src/debug/demangle.cpp b/src/debug/demangle.cpp index 1d94f0eb9..04fe80d9b 100644 --- a/src/debug/demangle.cpp +++ b/src/debug/demangle.cpp @@ -50,7 +50,7 @@ MangleCache mangle_cache; } -Util::ptr_shared<char> demangle(char const *name) { +Util::ptr_shared demangle(char const *name) { MangleCache::iterator found=mangle_cache.find(name); char const *result; diff --git a/src/debug/demangle.h b/src/debug/demangle.h index 7505d9550..c5e160caa 100644 --- a/src/debug/demangle.h +++ b/src/debug/demangle.h @@ -18,7 +18,7 @@ namespace Inkscape { namespace Debug { -Util::ptr_shared<char> demangle(char const *name); +Util::ptr_shared demangle(char const *name); } diff --git a/src/debug/event.h b/src/debug/event.h index 1cdd4f7e2..2d3751ff5 100644 --- a/src/debug/event.h +++ b/src/debug/event.h @@ -40,23 +40,23 @@ public: struct PropertyPair { public: PropertyPair() {} - PropertyPair(Util::ptr_shared<char> n, Util::ptr_shared<char> v) + PropertyPair(Util::ptr_shared n, Util::ptr_shared v) : name(n), value(v) {} - PropertyPair(char const *n, Util::ptr_shared<char> v) + PropertyPair(char const *n, Util::ptr_shared v) : name(Util::share_string(n)), value(v) {} - PropertyPair(Util::ptr_shared<char> n, char const *v) + PropertyPair(Util::ptr_shared n, char const *v) : name(n), value(Util::share_string(v)) {} PropertyPair(char const *n, char const *v) : name(Util::share_string(n)), value(Util::share_string(v)) {} - Util::ptr_shared<char> name; - Util::ptr_shared<char> value; + Util::ptr_shared name; + Util::ptr_shared value; }; static Category category() { return OTHER; } - virtual Util::ptr_shared<char> name() const=0; + virtual Util::ptr_shared name() const=0; virtual unsigned propertyCount() const=0; virtual PropertyPair property(unsigned property) const=0; diff --git a/src/debug/gc-heap.h b/src/debug/gc-heap.h index d120ddba9..0daf39487 100644 --- a/src/debug/gc-heap.h +++ b/src/debug/gc-heap.h @@ -23,7 +23,7 @@ public: int features() const { return SIZE_AVAILABLE | USED_AVAILABLE | GARBAGE_COLLECTED; } - Util::ptr_shared<char> name() const { + Util::ptr_shared name() const { return Util::share_static_string("libgc"); } Heap::Stats stats() const { diff --git a/src/debug/heap.h b/src/debug/heap.h index e1e01f022..d7d39efb9 100644 --- a/src/debug/heap.h +++ b/src/debug/heap.h @@ -36,7 +36,7 @@ public: virtual int features() const=0; - virtual Util::ptr_shared<char> name() const=0; + virtual Util::ptr_shared name() const=0; virtual Stats stats() const=0; virtual void force_collect()=0; }; diff --git a/src/debug/logger.cpp b/src/debug/logger.cpp index 2eb81a0ba..d422b8e72 100644 --- a/src/debug/logger.cpp +++ b/src/debug/logger.cpp @@ -26,7 +26,7 @@ bool Logger::_category_mask[Event::N_CATEGORIES]; namespace { -static void write_escaped_value(std::ostream &os, Util::ptr_shared<char> value) { +static void write_escaped_value(std::ostream &os, Util::ptr_shared value) { for ( char const *current=value ; *current ; ++current ) { switch (*current) { case '&': @@ -58,7 +58,7 @@ static void write_indent(std::ostream &os, unsigned depth) { static std::ofstream log_stream; static bool empty_tag=false; -typedef std::vector<Util::ptr_shared<char>, GC::Alloc<Util::ptr_shared<char>, GC::MANUAL> > TagStack; +typedef std::vector<Util::ptr_shared, GC::Alloc<Util::ptr_shared, GC::MANUAL> > TagStack; static TagStack &tag_stack() { static TagStack stack; return stack; @@ -158,7 +158,7 @@ void Logger::init() { } void Logger::_start(Event const &event) { - Util::ptr_shared<char> name=event.name(); + Util::ptr_shared name=event.name(); if (empty_tag) { log_stream << ">\n"; @@ -185,7 +185,7 @@ void Logger::_start(Event const &event) { } void Logger::_skip() { - tag_stack().push_back(Util::ptr_shared<char>()); + tag_stack().push_back(Util::ptr_shared()); } void Logger::_finish() { diff --git a/src/debug/makefile.in b/src/debug/makefile.in deleted file mode 100644 index 542f3a999..000000000 --- a/src/debug/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) debug/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) debug/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/debug/simple-event.h b/src/debug/simple-event.h index 03ce5d326..076b9b4b5 100644 --- a/src/debug/simple-event.h +++ b/src/debug/simple-event.h @@ -26,7 +26,7 @@ namespace Debug { template <Event::Category C=Event::OTHER> class SimpleEvent : public Event { public: - explicit SimpleEvent(Util::ptr_shared<char> name) : _name(name) {} + explicit SimpleEvent(Util::ptr_shared name) : _name(name) {} explicit SimpleEvent(char const *name) : _name(Util::share_string(name)) {} // default copy @@ -34,7 +34,7 @@ public: static Category category() { return C; } - Util::ptr_shared<char> name() const { return _name; } + Util::ptr_shared name() const { return _name; } unsigned propertyCount() const { return _properties.size(); } PropertyPair property(unsigned property) const { return _properties[property]; @@ -43,21 +43,21 @@ public: void generateChildEvents() const {} protected: - void _addProperty(Util::ptr_shared<char> name, - Util::ptr_shared<char> value) + void _addProperty(Util::ptr_shared name, + Util::ptr_shared value) { _properties.push_back(PropertyPair(name, value)); } - void _addProperty(Util::ptr_shared<char> name, char const *value) { + void _addProperty(Util::ptr_shared name, char const *value) { _addProperty(name, Util::share_string(value)); } - void _addProperty(char const *name, Util::ptr_shared<char> value) { + void _addProperty(char const *name, Util::ptr_shared value) { _addProperty(Util::share_string(name), value); } void _addProperty(char const *name, char const *value) { _addProperty(Util::share_string(name), Util::share_string(value)); } - void _addProperty(Util::ptr_shared<char> name, long value) { + void _addProperty(Util::ptr_shared name, long value) { _addFormattedProperty(name, "%ld", value); } void _addProperty(char const *name, long value) { @@ -65,10 +65,10 @@ protected: } private: - Util::ptr_shared<char> _name; + Util::ptr_shared _name; std::vector<PropertyPair, GC::Alloc<PropertyPair, GC::AUTO> > _properties; - void _addFormattedProperty(Util::ptr_shared<char> name, char const *format, ...) + void _addFormattedProperty(Util::ptr_shared name, char const *format, ...) { va_list args; va_start(args, format); diff --git a/src/debug/sysv-heap.h b/src/debug/sysv-heap.h index ba8f5db83..4bde77cd8 100644 --- a/src/debug/sysv-heap.h +++ b/src/debug/sysv-heap.h @@ -23,7 +23,7 @@ public: int features() const; - Util::ptr_shared<char> name() const { + Util::ptr_shared name() const { return Util::share_static_string("standard malloc()"); } Stats stats() const; diff --git a/src/debug/timestamp.cpp b/src/debug/timestamp.cpp index 6de03a463..cdd47e881 100644 --- a/src/debug/timestamp.cpp +++ b/src/debug/timestamp.cpp @@ -19,8 +19,8 @@ namespace Inkscape { namespace Debug { -Util::ptr_shared<char> timestamp() { - Util::ptr_shared<char> result; +Util::ptr_shared timestamp() { + Util::ptr_shared result; GTimeVal timestamp; g_get_current_time(×tamp); gchar *value = g_strdup_printf( "%d.%06d", static_cast<gint>(timestamp.tv_sec), static_cast<gint>(timestamp.tv_usec) ); diff --git a/src/debug/timestamp.h b/src/debug/timestamp.h index 336ed5d0f..c145ffbc9 100644 --- a/src/debug/timestamp.h +++ b/src/debug/timestamp.h @@ -18,7 +18,7 @@ namespace Inkscape { namespace Debug { -Util::ptr_shared<char> timestamp(); +Util::ptr_shared timestamp(); } diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp index 40b3272b8..758c3e939 100644 --- a/src/desktop-events.cpp +++ b/src/desktop-events.cpp @@ -559,7 +559,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data) desktop->guidesMessageContext()->clear(); break; case GDK_KEY_PRESS: - switch (Inkscape::UI::Tools::get_group0_keyval (&event->key)) { + switch (Inkscape::UI::Tools::get_latin_keyval (&event->key)) { case GDK_KEY_Delete: case GDK_KEY_KP_Delete: case GDK_KEY_BackSpace: @@ -588,7 +588,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data) } break; case GDK_KEY_RELEASE: - switch (Inkscape::UI::Tools::get_group0_keyval (&event->key)) { + switch (Inkscape::UI::Tools::get_latin_keyval (&event->key)) { case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: { diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index 19582c9ee..23f803d6a 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -197,10 +197,8 @@ sp_desktop_set_style(Inkscape::ObjectSet *set, SPDesktop *desktop, SPCSSAttr *cs SPObject *obj = *i; Box3DSide *side = dynamic_cast<Box3DSide *>(obj); if (side) { - const char * descr = box3d_side_axes_string(side); - if (descr != NULL) { - prefs->mergeStyle(Glib::ustring("/desktop/") + descr + "/style", css_write); - } + prefs->mergeStyle( + Glib::ustring("/desktop/") + box3d_side_axes_string(side) + "/style", css_write); } } sp_repr_css_attr_unref(css_write); diff --git a/src/desktop-style.h b/src/desktop-style.h index a404c94a8..bc2c56fac 100644 --- a/src/desktop-style.h +++ b/src/desktop-style.h @@ -46,7 +46,7 @@ enum { // which property was queried (add when you need more) QUERY_STYLE_PROPERTY_PAINTORDER, // paint-order QUERY_STYLE_PROPERTY_FONT_SPECIFICATION, //-inkscape-font-specification QUERY_STYLE_PROPERTY_FONTFAMILY, // font-family - QUERY_STYLE_PROPERTY_FONTSTYLE, // font style + QUERY_STYLE_PROPERTY_FONTSTYLE, // font style QUERY_STYLE_PROPERTY_FONTVARIANTS, // font variants (OpenType features) QUERY_STYLE_PROPERTY_FONTFEATURESETTINGS, // font feature settings (OpenType features) QUERY_STYLE_PROPERTY_FONTNUMBERS, // size, spacings diff --git a/src/desktop.cpp b/src/desktop.cpp index c56c42267..2d1aa8829 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1935,11 +1935,18 @@ SPDesktop::show_dialogs() mapVerbPreference.insert(std::make_pair ("Symbols", "/dialogs/symbols") ); mapVerbPreference.insert(std::make_pair ("ObjectsPanel", "/dialogs/objects") ); mapVerbPreference.insert(std::make_pair ("TagsPanel", "/dialogs/tags") ); + mapVerbPreference.insert(std::make_pair ("Prototype", "/dialogs/prototype") ); + for (std::map<Glib::ustring, Glib::ustring>::const_iterator iter = mapVerbPreference.begin(); iter != mapVerbPreference.end(); ++iter) { Glib::ustring pref = iter->second; int visible = prefs->getInt(pref + "/visible", 0); if (visible) { + + // Try to ensure that the panel is created attached to the correct desktop (bug 1720096). + // There must be a better way of handling this problem! + INKSCAPE.activate_desktop(this); + _dlg_mgr->showDialog(iter->first.c_str(), false); // without grabbing focus, we need focus to remain on the canvas } } diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 589cc849d..187597794 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -294,8 +294,8 @@ CanvasAxonomGrid::readRepr() gridunit = unit_table.getUnit(value); // Display unit identifier in grid menu } - for (GSList *l = canvasitems; l != NULL; l = l->next) { - sp_canvas_item_request_update ( SP_CANVAS_ITEM(l->data) ); + for (auto i:canvasitems) { + sp_canvas_item_request_update(i); } return; } diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 4243d3365..01bfc2fc0 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -149,7 +149,6 @@ CanvasGrid::CanvasGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocume } namedview = nv; - canvasitems = NULL; } CanvasGrid::~CanvasGrid() @@ -157,11 +156,9 @@ CanvasGrid::~CanvasGrid() if (repr) { repr->removeListenerByData (this); } - - while (canvasitems) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(canvasitems->data)); - canvasitems = g_slist_remove(canvasitems, canvasitems->data); - } + for (auto i:canvasitems) + sp_canvas_item_destroy(i); + canvasitems.clear(); } const char * @@ -276,8 +273,8 @@ CanvasGrid::createCanvasItem(SPDesktop * desktop) // but share the same CanvasGrid object; that is what this function is for. // check if there is already a canvasitem on this desktop linking to this grid - for (GSList *l = canvasitems; l != NULL; l = l->next) { - if ( desktop->getGridGroup() == SP_CANVAS_GROUP(SP_CANVAS_ITEM(l->data)->parent) ) { + for (auto i:canvasitems) { + if ( desktop->getGridGroup() == SP_CANVAS_GROUP(i->parent) ) { return NULL; } } @@ -287,7 +284,7 @@ CanvasGrid::createCanvasItem(SPDesktop * desktop) sp_canvas_item_show(SP_CANVAS_ITEM(item)); g_object_ref(item); // since we're keeping a link to this item, we need to bump up the ref count - canvasitems = g_slist_prepend(canvasitems, item); + canvasitems.push_back(item); return item; } @@ -650,8 +647,8 @@ CanvasXYGrid::readRepr() gridunit = unit_table.getUnit(value); // Display unit identifier in grid menu } - for (GSList *l = canvasitems; l != NULL; l = l->next) { - sp_canvas_item_request_update ( SP_CANVAS_ITEM(l->data) ); + for (auto i:canvasitems) { + sp_canvas_item_request_update(i); } return; diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index 91fa43e69..6b36390c8 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -112,7 +112,7 @@ protected: virtual Gtk::Widget * newSpecificWidget() = 0; - GSList * canvasitems; // list of created canvasitems + std::vector<SPCanvasItem*> canvasitems; // list of created canvasitems SPNamedView * namedview; diff --git a/src/display/canvas-rotate.cpp b/src/display/canvas-rotate.cpp index aaf6b962c..1d917a677 100644 --- a/src/display/canvas-rotate.cpp +++ b/src/display/canvas-rotate.cpp @@ -72,13 +72,13 @@ static void sp_canvas_rotate_update( SPCanvasItem *item, Geom::Affine const &/*a // std::cout << "sp_canvas_rotate_update: surface_copy is NULL" << std::endl; return; } - + // Destroy surface_rotated if it already exists. if (cr->surface_rotated != NULL) { cairo_surface_destroy (cr->surface_rotated); cr->surface_rotated = NULL; } - + // Create rotated surface cr->surface_rotated = ink_cairo_surface_create_identical(cr->surface_copy); double width = cairo_image_surface_get_width (cr->surface_rotated); @@ -91,7 +91,7 @@ static void sp_canvas_rotate_update( SPCanvasItem *item, Geom::Affine const &/*a cairo_set_source_surface( context, cr->surface_copy, 0, 0 ); cairo_paint( context ); cairo_destroy( context); - + // We cover the entire canvas item->x1 = -G_MAXINT; item->y1 = -G_MAXINT; @@ -108,8 +108,9 @@ static void sp_canvas_rotate_render( SPCanvasItem *item, SPCanvasBuf *buf) // std::cout << " buf->rect: " << buf->rect << std::endl; // std::cout << " buf->canvas_rect: " << buf->canvas_rect << std::endl; SPCanvasRotate *cr = SP_CANVAS_ROTATE(item); + auto ct = buf->ct; - if (!buf->ct) { + if (!ct) { return; } @@ -119,26 +120,26 @@ static void sp_canvas_rotate_render( SPCanvasItem *item, SPCanvasBuf *buf) } // Draw rotated canvas - cairo_save (buf->ct); - cairo_translate (buf->ct, + cairo_save (ct); + cairo_translate (ct, buf->canvas_rect.left() - buf->rect.left(), buf->canvas_rect.top() - buf->rect.top() ); - cairo_set_operator (buf->ct, CAIRO_OPERATOR_SOURCE ); - cairo_set_source_surface (buf->ct, cr->surface_rotated, 0, 0 ); - cairo_paint (buf->ct); - cairo_restore (buf->ct); + cairo_set_operator (ct, CAIRO_OPERATOR_SOURCE ); + cairo_set_source_surface (ct, cr->surface_rotated, 0, 0 ); + cairo_paint (ct); + cairo_restore (ct); // Draw line from center to cursor - cairo_save (buf->ct); - cairo_translate (buf->ct, -buf->rect.left(), -buf->rect.top()); - cairo_new_path (buf->ct); - cairo_move_to (buf->ct, cr->center[Geom::X], cr->center[Geom::Y]); - cairo_rel_line_to (buf->ct, cr->cursor[Geom::X], cr->cursor[Geom::Y]); - cairo_set_line_width (buf->ct, 2); - ink_cairo_set_source_rgba32 (buf->ct, 0xff00007f); - cairo_stroke (buf->ct); - cairo_restore (buf->ct); + cairo_save (ct); + cairo_translate (ct, -buf->rect.left(), -buf->rect.top()); + cairo_new_path (ct); + cairo_move_to (ct, cr->center[Geom::X], cr->center[Geom::Y]); + cairo_rel_line_to (ct, cr->cursor[Geom::X], cr->cursor[Geom::Y]); + cairo_set_line_width (ct, 2); + ink_cairo_set_source_rgba32 (ct, 0xff00007f); + cairo_stroke (ct); + cairo_restore (ct); } @@ -187,7 +188,7 @@ static int sp_canvas_rotate_event (SPCanvasItem *item, GdkEvent *event) // Correct line for snapping of angle double distance = rcursor.length(); - cr->cursor = Geom::Point::polar( Geom::rad_from_deg(angle), distance ); + cr->cursor = Geom::Point::polar( Geom::rad_from_deg(angle), distance ); // Update screen // sp_canvas_item_request_update( item ); @@ -214,7 +215,7 @@ static int sp_canvas_rotate_event (SPCanvasItem *item, GdkEvent *event) cr->surface_rotated = NULL; } // sp_canvas_item_show (desktop->drawing); - + break; case GDK_KEY_PRESS: // std::cout << " Key press: " << std::endl; @@ -260,10 +261,10 @@ void sp_canvas_rotate_paint (SPCanvasRotate *canvas_rotate, cairo_surface_t *bac double width = cairo_image_surface_get_width (background); double height = cairo_image_surface_get_height (background); - + // Draw rotated canvas cairo_t *context = cairo_create( background ); - + cairo_save (context); cairo_set_operator( context, CAIRO_OPERATOR_SOURCE ); cairo_translate( context, width/2.0, height/2.0 ); diff --git a/src/display/curve.cpp b/src/display/curve.cpp index 6e662b17b..1115978e9 100644 --- a/src/display/curve.cpp +++ b/src/display/curve.cpp @@ -38,6 +38,15 @@ SPCurve::SPCurve(Geom::PathVector const& pathv) _pathv(pathv) {} +//concat constructor +SPCurve::SPCurve(std::list<SPCurve *> const& l) : _refcount(1) +{ + for (auto c:l) { + _pathv.insert( _pathv.end(), c->get_pathvector().begin(), c->get_pathvector().end() ); + } +} + + SPCurve * SPCurve::new_from_rect(Geom::Rect const &rect, bool all_four_sides) { @@ -134,32 +143,24 @@ SPCurve::copy() const * Return new curve that is the concatenation of all curves in list. */ SPCurve * -SPCurve::concat(GSList const *list) -{ - SPCurve *new_curve = new SPCurve(); - - for (GSList const *l = list; l != NULL; l = l->next) { - SPCurve *c = static_cast<SPCurve *>(l->data); - new_curve->_pathv.insert( new_curve->_pathv.end(), c->get_pathvector().begin(), c->get_pathvector().end() ); - } - - return new_curve; -} +SPCurve::concat(std::list<SPCurve *> l){ + return new SPCurve(l); +}; /** * Returns a list of new curves corresponding to the subpaths in \a curve. * 2geomified */ -GSList * +std::list<SPCurve *> SPCurve::split() const { - GSList *l = NULL; + std::list<SPCurve *> l; for (Geom::PathVector::const_iterator path_it = _pathv.begin(); path_it != _pathv.end(); ++path_it) { Geom::PathVector newpathv; newpathv.push_back(*path_it); SPCurve * newcurve = new SPCurve(newpathv); - l = g_slist_prepend(l, newcurve); + l.push_back(newcurve); } return l; diff --git a/src/display/curve.h b/src/display/curve.h index 8375e1105..87b9984a8 100644 --- a/src/display/curve.h +++ b/src/display/curve.h @@ -16,8 +16,7 @@ #include <2geom/pathvector.h> #include <cstddef> #include <boost/optional.hpp> - -extern "C" { typedef struct _GSList GSList; } +#include <list> /** * Wrapper around a Geom::PathVector object. @@ -27,6 +26,7 @@ public: /* Constructors */ explicit SPCurve(); explicit SPCurve(Geom::PathVector const& pathv); + explicit SPCurve(std::list<SPCurve *> const& pathv); static SPCurve * new_from_rect(Geom::Rect const &rect, bool all_four_sides = false); virtual ~SPCurve(); @@ -78,8 +78,8 @@ public: SPCurve * append_continuous(SPCurve const *c1, double tolerance); SPCurve * create_reverse() const; - GSList * split() const; - static SPCurve * concat(GSList const *list); + std::list<SPCurve *> split() const; + static SPCurve * concat(std::list<SPCurve *> l); protected: size_t _refcount; diff --git a/src/display/drawing-surface.h b/src/display/drawing-surface.h index 7bec1606a..78471649a 100644 --- a/src/display/drawing-surface.h +++ b/src/display/drawing-surface.h @@ -12,7 +12,6 @@ #ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_SURFACE_H #define SEEN_INKSCAPE_DISPLAY_DRAWING_SURFACE_H -#include <boost/shared_ptr.hpp> #include <cairo.h> #include <2geom/affine.h> #include <2geom/rect.h> diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp index 21af7b200..3f6b5b34a 100644 --- a/src/display/drawing-text.cpp +++ b/src/display/drawing-text.cpp @@ -91,12 +91,11 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext if (_transform) { scale_bigbox /= _transform->descrim(); } - /* Because there can be text decorations the bounding box must correspond in Y to a little above the glyph's ascend and a little below its descend. This leaves room for overline and underline. The left and right sides - come from the glyph's bounding box. Note that the initial direction of ascender is positive down in Y, and - this flips after the transform is applied. So change the sign on descender. 1.1 provides a little extra space + come from the glyph's bounding box. Note that the initial direction of ascender is positive down in Y, and + this flips after the transform is applied. So change the sign on descender. 1.1 provides a little extra space above and below the max/min y positions of the letters to place the text decorations.*/ Geom::Rect b; @@ -129,10 +128,10 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext Geom::Rect pbigbox(Geom::Point(0.0, _asc*scale_bigbox*0.66),Geom::Point(_width*scale_bigbox, 0.0)); pb = pbigbox * ctx.ctm; } - + #if 0 /* FIXME if this is commented out then not even an approximation of pick on decorations */ - /* adjust the pick box up or down to include the decorations. + /* adjust the pick box up or down to include the decorations. This is only approximate since at this point we don't know how wide that line is, if it has an unusual offset, and so forth. The selection point is set at what is roughly the center of the decoration (vertically) for the wide ones, like wavy and double line. @@ -146,7 +145,7 @@ unsigned DrawingGlyphs::_updateItem(Geom::IntRect const &/*area*/, UpdateContext Geom::Rect padjbox(Geom::Point(0.0, top),Geom::Point(_width*scale_bigbox, bot)); pb.unionWith(padjbox * ctx.ctm); } -#endif +#endif if (ggroup->_nrstyle.stroke.type != NRStyle::PAINT_NONE) { // this expands the selection box for cases where the stroke is "thick" @@ -263,8 +262,8 @@ DrawingText::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, un void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2, double thickness) { double wave[16]={ - 0.000000, 0.382499, 0.706825, 0.923651, 1.000000, 0.923651, 0.706825, 0.382499, - 0.000000, -0.382499, -0.706825, -0.923651, -1.000000, -0.923651, -0.706825, -0.382499, + 0.000000, 0.382499, 0.706825, 0.923651, 1.000000, 0.923651, 0.706825, 0.382499, + 0.000000, -0.382499, -0.706825, -0.923651, -1.000000, -0.923651, -0.706825, -0.382499, }; int dashes[16]={ 8, 7, 6, 5, @@ -283,7 +282,7 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas /* For most spans draw the last little bit right to p2 or even a little beyond. This allows decoration continuity within the line, and does not step outside the clip box off the end - For the first/last section on the line though, stay well clear of the edge, or when the + For the first/last section on the line though, stay well clear of the edge, or when the text is dragged it may "spray" pixels. */ /* snap to nearest step in X */ @@ -329,7 +328,7 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas } i = 0; // once in phase, it stays in phase } - } + } else if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_DASHED){ Geom::Point pv = ps; while(1){ @@ -354,7 +353,7 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas } i = 0; // once in phase, it stays in phase } - } + } else if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_WAVY){ double amp = vextent/10.0; double x = ps[Geom::X]; @@ -375,10 +374,10 @@ void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphas if(x <= ps[Geom::X])break; } dc.closePath(); - } + } else { // TEXT_DECORATION_STYLE_SOLID, also default in case it was not set for some reason dc.rectangle( Geom::Rect(ps + poff, pf - poff)); - } + } } /* returns scaled line thickness */ @@ -629,7 +628,7 @@ unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*are { Inkscape::DrawingContext::Save save(dc); dc.transform(_ctm); // Needed so that fill pattern rotates with text - + if (has_td_fill && fill_first) { _nrstyle.applyTextDecorationFill(dc); dc.fillPreserve(); @@ -685,11 +684,7 @@ void DrawingText::_clipItem(DrawingContext &dc, Geom::IntRect const &/*area*/) DrawingItem * DrawingText::_pickItem(Geom::Point const &p, double delta, unsigned flags) { - DrawingItem *picked = DrawingGroup::_pickItem(p, delta, flags); - if (picked) { - return this; - } - return NULL; + return DrawingGroup::_pickItem(p, delta, flags) ? this : NULL; } bool diff --git a/src/display/makefile.in b/src/display/makefile.in deleted file mode 100644 index 747f18e11..000000000 --- a/src/display/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) display/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) display/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp index d0db6b42e..49dfc7ec4 100644 --- a/src/display/nr-filter-blend.cpp +++ b/src/display/nr-filter-blend.cpp @@ -3,7 +3,7 @@ *//* * "This filter composites two objects together using commonly used * imaging software blending modes. It performs a pixel-wise combination - * of two input images." + * of two input images." * http://www.w3.org/TR/SVG11/filters.html#feBlend * * Authors: @@ -32,7 +32,18 @@ namespace Inkscape { namespace Filters { -FilterBlend::FilterBlend() +const std::set<FilterBlendMode> FilterBlend::_valid_modes { + BLEND_NORMAL, BLEND_MULTIPLY, + BLEND_SCREEN, BLEND_DARKEN, + BLEND_LIGHTEN, BLEND_OVERLAY, + BLEND_COLORDODGE, BLEND_COLORBURN, + BLEND_HARDLIGHT, BLEND_SOFTLIGHT, + BLEND_DIFFERENCE, BLEND_EXCLUSION, + BLEND_HUE, BLEND_SATURATION, + BLEND_COLOR, BLEND_LUMINOSITY + }; + +FilterBlend::FilterBlend() : _blend_mode(BLEND_NORMAL), _input2(NR_FILTER_SLOT_NOT_SET) {} @@ -44,6 +55,47 @@ FilterPrimitive * FilterBlend::create() { FilterBlend::~FilterBlend() {} +static inline cairo_operator_t get_cairo_op(FilterBlendMode _blend_mode) +{ + switch (_blend_mode) { + case BLEND_MULTIPLY: + return CAIRO_OPERATOR_MULTIPLY; + case BLEND_SCREEN: + return CAIRO_OPERATOR_SCREEN; + case BLEND_DARKEN: + return CAIRO_OPERATOR_DARKEN; + case BLEND_LIGHTEN: + return CAIRO_OPERATOR_LIGHTEN; + // New in CSS Compositing and Blending Level 1 + case BLEND_OVERLAY: + return CAIRO_OPERATOR_OVERLAY; + case BLEND_COLORDODGE: + return CAIRO_OPERATOR_COLOR_DODGE; + case BLEND_COLORBURN: + return CAIRO_OPERATOR_COLOR_BURN; + case BLEND_HARDLIGHT: + return CAIRO_OPERATOR_HARD_LIGHT; + case BLEND_SOFTLIGHT: + return CAIRO_OPERATOR_SOFT_LIGHT; + case BLEND_DIFFERENCE: + return CAIRO_OPERATOR_DIFFERENCE; + case BLEND_EXCLUSION: + return CAIRO_OPERATOR_EXCLUSION; + case BLEND_HUE: + return CAIRO_OPERATOR_HSL_HUE; + case BLEND_SATURATION: + return CAIRO_OPERATOR_HSL_SATURATION; + case BLEND_COLOR: + return CAIRO_OPERATOR_HSL_COLOR; + case BLEND_LUMINOSITY: + return CAIRO_OPERATOR_HSL_LUMINOSITY; + + case BLEND_NORMAL: + default: + return CAIRO_OPERATOR_OVER; + } +} + void FilterBlend::render_cairo(FilterSlot &slot) { cairo_surface_t *input1 = slot.getcairo(_input); @@ -71,59 +123,7 @@ void FilterBlend::render_cairo(FilterSlot &slot) // All of the blend modes are implemented in Cairo as of 1.10. // For a detailed description, see: // http://cairographics.org/operators/ - switch (_blend_mode) { - case BLEND_MULTIPLY: - cairo_set_operator(out_ct, CAIRO_OPERATOR_MULTIPLY); - break; - case BLEND_SCREEN: - cairo_set_operator(out_ct, CAIRO_OPERATOR_SCREEN); - break; - case BLEND_DARKEN: - cairo_set_operator(out_ct, CAIRO_OPERATOR_DARKEN); - break; - case BLEND_LIGHTEN: - cairo_set_operator(out_ct, CAIRO_OPERATOR_LIGHTEN); - break; - // New in CSS Compositing and Blending Level 1 - case BLEND_OVERLAY: - cairo_set_operator(out_ct, CAIRO_OPERATOR_OVERLAY); - break; - case BLEND_COLORDODGE: - cairo_set_operator(out_ct, CAIRO_OPERATOR_COLOR_DODGE); - break; - case BLEND_COLORBURN: - cairo_set_operator(out_ct, CAIRO_OPERATOR_COLOR_BURN); - break; - case BLEND_HARDLIGHT: - cairo_set_operator(out_ct, CAIRO_OPERATOR_HARD_LIGHT); - break; - case BLEND_SOFTLIGHT: - cairo_set_operator(out_ct, CAIRO_OPERATOR_SOFT_LIGHT); - break; - case BLEND_DIFFERENCE: - cairo_set_operator(out_ct, CAIRO_OPERATOR_DIFFERENCE); - break; - case BLEND_EXCLUSION: - cairo_set_operator(out_ct, CAIRO_OPERATOR_EXCLUSION); - break; - case BLEND_HUE: - cairo_set_operator(out_ct, CAIRO_OPERATOR_HSL_HUE); - break; - case BLEND_SATURATION: - cairo_set_operator(out_ct, CAIRO_OPERATOR_HSL_SATURATION); - break; - case BLEND_COLOR: - cairo_set_operator(out_ct, CAIRO_OPERATOR_HSL_COLOR); - break; - case BLEND_LUMINOSITY: - cairo_set_operator(out_ct, CAIRO_OPERATOR_HSL_LUMINOSITY); - break; - - case BLEND_NORMAL: - default: - cairo_set_operator(out_ct, CAIRO_OPERATOR_OVER); - break; - } + cairo_set_operator(out_ct, get_cairo_op(_blend_mode)); cairo_paint(out_ct); cairo_destroy(out_ct); @@ -145,13 +145,8 @@ double FilterBlend::complexity(Geom::Affine const &) bool FilterBlend::uses_background() { - if (_input == NR_FILTER_BACKGROUNDIMAGE || _input == NR_FILTER_BACKGROUNDALPHA || - _input2 == NR_FILTER_BACKGROUNDIMAGE || _input2 == NR_FILTER_BACKGROUNDALPHA) - { - return true; - } else { - return false; - } + return (_input == NR_FILTER_BACKGROUNDIMAGE || _input == NR_FILTER_BACKGROUNDALPHA || + _input2 == NR_FILTER_BACKGROUNDIMAGE || _input2 == NR_FILTER_BACKGROUNDALPHA); } void FilterBlend::set_input(int slot) { @@ -164,15 +159,7 @@ void FilterBlend::set_input(int input, int slot) { } void FilterBlend::set_mode(FilterBlendMode mode) { - if (mode == BLEND_NORMAL || mode == BLEND_MULTIPLY || - mode == BLEND_SCREEN || mode == BLEND_DARKEN || - mode == BLEND_LIGHTEN || mode == BLEND_OVERLAY || - mode == BLEND_COLORDODGE || mode == BLEND_COLORBURN || - mode == BLEND_HARDLIGHT || mode == BLEND_SOFTLIGHT || - mode == BLEND_DIFFERENCE || mode == BLEND_EXCLUSION || - mode == BLEND_HUE || mode == BLEND_SATURATION || - mode == BLEND_COLOR || mode == BLEND_LUMINOSITY - ) + if (_valid_modes.count(mode)) { _blend_mode = mode; } diff --git a/src/display/nr-filter-blend.h b/src/display/nr-filter-blend.h index 30c9d6725..5b1295c88 100644 --- a/src/display/nr-filter-blend.h +++ b/src/display/nr-filter-blend.h @@ -6,7 +6,7 @@ * * "This filter composites two objects together using commonly used * imaging software blending modes. It performs a pixel-wise combination - * of two input images." + * of two input images." * http://www.w3.org/TR/SVG11/filters.html#feBlend * * Authors: @@ -16,6 +16,7 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <set> #include "display/nr-filter-primitive.h" @@ -29,14 +30,14 @@ enum FilterBlendMode { BLEND_DARKEN, BLEND_LIGHTEN, // New in CSS Compositing and Blending Level 1 - BLEND_OVERLAY, + BLEND_OVERLAY, BLEND_COLORDODGE, BLEND_COLORBURN, BLEND_HARDLIGHT, BLEND_SOFTLIGHT, BLEND_DIFFERENCE, BLEND_EXCLUSION, - BLEND_HUE, + BLEND_HUE, BLEND_SATURATION, BLEND_COLOR, BLEND_LUMINOSITY, @@ -59,6 +60,7 @@ public: void set_mode(FilterBlendMode mode); private: + static const std::set<FilterBlendMode> _valid_modes; FilterBlendMode _blend_mode; int _input2; }; diff --git a/src/display/nr-filter-diffuselighting.h b/src/display/nr-filter-diffuselighting.h index 7739b3ea6..5ce505979 100644 --- a/src/display/nr-filter-diffuselighting.h +++ b/src/display/nr-filter-diffuselighting.h @@ -7,7 +7,7 @@ * Authors: * Niko Kiirala <niko@kiirala.com> * Jean-Rene Reinhard <jr@komite.net> - * + * * Copyright (C) 2007 authors * * Released under GNU GPL, read the file 'COPYING' for more information @@ -26,7 +26,7 @@ typedef unsigned int guint32; namespace Inkscape { namespace Filters { - + class FilterDiffuseLighting : public FilterPrimitive { public: FilterDiffuseLighting(); @@ -54,7 +54,7 @@ private: } /* namespace Filters */ } /* namespace Inkscape */ -#endif /* __NR_FILTER_DIFFUSELIGHTING_H__ */ +#endif /* SEEN_NR_FILTER_DIFFUSELIGHTING_H */ /* Local Variables: mode:c++ diff --git a/src/display/nr-filter-primitive.h b/src/display/nr-filter-primitive.h index 4b7577159..a1339cc6c 100644 --- a/src/display/nr-filter-primitive.h +++ b/src/display/nr-filter-primitive.h @@ -69,7 +69,7 @@ public: // returns cache score factor, reflecting the cost of rendering this filter // this should return how many times slower this primitive is that normal rendering virtual double complexity(Geom::Affine const &/*ctm*/) { return 1.0; } - + virtual bool uses_background() { if (_input == NR_FILTER_BACKGROUNDIMAGE || _input == NR_FILTER_BACKGROUNDALPHA) { return true; @@ -138,10 +138,7 @@ protected: } /* namespace Filters */ } /* namespace Inkscape */ - - - -#endif /* __NR_FILTER_PRIMITIVE_H__ */ +#endif /* SEEN_NR_FILTER_PRIMITIVE_H */ /* Local Variables: mode:c++ diff --git a/src/document.cpp b/src/document.cpp index d9c709626..4c24d0a96 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -513,7 +513,7 @@ SPDocument *SPDocument::createChildDoc(std::string const &uri) } else { path = uri; } - std::cout << "Added base: '" << path << "'\n"; + std::cout << "Added base: '" << path << std::endl; document = createNewDoc(path.c_str(), false, false, this); } return document; diff --git a/src/doxygen-main.dox b/src/doxygen-main.dox index 6a5723bfd..c714c2cbf 100644 --- a/src/doxygen-main.dox +++ b/src/doxygen-main.dox @@ -178,13 +178,8 @@ namespace XML {} * <a href="http://developer.gnome.org/doc/API/2.0/gobject/index.html">GObject</a> * <a href="http://developer.gnome.org/doc/API/2.0/atk/index.html">atk</a> * <a href="http://developer.gnome.org/doc/API/2.0/pango/index.html">pango</a> - * <a href="http://developer.gnome.org/doc/API/2.0/ORBit/index.html">ORBit</a> - * <a href="http://developer.gnome.org/doc/API/2.0/libbonobo/index.html">bonobo</a> - * <a href="http://developer.gnome.org/doc/API/2.0/bonobo-activation/index.html">bonobo-activation</a> * <a href="http://xmlsoft.org/XSLT/html/libxslt-lib.html#LIBXSLT-LIB">libxslt</a> * <a href="http://xmlsoft.org/html/index.html">libxml2</a> - * Legacy: - * <a href="http://developer.gnome.org/doc/API/2.0/gnome-vfs-2.0/">GnomeVFS</a> * * \subsection stdlinks External standards documentation * @@ -200,7 +195,7 @@ namespace XML {} /** \page ObjectTree Object Tree Classes and Files * Inkscape::ObjectHierarchy [\ref object-hierarchy.cpp, \ref object-hierarchy.h] - * - SPObject [\ref sp-object.cpp, \ref sp-object.h, \ref object-edit.cpp, \ref sp-object-repr.cpp] + * - SPObject [\ref sp-object.cpp, \ref sp-object.h, \ref shape-editor-knotholders.cpp, \ref sp-object-repr.cpp] * - SPDefs [\ref sp-defs.cpp, \ref sp-defs.h] * - SPFlowline [\ref sp-flowdiv.cpp, \ref sp-flowdiv.h] * - SPFlowregionbreak [\ref sp-flowdiv.cpp, \ref sp-flowdiv.h] diff --git a/src/ege-color-prof-tracker.cpp b/src/ege-color-prof-tracker.cpp index 3a91fee4d..8401b2cc3 100644 --- a/src/ege-color-prof-tracker.cpp +++ b/src/ege-color-prof-tracker.cpp @@ -40,6 +40,8 @@ /* Note: this file should be kept compilable as both .cpp and .c */ #include <string.h> +#include <vector> +#include <algorithm> #include <gtk/gtk.h> @@ -63,14 +65,17 @@ enum { static void ege_color_prof_tracker_get_property( GObject* obj, guint propId, GValue* value, GParamSpec * pspec ); static void ege_color_prof_tracker_set_property( GObject* obj, guint propId, const GValue *value, GParamSpec* pspec ); -typedef struct _ScreenTrack { +class ScreenTrack { + public: #ifdef GDK_WINDOWING_X11 gboolean zeroSeen; gboolean otherSeen; #endif /* GDK_WINDOWING_X11 */ - GSList* trackers; + std::vector<EgeColorProfTracker *> *trackers; GPtrArray* profiles; -} ScreenTrack; + ~ScreenTrack(){ delete trackers; } +}; + #ifdef GDK_WINDOWING_X11 GdkFilterReturn x11_win_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data); @@ -86,7 +91,7 @@ static guint signals[LAST_SIGNAL] = {0}; // There is only one GdkScreen in Gtk+ 3 static ScreenTrack *tracked_screen = nullptr; -static GSList* abstract_trackers = 0; +static std::vector<EgeColorProfTracker *> abstract_trackers; struct _EgeColorProfTrackerPrivate { @@ -182,7 +187,7 @@ EgeColorProfTracker* ege_color_prof_tracker_new( GtkWidget* target ) target_hierarchy_changed_cb( target, 0, obj ); target_screen_changed_cb( target, 0, obj ); } else { - abstract_trackers = g_slist_append( abstract_trackers, obj ); + abstract_trackers.push_back(tracker); if(tracked_screen) { for ( gint monitor = 0; monitor < (gint)tracked_screen->profiles->len; monitor++ ) { @@ -280,9 +285,8 @@ void track_screen( GdkScreen* screen, EgeColorProfTracker* tracker ) { if ( tracked_screen ) { /* We found the screen already being tracked */ - GSList* trackHook = g_slist_find( tracked_screen->trackers, tracker ); - if ( !trackHook ) { - tracked_screen->trackers = g_slist_append( tracked_screen->trackers, tracker ); + if ( std::find(tracked_screen->trackers->begin(),tracked_screen->trackers->end(),tracker)==tracked_screen->trackers->end() ) { + tracked_screen->trackers->push_back(tracker); } } else { tracked_screen = g_new(ScreenTrack, 1); @@ -299,7 +303,8 @@ void track_screen( GdkScreen* screen, EgeColorProfTracker* tracker ) tracked_screen->zeroSeen = FALSE; tracked_screen->otherSeen = FALSE; #endif /* GDK_WINDOWING_X11 */ - tracked_screen->trackers = g_slist_append( 0, tracker ); + tracked_screen->trackers= new std::vector<EgeColorProfTracker *>; + tracked_screen->trackers->push_back(tracker ); tracked_screen->profiles = g_ptr_array_new(); for ( int i = 0; i < numMonitors; i++ ) { g_ptr_array_add( tracked_screen->profiles, 0 ); @@ -323,15 +328,12 @@ void target_finalized( gpointer data, GObject* where_the_object_was ) { (void)data; if ( tracked_screen ) { - GSList* trackHook = tracked_screen->trackers; - while ( trackHook ) { - if ( (void*)(((EgeColorProfTracker*)(trackHook->data))->private_data->_target) == (void*)where_the_object_was ) { + for (auto i = tracked_screen->trackers->begin(); i != tracked_screen->trackers->end(); ++i) { + if ( (void*)((*i)->private_data->_target) == (void*)where_the_object_was ) { /* The tracked widget is now gone, remove it */ - ((EgeColorProfTracker*)trackHook->data)->private_data->_target = 0; - tracked_screen->trackers = g_slist_remove( tracked_screen->trackers, trackHook ); - trackHook = 0; - } else { - trackHook = g_slist_next( trackHook ); + (*i)->private_data->_target = 0; + tracked_screen->trackers->erase(i); + break; } } } @@ -578,14 +580,10 @@ void add_x11_tracking_for_screen(GdkScreen* screen) void fire(gint monitor) { if ( tracked_screen ) { - GSList* trackHook = tracked_screen->trackers; - - while ( trackHook ) { - EgeColorProfTracker* tracker = (EgeColorProfTracker*)(trackHook->data); + for (auto tracker:(*(tracked_screen->trackers))) { if ( (monitor == -1) || (tracker->private_data->_monitor == monitor) ) { g_signal_emit( G_OBJECT(tracker), signals[CHANGED], 0 ); } - trackHook = g_slist_next(trackHook); } } } @@ -609,8 +607,6 @@ static void clear_profile( guint monitor ) static void set_profile( guint monitor, const guint8* data, guint len ) { if ( tracked_screen ) { - GSList* abstracts = 0; - for ( guint i = tracked_screen->profiles->len; i <= monitor; i++ ) { g_ptr_array_add( tracked_screen->profiles, 0 ); } @@ -627,8 +623,8 @@ static void set_profile( guint monitor, const guint8* data, guint len ) tracked_screen->profiles->pdata[monitor] = 0; } - for ( abstracts = abstract_trackers; abstracts; abstracts = g_slist_next(abstracts) ) { - g_signal_emit( G_OBJECT(abstracts->data), signals[MODIFIED], 0, monitor ); + for (auto i:abstract_trackers) { + g_signal_emit( G_OBJECT(i), signals[MODIFIED], 0, monitor ); } } } diff --git a/src/event-log.cpp b/src/event-log.cpp index 5a73b649e..41ab2f2d0 100644 --- a/src/event-log.cpp +++ b/src/event-log.cpp @@ -12,8 +12,6 @@ #include "event-log.h" #include <glibmm/i18n.h> -#include <boost/shared_ptr.hpp> -#include <boost/make_shared.hpp> #include "desktop.h" #include "inkscape.h" @@ -60,9 +58,9 @@ public: Inkscape::EventLog::CallbackMap *_callbacks; }; -void addBlocker(std::vector<boost::shared_ptr<SignalBlocker> > &blockers, sigc::connection *connection) +void addBlocker(std::vector<std::unique_ptr<SignalBlocker> > &blockers, sigc::connection *connection) { - blockers.push_back(boost::make_shared<SignalBlocker>(connection)); + blockers.emplace_back(new SignalBlocker(connection)); } @@ -98,7 +96,7 @@ public: dlg._event_list_selection->set_mode(Gtk::SELECTION_SINGLE); { - std::vector<boost::shared_ptr<SignalBlocker> > blockers; + std::vector<std::unique_ptr<SignalBlocker> > blockers; addBlocker(blockers, &(*dlg._callback_connections)[Inkscape::EventLog::CALLB_SELECTION_CHANGE]); addBlocker(blockers, &(*dlg._callback_connections)[Inkscape::EventLog::CALLB_EXPAND]); @@ -119,7 +117,7 @@ public: void collapseRow(Gtk::TreeModel::Path const &path) { - std::vector<boost::shared_ptr<SignalBlocker> > blockers; + std::vector<std::unique_ptr<SignalBlocker> > blockers; for (std::vector<DialogConnection>::iterator it(_connections.begin()); it != _connections.end(); ++it) { addBlocker(blockers, &(*it->_callback_connections)[Inkscape::EventLog::CALLB_SELECTION_CHANGE]); @@ -134,7 +132,7 @@ public: void selectRow(Gtk::TreeModel::Path const &path) { - std::vector<boost::shared_ptr<SignalBlocker> > blockers; + std::vector<std::unique_ptr<SignalBlocker> > blockers; for (std::vector<DialogConnection>::iterator it(_connections.begin()); it != _connections.end(); ++it) { addBlocker(blockers, &(*it->_callback_connections)[Inkscape::EventLog::CALLB_SELECTION_CHANGE]); @@ -152,7 +150,7 @@ public: void clearEventList(Glib::RefPtr<Gtk::TreeStore> eventListStore) { if (eventListStore) { - std::vector<boost::shared_ptr<SignalBlocker> > blockers; + std::vector<std::unique_ptr<SignalBlocker> > blockers; for (std::vector<DialogConnection>::iterator it(_connections.begin()); it != _connections.end(); ++it) { addBlocker(blockers, &(*it->_callback_connections)[Inkscape::EventLog::CALLB_SELECTION_CHANGE]); diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 435e347d0..513ec2f5c 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -968,10 +968,7 @@ document_interface_save_as (DocumentInterface *doc_interface, { // FIXME: Isn't there a verb we can use for this instead? SPDocument * doc = doc_interface->target.getDocument(); - #ifdef WITH_GNOME_VFS - const Glib::ustring file(filename); - return file_save_remote(doc, file, NULL, TRUE, TRUE); - #endif + if (!doc || strlen(filename)<1) { //Safety check return false; } diff --git a/src/extension/extension.cpp b/src/extension/extension.cpp index f1b328f05..d9ea5eca7 100644 --- a/src/extension/extension.cpp +++ b/src/extension/extension.cpp @@ -64,7 +64,6 @@ Extension::Extension (Inkscape::XML::Node * in_repr, Implementation::Implementat id = NULL; name = NULL; _state = STATE_UNLOADED; - parameters = NULL; if (in_imp == NULL) { imp = new Implementation::Implementation(); @@ -97,7 +96,7 @@ Extension::Extension (Inkscape::XML::Node * in_repr, Implementation::Implementat Parameter * param; param = Parameter::make(child_repr, this); if (param != NULL) - parameters = g_slist_append(parameters, param); + parameters.push_back(param); } /* param || _param */ if (!strcmp(chname, "dependency")) { _deps.push_back(new Dependency(child_repr)); @@ -146,12 +145,9 @@ Extension::~Extension (void) /** \todo Need to do parameters here */ // delete parameters: - for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) { - Parameter * param = reinterpret_cast<Parameter *>(list->data); + for (auto param:parameters) { delete param; } - g_slist_free(parameters); - for (unsigned int i = 0 ; i < _deps.size(); i++) { delete _deps[i]; @@ -402,14 +398,11 @@ Parameter *Extension::get_param(gchar const *name) if (name == NULL) { throw Extension::param_not_exist(); } - if (this->parameters == NULL) { - // the list of parameters is empty + if (this->parameters.empty()) { throw Extension::param_not_exist(); } - for (GSList * list = this->parameters; list != NULL; list = -g_slist_next(list)) { - Parameter * param = static_cast<Parameter*>(list->data); + for( auto param:this->parameters) { if (!strcmp(param->name(), name)) { return param; } else { @@ -730,8 +723,7 @@ Extension::autogui (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<v agui->set_spacing(Parameter::GUI_BOX_SPACING); //go through the list of parameters to see if there are any non-hidden ones - for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) { - Parameter * param = reinterpret_cast<Parameter *>(list->data); + for (auto param:parameters) { if (param->get_hidden()) continue; //Ignore hidden parameters Gtk::Widget * widg = param->get_widget(doc, node, changeSignal); gchar const * tip = param->get_tooltip(); @@ -751,8 +743,7 @@ Extension::autogui (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<v void Extension::paramListString (std::list <std::string> &retlist) { - for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) { - Parameter * param = reinterpret_cast<Parameter *>(list->data); + for(auto param:parameters) { param->string(retlist); } @@ -835,8 +826,7 @@ Extension::get_params_widget(void) unsigned int Extension::param_visible_count ( ) { unsigned int _visible_count = 0; - for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) { - Parameter * param = reinterpret_cast<Parameter *>(list->data); + for (auto param:parameters) { if (!param->get_hidden()) _visible_count++; } return _visible_count; diff --git a/src/extension/extension.h b/src/extension/extension.h index 962c3c8a7..9ccc9869b 100644 --- a/src/extension/extension.h +++ b/src/extension/extension.h @@ -133,7 +133,7 @@ public: /* Parameter Stuff */ private: - GSList * parameters; /**< A table to store the parameters for this extension. + std::vector<Parameter *> parameters; /**< A table to store the parameters for this extension. This only gets created if there are parameters in this extension */ @@ -141,8 +141,7 @@ public: /** \brief A function to get the number of parameters that the extension has. \return The number of parameters. */ - unsigned int param_count ( ) { return parameters == NULL ? 0 : - g_slist_length(parameters); }; + unsigned int param_count ( ) { return parameters.size(); }; /** \brief A function to get the number of parameters that are visible to the user that the extension has. \return The number of visible parameters. diff --git a/src/extension/implementation/makefile.in b/src/extension/implementation/makefile.in deleted file mode 100644 index d54ea1d3a..000000000 --- a/src/extension/implementation/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd ../.. && $(MAKE) extension/implementation/all - -clean %.a %.$(OBJEXT): - cd ../.. && $(MAKE) extension/implementation/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 8da56fecd..2901655f1 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -32,7 +32,6 @@ #include "extension/input.h" #include "extension/db.h" #include "inkscape.h" -#include "io/sys.h" #include "io/resource.h" #include "preferences.h" #include "script.h" @@ -398,7 +397,7 @@ ScriptDocCache::ScriptDocCache (Inkscape::UI::View::View * view) : _tempfd(0) { try { - _tempfd = Inkscape::IO::file_open_tmp(_filename, "ink_ext_XXXXXX.svg"); + _tempfd = Glib::file_open_tmp(_filename, "ink_ext_XXXXXX.svg"); } catch (...) { /// \todo Popup dialog here return; @@ -462,7 +461,7 @@ Gtk::Widget *Script::prefs_output(Inkscape::Extension::Output *module) \param filename File to open. First things first, this function needs a temporary file name. To - create on of those the function g_file_open_tmp is used with + create on of those the function Glib::file_open_tmp is used with the header of ink_ext_. The extension is then executed using the 'execute' function @@ -483,7 +482,7 @@ SPDocument *Script::open(Inkscape::Extension::Input *module, std::string tempfilename_out; int tempfd_out = 0; try { - tempfd_out = Inkscape::IO::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX.svg"); + tempfd_out = Glib::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX.svg"); } catch (...) { /// \todo Popup dialog here return NULL; @@ -513,7 +512,7 @@ SPDocument *Script::open(Inkscape::Extension::Input *module, mydoc->changeUriAndHrefs(filenameArg); } - // make sure we don't leak file descriptors from g_file_open_tmp + // make sure we don't leak file descriptors from Glib::file_open_tmp close(tempfd_out); unlink(tempfilename_out.c_str()); @@ -539,7 +538,7 @@ SPDocument *Script::open(Inkscape::Extension::Input *module, do that eh? First things first, the document is saved to a temporary file that - is an SVG file. To get the temporary filename g_file_open_tmp is used with + is an SVG file. To get the temporary filename Glib::file_open_tmp is used with ink_ext_ as a prefix. Don't worry, this file gets deleted at the end of the function. @@ -558,7 +557,7 @@ void Script::save(Inkscape::Extension::Output *module, std::string tempfilename_in; int tempfd_in = 0; try { - tempfd_in = Inkscape::IO::file_open_tmp(tempfilename_in, "ink_ext_XXXXXX.svg"); + tempfd_in = Glib::file_open_tmp(tempfilename_in, "ink_ext_XXXXXX.svg"); } catch (...) { /// \todo Popup dialog here throw Inkscape::Extension::Output::save_failed(); @@ -587,7 +586,7 @@ void Script::save(Inkscape::Extension::Output *module, success = fileout.toFile(lfilename); } - // make sure we don't leak file descriptors from g_file_open_tmp + // make sure we don't leak file descriptors from Glib::file_open_tmp close(tempfd_in); // FIXME: convert to utf8 (from "filename encoding") and unlink_utf8name unlink(tempfilename_in.c_str()); @@ -609,7 +608,7 @@ void Script::save(Inkscape::Extension::Output *module, This function is a little bit trickier than the previous two. It needs two temporary files to get it's work done. Both of these - files have random names created for them using the g_file_open_temp function + files have random names created for them using the Glib::file_open_temp function with the ink_ext_ prefix in the temporary directory. Like the other functions, the temporary files are deleted at the end. @@ -667,7 +666,7 @@ void Script::effect(Inkscape::Extension::Effect *module, std::string tempfilename_out; int tempfd_out = 0; try { - tempfd_out = Inkscape::IO::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX.svg"); + tempfd_out = Glib::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX.svg"); } catch (...) { /// \todo Popup dialog here return; @@ -740,7 +739,7 @@ void Script::effect(Inkscape::Extension::Effect *module, pump_events(); - // make sure we don't leak file descriptors from g_file_open_tmp + // make sure we don't leak file descriptors from Glib::file_open_tmp close(tempfd_out); g_unlink(tempfilename_out.c_str()); diff --git a/src/extension/implementation/xslt.cpp b/src/extension/implementation/xslt.cpp index 94852a98e..d11283db7 100644 --- a/src/extension/implementation/xslt.cpp +++ b/src/extension/implementation/xslt.cpp @@ -16,13 +16,13 @@ #include <config.h> #endif +#include <glibmm/fileutils.h> #include "file.h" #include "xslt.h" #include "../extension.h" #include "../output.h" #include "extension/input.h" -#include "io/sys.h" #include "io/resource.h" #include <unistd.h> #include <cstring> @@ -175,7 +175,7 @@ void XSLT::save(Inkscape::Extension::Output *module, SPDocument *doc, gchar cons std::string tempfilename_out; int tempfd_out = 0; try { - tempfd_out = Inkscape::IO::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX"); + tempfd_out = Glib::file_open_tmp(tempfilename_out, "ink_ext_XXXXXX"); } catch (...) { /// \todo Popup dialog here return; diff --git a/src/extension/init.cpp b/src/extension/init.cpp index 9830b0176..699c0382f 100644 --- a/src/extension/init.cpp +++ b/src/extension/init.cpp @@ -130,20 +130,9 @@ static void check_extensions(); */ static void update_pref(Glib::ustring const &pref_path, - gchar const *pref_default) // , GSList *extension_family) + gchar const *pref_default) { Glib::ustring pref = Inkscape::Preferences::get()->getString(pref_path); - /* - gboolean missing=TRUE; - for (GSList *list = extension_family; list; list = g_slist_next(list)) { - g_assert( list->data ); - - Inkscape::Extension *extension; - extension = reinterpret_cast<Inkscape::Extension *>(list->data); - - if (!strcmp(extension->get_id(),pref)) missing=FALSE; - } - */ if (!Inkscape::Extension::db.get( pref.data() ) /*missing*/) { Inkscape::Preferences::get()->setString(pref_path, pref_default); } diff --git a/src/extension/internal/bitmap/imagemagick.cpp b/src/extension/internal/bitmap/imagemagick.cpp index cc5b3d1bc..352271e26 100644 --- a/src/extension/internal/bitmap/imagemagick.cpp +++ b/src/extension/internal/bitmap/imagemagick.cpp @@ -39,7 +39,7 @@ namespace Bitmap { class ImageMagickDocCache: public Inkscape::Extension::Implementation::ImplementationDocumentCache { friend class ImageMagick; private: - void readImage(char const *xlink, Magick::Image *image); + void readImage(char const *xlink, char const *id, Magick::Image *image); protected: Inkscape::XML::Node** _nodes; @@ -85,11 +85,12 @@ ImageMagickDocCache::ImageMagickDocCache(Inkscape::UI::View::View * view) : { _nodes[_imageCount] = node; char const *xlink = node->attribute("xlink:href"); + char const *id = node->attribute("id"); _originals[_imageCount] = xlink; _caches[_imageCount] = (char*)""; _cacheLengths[_imageCount] = 0; _images[_imageCount] = new Magick::Image(); - readImage(xlink, _images[_imageCount]); + readImage(xlink, id, _images[_imageCount]); _imageItems[_imageCount] = item; _imageCount++; } @@ -113,26 +114,33 @@ ImageMagickDocCache::~ImageMagickDocCache ( ) { } void -ImageMagickDocCache::readImage(const char *xlink, Magick::Image *image) +ImageMagickDocCache::readImage(const char *xlink, const char *id, Magick::Image *image) { // Find if the xlink:href is base64 data, i.e. if the image is embedded - char *search = (char *) g_strndup(xlink, 30); + gchar *search = g_strndup(xlink, 30); if (strstr(search, "base64") != (char*)NULL) { // 7 = strlen("base64") + strlen(",") const char* pureBase64 = strstr(xlink, "base64") + 7; Magick::Blob blob; blob.base64(pureBase64); - image->read(blob); - } - else { - const gchar *path = xlink; - if (strncmp (xlink,"file:", 5) == 0) { - path = g_filename_from_uri(xlink, NULL, NULL); + try { + image->read(blob); + } catch (Magick::Exception &error_) { + g_warning("ImageMagick could not read '%s'\nDetails: %s", id, error_.what()); + } + } else { + gchar *path; + if (strncmp (xlink,"file:", 5) == 0) { + path = g_filename_from_uri(xlink, NULL, NULL); + } else { + path = g_strdup(xlink); } - try { image->read(path); - } catch (...) {} + } catch (Magick::Exception &error_) { + g_warning("ImageMagick could not read '%s' from '%s'\nDetails: %s", id, path, error_.what()); + } + g_free(path); } g_free(search); } diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index c513744a8..3edb58a13 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -163,10 +163,10 @@ CairoRenderState* CairoRenderContext::getCurrentState(void) const CairoRenderState* CairoRenderContext::getParentState(void) const { // if this is the root node just return it - if (g_slist_length(_state_stack) == 1) { + if (_state_stack.size() == 1) { return _state; } else { - return static_cast<CairoRenderState *>(g_slist_nth_data(_state_stack, 1)); + return _state_stack[_state_stack.size()-2]; } } @@ -975,7 +975,7 @@ void CairoRenderContext::pushState(void) CairoRenderState *new_state = _createState(); // copy current state's transform new_state->transform = _state->transform; - _state_stack = g_slist_prepend(_state_stack, new_state); + _state_stack.push_back(new_state); _state = new_state; } @@ -985,11 +985,11 @@ void CairoRenderContext::popState(void) cairo_restore(_cr); - g_free(_state_stack->data); - _state_stack = g_slist_remove_link(_state_stack, _state_stack); - _state = static_cast<CairoRenderState*>(_state_stack->data); + g_free(_state_stack.back()); + _state_stack.pop_back(); - g_assert( g_slist_length(_state_stack) > 0 ); + g_assert( !_state_stack.empty()); + _state = _state_stack.back(); } static bool pattern_hasItemChildren(SPPattern *pat) diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h index 9b976fd6d..be5169a74 100644 --- a/src/extension/internal/cairo-render-context.h +++ b/src/extension/internal/cairo-render-context.h @@ -198,7 +198,7 @@ protected: unsigned int _clip_rule : 8; unsigned int _clip_winding_failed : 1; - GSList *_state_stack; + std::vector<CairoRenderState *> _state_stack; CairoRenderState *_state; // the current state CairoRenderer *_renderer; diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index a2b8fb22f..116364739 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -27,7 +27,6 @@ #include <signal.h> #include <errno.h> -#include <boost/scoped_ptr.hpp> #include "libnrtype/Layout-TNG.h" #include <2geom/transforms.h> @@ -121,13 +120,12 @@ CairoRenderer::createContext(void) CairoRenderContext *new_context = new CairoRenderContext(this); g_assert( new_context != NULL ); - new_context->_state_stack = NULL; new_context->_state = NULL; // create initial render state CairoRenderState *state = new_context->_createState(); state->transform = Geom::identity(); - new_context->_state_stack = g_slist_prepend(new_context->_state_stack, state); + new_context->_state_stack.push_back(state); new_context->_state = state; return new_context; @@ -517,20 +515,17 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) // Do the export SPDocument *document = item->document; - GSList *items = NULL; - items = g_slist_append(items, item); - boost::scoped_ptr<Inkscape::Pixbuf> pb( + std::unique_ptr<Inkscape::Pixbuf> pb( sp_generate_internal_bitmap(document, NULL, bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y], - width, height, res, res, (guint32) 0xffffff00, items )); + width, height, res, res, (guint32) 0xffffff00, item )); if (pb) { //TEST(gdk_pixbuf_save( pb, "bitmap.png", "png", NULL, NULL )); ctx->renderImage(pb.get(), t, item->style); } - g_slist_free (items); } diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp index e0dc90981..26e6531dd 100644 --- a/src/extension/internal/gdkpixbuf-input.cpp +++ b/src/extension/internal/gdkpixbuf-input.cpp @@ -1,6 +1,7 @@ #include <gdk-pixbuf/gdk-pixbuf.h> +#include <gdkmm/pixbuf.h> +#include <gdkmm/pixbufformat.h> -#include <boost/scoped_ptr.hpp> #include <glib/gprintf.h> #include <glibmm/i18n.h> #include "dir-util.h" @@ -63,7 +64,7 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) bool embed = ( link.compare( "embed" ) == 0 ); SPDocument *doc = NULL; - boost::scoped_ptr<Inkscape::Pixbuf> pb(Inkscape::Pixbuf::create_from_file(uri)); + std::unique_ptr<Inkscape::Pixbuf> pb(Inkscape::Pixbuf::create_from_file(uri)); // TODO: the pixbuf is created again from the base64-encoded attribute in SPImage. // Find a way to create the pixbuf only once. @@ -163,14 +164,9 @@ GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri) void GdkpixbufInput::init(void) { - GSList * formatlist, * formatlisthead; - - /* \todo I'm not sure if I need to free this list */ - for (formatlist = formatlisthead = gdk_pixbuf_get_formats(); - formatlist != NULL; - formatlist = g_slist_next(formatlist)) { - - GdkPixbufFormat *pixformat = (GdkPixbufFormat *)formatlist->data; + static std::vector< Gdk::PixbufFormat > formatlist = Gdk::Pixbuf::get_formats(); + for (auto i: formatlist) { + GdkPixbufFormat *pixformat = i.gobj(); gchar *name = gdk_pixbuf_format_get_name(pixformat); gchar *description = gdk_pixbuf_format_get_description(pixformat); @@ -240,8 +236,6 @@ GdkpixbufInput::init(void) g_strfreev(mimetypes); g_strfreev(extensions); } - - g_slist_free(formatlisthead); } } } } /* namespace Inkscape, Extension, Implementation */ diff --git a/src/extension/internal/makefile.in b/src/extension/internal/makefile.in deleted file mode 100644 index 466309a8f..000000000 --- a/src/extension/internal/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd ../.. && $(MAKE) extension/internal/all - -clean %.a %.$(OBJEXT): - cd ../.. && $(MAKE) extension/internal/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/extension/internal/pdfinput/pdf-input.cpp b/src/extension/internal/pdfinput/pdf-input.cpp index 844d16c17..6e0ee75aa 100644 --- a/src/extension/internal/pdfinput/pdf-input.cpp +++ b/src/extension/internal/pdfinput/pdf-input.cpp @@ -846,14 +846,20 @@ PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) { } // Parse the document structure +#if defined(POPPLER_NEW_OBJECT_API) + Object obj = page->getContents(); +#else Object obj; page->getContents(&obj); +#endif if (!obj.isNull()) { pdf_parser->parse(&obj); } // Cleanup +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); +#endif delete pdf_parser; delete builder; g_free(docname); diff --git a/src/extension/internal/pdfinput/pdf-parser.cpp b/src/extension/internal/pdfinput/pdf-parser.cpp index 5ede59bf3..604b7f807 100644 --- a/src/extension/internal/pdfinput/pdf-parser.cpp +++ b/src/extension/internal/pdfinput/pdf-parser.cpp @@ -414,13 +414,21 @@ void PdfParser::parse(Object *obj, GBool topLevel) { if (obj->isArray()) { for (int i = 0; i < obj->arrayGetLength(); ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj2 = obj->arrayGet(i); +#else obj->arrayGet(i, &obj2); +#endif if (!obj2.isStream()) { error(errInternal, -1, "Weird page contents"); +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif return; } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif } } else if (!obj->isStream()) { error(errInternal, -1, "Weird page contents"); @@ -439,7 +447,11 @@ void PdfParser::go(GBool /*topLevel*/) // scan a sequence of objects int numArgs = 0; +#if defined(POPPLER_NEW_OBJECT_API) + obj = parser->getObj(); +#else parser->getObj(&obj); +#endif while (!obj.isEOF()) { // got a command - execute it @@ -457,14 +469,20 @@ void PdfParser::go(GBool /*topLevel*/) // Run the operation execOp(&obj, args, numArgs); +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); for (int i = 0; i < numArgs; ++i) args[i].free(); +#endif numArgs = 0; // got an argument - save it } else if (numArgs < maxArgs) { +#if defined(POPPLER_NEW_OBJECT_API) + args[numArgs++] = std::move(obj); +#else args[numArgs++] = obj; +#endif // too many arguments - something is wrong } else { @@ -475,13 +493,21 @@ void PdfParser::go(GBool /*topLevel*/) printf("\n"); fflush(stdout); } +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); +#endif } // grab the next object +#if defined(POPPLER_NEW_OBJECT_API) + obj = parser->getObj(); +#else parser->getObj(&obj); +#endif } +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); +#endif // args at end with no command if (numArgs > 0) { @@ -495,8 +521,10 @@ void PdfParser::go(GBool /*topLevel*/) printf("\n"); fflush(stdout); } +#if !defined(POPPLER_NEW_OBJECT_API) for (int i = 0; i < numArgs; ++i) args[i].free(); +#endif } } @@ -692,9 +720,13 @@ void PdfParser::opSetDash(Object args[], int /*numArgs*/) if (length != 0) { dash = (double *)gmallocn(length, sizeof(double)); for (int i = 0; i < length; ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + dash[i] = a->get(i).getNum(); +#else Object obj; dash[i] = a->get(i, &obj)->getNum(); obj.free(); +#endif } } state->setLineDash(dash, length, args[1].getNum()); @@ -744,12 +776,18 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) GBool haveBackdropColor = gFalse; GBool alpha = gFalse; +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj1 = res->lookupGState(args[0].getName())).isNull()) { +#else if (!res->lookupGState(args[0].getName(), &obj1)) { +#endif return; } if (!obj1.isDict()) { error(errSyntaxError, getPos(), "ExtGState '{0:s}' is wrong type"), args[0].getName(); +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif return; } if (printCommands) { @@ -759,7 +797,11 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) } // transparency support: blend mode, fill/stroke opacity +#if defined(POPPLER_NEW_OBJECT_API) + if (!((obj2 = obj1.dictLookup(const_cast<char*>("BM"))).isNull())) { +#else if (!obj1.dictLookup(const_cast<char*>("BM"), &obj2)->isNull()) { +#endif GfxBlendMode mode = gfxBlendNormal; if (state->parseBlendMode(&obj2, &mode)) { state->setBlendMode(mode); @@ -767,40 +809,71 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) error(errSyntaxError, getPos(), "Invalid blend mode in ExtGState"); } } +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj2 = obj1.dictLookup(const_cast<char*>("ca"))).isNum()) { +#else obj2.free(); if (obj1.dictLookup(const_cast<char*>("ca"), &obj2)->isNum()) { +#endif state->setFillOpacity(obj2.getNum()); } +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj2 = obj1.dictLookup(const_cast<char*>("CA"))).isNum()) { +#else obj2.free(); if (obj1.dictLookup(const_cast<char*>("CA"), &obj2)->isNum()) { +#endif state->setStrokeOpacity(obj2.getNum()); } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif // fill/stroke overprint GBool haveFillOP = gFalse; +#if defined(POPPLER_NEW_OBJECT_API) + if ((haveFillOP = (obj2 = obj1.dictLookup(const_cast<char*>("op"))).isBool())) { +#else if ((haveFillOP = (obj1.dictLookup(const_cast<char*>("op"), &obj2)->isBool()))) { +#endif state->setFillOverprint(obj2.getBool()); } +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj2 = obj1.dictLookup(const_cast<char*>("OP"))).isBool()) { +#else obj2.free(); if (obj1.dictLookup(const_cast<char*>("OP"), &obj2)->isBool()) { +#endif state->setStrokeOverprint(obj2.getBool()); if (!haveFillOP) { state->setFillOverprint(obj2.getBool()); } } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif // stroke adjust +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj2 = obj1.dictLookup(const_cast<char*>("SA"))).isBool()) { +#else if (obj1.dictLookup(const_cast<char*>("SA"), &obj2)->isBool()) { +#endif state->setStrokeAdjust(obj2.getBool()); } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif // transfer function +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj2 = obj1.dictLookup(const_cast<char*>("TR2"))).isNull()) { + obj2 = obj1.dictLookup(const_cast<char*>("TR")); +#else if (obj1.dictLookup(const_cast<char*>("TR2"), &obj2)->isNull()) { obj2.free(); obj1.dictLookup(const_cast<char*>("TR"), &obj2); +#endif } if (obj2.isName(const_cast<char*>("Default")) || obj2.isName(const_cast<char*>("Identity"))) { @@ -809,9 +882,15 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) } else if (obj2.isArray() && obj2.arrayGetLength() == 4) { int pos = 4; for (int i = 0; i < 4; ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj3 = obj2.arrayGet(i); +#else obj2.arrayGet(i, &obj3); +#endif funcs[i] = Function::parse(&obj3); +#if !defined(POPPLER_NEW_OBJECT_API) obj3.free(); +#endif if (!funcs[i]) { pos = i; break; @@ -828,21 +907,37 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) } else if (!obj2.isNull()) { error(errSyntaxError, getPos(), "Invalid transfer function in ExtGState"); } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif // soft mask +#if defined(POPPLER_NEW_OBJECT_API) + if (!((obj2 = obj1.dictLookup(const_cast<char*>("SMask"))).isNull())) { +#else if (!obj1.dictLookup(const_cast<char*>("SMask"), &obj2)->isNull()) { +#endif if (obj2.isName(const_cast<char*>("None"))) { builder->clearSoftMask(state); } else if (obj2.isDict()) { +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj3 = obj2.dictLookup(const_cast<char*>("S"))).isName(const_cast<char*>("Alpha"))) { +#else if (obj2.dictLookup(const_cast<char*>("S"), &obj3)->isName(const_cast<char*>("Alpha"))) { +#endif alpha = gTrue; } else { // "Luminosity" alpha = gFalse; } +#if !defined(POPPLER_NEW_OBJECT_API) obj3.free(); +#endif funcs[0] = NULL; +#if defined(POPPLER_NEW_OBJECT_API) + if (!((obj3 = obj2.dictLookup(const_cast<char*>("TR"))).isNull())) { +#else if (!obj2.dictLookup(const_cast<char*>("TR"), &obj3)->isNull()) { +#endif funcs[0] = Function::parse(&obj3); if (funcs[0]->getInputSize() != 1 || funcs[0]->getOutputSize() != 1) { @@ -851,26 +946,45 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) funcs[0] = NULL; } } +#if defined(POPPLER_NEW_OBJECT_API) + if ((haveBackdropColor = (obj3 = obj2.dictLookup(const_cast<char*>("BC"))).isArray())) { +#else obj3.free(); if ((haveBackdropColor = obj2.dictLookup(const_cast<char*>("BC"), &obj3)->isArray())) { +#endif for (int i = 0; i < gfxColorMaxComps; ++i) { backdropColor.c[i] = 0; } for (int i = 0; i < obj3.arrayGetLength() && i < gfxColorMaxComps; ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj4 = obj3.arrayGet(i); +#else obj3.arrayGet(i, &obj4); +#endif if (obj4.isNum()) { backdropColor.c[i] = dblToCol(obj4.getNum()); } +#if !defined(POPPLER_NEW_OBJECT_API) obj4.free(); +#endif } } +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj3 = obj2.dictLookup(const_cast<char*>("G"))).isStream()) { + if ((obj4 = obj3.streamGetDict()->lookup(const_cast<char*>("Group"))).isDict()) { +#else obj3.free(); if (obj2.dictLookup(const_cast<char*>("G"), &obj3)->isStream()) { if (obj3.streamGetDict()->lookup(const_cast<char*>("Group"), &obj4)->isDict()) { +#endif GfxColorSpace *blendingColorSpace = 0; GBool isolated = gFalse; GBool knockout = gFalse; +#if defined(POPPLER_NEW_OBJECT_API) + if (!((obj5 = obj4.dictLookup(const_cast<char*>("CS"))).isNull())) { +#else if (!obj4.dictLookup(const_cast<char*>("CS"), &obj5)->isNull()) { +#endif #if defined(POPPLER_EVEN_NEWER_NEW_COLOR_SPACE_API) blendingColorSpace = GfxColorSpace::parse(NULL, &obj5, NULL, NULL); #elif defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) @@ -879,15 +993,25 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) blendingColorSpace = GfxColorSpace::parse(&obj5, NULL); #endif } +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj5 = obj4.dictLookup(const_cast<char*>("I"))).isBool()) { +#else obj5.free(); if (obj4.dictLookup(const_cast<char*>("I"), &obj5)->isBool()) { +#endif isolated = obj5.getBool(); } +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj5 = obj4.dictLookup(const_cast<char*>("K"))).isBool()) { +#else obj5.free(); if (obj4.dictLookup(const_cast<char*>("K"), &obj5)->isBool()) { +#endif knockout = obj5.getBool(); } +#if !defined(POPPLER_NEW_OBJECT_API) obj5.free(); +#endif if (!haveBackdropColor) { if (blendingColorSpace) { blendingColorSpace->getDefaultColor(&backdropColor); @@ -906,18 +1030,24 @@ void PdfParser::opSetExtGState(Object args[], int /*numArgs*/) } else { error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState - missing group"); } +#if !defined(POPPLER_NEW_OBJECT_API) obj4.free(); +#endif } else { error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState - missing group"); } +#if !defined(POPPLER_NEW_OBJECT_API) obj3.free(); +#endif } else if (!obj2.isNull()) { error(errSyntaxError, getPos(), "Invalid soft mask in ExtGState"); } } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); obj1.free(); +#endif } void PdfParser::doSoftMask(Object *str, GBool alpha, @@ -938,43 +1068,79 @@ void PdfParser::doSoftMask(Object *str, GBool alpha, dict = str->streamGetDict(); // check form type +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("FormType")); +#else dict->lookup(const_cast<char*>("FormType"), &obj1); +#endif if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { error(errSyntaxError, getPos(), "Unknown form type"); } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif // get bounding box +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("BBox")); +#else dict->lookup(const_cast<char*>("BBox"), &obj1); +#endif if (!obj1.isArray()) { +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif error(errSyntaxError, getPos(), "Bad form bounding box"); return; } for (i = 0; i < 4; ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj2 = obj1.arrayGet(i); +#else obj1.arrayGet(i, &obj2); +#endif bbox[i] = obj2.getNum(); +#if defined(POPPLER_NEW_OBJECT_API) + } +#else obj2.free(); } obj1.free(); +#endif // get matrix +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("Matrix")); +#else dict->lookup(const_cast<char*>("Matrix"), &obj1); +#endif if (obj1.isArray()) { for (i = 0; i < 6; ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj2 = obj1.arrayGet(i); +#else obj1.arrayGet(i, &obj2); +#endif m[i] = obj2.getNum(); +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif } } else { m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif // get resources +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("Resources")); +#else dict->lookup(const_cast<char*>("Resources"), &obj1); +#endif resDict = obj1.isDict() ? obj1.getDict() : (Dict *)NULL; // draw it @@ -987,7 +1153,9 @@ void PdfParser::doSoftMask(Object *str, GBool alpha, if (blendingColorSpace) { delete blendingColorSpace; } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif } void PdfParser::opSetRenderingIntent(Object /*args*/[], int /*numArgs*/) @@ -1084,7 +1252,11 @@ void PdfParser::opSetFillColorSpace(Object args[], int /*numArgs*/) Object obj; state->setFillPattern(NULL); +#if defined(POPPLER_NEW_OBJECT_API) + obj = res->lookupColorSpace(args[0].getName()); +#else res->lookupColorSpace(args[0].getName(), &obj); +#endif GfxColorSpace *colorSpace = 0; #if defined(POPPLER_EVEN_NEWER_NEW_COLOR_SPACE_API) @@ -1106,7 +1278,9 @@ void PdfParser::opSetFillColorSpace(Object args[], int /*numArgs*/) colorSpace = GfxColorSpace::parse(&obj, NULL); } #endif +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); +#endif if (colorSpace) { GfxColor color; state->setFillColorSpace(colorSpace); @@ -1125,7 +1299,11 @@ void PdfParser::opSetStrokeColorSpace(Object args[], int /*numArgs*/) GfxColorSpace *colorSpace = 0; state->setStrokePattern(NULL); +#if defined(POPPLER_NEW_OBJECT_API) + obj = res->lookupColorSpace(args[0].getName()); +#else res->lookupColorSpace(args[0].getName(), &obj); +#endif #if defined(POPPLER_EVEN_NEWER_NEW_COLOR_SPACE_API) if (obj.isNull()) { colorSpace = GfxColorSpace::parse(NULL, &args[0], NULL, NULL); @@ -1145,7 +1323,9 @@ void PdfParser::opSetStrokeColorSpace(Object args[], int /*numArgs*/) colorSpace = GfxColorSpace::parse(&obj, NULL); } #endif +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); +#endif if (colorSpace) { GfxColor color; state->setStrokeColorSpace(colorSpace); @@ -2375,7 +2555,11 @@ void PdfParser::opShowSpaceText(Object args[], int /*numArgs*/) wMode = state->getFont()->getWMode(); a = args[0].getArray(); for (int i = 0; i < a->getLength(); ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj = a->get(i); +#else a->get(i, &obj); +#endif if (obj.isNum()) { // this uses the absolute value of the font size to match // Acrobat's behavior @@ -2392,7 +2576,9 @@ void PdfParser::opShowSpaceText(Object args[], int /*numArgs*/) } else { error(errSyntaxError, getPos(), "Element of show/space array must be number or string"); } +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); +#endif } } @@ -2465,7 +2651,11 @@ void PdfParser::doShowText(GooString *s) { //out->updateCTM(state, 1, 0, 0, 1, 0, 0); if (0){ /*!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy, code, u, uLen)) {*/ +#if defined(POPPLER_NEW_OBJECT_API) + charProc = ((Gfx8BitFont *)font)->getCharProc(code); +#else ((Gfx8BitFont *)font)->getCharProc(code, &charProc); +#endif if ((resDict = ((Gfx8BitFont *)font)->getResources())) { pushResources(resDict); } @@ -2478,7 +2668,9 @@ void PdfParser::doShowText(GooString *s) { if (resDict) { popResources(); } +#if !defined(POPPLER_NEW_OBJECT_API) charProc.free(); +#endif } restoreState(); // GfxState::restore() does *not* restore the current position, @@ -2541,23 +2733,43 @@ void PdfParser::opXObject(Object args[], int /*numArgs*/) Object obj1, obj2, obj3, refObj; char *name = args[0].getName(); +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj1 = res->lookupXObject(name)).isNull()) { +#else if (!res->lookupXObject(name, &obj1)) { +#endif return; } if (!obj1.isStream()) { error(errSyntaxError, getPos(), "XObject '{0:s}' is wrong type", name); +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif return; } +#if defined(POPPLER_NEW_OBJECT_API) + obj2 = obj1.streamGetDict()->lookup(const_cast<char*>("Subtype")); +#else obj1.streamGetDict()->lookup(const_cast<char*>("Subtype"), &obj2); +#endif if (obj2.isName(const_cast<char*>("Image"))) { +#if defined(POPPLER_NEW_OBJECT_API) + refObj = res->lookupXObjectNF(name); +#else res->lookupXObjectNF(name, &refObj); +#endif doImage(&refObj, obj1.getStream(), gFalse); +#if !defined(POPPLER_NEW_OBJECT_API) refObj.free(); +#endif } else if (obj2.isName(const_cast<char*>("Form"))) { doForm(&obj1); } else if (obj2.isName(const_cast<char*>("PS"))) { +#if defined(POPPLER_NEW_OBJECT_API) + obj3 = obj1.streamGetDict()->lookup(const_cast<char*>("Level1")); +#else obj1.streamGetDict()->lookup(const_cast<char*>("Level1"), &obj3); +#endif /* out->psXObject(obj1.getStream(), obj3.isStream() ? obj3.getStream() : (Stream *)NULL);*/ } else if (obj2.isName()) { @@ -2565,8 +2777,10 @@ void PdfParser::opXObject(Object args[], int /*numArgs*/) } else { error(errSyntaxError, getPos(), "XObject subtype is missing or wrong type"); } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); obj1.free(); +#endif } void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) @@ -2593,10 +2807,18 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) dict = str->getDict(); // get size +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("Width")); +#else dict->lookup(const_cast<char*>("Width"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("W")); +#else obj1.free(); dict->lookup(const_cast<char*>("W"), &obj1); +#endif } if (obj1.isInt()){ width = obj1.getInt(); @@ -2607,11 +2829,19 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) else { goto err2; } +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("Height")); +#else obj1.free(); dict->lookup(const_cast<char*>("Height"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("H")); +#else obj1.free(); dict->lookup(const_cast<char*>("H"), &obj1); +#endif } if (obj1.isInt()) { height = obj1.getInt(); @@ -2622,26 +2852,46 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) else { goto err2; } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif // image interpolation +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup("Interpolate"); +#else dict->lookup("Interpolate", &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup("I"); +#else obj1.free(); dict->lookup("I", &obj1); +#endif } if (obj1.isBool()) interpolate = obj1.getBool(); else interpolate = gFalse; +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif maskInterpolate = gFalse; // image or mask? +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("ImageMask")); +#else dict->lookup(const_cast<char*>("ImageMask"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("IM")); +#else obj1.free(); dict->lookup(const_cast<char*>("IM"), &obj1); +#endif } mask = gFalse; if (obj1.isBool()) { @@ -2650,14 +2900,24 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) else if (!obj1.isNull()) { goto err2; } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif // bit depth if (bits == 0) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("BitsPerComponent")); +#else dict->lookup(const_cast<char*>("BitsPerComponent"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("BPC")); +#else obj1.free(); dict->lookup(const_cast<char*>("BPC"), &obj1); +#endif } if (obj1.isInt()) { bits = obj1.getInt(); @@ -2666,7 +2926,9 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } else { goto err2; } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif } // display a mask @@ -2676,21 +2938,37 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) goto err1; } invert = gFalse; +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("Decode")); +#else dict->lookup(const_cast<char*>("Decode"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("D")); +#else obj1.free(); dict->lookup(const_cast<char*>("D"), &obj1); +#endif } if (obj1.isArray()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj2 = obj1.arrayGet(0); +#else obj1.arrayGet(0, &obj2); +#endif if (obj2.isInt() && obj2.getInt() == 1) { invert = gTrue; } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif } else if (!obj1.isNull()) { goto err2; } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif // draw it builder->addImageMask(state, str, width, height, invert, interpolate); @@ -2698,18 +2976,36 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } else { // get color space and color map GfxColorSpace *colorSpace; +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("ColorSpace")); +#else dict->lookup(const_cast<char*>("ColorSpace"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("CS")); +#else obj1.free(); dict->lookup(const_cast<char*>("CS"), &obj1); +#endif } if (obj1.isName()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj2 = res->lookupColorSpace(obj1.getName()); +#else res->lookupColorSpace(obj1.getName(), &obj2); +#endif if (!obj2.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = std::move(obj2); +#else obj1.free(); obj1 = obj2; +#endif } else { +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif } } if (!obj1.isNull()) { @@ -2729,17 +3025,29 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } else { colorSpace = NULL; } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif if (!colorSpace) { goto err1; } +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("Decode")); +#else dict->lookup(const_cast<char*>("Decode"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("D")); +#else obj1.free(); dict->lookup(const_cast<char*>("D"), &obj1); +#endif } GfxImageColorMap *colorMap = new GfxImageColorMap(bits, &obj1, colorSpace); +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif if (!colorMap->isOk()) { delete colorMap; goto err1; @@ -2753,8 +3061,13 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) int maskHeight = 0; maskInvert = gFalse; GfxImageColorMap *maskColorMap = NULL; +#if defined(POPPLER_NEW_OBJECT_API) + maskObj = dict->lookup(const_cast<char*>("Mask")); + smaskObj = dict->lookup(const_cast<char*>("SMask")); +#else dict->lookup(const_cast<char*>("Mask"), &maskObj); dict->lookup(const_cast<char*>("SMask"), &smaskObj); +#endif Dict* maskDict; if (smaskObj.isStream()) { // soft mask @@ -2763,58 +3076,108 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } maskStr = smaskObj.getStream(); maskDict = smaskObj.streamGetDict(); +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("Width")); +#else maskDict->lookup(const_cast<char*>("Width"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("W")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("W"), &obj1); +#endif } if (!obj1.isInt()) { goto err2; } maskWidth = obj1.getInt(); +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("Height")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("Height"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("H")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("H"), &obj1); +#endif } if (!obj1.isInt()) { goto err2; } maskHeight = obj1.getInt(); +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("BitsPerComponent")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("BitsPerComponent"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("BPC")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("BPC"), &obj1); +#endif } if (!obj1.isInt()) { goto err2; } int maskBits = obj1.getInt(); +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("Interpolate")); +#else obj1.free(); maskDict->lookup("Interpolate", &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("I")); +#else obj1.free(); maskDict->lookup("I", &obj1); +#endif } if (obj1.isBool()) maskInterpolate = obj1.getBool(); else maskInterpolate = gFalse; +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("ColorSpace")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("ColorSpace"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("CS")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("CS"), &obj1); +#endif } if (obj1.isName()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj2 = res->lookupColorSpace(obj1.getName()); +#else res->lookupColorSpace(obj1.getName(), &obj2); +#endif if (!obj2.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = std::move(obj2); +#else obj1.free(); obj1 = obj2; +#endif } else { +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif } } #if defined(POPPLER_EVEN_NEWER_NEW_COLOR_SPACE_API) @@ -2824,17 +3187,29 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) #else GfxColorSpace *maskColorSpace = GfxColorSpace::parse(&obj1, NULL); #endif +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { goto err1; } +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("Decode")); +#else maskDict->lookup(const_cast<char*>("Decode"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("D")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("D"), &obj1); +#endif } maskColorMap = new GfxImageColorMap(maskBits, &obj1, maskColorSpace); +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif if (!maskColorMap->isOk()) { delete maskColorMap; goto err1; @@ -2845,9 +3220,15 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) // color key mask int i; for (i = 0; i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps; ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskObj.arrayGet(i); +#else maskObj.arrayGet(i, &obj1); +#endif maskColors[i] = obj1.getInt(); +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif } haveColorKeyMask = gTrue; } else if (maskObj.isStream()) { @@ -2857,61 +3238,111 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } maskStr = maskObj.getStream(); maskDict = maskObj.streamGetDict(); +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("Width")); +#else maskDict->lookup(const_cast<char*>("Width"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("W")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("W"), &obj1); +#endif } if (!obj1.isInt()) { goto err2; } maskWidth = obj1.getInt(); +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("Height")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("Height"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("H")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("H"), &obj1); +#endif } if (!obj1.isInt()) { goto err2; } maskHeight = obj1.getInt(); +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("ImageMask")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("ImageMask"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("IM")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("IM"), &obj1); +#endif } if (!obj1.isBool() || !obj1.getBool()) { goto err2; } +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup("Interpolate"); +#else obj1.free(); maskDict->lookup("Interpolate", &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup("I"); +#else obj1.free(); maskDict->lookup("I", &obj1); +#endif } if (obj1.isBool()) maskInterpolate = obj1.getBool(); else maskInterpolate = gFalse; +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif maskInvert = gFalse; +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("Decode")); +#else maskDict->lookup(const_cast<char*>("Decode"), &obj1); +#endif if (obj1.isNull()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = maskDict->lookup(const_cast<char*>("D")); +#else obj1.free(); maskDict->lookup(const_cast<char*>("D"), &obj1); +#endif } if (obj1.isArray()) { +#if defined(POPPLER_NEW_OBJECT_API) + obj2 = obj1.arrayGet(0); +#else obj1.arrayGet(0, &obj2); +#endif if (obj2.isInt() && obj2.getInt() == 1) { maskInvert = gTrue; } +#if !defined(POPPLER_NEW_OBJECT_API) obj2.free(); +#endif } else if (!obj1.isNull()) { goto err2; } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif haveExplicitMask = gTrue; } @@ -2929,14 +3360,18 @@ void PdfParser::doImage(Object * /*ref*/, Stream *str, GBool inlineImg) } delete colorMap; +#if !defined(POPPLER_NEW_OBJECT_API) maskObj.free(); smaskObj.free(); +#endif } return; err2: +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif err1: error(errSyntaxError, getPos(), "Bad image parameters"); } @@ -2961,52 +3396,97 @@ void PdfParser::doForm(Object *str) { dict = str->streamGetDict(); // check form type +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = dict->lookup(const_cast<char*>("FormType")); +#else dict->lookup(const_cast<char*>("FormType"), &obj1); +#endif if (!(obj1.isNull() || (obj1.isInt() && obj1.getInt() == 1))) { error(errSyntaxError, getPos(), "Unknown form type"); } +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif // get bounding box +#if defined(POPPLER_NEW_OBJECT_API) + bboxObj = dict->lookup(const_cast<char*>("BBox")); +#else dict->lookup(const_cast<char*>("BBox"), &bboxObj); +#endif if (!bboxObj.isArray()) { +#if !defined(POPPLER_NEW_OBJECT_API) bboxObj.free(); +#endif error(errSyntaxError, getPos(), "Bad form bounding box"); return; } for (i = 0; i < 4; ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = bboxObj.arrayGet(i); +#else bboxObj.arrayGet(i, &obj1); +#endif bbox[i] = obj1.getNum(); +#if defined(POPPLER_NEW_OBJECT_API) + } +#else obj1.free(); } bboxObj.free(); +#endif // get matrix +#if defined(POPPLER_NEW_OBJECT_API) + matrixObj = dict->lookup(const_cast<char*>("Matrix")); +#else dict->lookup(const_cast<char*>("Matrix"), &matrixObj); +#endif if (matrixObj.isArray()) { for (i = 0; i < 6; ++i) { +#if defined(POPPLER_NEW_OBJECT_API) + obj1 = matrixObj.arrayGet(i); +#else matrixObj.arrayGet(i, &obj1); +#endif m[i] = obj1.getNum(); +#if !defined(POPPLER_NEW_OBJECT_API) obj1.free(); +#endif } } else { m[0] = 1; m[1] = 0; m[2] = 0; m[3] = 1; m[4] = 0; m[5] = 0; } +#if !defined(POPPLER_NEW_OBJECT_API) matrixObj.free(); +#endif // get resources +#if defined(POPPLER_NEW_OBJECT_API) + resObj = dict->lookup(const_cast<char*>("Resources")); +#else dict->lookup(const_cast<char*>("Resources"), &resObj); +#endif resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; // check for a transparency group transpGroup = isolated = knockout = gFalse; blendingColorSpace = NULL; +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj1 = dict->lookup(const_cast<char*>("Group"))).isDict()) { + if ((obj2 = obj1.dictLookup(const_cast<char*>("S"))).isName(const_cast<char*>("Transparency"))) { +#else if (dict->lookup(const_cast<char*>("Group"), &obj1)->isDict()) { if (obj1.dictLookup(const_cast<char*>("S"), &obj2)->isName(const_cast<char*>("Transparency"))) { +#endif transpGroup = gTrue; +#if defined(POPPLER_NEW_OBJECT_API) + if (!((obj3 = obj1.dictLookup(const_cast<char*>("CS"))).isNull())) { +#else if (!obj1.dictLookup(const_cast<char*>("CS"), &obj3)->isNull()) { +#endif #if defined(POPPLER_EVEN_NEWER_NEW_COLOR_SPACE_API) blendingColorSpace = GfxColorSpace::parse(NULL, &obj3, NULL, NULL); #elif defined(POPPLER_EVEN_NEWER_COLOR_SPACE_API) @@ -3015,19 +3495,32 @@ void PdfParser::doForm(Object *str) { blendingColorSpace = GfxColorSpace::parse(&obj3, NULL); #endif } +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj3 = obj1.dictLookup(const_cast<char*>("I"))).isBool()) { +#else obj3.free(); if (obj1.dictLookup(const_cast<char*>("I"), &obj3)->isBool()) { +#endif isolated = obj3.getBool(); } +#if defined(POPPLER_NEW_OBJECT_API) + if ((obj3 = obj1.dictLookup(const_cast<char*>("K"))).isBool()) { +#else obj3.free(); if (obj1.dictLookup(const_cast<char*>("K"), &obj3)->isBool()) { +#endif knockout = obj3.getBool(); } +#if defined(POPPLER_NEW_OBJECT_API) + } + } +#else obj3.free(); } obj2.free(); } obj1.free(); +#endif // draw it ++formDepth; @@ -3038,7 +3531,9 @@ void PdfParser::doForm(Object *str) { if (blendingColorSpace) { delete blendingColorSpace; } +#if !defined(POPPLER_NEW_OBJECT_API) resObj.free(); +#endif } void PdfParser::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox, @@ -3166,35 +3661,61 @@ Stream *PdfParser::buildImageStream() { Stream *str; // build dictionary +#if defined(POPPLER_NEW_OBJECT_API) + dict = Object(new Dict(xref)); + obj = parser->getObj(); +#else dict.initDict(xref); parser->getObj(&obj); +#endif while (!obj.isCmd(const_cast<char*>("ID")) && !obj.isEOF()) { if (!obj.isName()) { error(errSyntaxError, getPos(), "Inline image dictionary key must be a name object"); +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); +#endif } else { key = copyString(obj.getName()); +#if defined(POPPLER_NEW_OBJECT_API) + obj = parser->getObj(); +#else obj.free(); parser->getObj(&obj); +#endif if (obj.isEOF() || obj.isError()) { gfree(key); break; } +#if defined(POPPLER_NEW_OBJECT_API) + dict.dictAdd(key, std::move(obj)); + } + obj = parser->getObj(); +#else dict.dictAdd(key, &obj); } parser->getObj(&obj); +#endif } if (obj.isEOF()) { error(errSyntaxError, getPos(), "End of file in inline image"); +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); dict.free(); +#endif return NULL; } +#if !defined(POPPLER_NEW_OBJECT_API) obj.free(); +#endif // make stream +#if defined(POPPLER_NEW_OBJECT_API) + str = new EmbedStream(parser->getStream(), dict.copy(), gFalse, 0); + str = str->addFilters(dict.getDict()); +#else str = new EmbedStream(parser->getStream(), &dict, gFalse, 0); str = str->addFilters(&dict); +#endif return str; } diff --git a/src/extension/internal/svg.cpp b/src/extension/internal/svg.cpp index 9cde90519..b05a7c19b 100644 --- a/src/extension/internal/svg.cpp +++ b/src/extension/internal/svg.cpp @@ -17,21 +17,20 @@ #ifdef HAVE_CONFIG_H # include <config.h> #endif + +#include <vector> +#include <giomm/file.h> + #include "sp-object.h" #include "svg.h" #include "file.h" #include "extension/system.h" #include "extension/output.h" -#include <vector> #include "xml/attribute-record.h" #include "xml/simple-document.h" #include "sp-root.h" #include "document.h" -#ifdef WITH_GNOME_VFS -# include <libgnomevfs/gnome-vfs.h> -#endif - namespace Inkscape { namespace Extension { namespace Internal { @@ -157,80 +156,42 @@ Svg::init(void) "</output>\n" "</inkscape-extension>", new Svg()); -#ifdef WITH_GNOME_VFS - gnome_vfs_init(); -#endif - - return; } -#ifdef WITH_GNOME_VFS -#define BUF_SIZE 8192 - -static gchar * -_load_uri (const gchar *uri) -{ - GnomeVFSHandle *handle = NULL; - GnomeVFSFileSize bytes_read; - - gsize bytesRead = 0; - gsize bytesWritten = 0; - GError* error = NULL; - gchar* uri_local = g_filename_from_utf8( uri, -1, &bytesRead, &bytesWritten, &error); - - if ( uri_local == NULL ) { - g_warning( "Error converting filename to locale encoding."); - } - - GnomeVFSResult result = gnome_vfs_open (&handle, uri_local, GNOME_VFS_OPEN_READ); - - if (result != GNOME_VFS_OK) { - g_warning("%s", gnome_vfs_result_to_string(result)); - } - - std::vector<gchar> doc; - while (result == GNOME_VFS_OK) { - gchar buffer[BUF_SIZE]; - result = gnome_vfs_read (handle, buffer, BUF_SIZE, &bytes_read); - doc.insert(doc.end(), buffer, buffer+bytes_read); - } - - return g_strndup(&doc[0], doc.size()); -} -#endif - - /** \return A new document just for you! \brief This function takes in a filename of a SVG document and turns it into a SPDocument. \param mod Module to use - \param uri The path to the file (UTF-8) + \param uri The path or URI to the file (UTF-8) This function is really simple, it just calls sp_document_new... */ SPDocument * Svg::open (Inkscape::Extension::Input */*mod*/, const gchar *uri) { -#ifdef WITH_GNOME_VFS - if (!gnome_vfs_initialized() || gnome_vfs_uri_is_local(gnome_vfs_uri_new(uri))) { - // Use built-in loader instead of VFS for this - return SPDocument::createNewDoc(uri, TRUE); - } - gchar * buffer = _load_uri(uri); - if (buffer == NULL) { - g_warning("Error: Could not open file '%s' with VFS\n", uri); - return NULL; + auto file = Gio::File::create_for_uri(uri); + const auto path = file->get_path(); + + if (!file->get_uri_scheme().empty()) { + if (path.empty()) { + try { + char *contents; + gsize length; + file->load_contents(contents, length); + return SPDocument::createNewDocFromMem(contents, length, 1); + } catch (Gio::Error &e) { + g_warning("Could not load contents of non-local URI %s\n", uri); + return NULL; + } + } else { + uri = path.c_str(); + } } - SPDocument * doc = SPDocument::createNewDocFromMem(buffer, strlen(buffer), 1); - g_free(buffer); - return doc; -#else return SPDocument::createNewDoc(uri, TRUE); -#endif } /** diff --git a/src/extension/makefile.in b/src/extension/makefile.in deleted file mode 100644 index 5f19ccaa3..000000000 --- a/src/extension/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) extension/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) extension/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/extension/param/enum.cpp b/src/extension/param/enum.cpp index 7cd860465..db34a6ef9 100644 --- a/src/extension/param/enum.cpp +++ b/src/extension/param/enum.cpp @@ -32,20 +32,6 @@ namespace Inkscape { namespace Extension { -/* For internal use only. - Note that value and text MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */ -class enumentry { -public: - enumentry (Glib::ustring &val, Glib::ustring &text) : - value(val), - text(text) - {} - - Glib::ustring value; - Glib::ustring text; -}; - - ParamComboBox::ParamComboBox(const gchar * name, const gchar * text, const gchar * description, @@ -55,7 +41,6 @@ ParamComboBox::ParamComboBox(const gchar * name, Inkscape::XML::Node * xml) : Parameter(name, text, description, hidden, indent, ext) , _value(NULL) - , choices(NULL) { const char *xmlval = NULL; // the value stored in XML @@ -93,7 +78,7 @@ ParamComboBox::ParamComboBox(const gchar * name, } if ( (!newtext.empty()) && (!newvalue.empty()) ) { // logical error if this is not true here - choices = g_slist_append( choices, new enumentry(newvalue, newtext) ); + choices.push_back(new enumentry(newvalue, newtext) ); } } } @@ -120,11 +105,9 @@ ParamComboBox::ParamComboBox(const gchar * name, ParamComboBox::~ParamComboBox (void) { //destroy choice strings - for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { - delete (reinterpret_cast<enumentry *>(list->data)); + for (auto i:choices) { + delete i; } - g_slist_free(choices); - g_free(_value); } @@ -151,8 +134,7 @@ const gchar *ParamComboBox::set(const gchar * in, SPDocument * /*doc*/, Inkscape } Glib::ustring settext; - for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { - enumentry * entr = reinterpret_cast<enumentry *>(list->data); + for (auto entr:choices) { if ( !entr->text.compare(in) ) { settext = entr->value; break; // break out of for loop @@ -181,8 +163,7 @@ bool ParamComboBox::contains(const gchar * text, SPDocument const * /*doc*/, Ink return false; /* Can't have NULL string */ } - for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { - enumentry * entr = reinterpret_cast<enumentry *>(list->data); + for (auto entr:choices) { if ( !entr->text.compare(text) ) return true; } @@ -256,8 +237,7 @@ Gtk::Widget *ParamComboBox::get_widget(SPDocument * doc, Inkscape::XML::Node * n ParamComboBoxEntry * combo = Gtk::manage(new ParamComboBoxEntry(this, doc, node, changeSignal)); // add choice strings: Glib::ustring settext; - for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { - enumentry * entr = reinterpret_cast<enumentry *>(list->data); + for (auto entr:choices) { Glib::ustring text = entr->text; combo->append(text); diff --git a/src/extension/param/enum.h b/src/extension/param/enum.h index 143a648d7..d34c0dcaa 100644 --- a/src/extension/param/enum.h +++ b/src/extension/param/enum.h @@ -34,7 +34,23 @@ private: been allocated in memory. And should be free'd. It is the value of the current selected string */ gchar * _value; - GSList * choices; /**< A table to store the choice strings */ + + /* For internal use only. + * Note that value and text MUST be non-NULL. + * This is ensured by newing only at one location in the code where non-NULL checks are made. + */ + class enumentry { + public: + enumentry (Glib::ustring &val, Glib::ustring &text) : + value(val), + text(text) + {} + + Glib::ustring value; + Glib::ustring text; + }; + + std::vector<enumentry *> choices; /**< A table to store the choice strings */ public: ParamComboBox(const gchar * name, diff --git a/src/extension/param/notebook.cpp b/src/extension/param/notebook.cpp index 4e94b5216..220d6eb32 100644 --- a/src/extension/param/notebook.cpp +++ b/src/extension/param/notebook.cpp @@ -42,34 +42,7 @@ namespace Inkscape { namespace Extension { -/** - * A class to represent the pages of a notebookparameter of an extension. - */ -class ParamNotebookPage : public Parameter { -private: - GSList * parameters; /**< A table to store the parameters for this page. - This only gets created if there are parameters on this - page */ - -public: - static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext); - - ParamNotebookPage(const gchar * name, - const gchar * text, - const gchar * description, - bool hidden, - Inkscape::Extension::Extension * ext, - Inkscape::XML::Node * xml); - ~ParamNotebookPage(void); - - Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); - void paramString (std::list <std::string> &list); - gchar * get_text (void) {return _text;}; - Parameter * get_param (const gchar * name); -}; /* class ParamNotebookPage */ - - -ParamNotebookPage::ParamNotebookPage(const gchar * name, +ParamNotebook::ParamNotebookPage::ParamNotebookPage(const gchar * name, const gchar * text, const gchar * description, bool hidden, @@ -77,7 +50,6 @@ ParamNotebookPage::ParamNotebookPage(const gchar * name, Inkscape::XML::Node * xml) : Parameter(name, text, description, hidden, /*indent*/ 0, ext) { - parameters = NULL; // Read XML to build page if (xml != NULL) { @@ -92,28 +64,25 @@ ParamNotebookPage::ParamNotebookPage(const gchar * name, if (!strcmp(chname, "param") || !strcmp(chname, "_param")) { Parameter * param; param = Parameter::make(child_repr, ext); - if (param != NULL) parameters = g_slist_append(parameters, param); + if (param != NULL) parameters.push_back(param); } child_repr = child_repr->next(); } } } -ParamNotebookPage::~ParamNotebookPage (void) +ParamNotebook::ParamNotebookPage::~ParamNotebookPage (void) { //destroy parameters - for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) { - Parameter * param = reinterpret_cast<Parameter *>(list->data); + for (auto param:parameters) { delete param; } - g_slist_free(parameters); } /** Return the value as a string. */ -void ParamNotebookPage::paramString(std::list <std::string> &list) +void ParamNotebook::ParamNotebookPage::paramString(std::list <std::string> &list) { - for (GSList * plist = parameters; plist != NULL; plist = g_slist_next(plist)) { - Parameter * param = reinterpret_cast<Parameter *>(plist->data); + for (auto param:parameters) { param->string(list); } } @@ -143,8 +112,8 @@ void ParamNotebookPage::paramString(std::list <std::string> &list) straight forward. In all cases the value is set to the default value from the XML and the type is set to the interpreted type. */ -ParamNotebookPage * -ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext) +ParamNotebook::ParamNotebookPage * +ParamNotebook::ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext) { const char * name; const char * text; @@ -186,7 +155,7 @@ ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension: * * Builds a notebook page (a vbox) and puts parameters on it. */ -Gtk::Widget * ParamNotebookPage::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +Gtk::Widget * ParamNotebook::ParamNotebookPage::get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) { if (_hidden) { return NULL; @@ -197,8 +166,7 @@ Gtk::Widget * ParamNotebookPage::get_widget(SPDocument * doc, Inkscape::XML::Nod vbox->set_spacing(Parameter::GUI_BOX_SPACING); // add parameters onto page (if any) - for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) { - Parameter * param = reinterpret_cast<Parameter *>(list->data); + for (auto param:parameters) { Gtk::Widget * widg = param->get_widget(doc, node, changeSignal); if (widg) { int indent = param->get_indent(); @@ -224,6 +192,28 @@ Gtk::Widget * ParamNotebookPage::get_widget(SPDocument * doc, Inkscape::XML::Nod return dynamic_cast<Gtk::Widget *>(vbox); } +/** Search the parameter's name in the page content. */ +Parameter *ParamNotebook::ParamNotebookPage::get_param(const gchar * name) +{ + if (name == NULL) { + throw Extension::param_not_exist(); + } + if (this->parameters.empty()) { + // the list of parameters is empty + throw Extension::param_not_exist(); + } + + for (auto param:parameters) { + if (!strcmp(param->name(), name)) { + return param; + } + } + + return NULL; +} + +/** End ParamNotebookPage **/ +/** ParamNotebook **/ ParamNotebook::ParamNotebook(const gchar * name, const gchar * text, @@ -234,8 +224,6 @@ ParamNotebook::ParamNotebook(const gchar * name, Inkscape::XML::Node * xml) : Parameter(name, text, description, hidden, indent, ext) { - pages = NULL; - // Read XML tree to add pages: if (xml != NULL) { Inkscape::XML::Node *child_repr = xml->firstChild(); @@ -249,7 +237,7 @@ ParamNotebook::ParamNotebook(const gchar * name, if (!strcmp(chname, "page")) { ParamNotebookPage * page; page = ParamNotebookPage::makepage(child_repr, ext); - if (page != NULL) pages = g_slist_append(pages, page); + if (page != NULL) pages.push_back(page); } child_repr = child_repr->next(); } @@ -258,9 +246,8 @@ ParamNotebook::ParamNotebook(const gchar * name, // Initialize _value with the current page const char * defaultval = NULL; // set first page as default - if (pages != NULL) { - ParamNotebookPage * defpage = reinterpret_cast<ParamNotebookPage *>(pages->data); - defaultval = defpage->name(); + if (!pages.empty()) { + defaultval = pages[0]->name(); } gchar * pref_name = this->pref_name(); @@ -277,12 +264,9 @@ ParamNotebook::ParamNotebook(const gchar * name, ParamNotebook::~ParamNotebook (void) { //destroy pages - for (GSList * list = pages; list != NULL; list = g_slist_next(list)) { - ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data); + for (auto page:pages) { delete page; } - g_slist_free(pages); - g_free(_value); } @@ -304,12 +288,8 @@ ParamNotebook::~ParamNotebook (void) */ const gchar *ParamNotebook::set(const int in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) { - ParamNotebookPage * page = NULL; - int i = 0; - for (GSList * list = pages; (list != NULL) && (i <= in); list = g_slist_next(list)) { - page = reinterpret_cast<ParamNotebookPage *>(list->data); - i++; - } + int i = in < pages.size() ? in : pages.size()-1; + ParamNotebookPage * page = pages[i]; if (page == NULL) return _value; @@ -336,8 +316,7 @@ void ParamNotebook::string(std::list <std::string> &list) const param_string += "\""; list.insert(list.end(), param_string); - for (GSList * pglist = pages; pglist != NULL; pglist = g_slist_next(pglist)) { - ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(pglist->data); + for (auto page:pages) { page->paramString(list); } } @@ -384,8 +363,7 @@ Parameter *ParamNotebook::get_param(const gchar * name) if (name == NULL) { throw Extension::param_not_exist(); } - for (GSList * pglist = pages; pglist != NULL; pglist = g_slist_next(pglist)) { - ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(pglist->data); + for (auto page:pages) { Parameter * subparam = page->get_param(name); if (subparam) { return subparam; @@ -395,26 +373,6 @@ Parameter *ParamNotebook::get_param(const gchar * name) return NULL; } -/** Search the parameter's name in the page content. */ -Parameter *ParamNotebookPage::get_param(const gchar * name) -{ - if (name == NULL) { - throw Extension::param_not_exist(); - } - if (this->parameters == NULL) { - // the list of parameters is empty - throw Extension::param_not_exist(); - } - - for (GSList * list = this->parameters; list != NULL; list = g_slist_next(list)) { - Parameter * param = static_cast<Parameter*>(list->data); - if (!strcmp(param->name(), name)) { - return param; - } - } - - return NULL; -} /** * Creates a Notebook widget for a notebook parameter. @@ -432,9 +390,8 @@ Gtk::Widget * ParamNotebook::get_widget(SPDocument * doc, Inkscape::XML::Node * // add pages (if any) int i = -1; int pagenr = i; - for (GSList * list = pages; list != NULL; list = g_slist_next(list)) { + for (auto page:pages) { i++; - ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data); Gtk::Widget * widg = page->get_widget(doc, node, changeSignal); nb->append_page(*widg, _(page->get_text())); if (!strcmp(_value, page->name())) { diff --git a/src/extension/param/notebook.h b/src/extension/param/notebook.h index 8475de61d..f1bebd372 100644 --- a/src/extension/param/notebook.h +++ b/src/extension/param/notebook.h @@ -37,7 +37,34 @@ private: */ gchar * _value; - GSList * pages; /**< A table to store the pages with parameters for this notebook. + /** + * A class to represent the pages of a notebookparameter of an extension. + */ + class ParamNotebookPage : public Parameter { + private: + std::vector<Parameter *> parameters; /**< A table to store the parameters for this page. + This only gets created if there are parameters on this + page */ + + public: + static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext); + + ParamNotebookPage(const gchar * name, + const gchar * text, + const gchar * description, + bool hidden, + Inkscape::Extension::Extension * ext, + Inkscape::XML::Node * xml); + ~ParamNotebookPage(void); + + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void paramString (std::list <std::string> &list); + gchar * get_text (void) {return _text;}; + Parameter * get_param (const gchar * name); + }; /* class ParamNotebookPage */ + + + std::vector<ParamNotebookPage*> pages; /**< A table to store the pages with parameters for this notebook. This only gets created if there are pages in this notebook */ public: diff --git a/src/extension/param/radiobutton.cpp b/src/extension/param/radiobutton.cpp index a08ba6860..ca6dbb31d 100644 --- a/src/extension/param/radiobutton.cpp +++ b/src/extension/param/radiobutton.cpp @@ -42,20 +42,6 @@ namespace Extension { /* For internal use only. Note that value and text MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */ -class optionentry { -public: - optionentry (Glib::ustring * val, Glib::ustring * txt) { - value = val; - text = txt; - } - ~optionentry() { - delete value; - delete text; - } - - Glib::ustring * value; - Glib::ustring * text; -}; ParamRadioButton::ParamRadioButton(const gchar * name, const gchar * text, @@ -68,7 +54,6 @@ ParamRadioButton::ParamRadioButton(const gchar * name, : Parameter(name, text, description, hidden, indent, ext) , _value(0) , _mode(mode) - , choices(0) { // Read XML tree to add enumeration items: // printf("Extension Constructor: "); @@ -105,7 +90,7 @@ ParamRadioButton::ParamRadioButton(const gchar * name, } if ( (newtext) && (newvalue) ) { // logical error if this is not true here - choices = g_slist_append( choices, new optionentry(newvalue, newtext) ); + choices.push_back(new optionentry(newvalue, newtext)); } } child_repr = child_repr->next(); @@ -115,8 +100,8 @@ ParamRadioButton::ParamRadioButton(const gchar * name, // Initialize _value with the default value from xml // for simplicity : default to the contents of the first xml-child const char * defaultval = NULL; - if (choices) { - defaultval = (static_cast<optionentry*> (choices->data))->value->c_str(); + if (!choices.empty()) { + defaultval = (static_cast<optionentry*> (choices[0]))->value->c_str(); } gchar * pref_name = this->pref_name(); @@ -135,11 +120,9 @@ ParamRadioButton::ParamRadioButton(const gchar * name, ParamRadioButton::~ParamRadioButton (void) { //destroy choice strings - for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { - delete (reinterpret_cast<optionentry *>(list->data)); + for(auto i:choices) { + delete i; } - g_slist_free(choices); - g_free(_value); } @@ -166,8 +149,7 @@ const gchar *ParamRadioButton::set(const gchar * in, SPDocument * /*doc*/, Inksc } Glib::ustring * settext = NULL; - for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { - optionentry * entr = reinterpret_cast<optionentry *>(list->data); + for (auto entr:choices) { if ( !entr->value->compare(in) ) { settext = entr->value; break; // break out of for loop @@ -278,8 +260,7 @@ Glib::ustring ParamRadioButton::value_from_label(const Glib::ustring label) { Glib::ustring value = ""; - for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { - optionentry * entr = reinterpret_cast<optionentry *>(list->data); + for ( auto entr:choices) { if ( !entr->text->compare(label) ) { value = *(entr->value); break; @@ -319,8 +300,7 @@ Gtk::Widget * ParamRadioButton::get_widget(SPDocument * doc, Inkscape::XML::Node // add choice strings as radiobuttons // and select last selected option (_value) Gtk::RadioButtonGroup group; - for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { - optionentry * entr = reinterpret_cast<optionentry *>(list->data); + for (auto entr:choices) { Glib::ustring * text = entr->text; switch ( _mode ) { case MINIMAL: diff --git a/src/extension/param/radiobutton.h b/src/extension/param/radiobutton.h index b91b11ea3..e3ced8eb8 100644 --- a/src/extension/param/radiobutton.h +++ b/src/extension/param/radiobutton.h @@ -27,6 +27,7 @@ namespace Extension { class Extension; + // \brief A class to represent a radiobutton parameter of an extension class ParamRadioButton : public Parameter { public: @@ -63,7 +64,24 @@ private: It is the value of the current selected string */ gchar * _value; AppearanceMode _mode; - GSList * choices; /**< A table to store the choice strings */ + + /* For internal use only. + Note that value and text MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */ + class optionentry { + public: + optionentry (Glib::ustring * val, Glib::ustring * txt) { + value = val; + text = txt; + } + ~optionentry() { + delete value; + delete text; + } + Glib::ustring * value; + Glib::ustring * text; + }; + + std::vector<optionentry*> choices; /**< A table to store the choice strings */ }; /* class ParamRadioButton */ diff --git a/src/extension/plugins/grid2/CMakeLists.txt b/src/extension/plugins/grid2/CMakeLists.txt index f39e259de..eb200e96e 100644 --- a/src/extension/plugins/grid2/CMakeLists.txt +++ b/src/extension/plugins/grid2/CMakeLists.txt @@ -2,7 +2,7 @@ set(grid_PART_SRCS grid.cpp) include_directories( ${CMAKE_BINARY_DIR}/src ) -add_library(grid2 SHARED ${grid_PART_SRCS}) +add_library(grid2 SHARED EXCLUDE_FROM_ALL ${grid_PART_SRCS}) target_link_libraries(grid2 inkscape_base) diff --git a/src/file-update.cpp b/src/file-update.cpp index 3771d549b..303a5c4f1 100644 --- a/src/file-update.cpp +++ b/src/file-update.cpp @@ -359,7 +359,7 @@ void sp_file_convert_dpi(SPDocument *doc) "but is better for physical output that relies on accurate sizes and positions (for example, for " "3D printing.)\n\n" "More information about this change are available in the <a " - "href='https://inkscape.org/en/learn/faq#todo-todo-todo'>Inkscape FAQ</a>" + "href='https://inkscape.org/en/learn/faq#dpi_change'>Inkscape FAQ</a>" "</small>")); moreinfo_text.set_line_wrap(true); moreinfo_text.set_size_request(554,-1); diff --git a/src/file.cpp b/src/file.cpp index 549ed7d6e..320016a41 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -71,10 +71,6 @@ using Inkscape::DocumentUndo; using Inkscape::IO::Resource::TEMPLATES; using Inkscape::IO::Resource::USER; -#ifdef WITH_GNOME_VFS -# include <libgnomevfs/gnome-vfs.h> -#endif - #ifdef WITH_DBUS #include "extension/dbus/dbus-init.h" #endif @@ -687,91 +683,6 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri, return true; } -/* - * Used only for remote saving using VFS and a specific uri. Gets the file at the /tmp. - */ -bool -file_save_remote(SPDocument */*doc*/, - #ifdef WITH_GNOME_VFS - const Glib::ustring &uri, - #else - const Glib::ustring &/*uri*/, - #endif - Inkscape::Extension::Extension */*key*/, bool /*saveas*/, bool /*official*/) -{ -#ifdef WITH_GNOME_VFS - -#define BUF_SIZE 8192 - gnome_vfs_init(); - - GnomeVFSHandle *from_handle = NULL; - GnomeVFSHandle *to_handle = NULL; - GnomeVFSFileSize bytes_read; - GnomeVFSFileSize bytes_written; - GnomeVFSResult result; - guint8 buffer[8192]; - - gchar* uri_local = g_filename_from_utf8( uri.c_str(), -1, NULL, NULL, NULL); - - if ( uri_local == NULL ) { - g_warning( "Error converting filename to locale encoding."); - } - - // Gets the temp file name. - Glib::ustring fileName = Glib::get_tmp_dir (); - fileName.append(G_DIR_SEPARATOR_S); - fileName.append((gnome_vfs_uri_extract_short_name(gnome_vfs_uri_new(uri_local)))); - - // Open the temp file to send. - result = gnome_vfs_open (&from_handle, fileName.c_str(), GNOME_VFS_OPEN_READ); - - if (result != GNOME_VFS_OK) { - g_warning("Could not find the temp saving."); - return false; - } - - gnome_vfs_create (&to_handle, uri_local, GNOME_VFS_OPEN_WRITE, FALSE, GNOME_VFS_PERM_USER_ALL); - result = gnome_vfs_open (&to_handle, uri_local, GNOME_VFS_OPEN_WRITE); - - if (result != GNOME_VFS_OK) { - g_warning("file creating: %s", gnome_vfs_result_to_string(result)); - return false; - } - - while (1) { - - result = gnome_vfs_read (from_handle, buffer, 8192, &bytes_read); - - if ((result == GNOME_VFS_ERROR_EOF) &&(!bytes_read)){ - gnome_vfs_close (from_handle); - gnome_vfs_close (to_handle); - return true; - } - - if (result != GNOME_VFS_OK) { - g_warning("%s", gnome_vfs_result_to_string(result)); - return false; - } - result = gnome_vfs_write (to_handle, buffer, bytes_read, &bytes_written); - if (result != GNOME_VFS_OK) { - g_warning("%s", gnome_vfs_result_to_string(result)); - return false; - } - - - if (bytes_read != bytes_written){ - return false; - } - - } - return true; -#else - // in case we do not have GNOME_VFS - return false; -#endif - -} - /** * Check if a string ends with another string. diff --git a/src/file.h b/src/file.h index 9cd22d744..c86f065d3 100644 --- a/src/file.h +++ b/src/file.h @@ -86,13 +86,6 @@ void sp_file_revert_dialog (); ## S A V E ######################*/ -/* - * Added to make only the remote savings. - */ - -bool file_save_remote(SPDocument *doc, const Glib::ustring &uri, - Inkscape::Extension::Extension *key, bool saveas, bool official); - /** * */ diff --git a/src/filters/makefile.in b/src/filters/makefile.in deleted file mode 100644 index 5aa76ce1b..000000000 --- a/src/filters/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) filters/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) filters/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/gc-anchored.cpp b/src/gc-anchored.cpp index 4abd44b57..3ce6eff7b 100644 --- a/src/gc-anchored.cpp +++ b/src/gc-anchored.cpp @@ -27,7 +27,7 @@ typedef Debug::SimpleEvent<Debug::Event::REFCOUNT> RefCountEvent; class BaseAnchorEvent : public RefCountEvent { public: BaseAnchorEvent(Anchored const *object, int bias, - Util::ptr_shared<char> name) + Util::ptr_shared name) : RefCountEvent(name) { _addProperty("base", Util::format("%p", Core::base(const_cast<Anchored *>(object)))); diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index 05f594f86..cc676bffe 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -955,43 +955,36 @@ void sp_item_gradient_reverse_vector(SPItem *item, Inkscape::PaintTarget fill_or sp_gradient_repr_set_link(gradient->getRepr(), vector); } - GSList *child_reprs = NULL; - GSList *child_objects = NULL; + std::vector<SPObject *> child_objects; + std::vector<Inkscape::XML::Node *>child_reprs; std::vector<double> offsets; double offset; for (auto& child: vector->children) { - child_reprs = g_slist_prepend (child_reprs, child.getRepr()); - child_objects = g_slist_prepend (child_objects, &child); + child_reprs.push_back(child.getRepr()); + child_objects.push_back(&child); offset=0; sp_repr_get_double(child.getRepr(), "offset", &offset); offsets.push_back(offset); } - GSList *child_copies = NULL; - for (GSList *i = child_reprs; i != NULL; i = i->next) { - Inkscape::XML::Node *repr = (Inkscape::XML::Node *) i->data; + std::vector<Inkscape::XML::Node *> child_copies; + for (auto repr:child_reprs) { Inkscape::XML::Document *xml_doc = vector->getRepr()->document(); - child_copies = g_slist_append (child_copies, repr->duplicate(xml_doc)); + child_copies.push_back(repr->duplicate(xml_doc)); } - for (GSList *i = child_objects; i != NULL; i = i->next) { - SPObject *child = SP_OBJECT (i->data); - child->deleteObject(); + for (auto i:child_objects) { + i->deleteObject(); } std::vector<double>::iterator iter = offsets.end() - 1; - for (GSList *i = child_copies; i != NULL; i = i->next) { - Inkscape::XML::Node *copy = (Inkscape::XML::Node *) i->data; + for (auto copy:child_copies) { vector->appendChildRepr(copy); sp_repr_set_svg_double (copy, "offset", 1 - *iter); --iter; Inkscape::GC::release(copy); } - - g_slist_free (child_reprs); - g_slist_free (child_copies); - g_slist_free (child_objects); } void sp_item_gradient_invert_vector_color(SPItem *item, Inkscape::PaintTarget fill_or_stroke) diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 103a3df9c..2af665ec5 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -2875,8 +2875,9 @@ void GrDrag::deleteSelected(bool just_one) SPGradient * vector; }; - GSList *midstoplist = NULL; // list of stops that must be deleted (will be deleted first) - GSList *endstoplist = NULL; // list of stops that must be deleted + std::vector<SPStop *> midstoplist;// list of stops that must be deleted (will be deleted first) + std::vector<StructStopInfo *> endstoplist;// list of stops that must be deleted + while (!selected.empty()) { GrDragger *dragger = *(selected.begin()); for(std::vector<GrDraggable *>::const_iterator drgble = dragger->draggables.begin(); drgble != dragger->draggables.end(); ++drgble) { @@ -2892,14 +2893,14 @@ void GrDrag::deleteSelected(bool just_one) SPStop *stop = sp_get_stop_i(vector, draggable->point_i); // check if already present in list. (e.g. when both RG_MID1 and RG_MID2 were selected) bool present = false; - for (GSList const * l = midstoplist; l != NULL; l = l->next) { - if ( (SPStop*)l->data == stop ) { + for (auto i:midstoplist) { + if ( i == stop ) { present = true; break; // no need to search further. } } if (!present) - midstoplist = g_slist_append(midstoplist, stop); + midstoplist.push_back(stop); } break; case POINT_LG_BEGIN: @@ -2922,14 +2923,14 @@ void GrDrag::deleteSelected(bool just_one) stopinfo->vector = vector; // check if already present in list. (e.g. when both R1 and R2 were selected) bool present = false; - for (GSList const * l = endstoplist; l != NULL; l = l->next) { - if ( ((StructStopInfo*)l->data)->spstop == stopinfo->spstop ) { + for (auto i : endstoplist) { + if ( i->spstop == stopinfo->spstop ) { present = true; break; // no need to search further. } } if (!present) - endstoplist = g_slist_append(endstoplist, stopinfo); + endstoplist.push_back(stopinfo); } } break; @@ -2941,15 +2942,13 @@ void GrDrag::deleteSelected(bool just_one) selected.erase(dragger); if ( just_one ) break; // iterate once if just_one is set. } - while (midstoplist) { - SPStop *stop = (SPStop*) midstoplist->data; + for (auto stop:midstoplist) { document = stop->document; Inkscape::XML::Node * parent = stop->getRepr()->parent(); parent->removeChild(stop->getRepr()); - midstoplist = g_slist_remove(midstoplist, stop); } - while (endstoplist) { - StructStopInfo *stopinfo = (StructStopInfo*) endstoplist->data; + + for (auto stopinfo:endstoplist) { document = stopinfo->spstop->document; // 2 is the minimum, cannot delete more than that without deleting the whole vector @@ -3096,7 +3095,6 @@ void GrDrag::deleteSelected(bool just_one) sp_repr_css_attr_unref (css); } - endstoplist = g_slist_remove(endstoplist, stopinfo); delete stopinfo; } diff --git a/src/helper/CMakeLists.txt b/src/helper/CMakeLists.txt index 443648c5c..bcd9f7c58 100644 --- a/src/helper/CMakeLists.txt +++ b/src/helper/CMakeLists.txt @@ -17,7 +17,6 @@ set(helper_SRC geom-pathvectorsatellites.cpp geom-satellite.cpp gettext.cpp - gnome-utils.cpp pixbuf-ops.cpp png-write.cpp stock-items.cpp @@ -39,7 +38,6 @@ set(helper_SRC geom-satellite.h geom.h gettext.h - gnome-utils.h mathfns.h pixbuf-ops.h png-write.h diff --git a/src/helper/gnome-utils.cpp b/src/helper/gnome-utils.cpp deleted file mode 100644 index 3d2b333a2..000000000 --- a/src/helper/gnome-utils.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/** - * Helpers - * - * Authors: - * Mitsuru Oka - * Lauris Kaplinski <lauris@kaplinski.com> - * - * Copyright (C) 2002 authors - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include <string.h> -#include <ctype.h> -#include <glib.h> - -#include "gnome-utils.h" - -/** - * gnome_uri_list_extract_uris: - * @uri_list: an uri-list in the standard format. - * - * Returns a GList containing strings allocated with g_malloc - * that have been splitted from @uri-list. - */ -GList *gnome_uri_list_extract_uris(const gchar *uri_list) -{ - const gchar *p, *q; - gchar *retval; - GList *result = NULL; - - g_return_val_if_fail(uri_list != NULL, NULL); - - p = uri_list; - - /* We don't actually try to validate the URI according to RFC - * 2396, or even check for allowed characters - we just ignore - * comments and trim whitespace off the ends. We also - * allow LF delimination as well as the specified CRLF. - */ - while (p) { - if (*p != '#') { - while (isspace(*p)) - p++; - - q = p; - while (*q && (*q != '\n') && (*q != '\r')) - q++; - - if (q > p) { - q--; - while (q > p && isspace(*q)) - q--; - - retval = (gchar *)g_malloc(q - p + 2); - strncpy(retval, p, q - p + 1); - retval[q - p + 1] = '\0'; - - result = g_list_prepend(result, retval); - } - } - p = strchr(p, '\n'); - if (p) - p++; - } - - return g_list_reverse(result); -} - -/** - * gnome_uri_list_extract_filenames: - * @uri_list: an uri-list in the standard format - * - * Returns a GList containing strings allocated with g_malloc - * that contain the filenames in the uri-list. - * - * Note that unlike gnome_uri_list_extract_uris() function, this - * will discard any non-file uri from the result value. - */ -GList *gnome_uri_list_extract_filenames(const gchar *uri_list) -{ - g_return_val_if_fail(uri_list != NULL, NULL); - - GList *result = gnome_uri_list_extract_uris(uri_list); - - GList *tmp_list = result; - while (tmp_list) { - gchar *s = (gchar *)tmp_list->data; - - GList *node = tmp_list; - tmp_list = tmp_list->next; - - if (!strncmp(s, "file:", 5)) { - node->data = g_filename_from_uri(s, NULL, NULL); - /* not sure if this fallback is useful at all */ - if (!node->data) - node->data = g_strdup(s + 5); - } else { - result = g_list_remove_link(result, node); - g_list_free_1(node); - } - g_free(s); - } - return result; -} - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 : diff --git a/src/helper/gnome-utils.h b/src/helper/gnome-utils.h deleted file mode 100644 index 6f2f28223..000000000 --- a/src/helper/gnome-utils.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * GNOME Utils - Migration helper - * - * Authors: - * GNOME Developer - * Mitsuru Oka <oka326@parkcity.ne.jp> - * Lauris Kaplinski <lauris@ximian.com> - * - * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc. - * - * Released under GNU GPL - */ - -#ifndef SEEN_GNOME_UTILS_H -#define SEEN_GNOME_UTILS_H - -#include <glib.h> - -GList *gnome_uri_list_extract_uris(gchar const *uri_list); -GList *gnome_uri_list_extract_filenames(gchar const *uri_list); - -#endif // !SEEN_GNOME_UTILS_H - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 : diff --git a/src/helper/makefile.in b/src/helper/makefile.in deleted file mode 100644 index 7f40f58bc..000000000 --- a/src/helper/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) helper/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) helper/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp index bb33f7b15..8d7202111 100644 --- a/src/helper/pixbuf-ops.cpp +++ b/src/helper/pixbuf-ops.cpp @@ -15,7 +15,6 @@ #include <config.h> #endif -#include <boost/scoped_ptr.hpp> #include <2geom/transforms.h> #include "ui/interface.h" @@ -34,9 +33,9 @@ // TODO look for copy-n-paste duplication of this function: /** - * Hide all items that are not listed in list, recursively, skipping groups and defs. + * Hide all items except @item, recursively, skipping groups and defs. */ -static void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dkey) +static void hide_other_items_recursively(SPObject *o, SPItem *i, unsigned dkey) { SPItem *item = dynamic_cast<SPItem *>(o); if ( item @@ -44,15 +43,15 @@ static void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dke && !dynamic_cast<SPRoot *>(item) && !dynamic_cast<SPGroup *>(item) && !dynamic_cast<SPUse *>(item) - && !g_slist_find(list, o) ) + && (i != o) ) { item->invoke_hide(dkey); } // recurse - if (!g_slist_find(list, o)) { + if (i != o) { for (auto& child: o->children) { - hide_other_items_recursively(&child, list, dkey); + hide_other_items_recursively(&child, i, dkey); } } } @@ -65,11 +64,11 @@ static void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dke bool sp_export_jpg_file(SPDocument *doc, gchar const *filename, double x0, double y0, double x1, double y1, unsigned width, unsigned height, double xdpi, double ydpi, - unsigned long bgcolor, double quality,GSList *items) + unsigned long bgcolor, double quality, SPItem* item) { - boost::scoped_ptr<Inkscape::Pixbuf> pixbuf( + std::unique_ptr<Inkscape::Pixbuf> pixbuf( sp_generate_internal_bitmap(doc, filename, x0, y0, x1, y1, - width, height, xdpi, ydpi, bgcolor, items)); + width, height, xdpi, ydpi, bgcolor, item)); gchar c[32]; g_snprintf(c, 32, "%f", quality); @@ -78,6 +77,7 @@ bool sp_export_jpg_file(SPDocument *doc, gchar const *filename, return saved; } + /** generates a bitmap from given items the bitmap is stored in RAM and not written to file @@ -95,7 +95,7 @@ Inkscape::Pixbuf *sp_generate_internal_bitmap(SPDocument *doc, gchar const */*fi double x0, double y0, double x1, double y1, unsigned width, unsigned height, double xdpi, double ydpi, unsigned long /*bgcolor*/, - GSList *items_only) + SPItem *item_only) { if (width == 0 || height == 0) return NULL; @@ -128,8 +128,8 @@ Inkscape::Pixbuf *sp_generate_internal_bitmap(SPDocument *doc, gchar const */*fi // We show all and then hide all items we don't want, instead of showing only requested items, // because that would not work if the shown item references something in defs - if (items_only) { - hide_other_items_recursively(doc->getRoot(), items_only, dkey); + if (item_only) { + hide_other_items_recursively(doc->getRoot(), item_only, dkey); } Geom::IntRect final_bbox = Geom::IntRect::from_xywh(0, 0, width, height); diff --git a/src/helper/pixbuf-ops.h b/src/helper/pixbuf-ops.h index 61a879f9b..067bc0be4 100644 --- a/src/helper/pixbuf-ops.h +++ b/src/helper/pixbuf-ops.h @@ -17,12 +17,12 @@ class SPDocument; namespace Inkscape { class Pixbuf; } -bool sp_export_jpg_file (SPDocument *doc, gchar const *filename, double x0, double y0, double x1, double y1, - unsigned int width, unsigned int height, double xdpi, double ydpi, unsigned long bgcolor, double quality, GSList *items_only = NULL); + bool sp_export_jpg_file (SPDocument *doc, gchar const *filename, double x0, double y0, double x1, double y1, + unsigned int width, unsigned int height, double xdpi, double ydpi, unsigned long bgcolor, double quality, SPItem *item_only = NULL); Inkscape::Pixbuf *sp_generate_internal_bitmap(SPDocument *doc, gchar const *filename, double x0, double y0, double x1, double y1, unsigned width, unsigned height, double xdpi, double ydpi, - unsigned long bgcolor, GSList *items_only = NULL); + unsigned long bgcolor, SPItem *item_only = NULL); #endif diff --git a/src/icon-size.h b/src/icon-size.h deleted file mode 100644 index 8058e8da8..000000000 --- a/src/icon-size.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef SEEN_ICON_SIZE_H -#define SEEN_ICON_SIZE_H - -/* - * Generic icon widget - * - * Author: - * Lauris Kaplinski <lauris@kaplinski.com> - * - * Copyright (C) 2002 Lauris Kaplinski - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include <gtk/gtk.h> - -namespace Inkscape { - - enum IconSize { - ICON_SIZE_INVALID = ::GTK_ICON_SIZE_INVALID, - ICON_SIZE_MENU = ::GTK_ICON_SIZE_MENU, - ICON_SIZE_SMALL_TOOLBAR = ::GTK_ICON_SIZE_SMALL_TOOLBAR, - ICON_SIZE_LARGE_TOOLBAR = ::GTK_ICON_SIZE_LARGE_TOOLBAR, - ICON_SIZE_BUTTON = ::GTK_ICON_SIZE_BUTTON, - ICON_SIZE_DND = ::GTK_ICON_SIZE_DND, - ICON_SIZE_DIALOG = ::GTK_ICON_SIZE_DIALOG, - ICON_SIZE_DECORATION - }; -} // namespace Inkscape - -#endif // SEEN_ICON_SIZE_H diff --git a/src/inkscape.cpp b/src/inkscape.cpp index 8dfff3c63..e7e93929b 100644 --- a/src/inkscape.cpp +++ b/src/inkscape.cpp @@ -23,6 +23,7 @@ #include <map> #include <glibmm/fileutils.h> +#include <glibmm/regex.h> #include <gtkmm/cssprovider.h> #include <gtkmm/icontheme.h> @@ -47,6 +48,7 @@ #include "inkscape.h" #include "io/sys.h" #include "io/resource.h" +#include "libnrtype/FontFactory.h" #include "message-stack.h" #include "path-prefix.h" #include "resource-manager.h" @@ -429,6 +431,7 @@ Application::Application(const char* argv, bool use_gui) : _trackalt(FALSE), _use_gui(use_gui) { + using namespace Inkscape::IO::Resource; /* fixme: load application defaults */ segv_handler = signal (SIGSEGV, Application::crash_handler); @@ -487,9 +490,10 @@ Application::Application(const char* argv, bool use_gui) : Inkscape::UI::Dialog::DebugDialog::getInstance()->captureLogMessages(); } - /* Check for global remapping of Alt key */ if (use_gui) { + Inkscape::UI::Tools::init_latin_keys_group(); + /* Check for global remapping of Alt key */ mapalt(guint(prefs->getInt("/options/mapalt/value", 0))); trackalt(guint(prefs->getInt("/options/trackalt/value", 0))); } @@ -498,6 +502,22 @@ Application::Application(const char* argv, bool use_gui) : Inkscape::Extension::init(); autosave_init(); + + /* Initialize font factory */ + font_factory *factory = font_factory::Default(); + if (prefs->getBool("/options/font/use_fontsdir_system", true)) { + char const *fontsdir = get_path(SYSTEM, FONTS); + factory->AddFontsDir(fontsdir); + } + if (prefs->getBool("/options/font/use_fontsdir_user", true)) { + char const *fontsdir = get_path(USER, FONTS); + factory->AddFontsDir(fontsdir); + } + Glib::ustring fontdirs_pref = prefs->getString("/options/font/custom_fontdirs"); + std::vector<Glib::ustring> fontdirs = Glib::Regex::split_simple("\\|", fontdirs_pref); + for (auto &fontdir : fontdirs) { + factory->AddFontsDir(fontdir.c_str()); + } } Application::~Application() @@ -579,8 +599,8 @@ Application::crash_handler (int /*signum*/) gint count = 0; gchar *curdir = g_get_current_dir(); // This one needs to be freed explicitly gchar *inkscapedir = g_path_get_dirname(INKSCAPE._argv0); // Needs to be freed - GSList *savednames = NULL; - GSList *failednames = NULL; + std::vector<gchar *> savednames; + std::vector<gchar *> failednames; for (std::map<SPDocument*,int>::iterator iter = INKSCAPE._document_set.begin(), e = INKSCAPE._document_set.end(); iter != e; ++iter) { @@ -641,10 +661,10 @@ Application::crash_handler (int /*signum*/) // Save if (file) { sp_repr_save_stream (repr->document(), file, SP_SVG_NS_URI); - savednames = g_slist_prepend (savednames, g_strdup (c)); + savednames.push_back(g_strdup (c)); fclose (file); } else { - failednames = g_slist_prepend (failednames, (doc->getName()) ? g_strdup(doc->getName()) : g_strdup (_("Untitled document"))); + failednames.push_back((doc->getName()) ? g_strdup(doc->getName()) : g_strdup (_("Untitled document"))); } count++; } @@ -652,18 +672,16 @@ Application::crash_handler (int /*signum*/) g_free(curdir); g_free(inkscapedir); - savednames = g_slist_reverse (savednames); - failednames = g_slist_reverse (failednames); - if (savednames) { + if (!savednames.empty()) { fprintf (stderr, "\nEmergency save document locations:\n"); - for (GSList *l = savednames; l != NULL; l = l->next) { - fprintf (stderr, " %s\n", (gchar *) l->data); + for (auto i:savednames) { + fprintf (stderr, " %s\n", i); } } - if (failednames) { + if (!failednames.empty()) { fprintf (stderr, "\nFailed to do emergency save for documents:\n"); - for (GSList *l = failednames; l != NULL; l = l->next) { - fprintf (stderr, " %s\n", (gchar *) l->data); + for (auto i:failednames) { + fprintf (stderr, " %s\n", i); } } @@ -681,11 +699,11 @@ Application::crash_handler (int /*signum*/) char const *fstr = _("Automatic backup of the following documents failed:\n"); gint nllen = strlen ("\n"); gint len = strlen (istr) + strlen (sstr) + strlen (fstr); - for (GSList *l = savednames; l != NULL; l = l->next) { - len = len + SP_INDENT + strlen ((gchar *) l->data) + nllen; + for (auto i:savednames) { + len = len + SP_INDENT + strlen (i) + nllen; } - for (GSList *l = failednames; l != NULL; l = l->next) { - len = len + SP_INDENT + strlen ((gchar *) l->data) + nllen; + for (auto i:failednames) { + len = len + SP_INDENT + strlen (i) + nllen; } len += 1; gchar *b = g_new (gchar, len); @@ -693,29 +711,29 @@ Application::crash_handler (int /*signum*/) len = strlen (istr); memcpy (b + pos, istr, len); pos += len; - if (savednames) { + if (!savednames.empty()) { len = strlen (sstr); memcpy (b + pos, sstr, len); pos += len; - for (GSList *l = savednames; l != NULL; l = l->next) { + for (auto i:savednames) { memset (b + pos, ' ', SP_INDENT); pos += SP_INDENT; - len = strlen ((gchar *) l->data); - memcpy (b + pos, l->data, len); + len = strlen(i); + memcpy (b + pos, i, len); pos += len; memcpy (b + pos, "\n", nllen); pos += nllen; } } - if (failednames) { + if (!failednames.empty()) { len = strlen (fstr); memcpy (b + pos, fstr, len); pos += len; - for (GSList *l = failednames; l != NULL; l = l->next) { + for (auto i:failednames) { memset (b + pos, ' ', SP_INDENT); pos += SP_INDENT; - len = strlen ((gchar *) l->data); - memcpy (b + pos, l->data, len); + len = strlen(i); + memcpy (b + pos, i, len); pos += len; memcpy (b + pos, "\n", nllen); pos += nllen; diff --git a/src/io/makefile.in b/src/io/makefile.in deleted file mode 100644 index 74148f11a..000000000 --- a/src/io/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) io/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) io/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/io/resource.cpp b/src/io/resource.cpp index bc6c9f7b0..3f970dfa1 100644 --- a/src/io/resource.cpp +++ b/src/io/resource.cpp @@ -52,6 +52,7 @@ gchar *_get_path(Domain domain, Type type, char const *filename) case APPICONS: temp = INKSCAPE_APPICONDIR; break; case EXTENSIONS: temp = INKSCAPE_EXTENSIONDIR; break; case FILTERS: temp = INKSCAPE_FILTERDIR; break; + case FONTS: temp = INKSCAPE_FONTSDIR; break; case GRADIENTS: temp = INKSCAPE_GRADIENTSDIR; break; case ICONS: temp = INKSCAPE_PIXMAPDIR; break; case KEYS: temp = INKSCAPE_KEYSDIR; break; @@ -87,6 +88,7 @@ gchar *_get_path(Domain domain, Type type, char const *filename) switch (type) { case EXTENSIONS: name = "extensions"; break; case FILTERS: name = "filters"; break; + case FONTS: name = "fonts"; break; case GRADIENTS: name = "gradients"; break; case ICONS: name = "icons"; break; case KEYS: name = "keys"; break; @@ -113,10 +115,10 @@ gchar *_get_path(Domain domain, Type type, char const *filename) return path; } -Util::ptr_shared<char> get_path(Domain domain, Type type, char const *filename) +Util::ptr_shared get_path(Domain domain, Type type, char const *filename) { char *path = _get_path(domain, type, filename); - Util::ptr_shared<char> result=Util::share_string(path); + Util::ptr_shared result=Util::share_string(path); g_free(path); return result; } diff --git a/src/io/resource.h b/src/io/resource.h index d12372024..6ec08a28c 100644 --- a/src/io/resource.h +++ b/src/io/resource.h @@ -33,6 +33,7 @@ namespace Resource { enum Type { APPICONS, EXTENSIONS, + FONTS, GRADIENTS, ICONS, KEYS, @@ -56,7 +57,7 @@ enum Domain { USER }; -Util::ptr_shared<char> get_path(Domain domain, Type type, +Util::ptr_shared get_path(Domain domain, Type type, char const *filename=NULL); Glib::ustring get_path_ustring(Domain domain, Type type, diff --git a/src/io/sys.cpp b/src/io/sys.cpp index b06b550dd..2ff17cdc9 100644 --- a/src/io/sys.cpp +++ b/src/io/sys.cpp @@ -18,7 +18,6 @@ #include <fstream> #include <glib.h> #include <glib/gstdio.h> -#include <glibmm/fileutils.h> #include <glibmm/ustring.h> #include <gtk/gtk.h> @@ -71,10 +70,20 @@ FILE *Inkscape::IO::fopen_utf8name( char const *utf8name, char const *mode ) gchar *filename = g_filename_from_utf8( utf8name, -1, NULL, NULL, NULL ); if ( filename ) { + // ensure we open the file in binary mode (not needed in POSIX but doesn't hurt either) Glib::ustring how( mode ); if ( how.find("b") == Glib::ustring::npos ) { - how.append("b"); // not needed in POSIX but doesn't hurt either + how.append("b"); + } + // when opening a file for writing: create parent directories if they don't exist already + if ( how.find("w") != Glib::ustring::npos ) + { + gchar *dirname = g_path_get_dirname(utf8name); + if (g_mkdir_with_parents(dirname, 0777)) { + g_warning("Could not create directory '%s'", dirname); + } + g_free(dirname); } fp = g_fopen(filename, how.c_str()); g_free(filename); @@ -97,26 +106,6 @@ int Inkscape::IO::mkdir_utf8name( char const *utf8name ) return retval; } -/* - * Wrapper around Glib::file_open_tmp(). - * Returns a handle to the temp file. - * name_used contains the actual name used (a raw filename, not necessarily utf8). - * - * Returns: - * A file handle (as from open()) to the file opened for reading and writing. - * The file is opened in binary mode on platforms where there is a difference. - * The file handle should be closed with close(). - * - * Note: - * On Windows Vista Glib::file_open_tmp fails with the current version of glibmm - * A special case is implemented for WIN32. This can be removed if the issue is fixed - * in future versions of glibmm - * */ -int Inkscape::IO::file_open_tmp(std::string& name_used, const std::string& prefix) -{ - return Glib::file_open_tmp(name_used, prefix); -} - bool Inkscape::IO::file_test( char const *utf8name, GFileTest test ) { bool exists = false; diff --git a/src/io/sys.h b/src/io/sys.h index 78d25afa3..e349fc09c 100644 --- a/src/io/sys.h +++ b/src/io/sys.h @@ -32,8 +32,6 @@ FILE *fopen_utf8name( char const *utf8name, char const *mode ); int mkdir_utf8name( char const *utf8name ); -int file_open_tmp( std::string& name_used, const std::string& prefix ); - bool file_test( char const *utf8name, GFileTest test ); bool file_directory_exists( char const *utf8name ); diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp index 8add35d46..bb7ef6eb3 100644 --- a/src/knot-holder-entity.cpp +++ b/src/knot-holder-entity.cpp @@ -84,7 +84,7 @@ KnotHolderEntity::update_knot() { Geom::Point knot_pos(knot_get()); if (knot_pos.isFinite()) { - Geom::Point dp(knot_pos * item->i2dt_affine()); + Geom::Point dp(knot_pos * parent_holder->getEditTranform() * item->i2dt_affine()); _moved_connection.block(); knot->setPosition(dp, SP_KNOT_STATE_NORMAL); @@ -102,7 +102,7 @@ KnotHolderEntity::snap_knot_position(Geom::Point const &p, guint state) return p; } - Geom::Affine const i2dt (item->i2dt_affine()); + Geom::Affine const i2dt (parent_holder->getEditTranform() * item->i2dt_affine()); Geom::Point s = p * i2dt; SnapManager &m = desktop->namedview->snap_manager; @@ -120,7 +120,7 @@ KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape: return p; } - Geom::Affine const i2d (item->i2dt_affine()); + Geom::Affine const i2d (parent_holder->getEditTranform() * item->i2dt_affine()); Geom::Point s = p * i2d; SnapManager &m = desktop->namedview->snap_manager; diff --git a/src/knot.cpp b/src/knot.cpp index ff21f534a..8296891f4 100644 --- a/src/knot.cpp +++ b/src/knot.cpp @@ -326,7 +326,7 @@ static int sp_knot_handler(SPCanvasItem */*item*/, GdkEvent *event, SPKnot *knot consumed = TRUE; break; case GDK_KEY_PRESS: // keybindings for knot - switch (Inkscape::UI::Tools::get_group0_keyval(&event->key)) { + switch (Inkscape::UI::Tools::get_latin_keyval(&event->key)) { case GDK_KEY_Escape: knot->setFlag(SP_KNOT_GRABBED, FALSE); diff --git a/src/knotholder.cpp b/src/knotholder.cpp index 29054bcd9..5fbccf52d 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -56,7 +56,8 @@ KnotHolder::KnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFun sizeUpdatedConn(), released(relhandler), local_change(FALSE), - dragging(false) + dragging(false), + _edit_transform(Geom::identity()) { if (!desktop || !item) { g_print ("Error! Throw an exception, please!\n"); @@ -79,6 +80,12 @@ KnotHolder::~KnotHolder() { sizeUpdatedConn.disconnect(); } +void +KnotHolder::setEditTransform(Geom::Affine edit_transform) +{ + _edit_transform = edit_transform; +} + void KnotHolder::updateControlSizes() { ControlManager &mgr = ControlManager::getManager(); @@ -230,8 +237,8 @@ KnotHolder::knot_moved_handler(SPKnot *knot, Geom::Point const &p, guint state) for(std::list<KnotHolderEntity *>::iterator i = this->entity.begin(); i != this->entity.end(); ++i) { KnotHolderEntity *e = *i; if (e->knot == knot) { - Geom::Point const q = p * item->i2dt_affine().inverse(); - e->knot_set(q, e->knot->drag_origin * item->i2dt_affine().inverse(), state); + Geom::Point const q = p * item->i2dt_affine().inverse() * _edit_transform.inverse(); + e->knot_set(q, e->knot->drag_origin * item->i2dt_affine().inverse() * _edit_transform.inverse(), state); break; } } diff --git a/src/knotholder.h b/src/knotholder.h index d683b53ac..3c535cc31 100644 --- a/src/knotholder.h +++ b/src/knotholder.h @@ -18,6 +18,7 @@ */ #include <2geom/forward.h> +#include <2geom/affine.h> #include <list> #include <sigc++/connection.h> @@ -58,7 +59,8 @@ public: void add_pattern_knotholder(); - const SPItem *getItem() { return item; } + void setEditTransform(Geom::Affine edit_transform); + Geom::Affine getEditTranform() const { return _edit_transform; } bool knot_mouseover() const; @@ -83,6 +85,8 @@ protected: bool dragging; + Geom::Affine _edit_transform; + private: KnotHolder(); // declared but not defined }; diff --git a/src/layer-manager.cpp b/src/layer-manager.cpp index 3a6cce99c..f68175055 100644 --- a/src/layer-manager.cpp +++ b/src/layer-manager.cpp @@ -40,8 +40,8 @@ public: virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) {} virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) {} virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) {} - virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {} - virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) { + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { if ( name == _lockedAttr || name == _labelAttr ) { if ( _mgr && _obj ) { _mgr->_objectModified( _obj, 0 ); @@ -59,9 +59,9 @@ public: /* namespace { -Util::ptr_shared<char> stringify_node(Node const &node); +Util::ptr_shared stringify_node(Node const &node); -Util::ptr_shared<char> stringify_obj(SPObject const &obj) { +Util::ptr_shared stringify_obj(SPObject const &obj) { gchar *string; if (obj.id) { @@ -70,7 +70,7 @@ Util::ptr_shared<char> stringify_obj(SPObject const &obj) { string = g_strdup_printf("SPObject(%p) repr(%p)", &obj, obj.repr); } - Util::ptr_shared<char> result=Util::share_string(string); + Util::ptr_shared result=Util::share_string(string); g_free(string); return result; @@ -80,7 +80,7 @@ typedef Debug::SimpleEvent<Debug::Event::OTHER> DebugLayer; class DebugLayerNote : public DebugLayer { public: - DebugLayerNote(Util::ptr_shared<char> descr) + DebugLayerNote(Util::ptr_shared descr) : DebugLayer(Util::share_static_string("layer-note")) { _addProperty("descr", descr); @@ -97,7 +97,7 @@ public: class DebugLayerObj : public DebugLayer { public: - DebugLayerObj(SPObject const& obj, Util::ptr_shared<char> name) + DebugLayerObj(SPObject const& obj, Util::ptr_shared name) : DebugLayer(name) { _addProperty("layer", stringify_obj(obj)); diff --git a/src/libcola/colafd.cpp b/src/libcola/colafd.cpp index 7be18f7d6..748f3354b 100644 --- a/src/libcola/colafd.cpp +++ b/src/libcola/colafd.cpp @@ -75,7 +75,7 @@ void dumpSquareMatrix(unsigned n, T** L) { for(unsigned i=0;i<n;i++) { printf("{"); for(unsigned j=0;j<n;j++) { - std::cout<<L[i][j]; + std::cout<<L[i][j]<<std::endl;; char c=j==n-1?'}':','; printf("%c",c); } diff --git a/src/libcroco/cr-parser.c b/src/libcroco/cr-parser.c index 4e50b5402..449533c6e 100644 --- a/src/libcroco/cr-parser.c +++ b/src/libcroco/cr-parser.c @@ -1499,6 +1499,9 @@ cr_parser_parse_property (CRParser * a_this, *EMS S* | EXS S* | ANGLE S* | TIME S* | FREQ S* | function ] | *STRING S* | IDENT S* | URI S* | RGB S* | UNICODERANGE S* | hexcolor * + * As a special case for 'an+b', parse integer followed immediately by 'n'. + * The 'an' is parsed as a DIMEN. + * *TODO: handle parsing of 'RGB' * *Returns CR_OK upon successfull completion, an error code otherwise. @@ -1595,6 +1598,13 @@ cr_parser_parse_term (CRParser * a_this, CRTerm ** a_term) status = cr_term_set_hash (result, token->u.str); CHECK_PARSING_STATUS (status, TRUE); token->u.str = NULL; + } else if (token && token->type == DIMEN_TK) { + gboolean n = !strcmp(token->dimen->stryng->str, "n"); + status = cr_term_set_number (result, token->u.num); + result->n = n; // For nth-child (an+b) + CHECK_PARSING_STATUS (status, TRUE); + token->u.num = NULL; + status = CR_OK; } else { status = CR_PARSING_ERROR; } @@ -1819,22 +1829,21 @@ cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel) (&pseudo->location, &token->location) ; + /* Save selector name for use by 'type' pseudo selectors */ + if (sel->name) + pseudo->sel_name = cr_string_dup (sel->name); + if (token->type == IDENT_TK) { pseudo->type = IDENT_PSEUDO; pseudo->name = token->u.str; token->u.str = NULL; found_sel = TRUE; } else if (token->type == FUNCTION_TK) { - pseudo->name = token->u.str; - token->u.str = NULL; - cr_parser_try_to_skip_spaces_and_comments - (a_this); - status = cr_parser_parse_ident - (a_this, &pseudo->extra); - + status = cr_tknzr_unget_token (PRIVATE (a_this)->tknzr, token); + token = NULL; + status = cr_parser_parse_function (a_this, &pseudo->name, &pseudo->term); ENSURE_PARSING_COND (status == CR_OK); - READ_NEXT_CHAR (a_this, &cur_char); - ENSURE_PARSING_COND (cur_char == ')'); + pseudo->type = FUNCTION_PSEUDO; found_sel = TRUE; } else { @@ -1863,7 +1872,7 @@ cr_parser_parse_simple_selector (CRParser * a_this, CRSimpleSel ** a_sel) token = NULL; break; } - } + } // for loop if (status == CR_OK && found_sel == TRUE) { cr_parser_try_to_skip_spaces_and_comments (a_this); @@ -1960,6 +1969,10 @@ cr_parser_parse_simple_sels (CRParser * a_this, READ_NEXT_CHAR (a_this, &cur_char); comb = COMB_PLUS; cr_parser_try_to_skip_spaces_and_comments (a_this); + } else if (next_char == '~') { + READ_NEXT_CHAR (a_this, &cur_char); + comb = COMB_TILDE; + cr_parser_try_to_skip_spaces_and_comments (a_this); } else if (next_char == '>') { READ_NEXT_CHAR (a_this, &cur_char); comb = COMB_GT; diff --git a/src/libcroco/cr-pseudo.c b/src/libcroco/cr-pseudo.c index cee3fc869..8715c19f1 100644 --- a/src/libcroco/cr-pseudo.c +++ b/src/libcroco/cr-pseudo.c @@ -86,11 +86,6 @@ cr_pseudo_to_string (CRPseudo const * a_this) name = (guchar *) g_strndup (a_this->name->stryng->str, a_this->name->stryng->len); - if (a_this->extra) { - arg = (guchar *) g_strndup (a_this->extra->stryng->str, - a_this->extra->stryng->len); - } - if (name) { g_string_append_printf (str_buf, "%s(", name); g_free (name); @@ -158,9 +153,14 @@ cr_pseudo_destroy (CRPseudo * a_this) a_this->name = NULL; } - if (a_this->extra) { - cr_string_destroy (a_this->extra); - a_this->extra = NULL; + if (a_this->sel_name) { + cr_string_destroy (a_this->sel_name); + a_this->sel_name = NULL; + } + + if (a_this->term) { + cr_term_destroy (a_this->term); + a_this->term = NULL; } g_free (a_this); diff --git a/src/libcroco/cr-pseudo.h b/src/libcroco/cr-pseudo.h index 8917da45e..b78435014 100644 --- a/src/libcroco/cr-pseudo.h +++ b/src/libcroco/cr-pseudo.h @@ -27,6 +27,7 @@ #include <glib.h> #include "cr-attr-sel.h" #include "cr-parsing-location.h" +#include "cr-term.h" G_BEGIN_DECLS @@ -47,7 +48,8 @@ struct _CRPseudo { enum CRPseudoType type ; CRString *name ; - CRString *extra ; + CRString *sel_name; + CRTerm *term ; CRParsingLocation location ; } ; diff --git a/src/libcroco/cr-sel-eng.c b/src/libcroco/cr-sel-eng.c index 665ba4daf..9e35ad93f 100644 --- a/src/libcroco/cr-sel-eng.c +++ b/src/libcroco/cr-sel-eng.c @@ -87,26 +87,67 @@ static enum CRStatus put_css_properties_in_props_list (CRPropList ** a_props, a_ruleset); static gboolean pseudo_class_add_sel_matches_node (CRSelEng * a_this, - CRAdditionalSel * - a_add_sel, + CRAdditionalSel * a_add_sel, CRXMLNodePtr a_node); +static gboolean empty_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + +static gboolean root_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + static gboolean lang_pseudo_class_handler (CRSelEng * a_this, CRAdditionalSel * a_sel, CRXMLNodePtr a_node); +static gboolean only_child_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + static gboolean first_child_pseudo_class_handler (CRSelEng * a_this, CRAdditionalSel * a_sel, CRXMLNodePtr a_node); +static gboolean first_of_type_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + +static gboolean last_child_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + +static gboolean last_of_type_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + +static gboolean nth_child_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + +static gboolean nth_of_type_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + +static gboolean nth_last_child_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + +static gboolean nth_last_of_type_pseudo_class_handler (CRSelEng * a_this, + CRAdditionalSel * a_sel, + CRXMLNodePtr a_node); + static CRXMLNodePtr get_next_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node); -static CRXMLNodePtr get_next_child_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node); +static CRXMLNodePtr get_first_child_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node); static CRXMLNodePtr get_prev_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node); static CRXMLNodePtr get_next_parent_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node); +static CRArguments get_arguments_from_function (CRAdditionalSel * a_sel); + void cr_sel_eng_set_node_iface (CRSelEng *const a_this, CRNodeIface const *const a_node_iface) { @@ -120,6 +161,60 @@ cr_sel_eng_set_node_iface (CRSelEng *const a_this, CRNodeIface const *const a_no (strlen (str) != (lit_len) || memcmp (str, lit, lit_len)) static gboolean +root_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "root") + || a_sel->content.pseudo->type != IDENT_PSEUDO) { + cr_utils_trace_info ("This handler is for :root only"); + return FALSE; + } + + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + + // libxml apears to set the parent of the root element to an + // element of type 'xml'. + return (parent == NULL || !strcmp(node_iface->getLocalName(parent),"xml") ); +} + +static gboolean +empty_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "empty") + || a_sel->content.pseudo->type != IDENT_PSEUDO) { + cr_utils_trace_info ("This handler is for :empty only"); + return FALSE; + } + node_iface = PRIVATE(a_this)->node_iface; + + CRXMLNodePtr cur_node = NULL; + cur_node = node_iface->getFirstChild (a_node); + + return (cur_node == NULL); +} + +static gboolean lang_pseudo_class_handler (CRSelEng *const a_this, CRAdditionalSel * a_sel, CRXMLNodePtr a_node) { @@ -144,15 +239,16 @@ lang_pseudo_class_handler (CRSelEng *const a_this, return FALSE; } /*lang code should exist and be at least of length 2 */ - if (!a_sel->content.pseudo->extra - || !a_sel->content.pseudo->extra->stryng - || a_sel->content.pseudo->extra->stryng->len < 2) + if (!a_sel->content.pseudo->term + || a_sel->content.pseudo->term->type != TERM_IDENT + || !a_sel->content.pseudo->term->content.str->stryng + || a_sel->content.pseudo->term->content.str->stryng->len < 2) return FALSE; for (; node; node = get_next_parent_element_node (node_iface, node)) { char *val = node_iface->getProp (node, (const xmlChar *) "lang"); if (!val) val = node_iface->getProp (node, (const xmlChar *) "xml:lang"); if (val) { - if (!strcasecmp(val, a_sel->content.pseudo->extra->stryng->str)) { + if (!strcasecmp(val, a_sel->content.pseudo->term->content.str->stryng->str)) { result = TRUE; break; } @@ -165,11 +261,84 @@ lang_pseudo_class_handler (CRSelEng *const a_this, } static gboolean +only_child_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "only-child") + || a_sel->content.pseudo->type != IDENT_PSEUDO) { + cr_utils_trace_info ("This handler is for :only-child only"); + return FALSE; + } + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + if (!parent) + return FALSE; + + CRXMLNodePtr cur_node = NULL; + + cur_node = get_first_child_element_node (node_iface, parent); + return (cur_node == a_node && + !get_next_element_node(node_iface, cur_node) ); +} + +static gboolean +only_of_type_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "only-of-type") + || a_sel->content.pseudo->type != IDENT_PSEUDO) { + cr_utils_trace_info ("This handler is for :only-of-type selector only"); + return FALSE; + } + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + if (!parent) + return FALSE; + + CRXMLNodePtr cur_node = NULL; + int m = 0; + int child = 0; + cur_node = get_first_child_element_node (node_iface, parent); + + while (cur_node) { + if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) { + ++m; + } + if (cur_node == a_node) { + child = m; + } + cur_node = get_next_element_node (node_iface, cur_node); + } + return (child == m && child == 1); +} + +static gboolean first_child_pseudo_class_handler (CRSelEng *const a_this, CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) { CRNodeIface const *node_iface = NULL; - CRXMLNodePtr node = NULL, parent = NULL; + CRXMLNodePtr node = NULL; + CRXMLNodePtr parent = NULL; g_return_val_if_fail (a_this && PRIVATE (a_this) && a_sel && a_sel->content.pseudo @@ -178,8 +347,7 @@ first_child_pseudo_class_handler (CRSelEng *const a_this, && a_sel->content.pseudo->name->stryng && a_node, FALSE); - if (strcmp (a_sel->content.pseudo->name->stryng->str, - "first-child") + if (strcmp (a_sel->content.pseudo->name->stryng->str, "first-child") || a_sel->content.pseudo->type != IDENT_PSEUDO) { cr_utils_trace_info ("This handler is for :first-child only"); return FALSE; @@ -188,11 +356,398 @@ first_child_pseudo_class_handler (CRSelEng *const a_this, parent = node_iface->getParentNode (a_node); if (!parent) return FALSE; - node = get_next_child_element_node (node_iface, parent); + node = get_first_child_element_node (node_iface, parent); return (node == a_node); } static gboolean +first_of_type_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "first-of-type") + || a_sel->content.pseudo->type != IDENT_PSEUDO) { + cr_utils_trace_info ("This handler is for :first-of-type only"); + return FALSE; + } + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + if (!parent) + return FALSE; + + // Count which child no. of type + CRXMLNodePtr cur_node = NULL; + int child = 0; + int found = FALSE; + + cur_node = get_first_child_element_node (node_iface, parent); + + while (cur_node) { + if(!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) { + child++; + } + if (cur_node == a_node) { + found = TRUE; + break; + } + cur_node = get_next_element_node (node_iface, cur_node); + } + + if (!found) + return FALSE; + + return (child == 1); +} + +static gboolean +last_child_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "last-child") + || a_sel->content.pseudo->type != IDENT_PSEUDO) { + cr_utils_trace_info ("This handler is for :last-child only"); + return FALSE; + } + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + if (!parent) + return FALSE; + + CRXMLNodePtr cur_node = NULL; + int m = 0; + int child = 0; + + cur_node = get_first_child_element_node (node_iface, parent); + while (cur_node) { + ++m; + if (cur_node == a_node) { + child = m; + } + cur_node = get_next_element_node (node_iface, cur_node); + + } + return (m == child); +} + +static gboolean +last_of_type_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "last-of-type") + || a_sel->content.pseudo->type != IDENT_PSEUDO) { + cr_utils_trace_info ("This handler is for :last-of-type only"); + return FALSE; + } + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + if (!parent) + return FALSE; + + CRXMLNodePtr cur_node = NULL; + int m = 0; + int child = 0; + + cur_node = get_first_child_element_node (node_iface, parent); + + while (cur_node) { + if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) { + ++m; + } + if (cur_node == a_node) { + child = m; + } + cur_node = get_next_element_node (node_iface, cur_node); + } + + return (m == child); +} + +// See https://www.w3.org/TR/selectors/#nth-child-pseudo +static gboolean +nth_child_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-child") + || a_sel->content.pseudo->type != FUNCTION_PSEUDO) { + cr_utils_trace_info ("This handler is for :nth-child only"); + return FALSE; + } + + /*pseude code term should exist */ + if (!a_sel->content.pseudo->term) + return FALSE; + + CRArguments arg = get_arguments_from_function (a_sel); + + if (arg.a == 0 && arg.b == 0) + return FALSE; + + int a = arg.a; + int b = arg.b; + + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + if (!parent) + return FALSE; + + /* Count which child this is */ + CRXMLNodePtr cur_node = NULL; + int child = 0; + int found = FALSE; + + cur_node = get_first_child_element_node (node_iface, parent); + + while (cur_node) { + ++child; + if (cur_node == a_node) { + found = TRUE; + break; + } + cur_node = get_next_element_node (node_iface, cur_node); + } + + if (!found) + return FALSE; + + if (a == 0) + return (b == child); + + return ((child - b)%a == 0 && (child - b)/a > -1); +} + +static gboolean +nth_of_type_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-of-type") + || a_sel->content.pseudo->type != FUNCTION_PSEUDO) { + cr_utils_trace_info ("This handler is for :nth-of-type only"); + return FALSE; + } + + // pseudo code term should exist + if (!a_sel->content.pseudo->term) + return FALSE; + + CRArguments arg = get_arguments_from_function (a_sel); + + if (arg.a == 0 && arg.b == 0) + return FALSE; + + int a = arg.a; + int b = arg.b; + + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + if (!parent) + return FALSE; + + // Count which child no. of required type + CRXMLNodePtr cur_node = NULL; + int child = 0; + int found = FALSE; + + cur_node = get_first_child_element_node (node_iface, parent); + + while (cur_node) { + // check if type match + if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) + ++child; + if (cur_node == a_node) { + found = TRUE; + break; + } + cur_node = get_next_element_node (node_iface, cur_node); + } + + if (!found) + return FALSE; + + if (a == 0) + return (b == child); + + return ((child - b)%a == 0 && (child - b)/a > -1); +} + +static gboolean +nth_last_child_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-last-child")) { + cr_utils_trace_info ("This handler is for :nth-last-child only"); + return FALSE; + } + + /*pseudo code term should exist */ + if (!a_sel->content.pseudo->term) + return FALSE; + + CRArguments arg = get_arguments_from_function (a_sel); + + if (arg.a == 0 && arg.b == 0) + return FALSE; + + int a = arg.a; + int b = arg.b; + + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + + if (!parent) { + return FALSE; + } + + /* Count which child this is (child) and total number of children (m). */ + + CRXMLNodePtr cur_node = NULL; + int m = 0; + int child = 0; + int found = FALSE; + + cur_node = get_first_child_element_node (node_iface, parent); + + while (cur_node) { + if (cur_node == a_node) { + found = TRUE; + child = m; + } + cur_node = get_next_element_node (node_iface,cur_node); + ++m; + } + + if (!found) + return FALSE; + + if (a == 0) + return ((m - b) == child); + + return ((m - child - b)%a == 0 && (m - child - b)/a > -1); +} + +static gboolean +nth_last_of_type_pseudo_class_handler (CRSelEng *const a_this, + CRAdditionalSel * a_sel, CRXMLNodePtr const a_node) +{ + CRNodeIface const *node_iface = NULL; + CRXMLNodePtr parent = NULL; + + g_return_val_if_fail (a_this && PRIVATE (a_this) + && a_sel && a_sel->content.pseudo + && a_sel->content.pseudo + && a_sel->content.pseudo->name + && a_sel->content.pseudo->name->stryng + && a_node, FALSE); + + if (strcmp (a_sel->content.pseudo->name->stryng->str, "nth-last-of-type")) { + cr_utils_trace_info ("This handler is for :nth-last-of-type only"); + return FALSE; + } + + /*pseude code term should exist */ + if (!a_sel->content.pseudo->term) + return FALSE; + + CRArguments arg = get_arguments_from_function (a_sel); + + if (arg.a == 0 && arg.b == 0) + return FALSE; + + int a = arg.a; + int b = arg.b; + + node_iface = PRIVATE(a_this)->node_iface; + parent = node_iface->getParentNode (a_node); + if (!parent) { + return FALSE; + } + + CRXMLNodePtr cur_node = NULL; + int m = 0; + int child = 0; + int found = FALSE; + + cur_node = get_first_child_element_node (node_iface, parent); + + while (cur_node) { + if (!strcmp(node_iface->getLocalName(cur_node), a_sel->content.pseudo->sel_name->stryng->str)) + ++m; + if (cur_node == a_node) { + found = TRUE; + child = m; + } + cur_node = get_next_element_node (node_iface, cur_node); + } + + if (!found) + return FALSE; + + if (a == 0) + return ((m - b) == child); + + return ((m - child - b +1)%a == 0 && (m - child - b +1)/a > -1); + +} + +static gboolean pseudo_class_add_sel_matches_node (CRSelEng * a_this, CRAdditionalSel * a_add_sel, CRXMLNodePtr a_node) @@ -539,11 +1094,8 @@ get_next_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node) return cur_node; } -/* TODO: Consider renaming this to get_first_child_element_node. - (cf get_first_parent_element_node, which does getParent until element node - rather than getNextSibling). */ static CRXMLNodePtr -get_next_child_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node) +get_first_child_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_node) { CRXMLNodePtr cur_node = NULL; @@ -583,6 +1135,64 @@ get_next_parent_element_node (CRNodeIface const * a_node_iface, CRXMLNodePtr a_n return cur_node; } +static CRArguments +get_arguments_from_function (CRAdditionalSel * a_sel) +{ + CRArguments arg; + arg.a = 0; + arg.b = 0; + switch (a_sel->content.pseudo->term->type) { + case TERM_NUMBER: + if (a_sel->content.pseudo->term->content.num) { + arg.b = a_sel->content.pseudo->term->content.num->val; + } + if (a_sel->content.pseudo->term->n) { + arg.a = arg.b; + arg.b = 0; + } + break; + + case TERM_IDENT: + if (a_sel->content.pseudo->term->content.str) { + if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "even")) { + arg.a = 2; + arg.b = 0; + } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "odd")) { + arg.a = 2; + arg.b = 1; + } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "n")) { + /* 'n' without number */ + arg.a = 1; + } else if (!strcmp(a_sel->content.pseudo->term->content.str->stryng->str, "-n")) { + /* '-n' without number */ + arg.a = -1; + } else { + /* Unknown string */ + arg.a = 0; + arg.b = 0; + return (arg); + } + } + break; + + default: + cr_utils_trace_info ("Unknown term in nth style handler"); + arg.a = 0; + arg.b = 0; + return (arg); + } + + if (arg.a != 0 && a_sel->content.pseudo->term->next) { + /* check for b in 'an+b' */ + if (a_sel->content.pseudo->term->next->type == TERM_NUMBER && + a_sel->content.pseudo->term->next->content.num ) { + arg.b = a_sel->content.pseudo->term->next->content.num->val; + } + } + + return (arg); +} + /** *Evaluate a selector (a simple selectors list) and says *if it matches the xml node given in parameter. @@ -739,6 +1349,45 @@ sel_matches_node_real (CRSelEng * a_this, CRSimpleSel * a_sel, goto done; break; + case COMB_TILDE: /* General sibling selector. */ + { + CRXMLNodePtr n = NULL; + enum CRStatus status = CR_OK; + gboolean matches = FALSE; + + /* + * Walk through previous sibing nodes looking for a + * node that matches the preceding selector. + */ + for (n = get_prev_element_node (node_iface, cur_node); + n; + n = get_prev_element_node (node_iface, n)) { + status = sel_matches_node_real + (a_this, cur_sel->prev, + n, &matches, FALSE, TRUE); + + if (status != CR_OK) + goto done; + + if (matches == TRUE) { + cur_node = n ; + break; + } + } + + if (!n) { + /* + * Didn't find any previous sibling that matches + * the previous simple selector. + */ + goto done; + } + /* + * See note above in COMB_WS section. + */ + break; + } + case COMB_GT: cur_node = get_next_parent_element_node (node_iface, cur_node); if (!cur_node) @@ -1020,7 +1669,7 @@ put_css_properties_in_props_list (CRPropList ** a_props, CRStatement * a_stmt) *(unless the already selected declaration *has an UA origin) */ - if (decl->important == TRUE + if (decl->important == TRUE && cur_decl->important != TRUE && decl->parent_statement->parent_sheet->origin != ORIGIN_UA) { continue; @@ -1059,7 +1708,7 @@ put_css_properties_in_props_list (CRPropList ** a_props, CRStatement * a_stmt) */ if (a_stmt->specificity >= decl->parent_statement->specificity) { - if (decl->important == TRUE) + if (decl->important == TRUE && cur_decl->important != TRUE) continue; props = cr_prop_list_unlink (props, pair); if (pair) { @@ -1121,13 +1770,57 @@ cr_sel_eng_new (void) } memset (PRIVATE (result), 0, sizeof (CRSelEngPriv)); cr_sel_eng_register_pseudo_class_sel_handler - (result, (guchar *) "first-child", + (result, (guchar *) "root", IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ - first_child_pseudo_class_handler); + root_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "empty", + IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + empty_pseudo_class_handler); cr_sel_eng_register_pseudo_class_sel_handler (result, (guchar *) "lang", FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ lang_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "only-child", + IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + only_child_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "only-of-type", + IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + only_of_type_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "first-child", + IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + first_child_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "first-of-type", + IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + first_of_type_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "last-child", + IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + last_child_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "last-of-type", + IDENT_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + last_of_type_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "nth-child", + FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + nth_child_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "nth-of-type", + FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + nth_of_type_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "nth-last-child", + FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + nth_last_child_pseudo_class_handler); + cr_sel_eng_register_pseudo_class_sel_handler + (result, (guchar *) "nth-last-of-type", + FUNCTION_PSEUDO, /*(CRPseudoClassSelectorHandler)*/ + nth_last_of_type_pseudo_class_handler); return result; } diff --git a/src/libcroco/cr-sel-eng.h b/src/libcroco/cr-sel-eng.h index 564debc8d..206990eb6 100644 --- a/src/libcroco/cr-sel-eng.h +++ b/src/libcroco/cr-sel-eng.h @@ -44,6 +44,14 @@ G_BEGIN_DECLS typedef struct _CRSelEng CRSelEng ; typedef struct _CRSelEngPriv CRSelEngPriv ; +typedef struct _CRArguments CRArguments ; + +//stores arguments of function of type an+b +struct _CRArguments +{ + int a; + int b; +} ; /** *The Selection engine class. diff --git a/src/libcroco/cr-simple-sel.c b/src/libcroco/cr-simple-sel.c index 4df93fa77..3a4a3b2e2 100644 --- a/src/libcroco/cr-simple-sel.c +++ b/src/libcroco/cr-simple-sel.c @@ -125,6 +125,10 @@ cr_simple_sel_to_string (CRSimpleSel const * a_this) g_string_append (str_buf, "+"); break; + case COMB_TILDE: + g_string_append (str_buf, "~"); + break; + case COMB_GT: g_string_append (str_buf, ">"); break; diff --git a/src/libcroco/cr-simple-sel.h b/src/libcroco/cr-simple-sel.h index d8edc0025..552e44f00 100644 --- a/src/libcroco/cr-simple-sel.h +++ b/src/libcroco/cr-simple-sel.h @@ -40,9 +40,10 @@ G_BEGIN_DECLS enum Combinator { NO_COMBINATOR, - COMB_WS,/*whitespace: descendent*/ - COMB_PLUS,/*'+': preceded by*/ - COMB_GT/*greater than ('>'): child*/ + COMB_WS, /*whitespace: descendent*/ + COMB_PLUS, /*'+': immediately preceded by*/ + COMB_TILDE, /*'~': preceded by, CSS 3*/ + COMB_GT /*greater than ('>'): child*/ } ; enum SimpleSelectorType diff --git a/src/libcroco/cr-term.c b/src/libcroco/cr-term.c index 1c50aed2a..aec524b0b 100644 --- a/src/libcroco/cr-term.c +++ b/src/libcroco/cr-term.c @@ -74,6 +74,7 @@ cr_term_clear (CRTerm * a_this) } a_this->type = TERM_NO_TYPE; + a_this->n = FALSE; } /** diff --git a/src/libcroco/cr-term.h b/src/libcroco/cr-term.h index e85867afb..39b9c6a8b 100644 --- a/src/libcroco/cr-term.h +++ b/src/libcroco/cr-term.h @@ -123,6 +123,11 @@ struct _CRTerm } ext_content ; /** + *A flag to indicate if there is an n as in the nth child expression 'an+b'. + */ + gboolean n; + + /** *A spare pointer, just in case. *Can be used by the application. */ diff --git a/src/libcroco/cr-token.h b/src/libcroco/cr-token.h index f1257b7a8..35e914d2d 100644 --- a/src/libcroco/cr-token.h +++ b/src/libcroco/cr-token.h @@ -35,37 +35,37 @@ G_BEGIN_DECLS enum CRTokenType { - NO_TK, + NO_TK, // 0 S_TK, CDO_TK, CDC_TK, INCLUDES_TK, - DASHMATCH_TK, + DASHMATCH_TK, // 5 COMMENT_TK, STRING_TK, IDENT_TK, HASH_TK, - IMPORT_SYM_TK, + IMPORT_SYM_TK, // 10 PAGE_SYM_TK, MEDIA_SYM_TK, FONT_FACE_SYM_TK, CHARSET_SYM_TK, - ATKEYWORD_TK, + ATKEYWORD_TK, // 15 IMPORTANT_SYM_TK, EMS_TK, EXS_TK, LENGTH_TK, - ANGLE_TK, + ANGLE_TK, // 20 TIME_TK, FREQ_TK, DIMEN_TK, PERCENTAGE_TK, - NUMBER_TK, + NUMBER_TK, // 25 RGB_TK, URI_TK, FUNCTION_TK, UNICODERANGE_TK, - SEMICOLON_TK, + SEMICOLON_TK, // 30 CBO_TK, /*opening curly bracket*/ CBC_TK, /*closing curly bracket*/ PO_TK, /*opening parenthesis*/ diff --git a/src/libcroco/makefile.in b/src/libcroco/makefile.in deleted file mode 100644 index 554670f45..000000000 --- a/src/libcroco/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) libcroco/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) libcroco/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/libdepixelize/makefile.in b/src/libdepixelize/makefile.in deleted file mode 100644 index 51d020db1..000000000 --- a/src/libdepixelize/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) libdepixelize/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) libdepixelize/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/libnrtype/FontFactory.cpp b/src/libnrtype/FontFactory.cpp index 5c6a96694..90df81261 100644 --- a/src/libnrtype/FontFactory.cpp +++ b/src/libnrtype/FontFactory.cpp @@ -17,8 +17,11 @@ #endif #include <glibmm/i18n.h> +#include <fontconfig/fontconfig.h> +#include <pango/pangofc-fontmap.h> #include <pango/pangoft2.h> #include <pango/pango-ot.h> +#include "io/sys.h" #include "libnrtype/FontFactory.h" #include "libnrtype/font-instance.h" #include "util/unordered-containers.h" @@ -89,26 +92,20 @@ font_factory::font_factory(void) : nbEnt(0), // Note: this "ents" cache only keeps fonts from being unreffed, does not speed up access maxEnt(32), ents(static_cast<font_entry*>(g_malloc(maxEnt*sizeof(font_entry)))), - #ifdef USE_PANGO_WIN32 fontServer(pango_win32_font_map_for_display()), - fontContext(pango_win32_get_context()), pangoFontCache(pango_win32_font_map_get_font_cache(fontServer)), hScreenDC(pango_win32_get_dc()), #else fontServer(pango_ft2_font_map_new()), - fontContext(0), #endif + fontContext(pango_font_map_create_context(fontServer)), fontSize(512), loadedPtr(new FaceMapType()) { -#ifdef USE_PANGO_WIN32 -#else +#ifndef USE_PANGO_WIN32 pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontServer), 72, 72); - - fontContext = pango_font_map_create_context(fontServer); - pango_ft2_font_map_set_default_substitute(PANGO_FT2_FONT_MAP(fontServer), FactorySubstituteFunc, this, @@ -627,6 +624,154 @@ Glib::ustring extract_tag( guint32 *tag ) { return tag_name; } +// Extract which OpenType tables are in the font. A list of all tables (regardless of which script and langauge +// they are in) will be stored as a std::map in the openTypeTables field of the font_instance +// This Harfbuzz code replaces an earlier Pango version as the Pango functions are deprecated. +void extract_openTypeTables(font_instance *res) { + // Empty map... bitmap fonts seem to be loaded multiple times. + res->openTypeTables.clear(); + +#ifndef USE_PANGO_WIN32 + auto const face = hb_ft_face_create(res->theFace, NULL); + + // First time to get size of array + auto script_count = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, NULL, NULL); + auto const scripts_hb = g_new(hb_tag_t, script_count + 1); + + // Second time to fill array (this two step process was not necessary with Pango). + hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &script_count, scripts_hb); + + for(unsigned int i = 0; i < script_count; ++i) { + auto language_count = hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, NULL, NULL); + + if(language_count > 0) { + auto const languages_hb = g_new(hb_tag_t, language_count + 1); + hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, &language_count, languages_hb); + + for(unsigned int j = 0; j < language_count; ++j) { + auto feature_count = hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, j, 0, NULL, NULL); + auto const features_hb = g_new(hb_tag_t, feature_count + 1); + hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, j, 0, &feature_count, features_hb); + + for(unsigned int k = 0; k < feature_count; ++k) { + ++(res->openTypeTables[ extract_tag(&features_hb[k])]); + } + + g_free(features_hb); + } + + g_free(languages_hb); + } + else { + // Even if no languages are present there is still the default. + auto feature_count = hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, + HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, + 0, NULL, NULL); + auto const features_hb = g_new(hb_tag_t, feature_count + 1); + hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, + HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, + 0, &feature_count, features_hb); + + for(unsigned int k = 0; k < feature_count; ++k) { + ++(res->openTypeTables[ extract_tag(&features_hb[k])]); + } + + g_free(features_hb); + } + } + +// TODO: Ideally, we should use the HB_VERSION_ATLEAST macro here, +// but this was only released in harfbuzz >= 0.9.30 +// #if HB_VERSION_ATLEAST(1,2,3) +#if HB_VERSION_MAJOR*10000 + HB_VERSION_MINOR*100 + HB_VERSION_MICRO >= 10203 + // Find glyphs in OpenType substitution tables ('gsub'). + // Note that pango's functions are just dummies. Must use harfbuzz. + + // Loop over all tables + for (auto table: res->openTypeTables) { + + // Only look at style substitution tables ('salt', 'ss01', etc. but not 'ssty'). + if (table.first == "salt" || + (table.first[0] == 's' && table.first[1] == 's' && !(table.first[2] == 't') ) ) { + // std::cout << " Table: " << table.first << std::endl; + + Glib::ustring unicode_characters; + + unsigned int feature_index; + if ( hb_ot_layout_language_find_feature (face, HB_OT_TAG_GSUB, + 0, // Assume one script exists with index 0 + HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, + HB_TAG(table.first[0], + table.first[1], + table.first[2], + table.first[3]), + &feature_index ) ) { + + // std::cout << " Found feature, number: " << feature_index << std::endl; + unsigned int lookup_indexes[32]; + unsigned int lookup_count = 32; + int count = hb_ot_layout_feature_get_lookups (face, HB_OT_TAG_GSUB, + feature_index, + 0, // Start + &lookup_count, + lookup_indexes ); + // std::cout << " Lookup count: " << count << " total: " << lookup_count << std::endl; + + if (count > 0) { + hb_set_t* glyphs_before = NULL; // hb_set_create(); + hb_set_t* glyphs_input = hb_set_create(); + hb_set_t* glyphs_after = NULL; // hb_set_create(); + hb_set_t* glyphs_output = NULL; // hb_set_create(); + + // For now, just look at first index + hb_ot_layout_lookup_collect_glyphs (face, HB_OT_TAG_GSUB, + lookup_indexes[0], + glyphs_before, + glyphs_input, + glyphs_after, + glyphs_output ); + + hb_font_t *font = hb_font_create (face); + + // Without this, all functions return 0, etc. + hb_ft_font_set_funcs (font); + + hb_codepoint_t codepoint = -1; + while (hb_set_next (glyphs_input, &codepoint)) { + + // There is a unicode to glyph mapping function but not the inverse! + for (hb_codepoint_t unicode_i = 0; unicode_i < 0xffff; ++unicode_i) { + hb_codepoint_t glyph = 0; + hb_font_get_nominal_glyph (font, unicode_i, &glyph); + if ( glyph == codepoint) { + unicode_characters += (gunichar)unicode_i; + continue; + } + } + } + res->openTypeSubstitutions[table.first] = unicode_characters; + + hb_set_destroy (glyphs_input); + hb_font_destroy (font); + } + } else { + // std::cout << " Did not find '" << table.first << "'!" << std::endl; + } + } + } + // for (auto table: res->openTypeSubstitutions) { + // std::cout << table.first << ": " << table.second << std::endl; + // } +#else + std::cerr << "Requires Harfbuzz 1.2.3 for visualizing alternative glyph OpenType tables. " + << "Compiled with: " << HB_VERSION_STRING << "." << std::endl; +#endif + + hb_face_destroy (face); + g_free(scripts_hb); +#endif // USE_PANGO_WIN32 +} + font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) { #ifdef USE_PANGO_WIN32 @@ -685,157 +830,18 @@ font_instance *font_factory::Face(PangoFontDescription *descr, bool canFail) // no match if ( canFail ) { PANGO_DEBUG("falling back to 'sans-serif'\n"); - descr = pango_font_description_new(); - pango_font_description_set_family(descr,"sans-serif"); - res = Face(descr,false); - pango_font_description_free(descr); - } - } - - // Extract which OpenType tables are in the font. We'll make a list of all tables - // regardless of which script and langauge they are in. This Harfbuzz code replaces - // an earlier Pango version as the Pango functions are deprecated. - - // Empty map... bitmap fonts seem to be loaded multiple times. - res->openTypeTables.clear(); - - auto const face = hb_ft_face_create(res->theFace, NULL); - - // First time to get size of array - auto script_count = hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, NULL, NULL); - auto const scripts_hb = g_new(hb_tag_t, script_count + 1); - - // Second time to fill array (this two step process was not necessary with Pango). - hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &script_count, scripts_hb); - - for(unsigned int i = 0; i < script_count; ++i) { - auto language_count = hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, NULL, NULL); - - if(language_count > 0) { - auto const languages_hb = g_new(hb_tag_t, language_count + 1); - hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, i, 0, &language_count, languages_hb); - - for(unsigned int j = 0; j < language_count; ++j) { - auto feature_count = hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, j, 0, NULL, NULL); - auto const features_hb = g_new(hb_tag_t, feature_count + 1); - hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, j, 0, &feature_count, features_hb); - - for(unsigned int k = 0; k < feature_count; ++k) { - ++(res->openTypeTables[ extract_tag(&features_hb[k])]); - } - - g_free(features_hb); - } - - g_free(languages_hb); - } - else { - // Even if no languages are present there is still the default. - auto feature_count = hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, - HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, - 0, NULL, NULL); - auto const features_hb = g_new(hb_tag_t, feature_count + 1); - hb_ot_layout_language_get_feature_tags(face, HB_OT_TAG_GSUB, i, - HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, - 0, &feature_count, features_hb); - - for(unsigned int k = 0; k < feature_count; ++k) { - ++(res->openTypeTables[ extract_tag(&features_hb[k])]); - } - - g_free(features_hb); + PangoFontDescription *new_descr = pango_font_description_new(); + pango_font_description_set_family(new_descr, "sans-serif"); + res = Face(new_descr, false); + pango_font_description_free(new_descr); + } else { + g_critical("Could not load any face for font '%s'.", pango_font_description_to_string(descr)); } } -// TODO: Ideally, we should use the HB_VERSION_ATLEAST macro here, -// but this was only released in harfbuzz >= 0.9.30 -// #if HB_VERSION_ATLEAST(1,2,3) -#if HB_VERSION_MAJOR*10000 + HB_VERSION_MINOR*100 + HB_VERSION_MICRO >= 10203 - // Find glyphs in OpenType substitution tables ('gsub'). - // Note that pango's functions are just dummies. Must use harfbuzz. - - // Loop over all tables - for (auto table: res->openTypeTables) { - - // Only look at style substitution tables ('salt', 'ss01', etc. but not 'ssty'). - if (table.first == "salt" || - (table.first[0] == 's' && table.first[1] == 's' && !(table.first[2] == 't') ) ) { - // std::cout << " Table: " << table.first << std::endl; - - Glib::ustring unicode_characters; - - unsigned int feature_index; - if ( hb_ot_layout_language_find_feature (face, HB_OT_TAG_GSUB, - 0, // Assume one script exists with index 0 - HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX, - HB_TAG(table.first[0], - table.first[1], - table.first[2], - table.first[3]), - &feature_index ) ) { - - // std::cout << " Found feature, number: " << feature_index << std::endl; - unsigned int lookup_indexes[32]; - unsigned int lookup_count = 32; - int count = hb_ot_layout_feature_get_lookups (face, HB_OT_TAG_GSUB, - feature_index, - 0, // Start - &lookup_count, - lookup_indexes ); - // std::cout << " Lookup count: " << count << " total: " << lookup_count << std::endl; - - if (count > 0) { - hb_set_t* glyphs_before = NULL; // hb_set_create(); - hb_set_t* glyphs_input = hb_set_create(); - hb_set_t* glyphs_after = NULL; // hb_set_create(); - hb_set_t* glyphs_output = NULL; // hb_set_create(); - - // For now, just look at first index - hb_ot_layout_lookup_collect_glyphs (face, HB_OT_TAG_GSUB, - lookup_indexes[0], - glyphs_before, - glyphs_input, - glyphs_after, - glyphs_output ); - - hb_font_t *font = hb_font_create (face); - - // Without this, all functions return 0, etc. - hb_ft_font_set_funcs (font); - - hb_codepoint_t codepoint = -1; - while (hb_set_next (glyphs_input, &codepoint)) { - - // There is a unicode to glyph mapping function but not the inverse! - for (hb_codepoint_t unicode_i = 0; unicode_i < 0xffff; ++unicode_i) { - hb_codepoint_t glyph = 0; - hb_font_get_nominal_glyph (font, unicode_i, &glyph); - if ( glyph == codepoint) { - unicode_characters += (gunichar)unicode_i; - continue; - } - } - } - res->openTypeSubstitutions[table.first] = unicode_characters; - - hb_set_destroy (glyphs_input); - hb_font_destroy (font); - } - } else { - // std::cout << " Did not find '" << table.first << "'!" << std::endl; - } - } + if (res) { + extract_openTypeTables(res); } - // for (auto table: res->openTypeSubstitutions) { - // std::cout << table.first << ": " << table.second << std::endl; - // } -#else - std::cerr << "Requires Harfbuzz 1.2.3 for visualizing alternative glyph OpenType tables. " - << "Compiled with: " << HB_VERSION_STRING << "." << std::endl; -#endif - - hb_face_destroy (face); - g_free(scripts_hb); } else { // already here res = loadedFaces[descr]; @@ -911,6 +917,70 @@ void font_factory::AddInCache(font_instance *who) nbEnt++; } +void font_factory::AddFontsDir(char const *utf8dir) +{ +#ifdef USE_PANGO_WIN32 + g_info("Adding additional font directories only supported for fontconfig backend."); +#else + if (!Inkscape::IO::file_test(utf8dir, G_FILE_TEST_IS_DIR)) { + g_warning("Fonts dir '%s' does not exist and will be ignored.", utf8dir); + return; + } + + gchar *dir; +# ifdef WIN32 + dir = g_win32_locale_filename_from_utf8(utf8dir); +# else + dir = g_filename_from_utf8(utf8dir, -1, NULL, NULL, NULL); +# endif + + FcConfig *conf = NULL; +# if PANGO_VERSION_CHECK(1,38,0) + conf = pango_fc_font_map_get_config(PANGO_FC_FONT_MAP(fontServer)); +# endif + FcBool res = FcConfigAppFontAddDir(conf, (FcChar8 const *)dir); + if (res == FcTrue) { + g_info("Fonts dir '%s' added successfully.", utf8dir); + } else { + g_warning("Could not add fonts dir '%s'.", utf8dir); + } + + g_free(dir); +#endif +} + +void font_factory::AddFontFile(char const *utf8file) +{ +#ifdef USE_PANGO_WIN32 + g_info("Adding additional font only supported for fontconfig backend."); +#else + if (!Inkscape::IO::file_test(utf8file, G_FILE_TEST_IS_REGULAR)) { + g_warning("Font file '%s' does not exist and will be ignored.", utf8file); + return; + } + + gchar *file; +# ifdef WIN32 + file = g_win32_locale_filename_from_utf8(utf8file); +# else + file = g_filename_from_utf8(utf8file, -1, NULL, NULL, NULL); +# endif + + FcConfig *conf = NULL; +# if PANGO_VERSION_CHECK(1,38,0) + conf = pango_fc_font_map_get_config(PANGO_FC_FONT_MAP(fontServer)); +# endif + FcBool res = FcConfigAppFontAddFile(conf, (FcChar8 const *)file); + if (res == FcTrue) { + g_info("Font file '%s' added successfully.", utf8file); + } else { + g_warning("Could not add font file '%s'.", utf8file); + } + + g_free(file); +#endif +} + /* Local Variables: mode:c++ diff --git a/src/libnrtype/FontFactory.h b/src/libnrtype/FontFactory.h index 41c4cb6eb..12260f99a 100644 --- a/src/libnrtype/FontFactory.h +++ b/src/libnrtype/FontFactory.h @@ -136,6 +136,12 @@ public: // internal void AddInCache(font_instance *who); + /// Add a directory from which to include additional fonts + void AddFontsDir(char const *utf8dir); + + /// Add a an additional font. + void AddFontFile(char const *utf8file); + private: void* loadedPtr; diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index 7a16fc0c3..57aa22d48 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -556,10 +556,10 @@ bool font_instance::FontDecoration( double &underline_position, double &underl return false; } double scale=1.0/parent->fontSize; - underline_position = fabs(otm.otmUnderscorePosition *scale); - underline_thickness = fabs(otm.otmUnderscoreSize *scale); - linethrough_position = fabs(otm.otmStrikeoutPosition *scale); - linethrough_thickness = fabs(otm.otmStrikeoutSize *scale); + underline_position = fabs(otm.otmsUnderscorePosition *scale); + underline_thickness = fabs(otm.otmsUnderscoreSize *scale); + linethrough_position = fabs(otm.otmsStrikeoutPosition *scale); + linethrough_thickness = fabs(otm.otmsStrikeoutSize *scale); #else if ( theFace->units_per_EM == 0 ) { return false; // bitmap font @@ -683,12 +683,12 @@ void font_instance::FindFontMetrics() { if ( theFace ) { #ifdef USE_PANGO_WIN32 - + OUTLINETEXTMETRIC otm; if ( GetOutlineTextMetrics(parent->hScreenDC,sizeof(otm),&otm) ) { double scale=1.0/parent->fontSize; _ascent = fabs(otm.otmMacAscent * scale); _descent = fabs(otm.otmMacDescent * scale); - _xheight = fabs(otm.otmXHeight * scale); + _xheight = fabs(otm.otmsXHeight * scale); _ascent_max = fabs(otm.otmAscent * scale); _descent_max = fabs(otm.otmDescent * scale); diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index 63364ab34..eca795994 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -253,8 +253,7 @@ class Layout::Calculator UnbrokenSpanPosition const &start_span_pos, ScanlineMaker::ScanRun const &scan_run, std::vector<ChunkInfo> *chunk_info, - FontMetrics *line_height, - FontMetrics const *strut_height) const; + FontMetrics *line_height) const; bool _measureUnbrokenSpan(ParagraphInfo const ¶, BrokenSpan *span, @@ -399,24 +398,46 @@ bool Layout::Calculator::_measureUnbrokenSpan(ParagraphInfo const ¶, double char_width = 0.0; while (span->end_glyph_index < (unsigned)span->end.iter_span->glyph_string->num_glyphs && span->end.iter_span->glyph_string->log_clusters[span->end_glyph_index] <= (int)span->end.char_byte) { + + PangoGlyphInfo *info = &(span->end.iter_span->glyph_string->glyphs[span->end_glyph_index]); + // double glyph_width = font_size_multiplier * info->geometry.width; + // double glyph_x_offset = font_size_multiplier * info->geometry.x_offset; + // double glyph_y_offset = font_size_multiplier * info->geometry.y_offset; + // std::cout << " glyph: " << info->glyph << " width: " << glyph_width << " x_offset: " << glyph_x_offset << " y_offset: " << glyph_y_offset << std::endl; + + font_instance *font = para.pango_items[span->end.iter_span->pango_item_index].font; + double font_size = span->start.iter_span->font_size; + double glyph_h_advance = font_size * font->Advance(info->glyph, false); + double glyph_v_advance = font_size * font->Advance(info->glyph, true ); + // std::cout << " h_advance: " << glyph_h_advance << " v_advance: " << glyph_v_advance << std::endl; + // Geom::OptRect bbox = font->BBox(info->glyph); + // *bbox *= Geom::Scale(font_size); + // std::cout << " bbox: " << *bbox << std::endl; + // std::cout << " h_extent: " << bbox->width() << " v_extent: " << bbox->height() << std::endl; + if (_block_progression == LEFT_TO_RIGHT || _block_progression == RIGHT_TO_LEFT) { // Vertical text if( text_source->style->text_orientation.computed == SP_CSS_TEXT_ORIENTATION_SIDEWAYS || (text_source->style->text_orientation.computed == SP_CSS_TEXT_ORIENTATION_MIXED && - para.pango_items[span->end.iter_span->pango_item_index].item->analysis.gravity == 0) ) { + para.pango_items[span->end.iter_span->pango_item_index].item->analysis.gravity == PANGO_GRAVITY_SOUTH) ) { // Sideways orientation - char_width += span->start.iter_span->font_size * para.pango_items[span->end.iter_span->pango_item_index].font->Advance(span->end.iter_span->glyph_string->glyphs[span->end_glyph_index].glyph, false); + char_width += glyph_h_advance; } else { // Upright orientation - char_width += span->start.iter_span->font_size * para.pango_items[span->end.iter_span->pango_item_index].font->Advance(span->end.iter_span->glyph_string->glyphs[span->end_glyph_index].glyph, true); + guint32 c = *Glib::ustring::const_iterator(span->end.iter_span->input_stream_first_character.base() + span->end.char_byte); + if (g_unichar_type (c) != G_UNICODE_NON_SPACING_MARK) { + // Non-spacing marks should not contribute to width. Fonts may not report the correct advance, especially if the 'vmtx' table is missing. + char_width += glyph_v_advance; + } } } else { // Horizontal text - char_width += font_size_multiplier * span->end.iter_span->glyph_string->glyphs[span->end_glyph_index].geometry.width; + char_width += font_size_multiplier * info->geometry.width; } span->end_glyph_index++; } + if (char_attributes.is_cursor_position) char_width += text_source->style->letter_spacing.computed * _flow.getTextLengthMultiplierDue(); if (char_attributes.is_white) @@ -435,6 +456,7 @@ bool Layout::Calculator::_measureUnbrokenSpan(ParagraphInfo const ¶, if (is_soft_hyphen) soft_hyphen_glyph_width = char_width; + // Go to next character (resets end.char_byte to zero if at end) span->end.increment(); // Width should not include letter_spacing (or word_spacing) after last letter at end of line. @@ -663,8 +685,8 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, new_span.block_progression = _block_progression; new_span.text_orientation = unbroken_span.text_orientation; if ((_flow._input_stream[unbroken_span.input_index]->Type() == TEXT_SOURCE) && (new_span.font = para.pango_items[unbroken_span.pango_item_index].font)) - { - new_span.font->Ref(); + { + new_span.font->Ref(); new_span.font_size = unbroken_span.font_size; new_span.direction = para.pango_items[unbroken_span.pango_item_index].item->analysis.level & 1 ? RIGHT_TO_LEFT : LEFT_TO_RIGHT; new_span.input_stream_first_character = Glib::ustring::const_iterator(unbroken_span.input_stream_first_character.base() + it_span->start.char_byte); @@ -698,6 +720,7 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, if (_flow._input_stream[unbroken_span.input_index]->Type() == TEXT_SOURCE) { // the span is set up, push the glyphs and chars + InputStreamTextSource const *text_source = static_cast<InputStreamTextSource const *>(_flow._input_stream[unbroken_span.input_index]); Glib::ustring::const_iterator iter_source_text = Glib::ustring::const_iterator(unbroken_span.input_stream_first_character.base() + it_span->start.char_byte) ; unsigned char_index_in_unbroken_span = it_span->start.char_index; @@ -708,9 +731,9 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, for (unsigned glyph_index = it_span->start_glyph_index ; glyph_index < it_span->end_glyph_index ; glyph_index++) { unsigned char_byte = iter_source_text.base() - unbroken_span.input_stream_first_character.base(); - int newcluster = 0; - if (unbroken_span.glyph_string->glyphs[glyph_index].attr.is_cluster_start){ - newcluster = 1; + bool newcluster = false; + if (unbroken_span.glyph_string->glyphs[glyph_index].attr.is_cluster_start) { + newcluster = true; x_in_span = x_in_span_last; } @@ -750,10 +773,12 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, new_glyph.vertical_scale = 1.0; // Position glyph -------------------- - new_glyph.x = current_x + unbroken_span_glyph_info->geometry.x_offset * font_size_multiplier; + new_glyph.x = current_x; new_glyph.y =_y_offset; - // y-coordinate is flipped between vertical and horizontal text... delta_y is common offset but applied with opposite sign + // y-coordinate is flipped between vertical and horizontal text... + // delta_y is common offset but applied with opposite sign + double delta_x = unbroken_span_glyph_info->geometry.x_offset * font_size_multiplier; double delta_y = unbroken_span_glyph_info->geometry.y_offset * font_size_multiplier + unbroken_span.baseline_shift; SPCSSBaseline dominant_baseline = _flow._blockBaseline(); @@ -767,41 +792,53 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, if( dominant_baseline == SP_CSS_BASELINE_AUTO ) dominant_baseline = SP_CSS_BASELINE_ALPHABETIC; } - new_glyph.y += delta_y; - // TODO: Should also check 'glyph_orientation_vertical' if 'text-orientation' is unset... if( new_span.text_orientation == SP_CSS_TEXT_ORIENTATION_SIDEWAYS || (new_span.text_orientation == SP_CSS_TEXT_ORIENTATION_MIXED && - para.pango_items[unbroken_span.pango_item_index].item->analysis.gravity == 0) ) { + para.pango_items[unbroken_span.pango_item_index].item->analysis.gravity == PANGO_GRAVITY_SOUTH) ) { - // Sideways orientation (Latin characters, CJK punctuation), 90deg rotation done at output stage. zzzzzzz + // Sideways orientation (Latin characters, CJK punctuation), 90deg rotation done at output stage. new_glyph.orientation = ORIENTATION_SIDEWAYS; - new_glyph.y -= new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->GetBaselines()[ dominant_baseline ]; + new_glyph.x += delta_x; + new_glyph.y -= delta_y; + + new_glyph.y -= new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->GetBaselines()[ dominant_baseline ]; new_glyph.width = new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->Advance(unbroken_span_glyph_info->glyph, false); } else { // Upright orientation - new_glyph.x += new_span.line_height.ascent; + new_glyph.x += delta_x; + new_glyph.y -= delta_y; - // Glyph reference point is center (shift: left edge to center glyph) - new_glyph.y -= unbroken_span_glyph_info->geometry.width * 0.5 * font_size_multiplier; + // Adjust for alignment point (top of em box, horizontal center). + new_glyph.x += new_span.line_height.ascent; new_glyph.y -= new_span.font_size * (para.pango_items[unbroken_span.pango_item_index].font->GetBaselines()[ dominant_baseline ] - para.pango_items[unbroken_span.pango_item_index].font->GetBaselines()[ SP_CSS_BASELINE_CENTRAL ] ); - new_glyph.width = new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->Advance(unbroken_span_glyph_info->glyph, true); - if( new_glyph.width == 0 ) { - new_glyph.width = unbroken_span_glyph_info->geometry.width * font_size_multiplier; + static double shift_y = 0; // Save to use with non_spacing marks (should be shifted the same amount as previous glyph). + static double shift_x = 0; // Subtract incorrect Pango inclusion of horizontal advance (https://bugzilla.gnome.org 787526) + if (g_unichar_type (*iter_source_text) == G_UNICODE_NON_SPACING_MARK) { + new_glyph.width = 0; + new_glyph.x += shift_x; // Hack + shift_x = 0; + } else { + // Glyph reference point is center (shift: left edge to center glyph) + shift_y = unbroken_span_glyph_info->geometry.width * 0.5 * font_size_multiplier; + new_glyph.width = new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->Advance(unbroken_span_glyph_info->glyph, true); + shift_x = new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->Advance(unbroken_span_glyph_info->glyph, false); } - + new_glyph.y -= shift_y; } } else { // Horizontal text if( dominant_baseline == SP_CSS_BASELINE_AUTO ) dominant_baseline = SP_CSS_BASELINE_ALPHABETIC; - new_glyph.y -= delta_y; + new_glyph.x += delta_x; + new_glyph.y += delta_y; + new_glyph.y += new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->GetBaselines()[ dominant_baseline ]; new_glyph.width = unbroken_span_glyph_info->geometry.width * font_size_multiplier; @@ -810,7 +847,6 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, // for some reason pango returns zero width for invalid glyph characters (those empty boxes), so go to freetype for the info } - if (new_span.direction == RIGHT_TO_LEFT) { // pango wanted to give us glyphs in visual order but we refused, so we need to work // out where the cluster start is ourselves @@ -818,12 +854,7 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, for (unsigned rtl_index = glyph_index; rtl_index < it_span->end_glyph_index ; rtl_index++) { if (unbroken_span.glyph_string->glyphs[rtl_index].attr.is_cluster_start && rtl_index != glyph_index) break; - if (_block_progression == LEFT_TO_RIGHT || _block_progression == RIGHT_TO_LEFT) - // Vertical text - cluster_width += new_span.font_size * para.pango_items[unbroken_span.pango_item_index].font->Advance(unbroken_span.glyph_string->glyphs[rtl_index].glyph, true); - else - // Horizontal text - cluster_width += font_size_multiplier * unbroken_span.glyph_string->glyphs[rtl_index].geometry.width; + cluster_width += font_size_multiplier * unbroken_span.glyph_string->glyphs[rtl_index].geometry.width; } new_glyph.x -= cluster_width; } @@ -831,8 +862,9 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, // create the Layout::Character(s) double advance_width = new_glyph.width; - if (newcluster){ - newcluster = 0; + if (newcluster) { + newcluster = false; + // find where the text ends for this log_cluster end_byte = it_span->start.iter_span->text_bytes; // Upper limit for(int next_glyph_index = glyph_index+1; next_glyph_index < unbroken_span.glyph_string->num_glyphs; next_glyph_index++){ @@ -841,6 +873,7 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, break; } } + // Figure out how many glyphs and characters are in the log_cluster. log_cluster_size_glyphs = 0; log_cluster_size_chars = 0; @@ -848,6 +881,7 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, if(unbroken_span.glyph_string->log_clusters[glyph_index ] != unbroken_span.glyph_string->log_clusters[glyph_index + log_cluster_size_glyphs])break; } + Glib::ustring::const_iterator lclist = iter_source_text; unsigned lcb = char_byte; while(lcb < end_byte){ @@ -856,6 +890,7 @@ void Layout::Calculator::_outputLine(ParagraphInfo const ¶, lcb = lclist.base() - unbroken_span.input_stream_first_character.base(); } } + while (char_byte < end_byte) { /* Hack to survive ligatures: in log_cluster keep the number of available chars >= number of glyphs remaining. When there are no ligatures these two sizes are always the same. @@ -1472,8 +1507,8 @@ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, TRACE((" initial line_box_height (em size): %f\n", line_box_height->emSize() )); UnbrokenSpanPosition span_pos; + static int trys = 0; for( ; ; ) { - // Get regions where one can place one line of text (can be more than one, if filling a // donut for example). std::vector<ScanlineMaker::ScanRun> scan_runs; @@ -1495,10 +1530,9 @@ bool Layout::Calculator::_findChunksForLine(ParagraphInfo const ¶, unsigned scan_run_index; span_pos = *start_span_pos; for (scan_run_index = 0 ; scan_run_index < scan_runs.size() ; scan_run_index++) { - // Returns false if some text in line requires a taller line_box_height. // (We try again with a larger line_box_height.) - if (!_buildChunksInScanRun(para, span_pos, scan_runs[scan_run_index], chunk_info, line_box_height, strut_height)) { + if (!_buildChunksInScanRun(para, span_pos, scan_runs[scan_run_index], chunk_info, line_box_height)) { break; } @@ -1534,11 +1568,12 @@ bool Layout::Calculator::_buildChunksInScanRun(ParagraphInfo const ¶, UnbrokenSpanPosition const &start_span_pos, ScanlineMaker::ScanRun const &scan_run, std::vector<ChunkInfo> *chunk_info, - FontMetrics *line_height, - FontMetrics const *strut_height) const + FontMetrics *line_height) const { TRACE((" begin _buildChunksInScanRun: chunks: %lu, em size: %f\n", chunk_info->size(), line_height->emSize() )); + FontMetrics line_height_saved = *line_height; // Store for recalculating line height if chunks are backed out + ChunkInfo new_chunk; new_chunk.text_width = 0.0; new_chunk.whitespace_count = 0; @@ -1647,7 +1682,7 @@ bool Layout::Calculator::_buildChunksInScanRun(ParagraphInfo const ¶, } // Recalculate line_box_height after backing out chunks - *line_height = *strut_height; + *line_height = line_height_saved; for (std::vector<ChunkInfo>::const_iterator it_chunk = chunk_info->begin() ; it_chunk != chunk_info->end() ; it_chunk++) { for (std::vector<BrokenSpan>::const_iterator it_span = it_chunk->broken_spans.begin() ; it_span != it_chunk->broken_spans.end() ; it_span++) { FontMetrics span_height = it_span->start.iter_span->line_height; @@ -1751,6 +1786,10 @@ bool Layout::Calculator::calculate() if( _block_progression == RIGHT_TO_LEFT || _block_progression == LEFT_TO_RIGHT ) { // Vertical text, CJK pango_context_set_base_gravity(_pango_context, PANGO_GRAVITY_EAST); + + if( _flow._blockTextOrientation() == SP_CSS_TEXT_ORIENTATION_UPRIGHT ) { + pango_context_set_gravity_hint(_pango_context, PANGO_GRAVITY_HINT_STRONG); + } } else { // Horizontal text pango_context_set_base_gravity(_pango_context, PANGO_GRAVITY_AUTO); diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index 7f20dee95..9a73b9eca 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -800,7 +800,7 @@ void Layout::fitToPathAlign(SVGLength const &startOffset, Path const &path) SPCurve *Layout::convertToCurves(iterator const &from_glyph, iterator const &to_glyph) const { - GSList *cc = NULL; + std::list<SPCurve *> cc; for (int glyph_index = from_glyph._glyph_index ; glyph_index < to_glyph._glyph_index ; glyph_index++) { Geom::Affine glyph_matrix; @@ -811,22 +811,14 @@ SPCurve *Layout::convertToCurves(iterator const &from_glyph, iterator const &to_ if (pathv) { Geom::PathVector pathv_trans = (*pathv) * glyph_matrix; SPCurve *c = new SPCurve(pathv_trans); - if (c) cc = g_slist_prepend(cc, c); + if (c) cc.push_back(c); } } - cc = g_slist_reverse(cc); + SPCurve *curve = new SPCurve(cc); - SPCurve *curve; - if ( cc ) { - curve = SPCurve::concat(cc); - } else { - curve = new SPCurve(); - } - - while (cc) { + for (auto i:cc) { /* fixme: This is dangerous, as we are mixing art_alloc and g_new */ - reinterpret_cast<SPCurve *>(cc->data)->unref(); - cc = g_slist_remove(cc, cc->data); + i->unref(); } return curve; diff --git a/src/libuemf/makefile.in b/src/libuemf/makefile.in deleted file mode 100644 index f1a595e1d..000000000 --- a/src/libuemf/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) libuemf/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) libuemf/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/libvpsc/linesegment.h b/src/libvpsc/linesegment.h index caca3a2bb..ecf8800b0 100644 --- a/src/libvpsc/linesegment.h +++ b/src/libvpsc/linesegment.h @@ -103,21 +103,21 @@ void DoLineSegmentIntersection(const Vector& p0, const Vector& p1, const Vector& Vector intersection; std::cout << "Line Segment 0: (" << p0.x_ << ", " << p0.y_ << ") to (" << p1.x_ << ", " << p1.y_ << ")\n" - << "Line Segment 1: (" << p2.x_ << ", " << p2.y_ << ") to (" << p3.x_ << ", " << p3.y_ << ")\n"; + << "Line Segment 1: (" << p2.x_ << ", " << p2.y_ << ") to (" << p3.x_ << ", " << p3.y_ << ")" << std::endl; switch(linesegment0.Intersect(linesegment1, intersection)) { case LineSegment::PARALLEL: - std::cout << "The lines are parallel\n\n"; + std::cout << "The lines are parallel\n" << std::endl; break; case LineSegment::COINCIDENT: - std::cout << "The lines are coincident\n\n"; + std::cout << "The lines are coincident\n" << std::endl; break; case LineSegment::NOT_INTERSECTING: - std::cout << "The lines do not intersect\n\n"; + std::cout << "The lines do not intersect\n" << std::endl; break; case LineSegment::INTERSECTING: - std::cout << "The lines intersect at (" << intersection.x_ << ", " << intersection.y_ << ")\n\n"; + std::cout << "The lines intersect at (" << intersection.x_ << ", " << intersection.y_ << ")\n" << std::endl; break; } } diff --git a/src/livarot/makefile.in b/src/livarot/makefile.in deleted file mode 100644 index f92015275..000000000 --- a/src/livarot/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) livarot/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) livarot/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index b1000de01..9d18626bc 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -64,9 +64,12 @@ set(live_effects_SRC parameter/array.cpp parameter/bool.cpp + parameter/colorpicker.cpp parameter/hidden.cpp parameter/item-reference.cpp parameter/item.cpp + parameter/message.cpp + parameter/originalitemarray.cpp parameter/originalitem.cpp parameter/originalpath.cpp parameter/originalpatharray.cpp @@ -154,9 +157,12 @@ set(live_effects_SRC parameter/array.h parameter/bool.h + parameter/colorpicker.h parameter/hidden.h parameter/enum.h parameter/item.h + parameter/message.h + parameter/originalitemarray.cpp parameter/item-reference.h parameter/originalitem.h parameter/originalpath.h diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index b2ba0acdc..5674e29dc 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -81,6 +81,7 @@ #include "display/curve.h" #include <stdio.h> #include <string.h> +#include <gtkmm/expander.h> namespace Inkscape { @@ -562,8 +563,8 @@ void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) setCurrentShape(shape); doBeforeEffect(lpeitem); if (apply_to_clippath_and_mask && SP_IS_GROUP(sp_lpe_item)) { - sp_lpe_item->apply_to_clippath(sp_lpe_item); - sp_lpe_item->apply_to_mask(sp_lpe_item); + sp_lpe_item->applyToClipPath(sp_lpe_item); + sp_lpe_item->applyToMask(sp_lpe_item); } update_helperpath(); } @@ -826,29 +827,36 @@ Effect::defaultParamSet() Glib::ustring * tip = param->param_getTooltip(); const gchar * key = param->param_key.c_str(); const gchar * value = param->param_label.c_str(); - const gchar * tooltip_extra = _(". Change custom values for this parameter"); - Glib::ustring tooltip = param->param_tooltip + (Glib::ustring)tooltip_extra; + Glib::ustring pref_path = (Glib::ustring)"/live_effects/" + effectkey + (Glib::ustring)"/" + (Glib::ustring)key; bool valid = prefs->getEntry(pref_path).isValid(); const gchar * set_or_upd; + Glib::ustring def = Glib::ustring(_("<b>Default value:</b> ")) + Glib::ustring(param->param_getDefaultSVGValue()) + Glib::ustring("\n"); + Glib::ustring ove = Glib::ustring(_("<b>Default value overrided:</b> ")) + Glib::ustring(prefs->getString(pref_path)) + Glib::ustring("\n"); if (valid) { set_or_upd = _("Update"); + def = Glib::ustring(_("<b>Default value:</b> <s>")) + Glib::ustring(param->param_getDefaultSVGValue()) + Glib::ustring("</s>\n"); } else { set_or_upd = _("Set"); + ove = Glib::ustring(_("<b>Default value overrided:</b> None\n")); } + Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) + Glib::ustring(param->param_getSVGValue()); Gtk::HBox * vbox_param = Gtk::manage( new Gtk::HBox(true) ); Gtk::Label *parameter_label = Gtk::manage(new Gtk::Label(value, Gtk::ALIGN_START)); parameter_label->set_use_markup(true); - parameter_label->set_use_underline (true); + parameter_label->set_use_underline(true); + Glib::ustring tooltip = Glib::ustring("<b>") + parameter_label->get_text () + Glib::ustring("</b>\n") + param->param_tooltip + Glib::ustring("\n\n"); parameter_label->set_ellipsize(Pango::ELLIPSIZE_END); + parameter_label->set_tooltip_markup((tooltip + def + ove + cur).c_str()); vbox_param->pack_start(*parameter_label, true, true, 2); Gtk::Button *set = Gtk::manage(new Gtk::Button((Glib::ustring)set_or_upd)); Gtk::Button *unset = Gtk::manage(new Gtk::Button(Glib::ustring(_("Unset")))); - unset->signal_clicked().connect(sigc::bind<Glib::ustring, Gtk::Button *, Gtk::Button *>(sigc::mem_fun(*this, &Effect::unsetDefaultParam), pref_path, set, unset)); - set->signal_clicked().connect(sigc::bind<Glib::ustring, gchar *, Gtk::Button *, Gtk::Button *>(sigc::mem_fun(*this, &Effect::setDefaultParam), pref_path, param->param_getSVGValue(), set, unset)); + unset->signal_clicked().connect(sigc::bind<Glib::ustring, Glib::ustring, gchar *, gchar *, Gtk::Label *,Gtk::Button *, Gtk::Button *>(sigc::mem_fun(*this, &Effect::unsetDefaultParam), pref_path, tooltip, param->param_getSVGValue(), param->param_getDefaultSVGValue(), parameter_label, set, unset)); + + set->signal_clicked().connect(sigc::bind<Glib::ustring, Glib::ustring, gchar *, gchar *, Gtk::Label *,Gtk::Button *, Gtk::Button *>(sigc::mem_fun(*this, &Effect::setDefaultParam), pref_path, tooltip, param->param_getSVGValue(), param->param_getDefaultSVGValue(), parameter_label, set, unset)); if (!valid) { unset->set_sensitive(false); } @@ -866,30 +874,41 @@ Effect::defaultParamSet() expander->set_expanded(false); vbox->pack_start(*dynamic_cast<Gtk::Widget *> (expander), true, true, 2); if (has_params) { - return dynamic_cast<Gtk::Widget *>(vbox); + Gtk::Widget *vboxwidg = dynamic_cast<Gtk::Widget *>(vbox); + vboxwidg->set_margin_bottom(10); + vboxwidg->set_margin_top(5); + return vboxwidg; } else { return NULL; } } void -Effect::setDefaultParam(Glib::ustring pref_path, gchar * value, Gtk::Button *set , Gtk::Button *unset) +Effect::setDefaultParam(Glib::ustring pref_path, Glib::ustring tooltip, gchar * value, gchar * defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setString(pref_path, (Glib::ustring)value); gchar * label = _("Update"); set->set_label((Glib::ustring)label); unset->set_sensitive(true); + Glib::ustring def = Glib::ustring(_("<b>Default value:</b> <s>")) + Glib::ustring(defvalue) + Glib::ustring("</s>\n"); + Glib::ustring ove = Glib::ustring(_("<b>Default value overrided:</b> ")) + Glib::ustring(value) + Glib::ustring("\n"); + Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) + Glib::ustring(value); + parameter_label->set_tooltip_markup((tooltip + def + ove + cur).c_str()); } void -Effect::unsetDefaultParam(Glib::ustring pref_path, Gtk::Button *set, Gtk::Button *unset) +Effect::unsetDefaultParam(Glib::ustring pref_path, Glib::ustring tooltip, gchar * value, gchar * defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->remove(pref_path); gchar * label = _("Set"); set->set_label((Glib::ustring)label); unset->set_sensitive(false); + Glib::ustring def = Glib::ustring(_("<b>Default value:</b> ")) + Glib::ustring(defvalue) + Glib::ustring("\n"); + Glib::ustring ove = Glib::ustring(_("<b>Default value overrided:</b> None\n")); + Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) + Glib::ustring(value); + parameter_label->set_tooltip_markup((tooltip + def + ove + cur).c_str()); } Inkscape::XML::Node *Effect::getRepr() diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index e353eba23..d0024f877 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -181,8 +181,8 @@ protected: std::vector<Geom::Point> selectedNodesPoints; private: - void setDefaultParam(Glib::ustring pref_path, gchar * value, Gtk::Button *set , Gtk::Button *unset); - void unsetDefaultParam(Glib::ustring pref_path, Gtk::Button *set , Gtk::Button *unset); + void setDefaultParam(Glib::ustring pref_path, Glib::ustring par, gchar * value, gchar * defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset); + void unsetDefaultParam(Glib::ustring pref_path, Glib::ustring par, gchar * value, gchar * defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset); bool provides_own_flash_paths; // if true, the standard flash path is suppressed bool is_ready; diff --git a/src/live_effects/lpe-bendpath.cpp b/src/live_effects/lpe-bendpath.cpp index 5c1953fda..ff5f738eb 100644 --- a/src/live_effects/lpe-bendpath.cpp +++ b/src/live_effects/lpe-bendpath.cpp @@ -94,7 +94,7 @@ LPEBendPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd uskeleton = arc_length_parametrization(Piecewise<D2<SBasis> >(bend_path.get_pwd2()),2,.1); uskeleton = remove_short_cuts(uskeleton,.01); n = rot90(derivative(uskeleton)); - n = force_continuity(remove_short_cuts(n,.1)); + n = force_continuity(remove_short_cuts(n,.01)); bend_path.changed = false; } @@ -109,9 +109,10 @@ LPEBendPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd Interval bboxHorizontal = vertical_pattern.get_value() ? boundingbox_Y : boundingbox_X; Interval bboxVertical = vertical_pattern.get_value() ? boundingbox_X : boundingbox_Y; - + + //+0.1 in x fix bug #1658855 //We use the group bounding box size or the path bbox size to translate well x and y - x-= bboxHorizontal.min(); + x-= bboxHorizontal.min() + 0.1; y-= bboxVertical.middle(); double scaling = uskeleton.cuts.back()/bboxHorizontal.extent(); @@ -151,6 +152,14 @@ LPEBendPath::resetDefaults(SPItem const* item) } void +LPEBendPath::transform_multiply(Geom::Affine const& postmul, bool set) +{ + if (sp_lpe_item) { + sp_lpe_item_update_patheffect(sp_lpe_item, false, false); + } +} + +void LPEBendPath::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) { hp_vec.push_back(bp_helper_path); diff --git a/src/live_effects/lpe-bendpath.h b/src/live_effects/lpe-bendpath.h index 54c5d70fe..f232687ce 100644 --- a/src/live_effects/lpe-bendpath.h +++ b/src/live_effects/lpe-bendpath.h @@ -43,6 +43,8 @@ public: virtual void resetDefaults(SPItem const* item); + virtual void transform_multiply(Geom::Affine const& postmul, bool set); + void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec); virtual void addKnotHolderEntities(KnotHolder * knotholder, SPItem * item); diff --git a/src/live_effects/lpe-circle_3pts.cpp b/src/live_effects/lpe-circle_3pts.cpp index 3410b13f2..c49d5ca4d 100644 --- a/src/live_effects/lpe-circle_3pts.cpp +++ b/src/live_effects/lpe-circle_3pts.cpp @@ -40,12 +40,18 @@ static void _circle3(Geom::Point const &A, Geom::Point const &B, Geom::Point con Point v = (B - A).ccw(); Point w = (C - B).ccw(); + double det = -v[0] * w[1] + v[1] * w[0]; - Point F = E - D; - double lambda = 1/det * (-w[1] * F[0] + w[0] * F[1]); + Point M; + if (!v.isZero()) { + Point F = E - D; + double lambda = det == 0 ? 0 : (-w[1] * F[0] + w[0] * F[1]) / det; + M = D + v * lambda; + } else { + M = E; + } - Point M = D + v * lambda; double radius = L2(M - A); Geom::Circle c(M, radius); diff --git a/src/live_effects/lpe-clone-original.cpp b/src/live_effects/lpe-clone-original.cpp index 31bf0e270..15968dd56 100644 --- a/src/live_effects/lpe-clone-original.cpp +++ b/src/live_effects/lpe-clone-original.cpp @@ -5,6 +5,10 @@ */ #include "live_effects/lpe-clone-original.h" +#include "live_effects/lpe-spiro.h" +#include "live_effects/lpe-bspline.h" +#include "live_effects/lpeobject.h" +#include "live_effects/lpeobject-reference.h" #include "display/curve.h" #include "svg/path-string.h" #include "svg/svg.h" @@ -18,59 +22,50 @@ namespace Inkscape { namespace LivePathEffect { +static const Util::EnumData<Clonelpemethod> ClonelpemethodData[] = { + { CLM_NONE, N_("No shape"), "none" }, + { CLM_ORIGINALD, N_("Without LPE's"), "originald" }, + { CLM_BSPLINESPIRO, N_("With Spiro or BSpline"), "bsplinespiro" }, + { CLM_D, N_("With LPE's"), "d" } +}; +static const Util::EnumDataConverter<Clonelpemethod> CLMConverter(ClonelpemethodData, CLM_END); + LPECloneOriginal::LPECloneOriginal(LivePathEffectObject *lpeobject) : Effect(lpeobject), linkeditem(_("Linked Item:"), _("Item from which to take the original data"), "linkeditem", &wr, this), - scale(_("Scale %"), _("Scale item %"), "scale", &wr, this, 100.0), - preserve_position(_("Preserve position"), _("Preserve position"), "preserve_position", &wr, this, false), - inverse(_("Inverse clone"), _("Use LPE item as origin"), "inverse", &wr, this, false), - d(_("Clone shape -d-"), _("Clone shape -d-"), "d", &wr, this, true), - transform(_("Clone transforms"), _("Clone transforms"), "transform", &wr, this, true), - fill(_("Clone fill"), _("Clone fill"), "fill", &wr, this, false), - stroke(_("Clone stroke"), _("Clone stroke"), "stroke", &wr, this, false), - paintorder(_("Clone paint order"), _("Clone paint order"), "paintorder", &wr, this, false), - opacity(_("Clone opacity"), _("Clone opacity"), "opacity", &wr, this, false), - filter(_("Clone filter"), _("Clone filter"), "filter", &wr, this, false), + method(_("Shape linked"), _("Shape linked"), "method", CLMConverter, &wr, this, CLM_D), attributes("Attributes linked", "Attributes linked, comma separated atributes", "attributes", &wr, this,""), - style_attributes("Style attributes linked", "Style attributes linked, comma separated atributes", "style_attributes", &wr, this,""), - expanded(false), - origin(Geom::Point(0,0)) + style_attributes("Style attributes linked", "Style attributes linked, comma separated attributes like fill, filter, opacity", "style_attributes", &wr, this,""), + allow_transforms(_("Alow transforms"), _("Alow transforms"), "allow_transforms", &wr, this, true) { //0.92 compatibility const gchar * linkedpath = this->getRepr()->attribute("linkedpath"); if (linkedpath && strcmp(linkedpath, "") != 0){ this->getRepr()->setAttribute("linkeditem", linkedpath); this->getRepr()->setAttribute("linkedpath", NULL); - this->getRepr()->setAttribute("transform", "false"); + this->getRepr()->setAttribute("method", "bsplinespiro"); + this->getRepr()->setAttribute("allow_transforms", "false"); }; - + is_updating = false; + listening = false; + linked = g_strdup(this->getRepr()->attribute("linkeditem")); registerParameter(&linkeditem); - registerParameter(&scale); + registerParameter(&method); registerParameter(&attributes); registerParameter(&style_attributes); - registerParameter(&preserve_position); - registerParameter(&inverse); - registerParameter(&d); - registerParameter(&transform); - registerParameter(&fill); - registerParameter(&stroke); - registerParameter(&paintorder); - registerParameter(&opacity); - registerParameter(&filter); - scale.param_set_range(0.01, 999999.0); - scale.param_set_increments(1, 1); - scale.param_set_digits(2); + registerParameter(&allow_transforms); + prev_allow_trans = allow_transforms; + previus_method = method; + prev_affine = g_strdup(""); attributes.param_hide_canvas_text(); style_attributes.param_hide_canvas_text(); - preserve_position_changed = preserve_position; - preserve_affine = Geom::identity(); } void -LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * attributes, const char * style_attributes, bool root) +LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, const char * attributes, const char * style_attributes) { SPDocument * document = SP_ACTIVE_DOCUMENT; - if (!document) { + if (!document || !origin || !dest) { return; } if ( SP_IS_GROUP(origin) && SP_IS_GROUP(dest) && SP_GROUP(origin)->getItemCount() == SP_GROUP(dest)->getItemCount() ) { @@ -79,7 +74,7 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co for (std::vector<SPObject * >::iterator obj_it = childs.begin(); obj_it != childs.end(); ++obj_it) { SPObject *dest_child = dest->nthChild(index); - cloneAttrbutes((*obj_it), dest_child, live, attributes, style_attributes, false); + cloneAttrbutes((*obj_it), dest_child, attributes, style_attributes); index++; } } @@ -97,7 +92,7 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co for ( std::vector<SPObject*>::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) { SPObject * mask_data = *iter; SPObject * mask_dest_data = mask_list_dest[i]; - cloneAttrbutes(mask_data, mask_dest_data, live, attributes, style_attributes, false); + cloneAttrbutes(mask_data, mask_dest_data, attributes, style_attributes); i++; } } @@ -112,86 +107,60 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co for ( std::vector<SPObject*>::const_iterator iter=clippath_list.begin();iter!=clippath_list.end();++iter) { SPObject * clippath_data = *iter; SPObject * clippath_dest_data = clippath_list_dest[i]; - cloneAttrbutes(clippath_data, clippath_dest_data, live, attributes, style_attributes, false); + cloneAttrbutes(clippath_data, clippath_dest_data, attributes, style_attributes); i++; } } } gchar ** attarray = g_strsplit(attributes, ",", 0); gchar ** iter = attarray; - Geom::Affine affine_dest = Geom::identity(); - Geom::Affine affine_origin = Geom::identity(); - Geom::Affine affine_previous = Geom::identity(); - sp_svg_transform_read(SP_ITEM(dest)->getAttribute("transform"), &affine_dest); - sp_svg_transform_read(SP_ITEM(origin)->getAttribute("transform"), &affine_origin); while (*iter != NULL) { const char* attribute = (*iter); - if ( std::strcmp(attribute, "transform") == 0 ) { - if (preserve_position) { - Geom::Affine dest_affine = Geom::identity(); - if (root) { - dest_affine *= affine_origin; - if (preserve_affine == Geom::identity()) { - dest_affine *= Geom::Translate(affine_dest.translation()); - } - dest_affine *= Geom::Translate(affine_origin.translation()).inverse(); - dest_affine *= Geom::Translate(preserve_affine.translation()); - affine_previous = preserve_affine; - preserve_affine = Geom::identity(); - gchar * str = sp_svg_transform_write(dest_affine); - SP_ITEM(dest)->getRepr()->setAttribute("transform", str); - g_free(str); - } - } else { - gchar * str = sp_svg_transform_write(affine_origin); - SP_ITEM(dest)->getRepr()->setAttribute("transform", str); - g_free(str); - } - } else if ( shape_dest && shape_origin && live && (std::strcmp(attribute, "d") == 0)) { - SPCurve *c = NULL; - if (inverse) { - c = shape_origin->getCurveBeforeLPE(); - } else { - c = shape_origin->getCurve(); - } - if (c) { - Geom::PathVector c_pv = c->get_pathvector(); - Geom::OptRect orig_bbox = SP_ITEM(origin)->geometricBounds(); - Geom::OptRect dest_bbox = SP_ITEM(dest)->geometricBounds(); - if (dest_bbox && orig_bbox && root) { - Geom::Point orig_point = (*orig_bbox).corner(0); - Geom::Point dest_point = (*dest_bbox).corner(0); - if (scale != 100.0) { - double scale_affine = scale/100.0; - Geom::Scale scale = Geom::Scale(scale_affine); - c_pv *= Geom::Translate(orig_point).inverse(); - c_pv *= scale; - c_pv *= Geom::Translate(orig_point); - } - if (preserve_position) { - c_pv *= Geom::Translate(dest_point - orig_point); + if (strlen(attribute)) { + if ( shape_dest && shape_origin && (std::strcmp(attribute, "d") == 0)) { + SPCurve *c = NULL; + if (method == CLM_BSPLINESPIRO) { + c = shape_origin->getCurveBeforeLPE(); + SPLPEItem * lpe_item = SP_LPE_ITEM(origin); + if (lpe_item) { + PathEffectList lpelist = lpe_item->getEffectList(); + PathEffectList::iterator i; + for (i = lpelist.begin(); i != lpelist.end(); ++i) { + LivePathEffectObject *lpeobj = (*i)->lpeobject; + if (lpeobj) { + Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe(); + if (dynamic_cast<Inkscape::LivePathEffect::LPEBSpline *>(lpe)) { + LivePathEffect::sp_bspline_do_effect(c, 0); + } else if (dynamic_cast<Inkscape::LivePathEffect::LPESpiro *>(lpe)) { + LivePathEffect::sp_spiro_do_effect(c); + } + } + } } - } - if (inverse) { - c_pv *= i2anc_affine(origin, sp_lpe_item); + } else if(method == CLM_ORIGINALD) { + c = shape_origin->getCurveBeforeLPE(); } else { - c_pv *= i2anc_affine(dest, sp_lpe_item); + c = shape_origin->getCurve(); } - c->set_pathvector(c_pv); - if (!path_origin) { - shape_dest->setCurveInsync(c, TRUE); - gchar *str = sp_svg_write_path(c_pv); - dest->getRepr()->setAttribute(attribute, str); - g_free(str); + if (c) { + Geom::PathVector c_pv = c->get_pathvector(); + c_pv *= i2anc_affine(dest, sp_lpe_item); + c->set_pathvector(c_pv); + if (!path_origin) { + shape_dest->setCurveInsync(c, TRUE); + gchar *str = sp_svg_write_path(c_pv); + dest->getRepr()->setAttribute(attribute, str); + g_free(str); + } else { + shape_dest->setCurve(c, TRUE); + } + c->unref(); } else { - shape_dest->setCurve(c, TRUE); + dest->getRepr()->setAttribute(attribute, NULL); } - c->unref(); } else { - dest->getRepr()->setAttribute(attribute, NULL); + dest->getRepr()->setAttribute(attribute, origin->getRepr()->attribute(attribute)); } - } else { - dest->getRepr()->setAttribute(attribute, origin->getRepr()->attribute(attribute)); } iter++; } @@ -204,157 +173,142 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co gchar ** styleiter = styleattarray; while (*styleiter != NULL) { const char* attribute = (*styleiter); - const char* origin_attribute = sp_repr_css_property(css_origin, attribute, ""); - if (!strlen(origin_attribute)) { //==0 - sp_repr_css_set_property (css_dest, attribute, NULL); - } else { - sp_repr_css_set_property (css_dest, attribute, origin_attribute); + if (strlen(attribute)) { + const char* origin_attribute = sp_repr_css_property(css_origin, attribute, ""); + if (!strlen(origin_attribute)) { //==0 + sp_repr_css_set_property (css_dest, attribute, NULL); + } else { + sp_repr_css_set_property (css_dest, attribute, origin_attribute); + } } styleiter++; } g_strfreev (styleattarray); Glib::ustring css_str; sp_repr_css_write_string(css_dest,css_str); - dest->getRepr()->setAttribute("style", css_str.c_str()); + dest->getRepr()->setAttribute("style", g_strdup(css_str.c_str())); } - void LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){ + start_listening(); if (linkeditem.linksToItem()) { - linkeditem.setInverse(inverse); - if ( preserve_position_changed != preserve_position ) { - if (!preserve_position) { - sp_svg_transform_read(SP_ITEM(sp_lpe_item)->getAttribute("transform"), &preserve_affine); - } - preserve_position_changed = preserve_position; - } Glib::ustring attr = ""; - if (d) { - attr.append("d,"); - } - if (transform) { - attr.append("transform,"); + if (method != CLM_NONE) { + attr += Glib::ustring("d,"); } - attr.append(Glib::ustring(attributes.param_getSVGValue()).append(",")); + attr += Glib::ustring(attributes.param_getSVGValue()) + Glib::ustring(","); if (attr.size() && !Glib::ustring(attributes.param_getSVGValue()).size()) { attr.erase (attr.size()-1, 1); } Glib::ustring style_attr = ""; - if (fill) { - style_attr.append("fill,").append("fill-rule,"); - } - if (stroke) { - style_attr.append("stroke,").append("stroke-width,").append("stroke-linecap,").append("stroke-linejoin,"); - style_attr.append("stroke-opacity,").append("stroke-miterlimit,").append("stroke-dasharray,"); - style_attr.append("stroke-opacity,").append("stroke-dashoffset,").append("marker-start,"); - style_attr.append("marker-mid,").append("marker-end,"); + if (style_attr.size() && !Glib::ustring(style_attributes.param_getSVGValue()).size()) { + style_attr.erase (style_attr.size()-1, 1); } - if (paintorder) { - style_attr.append("paint-order,"); + style_attr += Glib::ustring(style_attributes.param_getSVGValue()) + Glib::ustring(","); + + SPItem * orig = SP_ITEM(linkeditem.getObject()); + SPItem * dest = SP_ITEM(sp_lpe_item); + Geom::OptRect o_bbox = orig->geometricBounds(); + Geom::OptRect d_bbox = dest->geometricBounds(); + gchar * id = g_strdup(orig->getId()); + if (allow_transforms && + !linkeditem.last_transform.isIdentity() && + linkeditem.last_transform.isTranslation() && + method != CLM_NONE) + { + Geom::Point expansion_dest = dest->transform.expansion(); + Geom::Point expansion_orig = orig->transform.expansion(); + dest->transform *= Geom::Scale(expansion_dest).inverse(); + dest->transform *= Geom::Scale(expansion_orig); + dest->transform *= linkeditem.last_transform.inverse(); + dest->transform *= Geom::Scale(expansion_orig).inverse(); + dest->transform *= Geom::Scale(expansion_dest); } - if (filter) { - style_attr.append("filter,"); + if ((strcmp(id, linked) != 0 || (previus_method != method && previus_method == CLM_NONE )) && + allow_transforms && + o_bbox && + d_bbox) + { + dest->transform *= Geom::Translate((*o_bbox).corner(0) - (*d_bbox).corner(0)).inverse(); } - if (opacity) { - style_attr.append("opacity,"); + cloneAttrbutes(orig, dest, g_strdup(attr.c_str()), g_strdup(style_attr.c_str())); + if (allow_transforms && + previus_method != method && + method == CLM_NONE) + { + dest->transform *= Geom::Translate((*d_bbox).corner(0) - (*o_bbox).corner(0)).inverse(); } - if (style_attr.size() && !Glib::ustring(style_attributes.param_getSVGValue()).size()) { - style_attr.erase (style_attr.size()-1, 1); - } - style_attr.append(Glib::ustring(style_attributes.param_getSVGValue()).append(",")); - SPItem * from = inverse ? SP_ITEM(sp_lpe_item) : SP_ITEM(linkeditem.getObject()); - SPItem * to = !inverse ? SP_ITEM(sp_lpe_item) : SP_ITEM(linkeditem.getObject()); - cloneAttrbutes(from, to, true, g_strdup(attr.c_str()), g_strdup(style_attr.c_str()), true); - Geom::OptRect bbox = from->geometricBounds(); - if (bbox && preserve_position && origin != Geom::Point(0,0)) { - origin = (*bbox).corner(0) - origin; - to->transform *= Geom::Translate(origin); + if (!allow_transforms) { + SP_ITEM(dest)->getRepr()->setAttribute("transform", SP_ITEM(orig)->getAttribute("transform")); + } else { + SP_ITEM(dest)->getRepr()->setAttribute("transform", sp_svg_transform_write(dest->transform)); + if (prev_allow_trans == allow_transforms) { + prev_affine = g_strdup(SP_ITEM(dest)->getAttribute("transform")); + } } - bbox = from->geometricBounds(); - if (bbox && preserve_position) { - origin = (*bbox).corner(0); + + if (prev_allow_trans != allow_transforms && allow_transforms) { + SP_ITEM(dest)->getRepr()->setAttribute("transform", prev_affine); } + + linked = g_strdup(id); + g_free(id); + } else { + linked = g_strdup(""); } + previus_method = method; + prev_allow_trans = allow_transforms; } - -Gtk::Widget * -LPECloneOriginal::newWidget() +void +LPECloneOriginal::start_listening() { - // use manage here, because after deletion of Effect object, others might - // still be pointing to this widget. - Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget())); - vbox->set_border_width(5); - vbox->set_homogeneous(false); - vbox->set_spacing(2); - Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); - vbox_expander->set_border_width(0); - vbox_expander->set_spacing(2); - std::vector<Parameter *>::iterator it = param_vector.begin(); - while (it != param_vector.end()) { - if ((*it)->widget_is_visible) { - Parameter * param = *it; - if (param->param_key == "linkedpath") { - ++it; - continue; - } - Gtk::Widget * widg = param->param_newWidget(); - Glib::ustring * tip = param->param_getTooltip(); - if (widg) { - if (param->param_key != "attributes" && - param->param_key != "style_attributes") { - vbox->pack_start(*widg, true, true, 2); - } else { - vbox_expander->pack_start(*widg, true, true, 2); - } - if (tip) { - widg->set_tooltip_text(*tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); - } - } - } - - ++it; + if ( !sp_lpe_item || listening ) { + return; } - expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show attributes override")))); - expander->add(*vbox_expander); - expander->set_expanded(expanded); - expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPECloneOriginal::onExpanderChanged) ); - vbox->pack_start(*expander, true, true, 2); - return dynamic_cast<Gtk::Widget *>(vbox); + quit_listening(); + modified_connection = SP_OBJECT(sp_lpe_item)->connectModified(sigc::mem_fun(*this, &LPECloneOriginal::modified)); + listening = true; } void -LPECloneOriginal::onExpanderChanged() +LPECloneOriginal::quit_listening(void) { - expanded = expander->get_expanded(); - if(expanded) { - expander->set_label (Glib::ustring(_("Hide attributes override"))); - } else { - expander->set_label (Glib::ustring(_("Show attributes override"))); + modified_connection.disconnect(); + listening = false; +} + +void +LPECloneOriginal::modified(SPObject */*obj*/, guint /*flags*/) +{ + if ( !sp_lpe_item || is_updating) { + is_updating = false; + return; } + SP_OBJECT(this->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); + is_updating = true; } LPECloneOriginal::~LPECloneOriginal() { - + quit_listening(); + g_free(linked); + g_free(prev_affine); } void LPECloneOriginal::transform_multiply(Geom::Affine const& postmul, bool set) { - if (linkeditem.linksToItem()) { - linkeditem.getObject()->requestModified(SP_OBJECT_MODIFIED_FLAG); + if (!allow_transforms && linkeditem.linksToItem()) { + sp_lpe_item->transform *= postmul.inverse(); } } void LPECloneOriginal::doEffect (SPCurve * curve) { - if (linkeditem.linksToItem() && !inverse) { + if (linkeditem.linksToItem()) { SPShape * shape = getCurrentShape(); if(shape){ curve->set_pathvector(shape->getCurve()->get_pathvector()); diff --git a/src/live_effects/lpe-clone-original.h b/src/live_effects/lpe-clone-original.h index 9bab8553f..8327b6767 100644 --- a/src/live_effects/lpe-clone-original.h +++ b/src/live_effects/lpe-clone-original.h @@ -8,18 +8,25 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <gtkmm/expander.h> #include "live_effects/effect.h" +#include "live_effects/parameter/enum.h" #include "live_effects/parameter/originalitem.h" -#include "live_effects/parameter/originalpath.h" -#include "live_effects/parameter/parameter.h" -#include "live_effects/parameter/point.h" #include "live_effects/parameter/text.h" #include "live_effects/lpegroupbbox.h" +#include <sigc++/sigc++.h> + namespace Inkscape { namespace LivePathEffect { +enum Clonelpemethod { + CLM_NONE, + CLM_ORIGINALD, + CLM_BSPLINESPIRO, + CLM_D, + CLM_END +}; + class LPECloneOriginal : public Effect, GroupBBoxEffect { public: LPECloneOriginal(LivePathEffectObject *lpeobject); @@ -27,29 +34,24 @@ public: virtual void doEffect (SPCurve * curve); virtual void doBeforeEffect (SPLPEItem const* lpeitem); virtual void transform_multiply(Geom::Affine const& postmul, bool set); - virtual Gtk::Widget * newWidget(); - void onExpanderChanged(); - void cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * attributes, const char * style_attributes, bool root); + void cloneAttrbutes(SPObject *origin, SPObject *dest, const char * attributes, const char * style_attributes); + void modified(SPObject */*obj*/, guint /*flags*/); + void start_listening(); + void quit_listening(); private: - OriginalItemParam linkeditem; - ScalarParam scale; - BoolParam preserve_position; - BoolParam inverse; - BoolParam d; - BoolParam transform; - BoolParam fill; - BoolParam stroke; - BoolParam paintorder; - BoolParam opacity; - BoolParam filter; + OriginalItemParam linkeditem; + EnumParam<Clonelpemethod> method; TextParam attributes; TextParam style_attributes; - Geom::Point origin; - bool preserve_position_changed; - bool expanded; - Gtk::Expander * expander; - Geom::Affine preserve_affine; + BoolParam allow_transforms; + gchar * linked; + Clonelpemethod previus_method; + bool listening; + bool is_updating; + bool prev_allow_trans; + gchar * prev_affine; + sigc::connection modified_connection; LPECloneOriginal(const LPECloneOriginal&); LPECloneOriginal& operator=(const LPECloneOriginal&); }; diff --git a/src/live_effects/lpe-fill-between-many.cpp b/src/live_effects/lpe-fill-between-many.cpp index 40fa91c68..7e2131f76 100644 --- a/src/live_effects/lpe-fill-between-many.cpp +++ b/src/live_effects/lpe-fill-between-many.cpp @@ -6,10 +6,14 @@ #include "live_effects/lpe-fill-between-many.h" - +#include "live_effects/lpeobject.h" +#include "xml/node.h" #include "display/curve.h" +#include "inkscape.h" +#include "selection.h" #include "sp-shape.h" #include "sp-text.h" +#include "sp-defs.h" #include "svg/svg.h" // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> @@ -17,20 +21,31 @@ namespace Inkscape { namespace LivePathEffect { +static const Util::EnumData<Filllpemethod> FilllpemethodData[] = { + { FLM_ORIGINALD, N_("Without LPE's"), "originald" }, + { FLM_BSPLINESPIRO, N_("With Spiro or BSpline"), "bsplinespiro" }, + { FLM_D, N_("With LPE's"), "d" } +}; +static const Util::EnumDataConverter<Filllpemethod> FLMConverter(FilllpemethodData, FLM_END); + LPEFillBetweenMany::LPEFillBetweenMany(LivePathEffectObject *lpeobject) : Effect(lpeobject), linked_paths(_("Linked path:"), _("Paths from which to take the original path data"), "linkedpaths", &wr, this), + method(_("LPE's on linked:"), _("LPE's on linked"), "method", FLMConverter, &wr, this, FLM_BSPLINESPIRO), fuse(_("Fuse coincident points"), _("Fuse coincident points"), "fuse", &wr, this, false), allow_transforms(_("Allow transforms"), _("Allow transforms"), "allow_transforms", &wr, this, false), join(_("Join subpaths"), _("Join subpaths"), "join", &wr, this, true), - close(_("Close"), _("Close path"), "close", &wr, this, true) + close(_("Close"), _("Close path"), "close", &wr, this, true), + applied("Store the first apply", "", "applied", &wr, this, "false", false) { registerParameter(&linked_paths); + registerParameter(&method); registerParameter(&fuse); registerParameter(&allow_transforms); registerParameter(&join); registerParameter(&close); - transformmultiply = false; + registerParameter(&applied); + previous_method = FLM_END; } LPEFillBetweenMany::~LPEFillBetweenMany() @@ -38,13 +53,73 @@ LPEFillBetweenMany::~LPEFillBetweenMany() } +void LPEFillBetweenMany::doOnApply (SPLPEItem const* lpeitem) +{ + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return; + } + SPLPEItem *lpe_item = const_cast<SPLPEItem *>(lpeitem); + SPObject * parent = lpe_item->parent; + if (lpe_item) { + SPShape *shape = dynamic_cast<SPShape *>(lpe_item); + if (shape) { + Inkscape::SVGOStringStream os; + if (strcmp(this->lpeobj->getRepr()->attribute("applied"), "false") == 0) { + os << '#' << SP_ITEM(lpe_item)->getId() << ",0,1"; + + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + // create the LPE + Inkscape::XML::Node *lpe_repr = xml_doc->createElement("inkscape:path-effect"); + { + lpe_repr->setAttribute("effect", "fill_between_many"); + lpe_repr->setAttribute("linkedpaths", os.str()); + lpe_repr->setAttribute("applied", "true"); + lpe_repr->setAttribute("method", "partial"); + lpe_repr->setAttribute("allow_transforms", "false"); + document->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to <defs> and assigns the 'id' attribute + } + std::string lpe_id_href = std::string("#") + lpe_repr->attribute("id"); + Inkscape::GC::release(lpe_repr); + Inkscape::XML::Node *clone = xml_doc->createElement("svg:path"); + { + clone->setAttribute("d", "M 0 0", false); + // add the new clone to the top of the original's parent + parent->appendChildRepr(clone); + SPObject *clone_obj = document->getObjectById(clone->attribute("id")); + SPLPEItem *clone_lpeitem = dynamic_cast<SPLPEItem *>(clone_obj); + if (clone_lpeitem) { + clone_lpeitem->addPathEffect(lpe_id_href, false); + } + } + Inkscape::Selection * sel = SP_ACTIVE_DESKTOP->getSelection(); + sel->set(clone); + Inkscape::GC::release(clone); + lpe_item->removeCurrentPathEffect(false); + } + } + } +} + void LPEFillBetweenMany::doEffect (SPCurve * curve) { + if (previous_method != method) { + if (method == FLM_BSPLINESPIRO) { + linked_paths.allowOnlyBsplineSpiro(true); + linked_paths.setFromOriginalD(false); + } else if(method == FLM_ORIGINALD) { + linked_paths.allowOnlyBsplineSpiro(false); + linked_paths.setFromOriginalD(true); + } else { + linked_paths.allowOnlyBsplineSpiro(false); + linked_paths.setFromOriginalD(false); + } + previous_method = method; + } Geom::PathVector res_pathv; - SPItem * firstObj = NULL; - for (std::vector<PathAndDirection*>::iterator iter = linked_paths._vector.begin(); iter != linked_paths._vector.end(); ++iter) { + for (std::vector<PathAndDirectionAndVisible*>::iterator iter = linked_paths._vector.begin(); iter != linked_paths._vector.end(); ++iter) { SPObject *obj; - if ((*iter)->ref.isAttached() && (obj = (*iter)->ref.getObject()) && SP_IS_ITEM(obj) && !(*iter)->_pathvector.empty()) { + if ((*iter)->ref.isAttached() && (obj = (*iter)->ref.getObject()) && SP_IS_ITEM(obj) && !(*iter)->_pathvector.empty() && (*iter)->visibled) { Geom::Path linked_path; if ((*iter)->reversed) { linked_path = (*iter)->_pathvector.front().reversed(); @@ -53,36 +128,43 @@ void LPEFillBetweenMany::doEffect (SPCurve * curve) } if (!res_pathv.empty() && join) { - linked_path = linked_path * SP_ITEM(obj)->getRelativeTransform(firstObj); if (!are_near(res_pathv.front().finalPoint(), linked_path.initialPoint(), 0.01) || !fuse) { res_pathv.front().appendNew<Geom::LineSegment>(linked_path.initialPoint()); } else { linked_path.setInitial(res_pathv.front().finalPoint()); } + if(!allow_transforms) { + Geom::Affine affine = Geom::identity(); + sp_svg_transform_read(SP_ITEM(obj)->getAttribute("transform"), &affine); + linked_path *= affine; + } res_pathv.front().append(linked_path); } else { - firstObj = SP_ITEM(obj); if (close && !join) { linked_path.close(); } + if(!allow_transforms) { + Geom::Affine affine = Geom::identity(); + sp_svg_transform_read(SP_ITEM(obj)->getAttribute("transform"), &affine); + linked_path *= affine; + } res_pathv.push_back(linked_path); } } } + + if(!allow_transforms && sp_lpe_item) { + SP_ITEM(sp_lpe_item)->transform = Geom::identity(); + } + if (!res_pathv.empty() && close) { res_pathv.front().close(); } + if (res_pathv.empty()) { res_pathv = curve->get_pathvector(); } - if(!allow_transforms && !transformmultiply) { - Geom::Affine affine = Geom::identity(); - sp_svg_transform_read(SP_ITEM(sp_lpe_item)->getAttribute("transform"), &affine); - res_pathv *= affine.inverse(); - } - if(transformmultiply) { - transformmultiply = false; - } + curve->set_pathvector(res_pathv); } @@ -91,8 +173,6 @@ LPEFillBetweenMany::transform_multiply(Geom::Affine const& postmul, bool set) { if(!allow_transforms && sp_lpe_item) { SP_ITEM(sp_lpe_item)->transform *= postmul.inverse(); - transformmultiply = true; - sp_lpe_item_update_patheffect(sp_lpe_item, false, false); } } diff --git a/src/live_effects/lpe-fill-between-many.h b/src/live_effects/lpe-fill-between-many.h index fe824e936..7ff998309 100644 --- a/src/live_effects/lpe-fill-between-many.h +++ b/src/live_effects/lpe-fill-between-many.h @@ -10,25 +10,37 @@ */ #include "live_effects/effect.h" +#include "live_effects/parameter/enum.h" #include "live_effects/parameter/originalpatharray.h" +#include "live_effects/parameter/hidden.h" namespace Inkscape { namespace LivePathEffect { +enum Filllpemethod { + FLM_ORIGINALD, + FLM_BSPLINESPIRO, + FLM_D, + FLM_END +}; + class LPEFillBetweenMany : public Effect { public: LPEFillBetweenMany(LivePathEffectObject *lpeobject); virtual ~LPEFillBetweenMany(); + virtual void doOnApply (SPLPEItem const* lpeitem); virtual void transform_multiply(Geom::Affine const& postmul, bool set); virtual void doEffect (SPCurve * curve); private: OriginalPathArrayParam linked_paths; + EnumParam<Filllpemethod> method; BoolParam fuse; BoolParam allow_transforms; BoolParam join; BoolParam close; - bool transformmultiply; + HiddenParam applied; + Filllpemethod previous_method; private: LPEFillBetweenMany(const LPEFillBetweenMany&); LPEFillBetweenMany& operator=(const LPEFillBetweenMany&); diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index be5979f31..2b052ace1 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -98,14 +98,12 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) Geom::PathVector const pathv = pathv_to_linear_and_cubic_beziers(shape->getCurve()->get_pathvector()); Satellites satellites; double power = radius; - std::cout << power << "power\n"; if (!flexible) { SPDocument * document = SP_ACTIVE_DOCUMENT; SPNamedView *nv = sp_document_namedview(document, NULL); Glib::ustring display_unit = nv->display_units->abbr; power = Inkscape::Util::Quantity::convert(power, unit.get_abbreviation(), display_unit.c_str()); } - std::cout << power << "power22222222\n"; SatelliteType satellite_type = FILLET; std::map<std::string, SatelliteType> gchar_map_to_satellite_type = boost::assign::map_list_of("F", FILLET)("IF", INVERSE_FILLET)("C", CHAMFER)("IC", INVERSE_CHAMFER)("KO", INVALID_SATELLITE); diff --git a/src/live_effects/lpe-interpolate_points.cpp b/src/live_effects/lpe-interpolate_points.cpp index 0a0bcea14..7d4c88dc1 100644 --- a/src/live_effects/lpe-interpolate_points.cpp +++ b/src/live_effects/lpe-interpolate_points.cpp @@ -51,11 +51,7 @@ Geom::PathVector LPEInterpolatePoints::doEffect_path (Geom::PathVector const & path_in) { Geom::PathVector path_out; -#if __cplusplus <= 199711L - std::auto_ptr<Geom::Interpolate::Interpolator> interpolator( Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value())) ); -#else std::unique_ptr<Geom::Interpolate::Interpolator> interpolator( Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value())) ); -#endif for(Geom::PathVector::const_iterator path_it = path_in.begin(); path_it != path_in.end(); ++path_it) { if (path_it->empty()) diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp index 261612fdb..22c548c1d 100644 --- a/src/live_effects/lpe-knot.cpp +++ b/src/live_effects/lpe-knot.cpp @@ -199,7 +199,7 @@ CrossingPoints::CrossingPoints(Geom::PathVector const &paths) : std::vector<Cros cp.tj = times[k].second + jj; push_back(cp); }else{ - std::cout<<"ooops: find_(self)_intersections returned NaN:"; + std::cout<<"ooops: find_(self)_intersections returned NaN:" << std::endl; //std::cout<<"intersection "<<i<<"["<<ii<<"](NaN)= "<<j<<"["<<jj<<"](NaN)\n"; } } diff --git a/src/live_effects/lpe-measure-segments.cpp b/src/live_effects/lpe-measure-segments.cpp index 2ac40b580..5ed587922 100644 --- a/src/live_effects/lpe-measure-segments.cpp +++ b/src/live_effects/lpe-measure-segments.cpp @@ -9,6 +9,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ #include "live_effects/lpe-measure-segments.h" +#include "live_effects/lpeobject.h" #include <pangomm/fontdescription.h> #include "ui/dialog/livepatheffect-editor.h" #include <libnrtype/font-lister.h> @@ -30,7 +31,10 @@ #include "sp-item.h" #include "sp-shape.h" #include "sp-path.h" +#include "sp-star.h" +#include "sp-spiral.h" #include "document.h" +#include "document-undo.h" #include <iomanip> #include <cmath> @@ -50,17 +54,19 @@ static const Util::EnumDataConverter<OrientationMethod> OMConverter(OrientationM LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) : Effect(lpeobject), - unit(_("Unit"), _("Unit"), "unit", &wr, this, "px"), - fontbutton(_("Font"), _("Font Selector"), "fontbutton", &wr, this), + unit(_("Unit"), _("Unit"), "unit", &wr, this, "mm"), orientation(_("Orientation"), _("Orientation method"), "orientation", OMConverter, &wr, this, OM_PARALLEL, false), + coloropacity(_("Color and opacity"), _("Set color and opacity of the measurements"), "coloropacity", &wr, this, 0x000000ff), + fontbutton(_("Font"), _("Font Selector"), "fontbutton", &wr, this), precision(_("Precision"), _("Precision"), "precision", &wr, this, 2), fix_overlaps(_("Fix overlaps °"), _("Min angle where overlaps are fixed, 180° no fix"), "fix_overlaps", &wr, this, 0), position(_("Position"), _("Position"), "position", &wr, this, 5), text_top_bottom(_("Text top/bottom"), _("Text top/bottom"), "text_top_bottom", &wr, this, 0), - text_right_left(_("Text right/left"), _("Text right/left"), "text_right_left", &wr, this, 0), helpline_distance(_("Helpline distance"), _("Helpline distance"), "helpline_distance", &wr, this, 0.0), helpline_overlap(_("Helpline overlap"), _("Helpline overlap"), "helpline_overlap", &wr, this, 2.0), + line_width(_("Line width"), _("Line width. DIM line group standard are 0.25 or 0.35"), "line_width", &wr, this, 0.25), scale(_("Scale"), _("Scaling factor"), "scale", &wr, this, 1.0), + format(_("Format"), _("Format the number ex:{measure} {unit}, return to save"), "format", &wr, this,"{measure}{unit}"), blacklist(_("Blacklist"), _("Optional segment index that exclude measure, comma limited, you can add more LPE like this to fill the holes"), "blacklist", &wr, this,""), whitelist(_("Inverse blacklist"), _("Blacklist as whitelist"), "whitelist", &wr, this, false), @@ -68,26 +74,22 @@ LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) : flip_side(_("Flip side"), _("Flip side"), "flip_side", &wr, this, false), scale_sensitive(_("Scale sensitive"), _("Costrained scale sensitive to transformed containers"), "scale_sensitive", &wr, this, true), local_locale(_("Local Number Format"), _("Local number format"), "local_locale", &wr, this, true), - line_group_05(_("Line Group 0.5"), _("Line Group 0.5, from 0.7"), "line_group_05", &wr, this, true), rotate_anotation(_("Rotate Anotation"), _("Rotate Anotation"), "rotate_anotation", &wr, this, true), hide_back(_("Hide if label over"), _("Hide DIN line if label over"), "hide_back", &wr, this, true), - dimline_format(_("CSS DIN line"), _("Override CSS to DIN line, return to save, empty to reset to DIM"), "dimline_format", &wr, this,""), - helperlines_format(_("CSS helpers"), _("Override CSS to helper lines, return to save, empty to reset to DIM"), "helperlines_format", &wr, this,""), - anotation_format(_("CSS anotation"), _("Override CSS to anotation text, return to save, empty to reset to DIM"), "anotation_format", &wr, this,""), - arrows_format(_("CSS arrows"), _("Override CSS to arrows, return to save, empty to reset DIM"), "arrows_format", &wr, this,""), - expanded(false) + message(_("Info Box"), _("Important messages"), "message", &wr, this, _("Use <b>\"Style Dialog\"</b> to more styling. Each meassure element has extra selectors. Use !important to override defaults...")) { //set to true the parameters you want to be changed his default values registerParameter(&unit); - registerParameter(&fontbutton); registerParameter(&orientation); + registerParameter(&coloropacity); + registerParameter(&fontbutton); registerParameter(&precision); registerParameter(&fix_overlaps); registerParameter(&position); registerParameter(&text_top_bottom); - registerParameter(&text_right_left); registerParameter(&helpline_distance); registerParameter(&helpline_overlap); + registerParameter(&line_width); registerParameter(&scale); registerParameter(&format); registerParameter(&blacklist); @@ -96,13 +98,9 @@ LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) : registerParameter(&flip_side); registerParameter(&scale_sensitive); registerParameter(&local_locale); - registerParameter(&line_group_05); registerParameter(&rotate_anotation); registerParameter(&hide_back); - registerParameter(&dimline_format); - registerParameter(&helperlines_format); - registerParameter(&anotation_format); - registerParameter(&arrows_format); + registerParameter(&message); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -114,10 +112,6 @@ LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) : format.param_hide_canvas_text(); blacklist.param_hide_canvas_text(); - dimline_format.param_hide_canvas_text(); - helperlines_format.param_hide_canvas_text(); - anotation_format.param_hide_canvas_text(); - arrows_format.param_hide_canvas_text(); precision.param_set_range(0, 100); precision.param_set_increments(1, 1); precision.param_set_digits(0); @@ -135,15 +129,16 @@ LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) : text_top_bottom.param_set_range(-999999.0, 999999.0); text_top_bottom.param_set_increments(1, 1); text_top_bottom.param_set_digits(2); - text_right_left.param_set_range(-999999.0, 999999.0); - text_right_left.param_set_increments(1, 1); - text_right_left.param_set_digits(2); + line_width.param_set_range(-999999.0, 999999.0); + line_width.param_set_increments(1, 1); + line_width.param_set_digits(2); helpline_distance.param_set_range(-999999.0, 999999.0); helpline_distance.param_set_increments(1, 1); helpline_distance.param_set_digits(2); helpline_overlap.param_set_range(-999999.0, 999999.0); helpline_overlap.param_set_increments(1, 1); helpline_overlap.param_set_digits(2); + star_ellipse_fix = Geom::identity(); } LPEMeasureSegments::~LPEMeasureSegments() {} @@ -155,6 +150,14 @@ LPEMeasureSegments::createArrowMarker(const char * mode) if (!document) { return; } + Glib::ustring style; + gchar c[32]; + unsigned const rgb24 = coloropacity.get_value() >> 8; + sprintf(c, "#%06x", rgb24); + style = Glib::ustring("fill:") + Glib::ustring(c); + Inkscape::SVGOStringStream os; + os << SP_RGBA32_A_F(coloropacity.get_value()); + style = style + Glib::ustring(";fill-opacity:") + Glib::ustring(os.str()); Inkscape::XML::Document *xml_doc = document->getReprDoc(); SPObject *elemref = NULL; Inkscape::XML::Node *arrow = NULL; @@ -165,24 +168,19 @@ LPEMeasureSegments::createArrowMarker(const char * mode) arrow->setAttribute("transform", NULL); Inkscape::XML::Node *arrow_data = arrow->firstChild(); if (arrow_data) { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property (css, "fill","#000000"); - sp_repr_css_set_property (css, "stroke","none"); arrow_data->setAttribute("transform", NULL); - sp_repr_css_attr_add_from_string(css, arrows_format.param_getSVGValue()); - Glib::ustring css_str; - sp_repr_css_write_string(css,css_str); - arrow_data->setAttribute("style", css_str.c_str()); + arrow_data->setAttribute("style", style.c_str()); } } } else { arrow = xml_doc->createElement("svg:marker"); arrow->setAttribute("id", mode); + arrow->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-arrows-marker")).c_str()); arrow->setAttribute("inkscape:stockid", mode); arrow->setAttribute("orient", "auto"); arrow->setAttribute("refX", "0.0"); arrow->setAttribute("refY", "0.0"); - arrow->setAttribute("style", "overflow:visible"); + arrow->setAttribute("sodipodi:insensitive", "true"); /* Create <path> */ Inkscape::XML::Node *arrow_path = xml_doc->createElement("svg:path"); @@ -193,17 +191,11 @@ LPEMeasureSegments::createArrowMarker(const char * mode) } else if (std::strcmp(mode, "ArrowDINout-start") == 0) { arrow_path->setAttribute("d", "M 0,0 -16,2.11 -16,0.5 -26,0.5 -26,-0.5 -16,-0.5 -16,-2.11 z"); } else { - arrow_path->setAttribute("d", "M 0,0 16,2.11 16,0.5 26,0.5 26,-0.5 16,-0.5 16,-2.11 z"); + arrow_path->setAttribute("d", "M 0,0 16,-2.11 16,-0.5 26,-0.5 26,0.5 16,0.5 16,2.11 z"); } - + arrow_path->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-arrows")).c_str()); arrow_path->setAttribute("id", Glib::ustring(mode).append("_path").c_str()); - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property (css, "fill","#000000"); - sp_repr_css_set_property (css, "stroke","none"); - sp_repr_css_attr_add_from_string(css, arrows_format.param_getSVGValue()); - Glib::ustring css_str; - sp_repr_css_write_string(css,css_str); - arrow_path->setAttribute("style", css_str.c_str()); + arrow_path->setAttribute("style", style.c_str()); arrow->addChild(arrow_path, NULL); Inkscape::GC::release(arrow_path); elemref = SP_OBJECT(document->getDefs()->appendChildRepr(arrow)); @@ -243,7 +235,6 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng elemref->deleteObject(); return; } - pos = pos - Point::polar(angle, text_right_left); rtext = elemref->getRepr(); sp_repr_set_svg_double(rtext, "x", pos[Geom::X]); sp_repr_set_svg_double(rtext, "y", pos[Geom::Y]); @@ -256,8 +247,8 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng rtext = xml_doc->createElement("svg:text"); rtext->setAttribute("xml:space", "preserve"); rtext->setAttribute("id", id); + rtext->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-labels")).c_str()); rtext->setAttribute("sodipodi:insensitive", "true"); - pos = pos - Point::polar(angle, text_right_left); sp_repr_set_svg_double(rtext, "x", pos[Geom::X]); sp_repr_set_svg_double(rtext, "y", pos[Geom::Y]); rtspan = xml_doc->createElement("svg:tspan"); @@ -281,27 +272,25 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng rtext->setAttribute("transform", transform); g_free(transform); SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_attr_add_from_string(css, anotation_format.param_getSVGValue()); Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance(); fontlister->fill_css(css, Glib::ustring(fontbutton.param_getSVGValue())); std::stringstream font_size; font_size.imbue(std::locale::classic()); font_size << fontsize << "pt"; - sp_repr_css_set_property (css, "font-size",font_size.str().c_str()); - sp_repr_css_set_property (css, "line-height","125%"); - sp_repr_css_set_property (css, "letter-spacing","0"); - sp_repr_css_set_property (css, "word-spacing", "0"); - sp_repr_css_set_property (css, "text-align", "center"); - sp_repr_css_set_property (css, "text-anchor", "middle"); - sp_repr_css_set_property (css, "fill", "#000000"); - sp_repr_css_set_property (css, "fill-opacity", "1"); - sp_repr_css_set_property (css, "stroke", "none"); - sp_repr_css_attr_add_from_string(css, anotation_format.param_getSVGValue()); - Glib::ustring css_str; - sp_repr_css_write_string(css,css_str); + + gchar c[32]; + unsigned const rgb24 = coloropacity.get_value() >> 8; + sprintf(c, "#%06x", rgb24); + sp_repr_css_set_property (css, "fill",c); + Inkscape::SVGOStringStream os; + os << SP_RGBA32_A_F(coloropacity.get_value()); + sp_repr_css_set_property (css, "fill-opacity",os.str().c_str()); if (!rtspan) { rtspan = rtext->firstChild(); } + sp_repr_css_set_property (css, "font-size",font_size.str().c_str()); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); rtext->setAttribute("style", css_str.c_str()); rtspan->setAttribute("style", NULL); rtspan->setAttribute("transform", NULL); @@ -362,7 +351,7 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng } void -LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool overflow, bool remove, bool arrows) +LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool remove, bool arrows) { SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { @@ -378,8 +367,11 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i end = end + Point::polar(angle, helpline_overlap ); } Geom::PathVector line_pathv; - if (main && std::abs(text_top_bottom) < fontsize/1.5 && hide_back && !overflow){ - Geom::Path line_path; + + if (main && + std::abs(text_top_bottom) < fontsize/1.5 && + hide_back) + { double k = 0; if (flip_side) { k = (Geom::distance(start,end)/2.0) + arrow_gap - (anotation_width/2.0); @@ -397,7 +389,7 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i //k = std::max(k , arrow_gap -1); Geom::Ray ray(end, start); Geom::Coord angle = ray.angle(); - line_path.start(start); + Geom::Path line_path(start); line_path.appendNew<Geom::LineSegment>(start - Point::polar(angle, k)); line_pathv.push_back(line_path); line_path.clear(); @@ -405,8 +397,7 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i line_path.appendNew<Geom::LineSegment>(end); line_pathv.push_back(line_path); } else { - Geom::Path line_path; - line_path.start(start); + Geom::Path line_path(start); line_path.appendNew<Geom::LineSegment>(end); line_pathv.push_back(line_path); } @@ -427,6 +418,11 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i } line = xml_doc->createElement("svg:path"); line->setAttribute("id", id); + if (main) { + line->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-DIM-lines measure-lines")).c_str()); + } else { + line->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-helper-lines measure-lines")).c_str()); + } gchar * line_str = sp_svg_write_path( line_pathv ); line->setAttribute("d" , line_str); g_free(line_str); @@ -434,10 +430,8 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i line->setAttribute("sodipodi:insensitive", "true"); line_pathv.clear(); - Glib::ustring style = Glib::ustring("stroke:#000000;fill:none;"); - if (overflow && !arrows) { - line->setAttribute("inkscape:label", "downline"); - } else if (main) { + Glib::ustring style; + if (main) { line->setAttribute("inkscape:label", "dinline"); if (arrows_outside) { style = style + Glib::ustring("marker-start:url(#ArrowDINout-start);marker-end:url(#ArrowDINout-end);"); @@ -449,22 +443,18 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i } std::stringstream stroke_w; stroke_w.imbue(std::locale::classic()); - if (line_group_05) { - double stroke_width = Inkscape::Util::Quantity::convert(0.25 / doc_scale, "mm", display_unit.c_str()); - stroke_w << stroke_width; - style = style + Glib::ustring("stroke-width:" + stroke_w.str()); - } else { - double stroke_width = Inkscape::Util::Quantity::convert(0.35 / doc_scale, "mm", display_unit.c_str()); - stroke_w << stroke_width; - style = style + Glib::ustring("stroke-width:" + stroke_w.str()); - } + double stroke_width = Inkscape::Util::Quantity::convert(line_width / doc_scale, "mm", display_unit.c_str()); + stroke_w << stroke_width; + style = style + Glib::ustring("stroke-width:" + stroke_w.str()); + gchar c[32]; + unsigned const rgb24 = coloropacity.get_value() >> 8; + sprintf(c, "#%06x", rgb24); + style = style + Glib::ustring(";stroke:") + Glib::ustring(c); + Inkscape::SVGOStringStream os; + os << SP_RGBA32_A_F(coloropacity.get_value()); + style = style + Glib::ustring(";stroke-opacity:") + Glib::ustring(os.str()); SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_attr_add_from_string(css, style.c_str()); - if (main) { - sp_repr_css_attr_add_from_string(css, dimline_format.param_getSVGValue()); - } else { - sp_repr_css_attr_add_from_string(css, helperlines_format.param_getSVGValue()); - } Glib::ustring css_str; sp_repr_css_write_string(css,css_str); line->setAttribute("style", css_str.c_str()); @@ -489,7 +479,54 @@ LPEMeasureSegments::doOnApply(SPLPEItem const* lpeitem) g_warning("LPE measure line can only be applied to shapes (not groups)."); SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); item->removeCurrentPathEffect(false); + return; + } + SPDocument *document = SP_ACTIVE_DOCUMENT; + bool saved = DocumentUndo::getUndoSensitive(document); + DocumentUndo::setUndoSensitive(document, false); + Inkscape::XML::Node *styleNode = NULL; + Inkscape::XML::Node* textNode = NULL; + Inkscape::XML::Node *root = SP_ACTIVE_DOCUMENT->getReprRoot(); + for (unsigned i = 0; i < root->childCount(); ++i) { + if (Glib::ustring(root->nthChild(i)->name()) == "svg:style") { + + styleNode = root->nthChild(i); + + for (unsigned j = 0; j < styleNode->childCount(); ++j) { + if (styleNode->nthChild(j)->type() == Inkscape::XML::TEXT_NODE) { + textNode = styleNode->nthChild(j); + } + } + + if (textNode == NULL) { + // Style element found but does not contain text node! + std::cerr << "StyleDialog::_getStyleTextNode(): No text node!" << std::endl; + textNode = SP_ACTIVE_DOCUMENT->getReprDoc()->createTextNode(""); + styleNode->appendChild(textNode); + Inkscape::GC::release(textNode); + } + } + } + + if (styleNode == NULL) { + // Style element not found, create one + styleNode = SP_ACTIVE_DOCUMENT->getReprDoc()->createElement("svg:style"); + textNode = SP_ACTIVE_DOCUMENT->getReprDoc()->createTextNode(""); + + styleNode->appendChild(textNode); + Inkscape::GC::release(textNode); + + root->addChild(styleNode, NULL); + Inkscape::GC::release(styleNode); } + Glib::ustring styleContent = Glib::ustring(textNode->content()); + if (styleContent.find(".measure-arrows\n{\n") == -1) { + styleContent = styleContent + Glib::ustring("\n.measure-arrows") + Glib::ustring("\n{\n}"); + styleContent = styleContent + Glib::ustring("\n.measure-labels") + Glib::ustring("\n{\nline-height:125%;\nletter-spacing:0;\nword-spacing:0;\ntext-align:center;\ntext-anchor:middle;\nstroke:none;\n}"); + styleContent = styleContent + Glib::ustring("\n.measure-lines") + Glib::ustring("\n{\n}"); + textNode->setContent(styleContent.c_str()); + } + DocumentUndo::setUndoSensitive(document, saved); } bool @@ -532,7 +569,7 @@ void LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) { SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem); - sp_lpe_item->parent = dynamic_cast<SPObject *>(splpeitem->parent); + SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { return; @@ -555,12 +592,17 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) } Geom::Point start_stored; Geom::Point end_stored; - Geom::Affine affinetransform = i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(document->getRoot())); + Geom::Affine affinetransform = i2anc_affine(SP_OBJECT(lpeitem->parent), SP_OBJECT(document->getRoot())); Geom::PathVector pathvector = pathv_to_linear_and_cubic_beziers(c->get_pathvector()); c->unref(); Geom::Affine writed_transform = Geom::identity(); sp_svg_transform_read(splpeitem->getAttribute("transform"), &writed_transform ); - pathvector *= writed_transform; + if (star_ellipse_fix != Geom::identity()) { + pathvector *= star_ellipse_fix; + star_ellipse_fix = Geom::identity(); + } else { + pathvector *= writed_transform; + } if ((Glib::ustring(format.param_getSVGValue()).empty())) { format.param_setValue(Glib::ustring("{measure}{unit}")); } @@ -670,7 +712,7 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) } else { hstart = hstart - Point::polar(angle_cross, position); } - createLine(start, hstart, g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), false, false, remove); + createLine(start, hstart, g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), false, remove); if (fix_overlaps != 180 && end_angle_cross != 0) { double position_turned = position / sin(end_angle_cross/2.0); @@ -701,47 +743,18 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) if (scale_sensitive) { length *= parents_scale; } + if ((anotation_width/2) > Geom::distance(hstart,hend)/2.0) { + pos = pos - Point::polar(angle_cross, position); + } if (scale_sensitive && !affinetransform.preservesAngles()) { createTextLabel(pos, counter, length, angle, remove, false); } else { createTextLabel(pos, counter, length, angle, remove, true); } - bool overflow = false; const char * downline = g_strdup(Glib::ustring("downline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); - //delete residual lines if exist - createLine(Geom::Point(),Geom::Point(), downline, true, overflow, true, false); - //Create it - if ((anotation_width/2) + std::abs(text_right_left / doc_scale) > Geom::distance(hstart,hend)/2.0) { - Geom::Point sstart = hend - Point::polar(angle_cross, position); - Geom::Point send = hend - Point::polar(angle_cross, position); - if ((text_right_left < 0 && flip_side) || (text_right_left > 0 && !flip_side)) { - sstart = hstart - Point::polar(angle_cross, position); - send = hstart - Point::polar(angle_cross, position); - } - Geom::Point prog_end = Geom::Point(); - if (std::abs(text_top_bottom / doc_scale) < fontsize/1.5 && hide_back) { - if (text_right_left > 0 ) { - prog_end = sstart - Point::polar(angle, std::abs(text_right_left / doc_scale) - (anotation_width/1.9) - (Geom::distance(hstart,hend)/2.0)); - } else { - prog_end = sstart + Point::polar(angle, std::abs(text_right_left / doc_scale) - (anotation_width/1.9) - (Geom::distance(hstart,hend)/2.0)); - } - } else { - if (text_right_left / doc_scale > 0 ) { - prog_end = sstart - Point::polar(angle,(anotation_width/2) + std::abs(text_right_left / doc_scale) - (Geom::distance(hstart,hend)/2.0)); - } else { - prog_end = sstart + Point::polar(angle,(anotation_width/2) + std::abs(text_right_left / doc_scale) - (Geom::distance(hstart,hend)/2.0)); - } - } - overflow = true; - createLine(sstart, prog_end, downline, true, overflow, false, false); - } - //LINE - arrow_gap = 8 * Inkscape::Util::Quantity::convert(0.35 / doc_scale, "mm", display_unit.c_str()); - if (line_group_05) { - arrow_gap = 8 * Inkscape::Util::Quantity::convert(0.25 / doc_scale, "mm", display_unit.c_str()); - } + arrow_gap = 8 * Inkscape::Util::Quantity::convert(line_width / doc_scale, "mm", display_unit.c_str()); SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_attr_add_from_string(css, dimline_format.param_getSVGValue()); + char *oldlocale = g_strdup (setlocale(LC_NUMERIC, NULL)); setlocale (LC_NUMERIC, "C"); double width_line = atof(sp_repr_css_property(css,"stroke-width","-1")); @@ -753,18 +766,22 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) if(flip_side) { arrow_gap *= -1; } - createLine(end, hend, g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), false, false, remove); + createLine(end, hend, g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), false, remove); if (!arrows_outside) { hstart = hstart + Point::polar(angle, arrow_gap); hend = hend - Point::polar(angle, arrow_gap ); } - createLine(hstart, hend, g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, overflow, remove, true); + if ((anotation_width/2) < Geom::distance(hstart,hend)/2.0) { + createLine(hstart, hend, g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, remove, true); + } else { + createLine(hstart, hend, g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); + } } else { const char * downline = g_strdup(Glib::ustring("downline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); - createLine(Geom::Point(),Geom::Point(), downline, true, true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); + createLine(Geom::Point(),Geom::Point(), downline, true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); const char * id = g_strdup(Glib::ustring("text-on-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); SPObject *elemref = NULL; if ((elemref = document->getObjectById(id))) { @@ -775,10 +792,10 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) } for (size_t k = ncurves; k <= previous_size; k++) { const char * downline = g_strdup(Glib::ustring("downline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); - createLine(Geom::Point(),Geom::Point(), downline, true, true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true, true); + createLine(Geom::Point(),Geom::Point(), downline, true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); + createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); const char * id = g_strdup(Glib::ustring("text-on-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); SPObject *elemref = NULL; if ((elemref = document->getObjectById(id))) { @@ -807,61 +824,14 @@ LPEMeasureSegments::doOnRemove (SPLPEItem const* /*lpeitem*/) processObjects(LPE_ERASE); } -Gtk::Widget *LPEMeasureSegments::newWidget() -{ - // use manage here, because after deletion of Effect object, others might - // still be pointing to this widget. - Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget())); - - vbox->set_border_width(5); - vbox->set_homogeneous(false); - vbox->set_spacing(2); - - std::vector<Parameter *>::iterator it = param_vector.begin(); - Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); - vbox_expander->set_border_width(0); - vbox_expander->set_spacing(2); - while (it != param_vector.end()) { - if ((*it)->widget_is_visible) { - Parameter *param = *it; - Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); - Glib::ustring *tip = param->param_getTooltip(); - if (widg) { - if (param->param_key != "dimline_format" && - param->param_key != "helperlines_format" && - param->param_key != "arrows_format" && - param->param_key != "anotation_format") { - vbox->pack_start(*widg, true, true, 2); - } else { - vbox_expander->pack_start(*widg, true, true, 2); - } - if (tip) { - widg->set_tooltip_text(*tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); - } - } - } - - ++it; - } - expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show DIM CSS style override")))); - expander->add(*vbox_expander); - expander->set_expanded(expanded); - expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPEMeasureSegments::onExpanderChanged) ); - vbox->pack_start(*expander, true, true, 2); - return dynamic_cast<Gtk::Widget *>(vbox); -} - void -LPEMeasureSegments::onExpanderChanged() +LPEMeasureSegments::transform_multiply(Geom::Affine const& postmul, bool set) { - expanded = expander->get_expanded(); - if(expanded) { - expander->set_label (Glib::ustring(_("Hide DIM CSS style override"))); - } else { - expander->set_label (Glib::ustring(_("Show DIM CSS style override"))); + SPStar * star = dynamic_cast<SPStar *>(sp_lpe_item); + SPSpiral * spiral = dynamic_cast<SPSpiral *>(sp_lpe_item); + if((spiral || star) && !postmul.withoutTranslation().isUniformScale()) { + star_ellipse_fix = postmul; + sp_lpe_item_update_patheffect(sp_lpe_item, false, false); } } diff --git a/src/live_effects/lpe-measure-segments.h b/src/live_effects/lpe-measure-segments.h index f7f5be1e3..903a5cbd2 100644 --- a/src/live_effects/lpe-measure-segments.h +++ b/src/live_effects/lpe-measure-segments.h @@ -11,15 +11,15 @@ */ #include "live_effects/effect.h" - -#include <gtkmm/expander.h> +#include "ui/dialog/styledialog.h" #include "live_effects/parameter/enum.h" #include "live_effects/parameter/fontbutton.h" #include "live_effects/parameter/text.h" #include "live_effects/parameter/unit.h" #include "live_effects/parameter/bool.h" -#include "live_effects/parameter/originalpath.h" +#include "live_effects/parameter/colorpicker.h" +#include "live_effects/parameter/message.h" #include <libnrtype/font-lister.h> #include <2geom/angle.h> #include <2geom/ray.h> @@ -44,24 +44,24 @@ public: virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); virtual void doEffect (SPCurve * curve){}; //stop the chain virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); + virtual void transform_multiply(Geom::Affine const& postmul, bool set); virtual Geom::PathVector doEffect_path(Geom::PathVector const &path_in); - void createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool overflow, bool remove, bool arrows = false); + void createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool remove, bool arrows = false); void createTextLabel(Geom::Point pos, size_t counter, double length, Geom::Coord angle, bool remove, bool valid); - void onExpanderChanged(); void createArrowMarker(const char * mode); bool hasMeassure (size_t i); - virtual Gtk::Widget *newWidget(); private: UnitParam unit; - FontButtonParam fontbutton; EnumParam<OrientationMethod> orientation; + ColorPickerParam coloropacity; + FontButtonParam fontbutton; ScalarParam precision; ScalarParam fix_overlaps; ScalarParam position; ScalarParam text_top_bottom; - ScalarParam text_right_left; ScalarParam helpline_distance; ScalarParam helpline_overlap; + ScalarParam line_width; ScalarParam scale; TextParam format; TextParam blacklist; @@ -70,22 +70,16 @@ private: BoolParam flip_side; BoolParam scale_sensitive; BoolParam local_locale; - BoolParam line_group_05; BoolParam rotate_anotation; BoolParam hide_back; - TextParam dimline_format; - TextParam helperlines_format; - TextParam anotation_format; - TextParam arrows_format; + MessageParam message; Glib::ustring display_unit; - bool expanded; - Gtk::Expander * expander; double doc_scale; double fontsize; double anotation_width; double previous_size; double arrow_gap; - + Geom::Affine star_ellipse_fix; LPEMeasureSegments(const LPEMeasureSegments &); LPEMeasureSegments &operator=(const LPEMeasureSegments &); diff --git a/src/live_effects/lpe-patternalongpath.cpp b/src/live_effects/lpe-patternalongpath.cpp index 22b18e077..4aa172161 100644 --- a/src/live_effects/lpe-patternalongpath.cpp +++ b/src/live_effects/lpe-patternalongpath.cpp @@ -294,25 +294,29 @@ KnotHolderEntityWidthPatternAlongPath::knot_set(Geom::Point const &p, Geom::Poin Geom::Point const s = snap_knot_position(p, state); SPShape const *sp_shape = dynamic_cast<SPShape const *>(SP_LPE_ITEM(item)); if (sp_shape) { - Geom::Path const *path_in = sp_shape->getCurveBeforeLPE()->first_path(); - Geom::Point ptA = path_in->pointAt(Geom::PathTime(0, 0.0)); - Geom::Point B = path_in->pointAt(Geom::PathTime(1, 0.0)); - Geom::Curve const *first_curve = &path_in->curveAt(Geom::PathTime(0, 0.0)); - Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*first_curve); - Geom::Ray ray(ptA, B); - if (cubic) { - ray.setPoints(ptA, (*cubic)[1]); - } - ray.setAngle(ray.angle() + Geom::rad_from_deg(90)); - Geom::Point knot_pos = this->knot->pos * item->i2dt_affine().inverse(); - Geom::Coord nearest_to_ray = ray.nearestTime(knot_pos); - if(nearest_to_ray == 0){ - lpe->prop_scale.param_set_value(-Geom::distance(s , ptA)/(lpe->original_height/2.0)); - } else { - lpe->prop_scale.param_set_value(Geom::distance(s , ptA)/(lpe->original_height/2.0)); + SPCurve *curve_before = sp_shape->getCurveBeforeLPE(); + if (curve_before) { + Geom::Path const *path_in = curve_before->first_path(); + Geom::Point ptA = path_in->pointAt(Geom::PathTime(0, 0.0)); + Geom::Point B = path_in->pointAt(Geom::PathTime(1, 0.0)); + Geom::Curve const *first_curve = &path_in->curveAt(Geom::PathTime(0, 0.0)); + Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*first_curve); + Geom::Ray ray(ptA, B); + if (cubic) { + ray.setPoints(ptA, (*cubic)[1]); + } + ray.setAngle(ray.angle() + Geom::rad_from_deg(90)); + Geom::Point knot_pos = this->knot->pos * item->i2dt_affine().inverse(); + Geom::Coord nearest_to_ray = ray.nearestTime(knot_pos); + if(nearest_to_ray == 0){ + lpe->prop_scale.param_set_value(-Geom::distance(s , ptA)/(lpe->original_height/2.0)); + } else { + lpe->prop_scale.param_set_value(Geom::distance(s , ptA)/(lpe->original_height/2.0)); + } + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setDouble("/live_effect/pap/width", lpe->prop_scale); + curve_before->unref(); } - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setDouble("/live_effect/pap/width", lpe->prop_scale); } sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); } @@ -324,25 +328,28 @@ KnotHolderEntityWidthPatternAlongPath::knot_get() const SPShape const *sp_shape = dynamic_cast<SPShape const *>(SP_LPE_ITEM(item)); if (sp_shape) { - Geom::Path const *path_in = sp_shape->getCurveBeforeLPE()->first_path(); - Geom::Point ptA = path_in->pointAt(Geom::PathTime(0, 0.0)); - Geom::Point B = path_in->pointAt(Geom::PathTime(1, 0.0)); - Geom::Curve const *first_curve = &path_in->curveAt(Geom::PathTime(0, 0.0)); - Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*first_curve); - Geom::Ray ray(ptA, B); - if (cubic) { - ray.setPoints(ptA, (*cubic)[1]); + SPCurve *curve_before = sp_shape->getCurveBeforeLPE(); + if (curve_before) { + Geom::Path const *path_in = curve_before->first_path(); + Geom::Point ptA = path_in->pointAt(Geom::PathTime(0, 0.0)); + Geom::Point B = path_in->pointAt(Geom::PathTime(1, 0.0)); + Geom::Curve const *first_curve = &path_in->curveAt(Geom::PathTime(0, 0.0)); + Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*first_curve); + Geom::Ray ray(ptA, B); + if (cubic) { + ray.setPoints(ptA, (*cubic)[1]); + } + ray.setAngle(ray.angle() + Geom::rad_from_deg(90)); + Geom::Point result_point = Geom::Point::polar(ray.angle(), (lpe->original_height/2.0) * lpe->prop_scale) + ptA; + + pap_helper_path.clear(); + Geom::Path hp(result_point); + hp.appendNew<Geom::LineSegment>(ptA); + pap_helper_path.push_back(hp); + hp.clear(); + curve_before->unref(); + return result_point; } - ray.setAngle(ray.angle() + Geom::rad_from_deg(90)); - Geom::Point result_point = Geom::Point::polar(ray.angle(), (lpe->original_height/2.0) * lpe->prop_scale) + ptA; - - pap_helper_path.clear(); - Geom::Path hp(result_point); - hp.appendNew<Geom::LineSegment>(ptA); - pap_helper_path.push_back(hp); - hp.clear(); - - return result_point; } return Geom::Point(); } diff --git a/src/live_effects/lpe-powerclip.cpp b/src/live_effects/lpe-powerclip.cpp index 43faa35e0..40a9cdbfb 100644 --- a/src/live_effects/lpe-powerclip.cpp +++ b/src/live_effects/lpe-powerclip.cpp @@ -4,7 +4,6 @@ #include "live_effects/lpe-powerclip.h" #include <2geom/path-intersection.h> #include <2geom/intersection-graph.h> -#include "display/drawing-item.h" #include "display/curve.h" #include "helper/geom.h" #include "sp-clippath.h" @@ -13,6 +12,9 @@ #include "sp-item-group.h" #include "ui/tools-switch.h" #include "path-chemistry.h" +#include "uri.h" +#include "extract-uri.h" +#include <bad-uri-exception.h> // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> @@ -22,19 +24,17 @@ namespace LivePathEffect { LPEPowerClip::LPEPowerClip(LivePathEffectObject *lpeobject) : Effect(lpeobject), + hide_clip(_("Hide clip"), _("Hide clip"), "hide_clip", &wr, this, false), + is_inverse("Store the last inverse apply", "", "is_inverse", &wr, this, "false", false), + uri("Store the uri of clip", "", "uri", &wr, this, "false", false), inverse(_("Inverse clip"), _("Inverse clip"), "inverse", &wr, this, false), - flatten(_("Flatten clip"), _("Flatten clip, see fill rule once convert to paths"), "flatten", &wr, this, false), - //loock(_("Lock clip"), _("Lock clip"), "lock", &wr, this, false), - //tooltip empty to no show in default param set - is_inverse("Store the last inverse apply", "", "is_inverse", &wr, this, "false", false) + flatten(_("Flatten clip"), _("Flatten clip, see fill rule once convert to paths"), "flatten", &wr, this, false) { + registerParameter(&uri); registerParameter(&inverse); registerParameter(&flatten); + registerParameter(&hide_clip); registerParameter(&is_inverse); - //registerParameter(&lock); - //lock.param_setValue(false); - is_clip = false; - hide_clip = false; convert_shapes = false; } @@ -42,22 +42,48 @@ LPEPowerClip::~LPEPowerClip() {} void LPEPowerClip::doBeforeEffect (SPLPEItem const* lpeitem){ - original_bbox(lpeitem); - SPClipPath *clip_path = SP_ITEM(lpeitem)->clip_ref->getObject(); - Geom::Point topleft = Geom::Point(boundingbox_X.min() - 5,boundingbox_Y.max() + 5); - Geom::Point topright = Geom::Point(boundingbox_X.max() + 5,boundingbox_Y.max() + 5); - Geom::Point bottomright = Geom::Point(boundingbox_X.max() + 5,boundingbox_Y.min() - 5); - Geom::Point bottomleft = Geom::Point(boundingbox_X.min() - 5,boundingbox_Y.min() - 5); - clip_box.clear(); - clip_box.start(topleft); - clip_box.appendNew<Geom::LineSegment>(topright); - clip_box.appendNew<Geom::LineSegment>(bottomright); - clip_box.appendNew<Geom::LineSegment>(bottomleft); - clip_box.close(); - //clip_path *= sp_lpe_item->i2dt_affine(); + SPObject * clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); + if(hide_clip && clip_path) { + SP_ITEM(sp_lpe_item)->clip_ref->detach(); + } else if (!hide_clip && !clip_path && uri.param_getSVGValue()) { + try { + SP_ITEM(sp_lpe_item)->clip_ref->attach(Inkscape::URI(uri.param_getSVGValue())); + } catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + SP_ITEM(sp_lpe_item)->clip_ref->detach(); + } + } + clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); if (clip_path) { - is_clip = true; - const Glib::ustring uri = (Glib::ustring)sp_lpe_item->getRepr()->attribute("clip-path"); + uri.param_setValue(Glib::ustring(extract_uri(sp_lpe_item->getRepr()->attribute("clip-path"))), true); + SP_ITEM(sp_lpe_item)->clip_ref->detach(); + Geom::OptRect bbox = sp_lpe_item->visualBounds(); + if(!bbox) { + return; + } + if (uri.param_getSVGValue()) { + try { + SP_ITEM(sp_lpe_item)->clip_ref->attach(Inkscape::URI(uri.param_getSVGValue())); + } catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + SP_ITEM(sp_lpe_item)->clip_ref->detach(); + } + } else { + SP_ITEM(sp_lpe_item)->clip_ref->detach(); + } + Geom::Rect bboxrect = (*bbox); + bboxrect.expandBy(1); + Geom::Point topleft = bboxrect.corner(0); + Geom::Point topright = bboxrect.corner(1); + Geom::Point bottomright = bboxrect.corner(2); + Geom::Point bottomleft = bboxrect.corner(3); + clip_box.clear(); + clip_box.start(topleft); + clip_box.appendNew<Geom::LineSegment>(topright); + clip_box.appendNew<Geom::LineSegment>(bottomright); + clip_box.appendNew<Geom::LineSegment>(bottomleft); + clip_box.close(); + //clip_box *= sp_lpe_item->i2dt_affine(); std::vector<SPObject*> clip_path_list = clip_path->childList(true); for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { SPObject * clip_data = *iter; @@ -133,8 +159,6 @@ LPEPowerClip::doBeforeEffect (SPLPEItem const* lpeitem){ removeInverse(SP_ITEM(clip_data)); } } - } else { - is_clip = false; } } @@ -217,36 +241,6 @@ LPEPowerClip::removeInverse (SPItem * clip_data){ } void -LPEPowerClip::toggleClip() { - SPItem * item = SP_ITEM(sp_lpe_item); - if (item) { - SPClipPath *clip_path = item->clip_ref->getObject(); - if (clip_path) { - hide_clip = !hide_clip; - if(hide_clip) { - SPItemView *v; - for (v = item->display; v != NULL; v = v->next) { - clip_path->hide(v->arenaitem->key()); - } - } else { - Geom::OptRect bbox = item->geometricBounds(); - for (SPItemView *v = item->display; v != NULL; v = v->next) { - if (!v->arenaitem->key()) { - v->arenaitem->setKey(SPItem::display_key_new(3)); - } - Inkscape::DrawingItem *ai = clip_path->show( - v->arenaitem->drawing(), - v->arenaitem->key()); - v->arenaitem->setClip(ai); - clip_path->setBBox(v->arenaitem->key(), bbox); - } - } - clip_path->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - } - } -} - -void LPEPowerClip::convertShapes() { convert_shapes = true; sp_lpe_item_update_patheffect(SP_LPE_ITEM(sp_lpe_item), false, false); @@ -256,7 +250,7 @@ Gtk::Widget * LPEPowerClip::newWidget() { // use manage here, because after deletion of Effect object, others might still be pointing to this widget. - Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); + Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget())); vbox->set_border_width(5); vbox->set_homogeneous(false); @@ -281,17 +275,11 @@ LPEPowerClip::newWidget() ++it; } Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0)); - Gtk::Button * toggle_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Toggle clip visibiliy")))); - toggle_button->signal_clicked().connect(sigc::mem_fun (*this,&LPEPowerClip::toggleClip)); - toggle_button->set_size_request(180,30); - vbox->pack_start(*hbox, true,true,2); - hbox->pack_start(*toggle_button, false, false,2); - Gtk::HBox * hbox2 = Gtk::manage(new Gtk::HBox(false,0)); Gtk::Button * topaths_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Convert clips to paths, undoable")))); topaths_button->signal_clicked().connect(sigc::mem_fun (*this,&LPEPowerClip::convertShapes)); topaths_button->set_size_request(220,30); - vbox->pack_start(*hbox2, true,true,2); - hbox2->pack_start(*topaths_button, false, false,2); + hbox->pack_start(*topaths_button, false, false,2); + vbox->pack_start(*hbox, true,true,2); return dynamic_cast<Gtk::Widget *>(vbox); } @@ -301,7 +289,6 @@ LPEPowerClip::doOnRemove (SPLPEItem const* /*lpeitem*/) SPClipPath *clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); if(!keep_paths) { if(clip_path) { - is_clip = true; std::vector<SPObject*> clip_path_list = clip_path->childList(true); for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { SPObject * clip_data = *iter; @@ -313,7 +300,6 @@ LPEPowerClip::doOnRemove (SPLPEItem const* /*lpeitem*/) } else { if (flatten && clip_path) { clip_path->deleteObject(); - sp_lpe_item->getRepr()->setAttribute("clip-path", NULL); } } } @@ -321,7 +307,7 @@ LPEPowerClip::doOnRemove (SPLPEItem const* /*lpeitem*/) Geom::PathVector LPEPowerClip::doEffect_path(Geom::PathVector const & path_in){ Geom::PathVector path_out = pathv_to_linear_and_cubic_beziers(path_in); - if (flatten && is_clip && isVisible()) { + if (!hide_clip && flatten && isVisible()) { SPClipPath *clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); if(clip_path) { std::vector<SPObject*> clip_path_list = clip_path->childList(true); @@ -330,6 +316,7 @@ LPEPowerClip::doEffect_path(Geom::PathVector const & path_in){ flattenClip(SP_ITEM(clip_data), path_out); } } + SP_ITEM(sp_lpe_item)->clip_ref->detach(); } return path_out; } @@ -346,13 +333,13 @@ LPEPowerClip::doOnVisibilityToggled(SPLPEItem const* lpeitem) //{ // SPDocument * doc = SP_ACTIVE_DOCUMENT; // SPClipPath *clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); -// if (is_clip && lock) { +// if (clip_path && lock) { // std::vector<SPObject*> clip_path_list = clip_path->childList(true); // Glib::ustring clip_id = (Glib::ustring)clip_path->getId(); // Glib::ustring box_id = clip_id + (Glib::ustring)"_box"; // for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { // SPItem * clip_data = SP_ITEM(*iter); -// if(inverse && is_clip && lock) { +// if(inverse && lock) { // removeInverse(clip_data); // } // if (lock) { @@ -371,7 +358,7 @@ LPEPowerClip::doOnVisibilityToggled(SPLPEItem const* lpeitem) //// } //// } // } -// if(inverse && is_clip && lock) { +// if(inverse && lock) { // doBeforeEffect(sp_lpe_item); // } // } @@ -381,8 +368,8 @@ LPEPowerClip::doOnVisibilityToggled(SPLPEItem const* lpeitem) // Parameter * param = *it; // param->param_transform_multiply(postmul, set); // } -// toggleClip(); -// toggleClip(); +// toggleClipVisibility(); +// toggleClipVisibility(); //} void diff --git a/src/live_effects/lpe-powerclip.h b/src/live_effects/lpe-powerclip.h index ce46b560a..38485b798 100644 --- a/src/live_effects/lpe-powerclip.h +++ b/src/live_effects/lpe-powerclip.h @@ -9,12 +9,11 @@ #include "live_effects/effect.h" #include "live_effects/parameter/hidden.h" -#include "live_effects/lpegroupbbox.h" namespace Inkscape { namespace LivePathEffect { -class LPEPowerClip : public Effect, GroupBBoxEffect { +class LPEPowerClip : public Effect { public: LPEPowerClip(LivePathEffectObject *lpeobject); virtual ~LPEPowerClip(); @@ -24,22 +23,19 @@ public: virtual Gtk::Widget * newWidget(); //virtual void transform_multiply(Geom::Affine const& postmul, bool set); virtual void doOnVisibilityToggled(SPLPEItem const* lpeitem); - void toggleClip(); void addInverse (SPItem * clip_data); void removeInverse (SPItem * clip_data); void flattenClip(SPItem * clip_data, Geom::PathVector &path_in); void convertShapes(); private: + HiddenParam is_inverse; + HiddenParam uri; BoolParam inverse; BoolParam flatten; - // BoolParam lock; - HiddenParam is_inverse; + BoolParam hide_clip; Geom::Path clip_box; Geom::Affine base; - bool is_clip; bool convert_shapes; - bool hide_clip; - bool previous_hide_clip; }; } //namespace LivePathEffect diff --git a/src/live_effects/lpe-powermask.cpp b/src/live_effects/lpe-powermask.cpp index 434ad6dd4..05510f258 100644 --- a/src/live_effects/lpe-powermask.cpp +++ b/src/live_effects/lpe-powermask.cpp @@ -4,7 +4,6 @@ #include "live_effects/lpe-powermask.h" #include <2geom/path-intersection.h> #include <2geom/intersection-graph.h> -#include "display/drawing-item.h" #include "display/curve.h" #include "helper/geom.h" #include "sp-mask.h" @@ -16,6 +15,9 @@ #include "svg/svg.h" #include "ui/tools-switch.h" #include "path-chemistry.h" +#include "uri.h" +#include "extract-uri.h" +#include <bad-uri-exception.h> // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> @@ -25,40 +27,68 @@ namespace LivePathEffect { LPEPowerMask::LPEPowerMask(LivePathEffectObject *lpeobject) : Effect(lpeobject), + uri("Store the uri of mask", "", "uri", &wr, this, "false", false), invert(_("Invert mask"), _("Invert mask"), "invert", &wr, this, false), wrap(_("Wrap mask data"), _("Wrap mask data allowing previous filters"), "wrap", &wr, this, false), + hide_mask(_("Hide mask"), _("Hide mask"), "hide_mask", &wr, this, false), background(_("Add background to mask"), _("Add background to mask"), "background", &wr, this, false), - //lock(_("Lock mask"), _("Lock mask"), "lock", &wr, this, false), background_style(_("Background Style"), _("CSS to background"), "background_style", &wr, this,"fill:#ffffff;opacity:1;") - { + registerParameter(&uri); registerParameter(&invert); registerParameter(&wrap); - //registerParameter(&lock); + registerParameter(&hide_mask); registerParameter(&background); registerParameter(&background_style); //lock.param_setValue(false); background_style.param_hide_canvas_text(); - hide_mask = false; } LPEPowerMask::~LPEPowerMask() {} void LPEPowerMask::doBeforeEffect (SPLPEItem const* lpeitem){ - original_bbox(lpeitem); - SPMask *mask = SP_ITEM(lpeitem)->mask_ref->getObject(); - Geom::Point topleft = Geom::Point(boundingbox_X.min() - 5,boundingbox_Y.max() + 5); - Geom::Point topright = Geom::Point(boundingbox_X.max() + 5,boundingbox_Y.max() + 5); - Geom::Point bottomright = Geom::Point(boundingbox_X.max() + 5,boundingbox_Y.min() - 5); - Geom::Point bottomleft = Geom::Point(boundingbox_X.min() - 5,boundingbox_Y.min() - 5); - mask_box.clear(); - mask_box.start(topleft); - mask_box.appendNew<Geom::LineSegment>(topright); - mask_box.appendNew<Geom::LineSegment>(bottomright); - mask_box.appendNew<Geom::LineSegment>(bottomleft); - mask_box.close(); - if(mask) { + SPObject * mask = SP_ITEM(sp_lpe_item)->mask_ref->getObject(); + if(hide_mask && mask) { + SP_ITEM(sp_lpe_item)->mask_ref->detach(); + } else if (!hide_mask && !mask && uri.param_getSVGValue()) { + try { + SP_ITEM(sp_lpe_item)->mask_ref->attach(Inkscape::URI(uri.param_getSVGValue())); + } catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + SP_ITEM(sp_lpe_item)->mask_ref->detach(); + } + } + mask = SP_ITEM(sp_lpe_item)->mask_ref->getObject(); + if (mask) { + uri.param_setValue(Glib::ustring(extract_uri(sp_lpe_item->getRepr()->attribute("mask"))), true); + SP_ITEM(sp_lpe_item)->mask_ref->detach(); + Geom::OptRect bbox = sp_lpe_item->visualBounds(); + if(!bbox) { + return; + } + if (uri.param_getSVGValue()) { + try { + SP_ITEM(sp_lpe_item)->mask_ref->attach(Inkscape::URI(uri.param_getSVGValue())); + } catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + SP_ITEM(sp_lpe_item)->mask_ref->detach(); + } + } else { + SP_ITEM(sp_lpe_item)->mask_ref->detach(); + } + Geom::Rect bboxrect = (*bbox); + bboxrect.expandBy(1); + Geom::Point topleft = bboxrect.corner(0); + Geom::Point topright = bboxrect.corner(1); + Geom::Point bottomright = bboxrect.corner(2); + Geom::Point bottomleft = bboxrect.corner(3); + mask_box.clear(); + mask_box.start(topleft); + mask_box.appendNew<Geom::LineSegment>(topright); + mask_box.appendNew<Geom::LineSegment>(bottomright); + mask_box.appendNew<Geom::LineSegment>(bottomleft); + mask_box.close(); setMask(); } } @@ -225,37 +255,6 @@ LPEPowerMask::doEffect (SPCurve * curve) { } -void -LPEPowerMask::toggleMask() { - SPItem * item = SP_ITEM(sp_lpe_item); - if (item) { - SPMask *mask = item->mask_ref->getObject(); - if (mask) { - hide_mask = !hide_mask; - if(hide_mask) { - SPItemView *v; - for (v = item->display; v != NULL; v = v->next) { - mask->sp_mask_hide(v->arenaitem->key()); - } - } else { - Geom::OptRect bbox = item->geometricBounds(); - for (SPItemView *v = item->display; v != NULL; v = v->next) { - if (!v->arenaitem->key()) { - v->arenaitem->setKey(SPItem::display_key_new(3)); - } - Inkscape::DrawingItem *ai = mask->sp_mask_show( - v->arenaitem->drawing(), - v->arenaitem->key()); - bbox.unionWith(ai->geometricBounds()); - v->arenaitem->setMask(ai); - mask->sp_mask_set_bbox(v->arenaitem->key(), bbox); - } - } - mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - } - } -} - //void //LPEPowerMask::transform_multiply(Geom::Affine const& postmul, bool set) //{ @@ -283,44 +282,6 @@ LPEPowerMask::toggleMask() { -Gtk::Widget * -LPEPowerMask::newWidget() -{ - // use manage here, because after deletion of Effect object, others might still be pointing to this widget. - Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); - - vbox->set_border_width(5); - vbox->set_homogeneous(false); - vbox->set_spacing(6); - - std::vector<Parameter *>::iterator it = param_vector.begin(); - while (it != param_vector.end()) { - if ((*it)->widget_is_visible) { - Parameter * param = *it; - Gtk::Widget * widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); - Glib::ustring * tip = param->param_getTooltip(); - if (widg) { - vbox->pack_start(*widg, true, true, 2); - if (tip) { - widg->set_tooltip_text(*tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); - } - } - } - - ++it; - } - Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0)); - Gtk::Button * toggle_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Toggle mask visibiliy")))); - toggle_button->signal_clicked().connect(sigc::mem_fun (*this,&LPEPowerMask::toggleMask)); - toggle_button->set_size_request(140,30); - vbox->pack_start(*hbox, true,true,2); - hbox->pack_start(*toggle_button, false, false,2); - return dynamic_cast<Gtk::Widget *>(vbox); -} - void LPEPowerMask::doOnRemove (SPLPEItem const* lpeitem) { diff --git a/src/live_effects/lpe-powermask.h b/src/live_effects/lpe-powermask.h index cd36b3b37..a54424e2f 100644 --- a/src/live_effects/lpe-powermask.h +++ b/src/live_effects/lpe-powermask.h @@ -9,31 +9,30 @@ #include "live_effects/effect.h" #include "live_effects/parameter/text.h" -#include "live_effects/lpegroupbbox.h" +#include "live_effects/parameter/hidden.h" namespace Inkscape { namespace LivePathEffect { -class LPEPowerMask : public Effect, GroupBBoxEffect { +class LPEPowerMask : public Effect { public: LPEPowerMask(LivePathEffectObject *lpeobject); virtual ~LPEPowerMask(); virtual void doBeforeEffect (SPLPEItem const* lpeitem); virtual void doEffect (SPCurve * curve); virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); - virtual Gtk::Widget * newWidget(); virtual void doOnVisibilityToggled(SPLPEItem const* lpeitem); //virtual void transform_multiply(Geom::Affine const& postmul, bool set); - void toggleMask(); + void toggleMaskVisibility(); void setMask(); private: + HiddenParam uri; BoolParam invert; BoolParam wrap; + BoolParam hide_mask; BoolParam background; - //BoolParam lock; TextParam background_style; Geom::Path mask_box; - bool hide_mask; }; } //namespace LivePathEffect diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 85d7e1e17..51c8451a5 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -267,7 +267,7 @@ LPEPowerStroke::doOnApply(SPLPEItem const* lpeitem) void LPEPowerStroke::doOnRemove(SPLPEItem const* lpeitem) { - if (SP_IS_SHAPE(lpeitem)) { + if (SP_IS_SHAPE(lpeitem) && !keep_paths) { SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem); SPCSSAttr *css = sp_repr_css_attr_new (); if (lpeitem->style->fill.isPaintserver()) { @@ -288,7 +288,7 @@ void LPEPowerStroke::doOnRemove(SPLPEItem const* lpeitem) } Inkscape::CSSOStringStream os; - os << offset_points.median_width() * 2; + os << std::abs(offset_points.median_width()) * 2; sp_repr_css_set_property (css, "stroke-width", os.str().c_str()); sp_repr_css_set_property(css, "fill", "none"); diff --git a/src/live_effects/lpe-ruler.cpp b/src/live_effects/lpe-ruler.cpp index 852592219..7ba5a7913 100644 --- a/src/live_effects/lpe-ruler.cpp +++ b/src/live_effects/lpe-ruler.cpp @@ -78,9 +78,12 @@ LPERuler::ruler_mark(Geom::Point const &A, Geom::Point const &n, MarkType const using namespace Geom; double real_mark_length = mark_length; - real_mark_length = Inkscape::Util::Quantity::convert(real_mark_length, unit.get_abbreviation(), "px"); + SPDocument * document = SP_ACTIVE_DOCUMENT; + SPNamedView *nv = sp_document_namedview(document, NULL); + Glib::ustring display_unit = nv->display_units->abbr; + real_mark_length = Inkscape::Util::Quantity::convert(real_mark_length, unit.get_abbreviation(), display_unit.c_str()); double real_minor_mark_length = minor_mark_length; - real_minor_mark_length = Inkscape::Util::Quantity::convert(real_minor_mark_length, unit.get_abbreviation(), "px"); + real_minor_mark_length = Inkscape::Util::Quantity::convert(real_minor_mark_length, unit.get_abbreviation(), display_unit.c_str()); n_major = real_mark_length * n; n_minor = real_minor_mark_length * n; @@ -130,10 +133,13 @@ LPERuler::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_i std::vector<double> s_cuts; double real_mark_distance = mark_distance; - real_mark_distance = Inkscape::Util::Quantity::convert(real_mark_distance, unit.get_abbreviation(), "px"); + SPDocument * document = SP_ACTIVE_DOCUMENT; + SPNamedView *nv = sp_document_namedview(document, NULL); + Glib::ustring display_unit = nv->display_units->abbr; + real_mark_distance = Inkscape::Util::Quantity::convert(real_mark_distance, unit.get_abbreviation(), display_unit.c_str()); double real_offset = offset; - real_offset = Inkscape::Util::Quantity::convert(real_offset, unit.get_abbreviation(), "px"); + real_offset = Inkscape::Util::Quantity::convert(real_offset, unit.get_abbreviation(), display_unit.c_str()); for (double s = real_offset; s<totlength; s+=real_mark_distance){ s_cuts.push_back(s); } diff --git a/src/live_effects/makefile.in b/src/live_effects/makefile.in deleted file mode 100644 index 8a4da813b..000000000 --- a/src/live_effects/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) live_effects/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) live_effects/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/live_effects/parameter/array.h b/src/live_effects/parameter/array.h index e65d3b55c..c66d53266 100644 --- a/src/live_effects/parameter/array.h +++ b/src/live_effects/parameter/array.h @@ -67,6 +67,10 @@ public: gchar * str = g_strdup(os.str().c_str()); return str; } + + virtual gchar * param_getDefaultSVGValue() const { + return g_strdup(""); + } void param_setValue(std::vector<StorageType> const &new_vector) { _vector = new_vector; diff --git a/src/live_effects/parameter/bool.cpp b/src/live_effects/parameter/bool.cpp index f291a8104..1a01f269b 100644 --- a/src/live_effects/parameter/bool.cpp +++ b/src/live_effects/parameter/bool.cpp @@ -61,6 +61,13 @@ BoolParam::param_getSVGValue() const return str; } +gchar * +BoolParam::param_getDefaultSVGValue() const +{ + gchar * str = g_strdup(defvalue ? "true" : "false"); + return str; +} + Gtk::Widget * BoolParam::param_newWidget() { diff --git a/src/live_effects/parameter/bool.h b/src/live_effects/parameter/bool.h index 417752050..1aa0e3c4a 100644 --- a/src/live_effects/parameter/bool.h +++ b/src/live_effects/parameter/bool.h @@ -32,6 +32,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; void param_setValue(bool newvalue); virtual void param_set_default(); diff --git a/src/live_effects/parameter/colorpicker.cpp b/src/live_effects/parameter/colorpicker.cpp new file mode 100644 index 000000000..f6521d0c0 --- /dev/null +++ b/src/live_effects/parameter/colorpicker.cpp @@ -0,0 +1,151 @@ +/* + * Authors: + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm.h> +#include "ui/widget/registered-widget.h" +#include "live_effects/parameter/colorpicker.h" +#include "live_effects/effect.h" +#include "ui/widget/color-picker.h" +#include "svg/svg.h" +#include "svg/svg-color.h" +#include "color.h" +#include "inkscape.h" +#include "svg/stringstream.h" +#include "verbs.h" +#include "document.h" +#include "document-undo.h" + +#include <glibmm/i18n.h> + +namespace Inkscape { + +namespace LivePathEffect { + +ColorPickerParam::ColorPickerParam( const Glib::ustring& label, const Glib::ustring& tip, + const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, + Effect* effect, const guint32 default_color ) + : Parameter(label, tip, key, wr, effect), + value(default_color), + defvalue(default_color) +{ + +} + +void +ColorPickerParam::param_set_default() +{ + param_setValue(defvalue); +} + +static guint32 sp_read_color_alpha(gchar const *str, guint32 def) +{ + guint32 val = 0; + if (str == NULL) return def; + while ((*str <= ' ') && *str) str++; + if (!*str) return def; + + if (str[0] == '#') { + gint i; + for (i = 1; str[i]; i++) { + int hexval; + if (str[i] >= '0' && str[i] <= '9') + hexval = str[i] - '0'; + else if (str[i] >= 'A' && str[i] <= 'F') + hexval = str[i] - 'A' + 10; + else if (str[i] >= 'a' && str[i] <= 'f') + hexval = str[i] - 'a' + 10; + else + break; + val = (val << 4) + hexval; + } + if (i != 1 + 8) { + return def; + } + } + return val; +} + +void +ColorPickerParam::param_update_default(const gchar * default_value) +{ + defvalue = sp_read_color_alpha(default_value, 0x000000ff); +} + +bool +ColorPickerParam::param_readSVGValue(const gchar * strvalue) +{ + param_setValue(sp_read_color_alpha(strvalue, 0x000000ff)); + return true; +} + +gchar * +ColorPickerParam::param_getSVGValue() const +{ + gchar c[32]; + sprintf(c, "#%08x", value); + return strdup(c); +} + +gchar * +ColorPickerParam::param_getDefaultSVGValue() const +{ + gchar c[32]; + sprintf(c, "#%08x", defvalue); + return strdup(c); +} + +Gtk::Widget * +ColorPickerParam::param_newWidget() +{ + Gtk::HBox *hbox = Gtk::manage(new Gtk::HBox()); + + hbox->set_border_width(5); + hbox->set_homogeneous(false); + hbox->set_spacing(2); + Inkscape::UI::Widget::RegisteredColorPicker * colorpickerwdg = Gtk::manage( + new Inkscape::UI::Widget::RegisteredColorPicker( param_label, + param_label, + param_tooltip, + param_key, + param_key + "_opacity_LPE", + *param_wr, + param_effect->getRepr(), + param_effect->getSPDoc() ) ); + Gtk::Label * label = new Gtk::Label (param_label, Gtk::ALIGN_END); + label->set_use_underline (true); + label->set_mnemonic_widget (*colorpickerwdg); + SPDocument *document = SP_ACTIVE_DOCUMENT; + bool saved = DocumentUndo::getUndoSensitive(document); + DocumentUndo::setUndoSensitive(document, false); + colorpickerwdg->setRgba32(value); + DocumentUndo::setUndoSensitive(document, saved); + colorpickerwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change color button parameter")); + hbox->pack_start(*dynamic_cast<Gtk::Widget *> (label), true, true); + hbox->pack_start(*dynamic_cast<Gtk::Widget *> (colorpickerwdg), true, true); + return dynamic_cast<Gtk::Widget *> (hbox); +} + +void +ColorPickerParam::param_setValue(const guint32 newvalue) +{ + value = newvalue; +} + + +} /* namespace LivePathEffect */ + +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/colorpicker.h b/src/live_effects/parameter/colorpicker.h new file mode 100644 index 000000000..84ae2f6d5 --- /dev/null +++ b/src/live_effects/parameter/colorpicker.h @@ -0,0 +1,61 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_COLOR_BUTTON_H +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_COLOR_BUTTON_H + +/* + * Inkscape::LivePathEffectParameters + * + * Authors: + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#include <glib.h> +#include "live_effects/parameter/parameter.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class ColorPickerParam : public Parameter { +public: + ColorPickerParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect, + const guint32 default_color = 0x000000ff); + virtual ~ColorPickerParam() {} + + virtual Gtk::Widget * param_newWidget(); + virtual bool param_readSVGValue(const gchar * strvalue); + void param_update_default(const gchar * default_value); + virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; + + void param_setValue(guint32 newvalue); + + virtual void param_set_default(); + + const guint32 get_value() const { return value; }; + +private: + ColorPickerParam(const ColorPickerParam&); + ColorPickerParam& operator=(const ColorPickerParam&); + guint32 value; + guint32 defvalue; +}; + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/enum.h b/src/live_effects/parameter/enum.h index 78fa87a4f..ca237c0f7 100644 --- a/src/live_effects/parameter/enum.h +++ b/src/live_effects/parameter/enum.h @@ -64,7 +64,12 @@ public: gchar * str = g_strdup( enumdataconv->get_key(value).c_str() ); return str; }; - + + gchar * param_getDefaultSVGValue() const { + gchar * str = g_strdup( enumdataconv->get_key(defvalue).c_str() ); + return str; + }; + E get_value() const { return value; } diff --git a/src/live_effects/parameter/fontbutton.cpp b/src/live_effects/parameter/fontbutton.cpp index ca8908f0e..49edb850a 100644 --- a/src/live_effects/parameter/fontbutton.cpp +++ b/src/live_effects/parameter/fontbutton.cpp @@ -55,6 +55,14 @@ FontButtonParam::param_getSVGValue() const return g_strdup(value.c_str()); } +gchar * +FontButtonParam::param_getDefaultSVGValue() const +{ + return g_strdup(defvalue.c_str()); +} + + + Gtk::Widget * FontButtonParam::param_newWidget() { diff --git a/src/live_effects/parameter/fontbutton.h b/src/live_effects/parameter/fontbutton.h index 60e1aa46e..e2d0e1bb2 100644 --- a/src/live_effects/parameter/fontbutton.h +++ b/src/live_effects/parameter/fontbutton.h @@ -28,6 +28,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); void param_update_default(const gchar * default_value); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; void param_setValue(Glib::ustring newvalue); diff --git a/src/live_effects/parameter/hidden.cpp b/src/live_effects/parameter/hidden.cpp index e8c55ebd3..e08881f6d 100644 --- a/src/live_effects/parameter/hidden.cpp +++ b/src/live_effects/parameter/hidden.cpp @@ -59,6 +59,15 @@ HiddenParam::param_getSVGValue() const return str; } +gchar * +HiddenParam::param_getDefaultSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << defvalue; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + Gtk::Widget * HiddenParam::param_newWidget() { diff --git a/src/live_effects/parameter/hidden.h b/src/live_effects/parameter/hidden.h index c3fba5575..b41c6c93c 100644 --- a/src/live_effects/parameter/hidden.h +++ b/src/live_effects/parameter/hidden.h @@ -37,6 +37,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; void param_setValue(Glib::ustring newvalue, bool write = false); virtual void param_set_default(); diff --git a/src/live_effects/parameter/item.cpp b/src/live_effects/parameter/item.cpp index 71134b118..bf7402d99 100644 --- a/src/live_effects/parameter/item.cpp +++ b/src/live_effects/parameter/item.cpp @@ -43,6 +43,7 @@ ItemParam::ItemParam( const Glib::ustring& label, const Glib::ustring& tip, href(NULL), ref( (SPObject*)effect->getLPEObj() ) { + last_transform = Geom::identity(); defvalue = g_strdup(default_value); ref_changed_connection = ref.changedSignal().connect(sigc::mem_fun(*this, &ItemParam::ref_changed)); } @@ -101,7 +102,16 @@ ItemParam::param_readSVGValue(const gchar * strvalue) gchar * ItemParam::param_getSVGValue() const { - return g_strdup(href); + if (href) { + return g_strdup(href); + } + return g_strdup(""); +} + +gchar * +ItemParam::param_getDefaultSVGValue() const +{ + return g_strdup(defvalue); } Gtk::Widget * @@ -204,9 +214,18 @@ ItemParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/) { emit_changed(); SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); + last_transform = Geom::identity(); } void +ItemParam::linked_transformed_callback(Geom::Affine const *rel_transf, SPItem */*moved_item*/) +{ + last_transform = *rel_transf; + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); +} + + +void ItemParam::on_link_button_click() { Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); diff --git a/src/live_effects/parameter/item.h b/src/live_effects/parameter/item.h index 89c32f9bd..d32098db5 100644 --- a/src/live_effects/parameter/item.h +++ b/src/live_effects/parameter/item.h @@ -34,14 +34,14 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; - + virtual gchar * param_getDefaultSVGValue() const; virtual void param_set_default(); virtual void param_update_default(const gchar * default_value); void param_set_and_write_default(); virtual void addCanvasIndicators(SPLPEItem const* lpeitem, std::vector<Geom::PathVector> &hp_vec); - sigc::signal <void> signal_item_pasted; sigc::signal <void> signal_item_changed; + Geom::Affine last_transform; bool changed; /* this gets set whenever the path is changed (this is set to true, and then the signal_item_changed signal is emitted). * the user must set it back to false if she wants to use it sensibly */ protected: @@ -60,7 +60,7 @@ protected: void linked_modified(SPObject *linked_obj, guint flags); void linked_transformed(Geom::Affine const *rel_transf, SPItem *moved_item); virtual void linked_modified_callback(SPObject *linked_obj, guint flags); - virtual void linked_transformed_callback(Geom::Affine const * /*rel_transf*/, SPItem * /*moved_item*/) {}; + virtual void linked_transformed_callback(Geom::Affine const *rel_transf, SPItem */*moved_item*/); void on_link_button_click(); void emit_changed(); diff --git a/src/live_effects/parameter/makefile.in b/src/live_effects/parameter/makefile.in deleted file mode 100644 index af48c8e7a..000000000 --- a/src/live_effects/parameter/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd ../.. && $(MAKE) live_effects/parameter/all - -clean %.a %.$(OBJEXT): - cd ../.. && $(MAKE) live_effects/parameter/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/live_effects/parameter/message.cpp b/src/live_effects/parameter/message.cpp new file mode 100644 index 000000000..39d8f12c7 --- /dev/null +++ b/src/live_effects/parameter/message.cpp @@ -0,0 +1,101 @@ +/* + * Authors: + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm.h> +#include "live_effects/parameter/message.h" +#include "live_effects/effect.h" +#include <glibmm/i18n.h> + +namespace Inkscape { + +namespace LivePathEffect { + +MessageParam::MessageParam( const Glib::ustring& label, const Glib::ustring& tip, + const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, + Effect* effect, const gchar * default_message ) + : Parameter(label, tip, key, wr, effect), + message(g_strdup(default_message)), + defmessage(g_strdup(default_message)) +{ + +} + +void +MessageParam::param_set_default() +{ + param_setValue(defmessage); +} + +void +MessageParam::param_update_default(const gchar * default_message) +{ + defmessage = g_strdup(default_message); +} + +bool +MessageParam::param_readSVGValue(const gchar * strvalue) +{ + param_setValue(strvalue); + return true; +} + +gchar * +MessageParam::param_getSVGValue() const +{ + return message; +} + +gchar * +MessageParam::param_getDefaultSVGValue() const +{ + return defmessage; +} + +Gtk::Widget * +MessageParam::param_newWidget() +{ + Gtk::Frame * frame = new Gtk::Frame (param_label); + Gtk::Widget * widg_frame = frame->get_label_widget(); + widg_frame->set_margin_right(5); + widg_frame->set_margin_left(5); + Gtk::Label * label = new Gtk::Label (message, Gtk::ALIGN_END); + label->set_use_underline (true); + label->set_use_markup(); + label->set_line_wrap(true); + Gtk::Widget * widg_label = dynamic_cast<Gtk::Widget *> (label); + widg_label->set_margin_top(8); + widg_label->set_margin_bottom(10); + widg_label->set_margin_right(6); + widg_label->set_margin_left(6); + + frame->add(*widg_label); + return dynamic_cast<Gtk::Widget *> (frame); +} + +void +MessageParam::param_setValue(const gchar * strvalue) +{ + if (strcmp(strvalue, message) != 0) { + param_effect->upd_params = true; + } + message = g_strdup(strvalue); +} + + +} /* namespace LivePathEffect */ + +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/message.h b/src/live_effects/parameter/message.h new file mode 100644 index 000000000..63075cf96 --- /dev/null +++ b/src/live_effects/parameter/message.h @@ -0,0 +1,61 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_MESSAGE_H +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_MESSAGE_H + +/* + * Inkscape::LivePathEffectParameters + * + * Authors: + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#include <glib.h> +#include "live_effects/parameter/parameter.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class MessageParam : public Parameter { +public: + MessageParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect, + const gchar * default_message = "Default message"); + virtual ~MessageParam() {} + + virtual Gtk::Widget * param_newWidget(); + virtual bool param_readSVGValue(const gchar * strvalue); + void param_update_default(const gchar * default_value); + virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; + + void param_setValue(const gchar * message); + + virtual void param_set_default(); + + const gchar * get_value() const { return message; }; + +private: + MessageParam(const MessageParam&); + MessageParam& operator=(const MessageParam&); + gchar * message; + gchar * defmessage; +}; + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/originalitem.cpp b/src/live_effects/parameter/originalitem.cpp index 81ab41c56..e828e1800 100644 --- a/src/live_effects/parameter/originalitem.cpp +++ b/src/live_effects/parameter/originalitem.cpp @@ -87,17 +87,16 @@ OriginalItemParam::param_newWidget() void OriginalItemParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/) { - if (!inverse) { - emit_changed(); - SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); - } + emit_changed(); + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); + last_transform = Geom::identity(); } void -OriginalItemParam::linked_transformed_callback(Geom::Affine const * /*rel_transf*/, SPItem * /*moved_item*/) +OriginalItemParam::linked_transformed_callback(Geom::Affine const * rel_transf, SPItem *moved_item) { -/** \todo find good way to compensate for referenced item transform, like done for normal clones. - * See sp-use.cpp: sp_use_move_compensate */ + last_transform = *rel_transf; + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); } diff --git a/src/live_effects/parameter/originalitem.h b/src/live_effects/parameter/originalitem.h index 58d04e05a..168728f86 100644 --- a/src/live_effects/parameter/originalitem.h +++ b/src/live_effects/parameter/originalitem.h @@ -23,7 +23,6 @@ public: Inkscape::UI::Widget::Registry* wr, Effect* effect); virtual ~OriginalItemParam(); - void setInverse(bool inversed) { inverse = inversed; } bool linksToItem() const { return (href != NULL); } SPItem * getObject() const { return ref.getObject(); } @@ -36,7 +35,6 @@ protected: void on_select_original_button_click(); private: - bool inverse; OriginalItemParam(const OriginalItemParam&); OriginalItemParam& operator=(const OriginalItemParam&); }; diff --git a/src/live_effects/parameter/originalitemarray.cpp b/src/live_effects/parameter/originalitemarray.cpp new file mode 100644 index 000000000..f45de4ad8 --- /dev/null +++ b/src/live_effects/parameter/originalitemarray.cpp @@ -0,0 +1,470 @@ +/* + * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com> + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "live_effects/parameter/originalitemarray.h" + +#include <gtkmm/widget.h> +#include <gtkmm/icontheme.h> +#include <gtkmm/imagemenuitem.h> +#include <gtkmm/separatormenuitem.h> +#include <gtkmm/scrolledwindow.h> + +#include <glibmm/i18n.h> + +#include "inkscape.h" +#include "ui/clipboard.h" +#include "svg/svg.h" +#include "svg/stringstream.h" +#include "originalitem.h" +#include "uri.h" + +#include "live_effects/effect.h" + +#include "verbs.h" +#include "document-undo.h" +#include "document.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class OriginalItemArrayParam::ModelColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + ModelColumns() + { + add(_colObject); + add(_colLabel); + add(_colActive); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn<ItemAndActive*> _colObject; + Gtk::TreeModelColumn<Glib::ustring> _colLabel; + Gtk::TreeModelColumn<bool> _colActive; +}; + +OriginalItemArrayParam::OriginalItemArrayParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect ) +: Parameter(label, tip, key, wr, effect), + _vector(), + _tree(), + _text_renderer(), + _toggle_active(), + _scroller() +{ + _model = new ModelColumns(); + _store = Gtk::TreeStore::create(*_model); + _tree.set_model(_store); + + _tree.set_reorderable(true); + _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Gtk::CellRendererToggle * _toggle_active = manage(new Gtk::CellRendererToggle()); + int activeColNum = _tree.append_column(_("Active"), *_toggle_active) - 1; + Gtk::TreeViewColumn* col_active = _tree.get_column(activeColNum); + _toggle_active->set_activatable(true); + _toggle_active->signal_toggled().connect(sigc::mem_fun(*this, &OriginalItemArrayParam::on_active_toggled)); + col_active->add_attribute(_toggle_active->property_active(), _model->_colActive); + + _text_renderer = manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column(_("Name"), *_text_renderer) - 1; + _name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + _tree.set_search_column(_model->_colLabel); + + //quick little hack -- newer versions of gtk gave the item zero space allotment + _scroller.set_size_request(-1, 120); + + _scroller.add(_tree); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + //_scroller.set_shadow_type(Gtk::SHADOW_IN); + + oncanvas_editable = true; +} + +OriginalItemArrayParam::~OriginalItemArrayParam() +{ + while (!_vector.empty()) { + ItemAndActive *w = _vector.back(); + _vector.pop_back(); + unlink(w); + delete w; + } + delete _model; +} + +void OriginalItemArrayParam::on_active_toggled(const Glib::ustring& item) +{ + Gtk::TreeModel::iterator iter = _store->get_iter(item); + Gtk::TreeModel::Row row = *iter; + ItemAndActive *w = row[_model->_colObject]; + row[_model->_colActive] = !row[_model->_colActive]; + w->actived = row[_model->_colActive]; + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Link item parameter to item")); +} + +void OriginalItemArrayParam::param_set_default() +{ + +} + +Gtk::Widget* OriginalItemArrayParam::param_newWidget() +{ + Gtk::VBox* vbox = Gtk::manage(new Gtk::VBox()); + Gtk::HBox* hbox = Gtk::manage(new Gtk::HBox()); + + vbox->pack_start(_scroller, Gtk::PACK_EXPAND_WIDGET); + + + { // Paste item to link button + Gtk::Image *pIcon = Gtk::manage(new Gtk::Image()); + pIcon->set_from_icon_name("edit-clone", Gtk::ICON_SIZE_BUTTON); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalItemArrayParam::on_link_button_click)); + hbox->pack_start(*pButton, Gtk::PACK_SHRINK); + pButton->set_tooltip_text(_("Link to item")); + } + + { // Remove linked item + Gtk::Image *pIcon = Gtk::manage(new Gtk::Image()); + pIcon->set_from_icon_name("gtk-remove", Gtk::ICON_SIZE_BUTTON); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalItemArrayParam::on_remove_button_click)); + hbox->pack_start(*pButton, Gtk::PACK_SHRINK); + pButton->set_tooltip_text(_("Remove Item")); + } + + { // Move Down + Gtk::Image *pIcon = Gtk::manage(new Gtk::Image()); + pIcon->set_from_icon_name( "gtk-go-down", Gtk::ICON_SIZE_BUTTON); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalItemArrayParam::on_down_button_click)); + hbox->pack_end(*pButton, Gtk::PACK_SHRINK); + pButton->set_tooltip_text(_("Move Down")); + } + + { // Move Down + Gtk::Image *pIcon = Gtk::manage(new Gtk::Image()); + pIcon->set_from_icon_name( "gtk-go-up", Gtk::ICON_SIZE_BUTTON); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalItemArrayParam::on_up_button_click)); + hbox->pack_end(*pButton, Gtk::PACK_SHRINK); + pButton->set_tooltip_text(_("Move Up")); + } + + vbox->pack_end(*hbox, Gtk::PACK_SHRINK); + + vbox->show_all_children(true); + + return vbox; +} + +bool OriginalItemArrayParam::_selectIndex(const Gtk::TreeIter& iter, int* i) +{ + if ((*i)-- <= 0) { + _tree.get_selection()->select(iter); + return true; + } + return false; +} + +void OriginalItemArrayParam::on_up_button_click() +{ + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + + int i = -1; + std::vector<ItemAndActive*>::iterator piter = _vector.begin(); + for (std::vector<ItemAndActive*>::iterator iter = _vector.begin(); iter != _vector.end(); piter = iter, i++, ++iter) { + if (*iter == row[_model->_colObject]) { + _vector.erase(iter); + _vector.insert(piter, row[_model->_colObject]); + break; + } + } + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Move item up")); + + _store->foreach_iter(sigc::bind<int*>(sigc::mem_fun(*this, &OriginalItemArrayParam::_selectIndex), &i)); + } +} + +void OriginalItemArrayParam::on_down_button_click() +{ + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + + int i = 0; + for (std::vector<ItemAndActive*>::iterator iter = _vector.begin(); iter != _vector.end(); i++, ++iter) { + if (*iter == row[_model->_colObject]) { + std::vector<ItemAndActive*>::iterator niter = _vector.erase(iter); + if (niter != _vector.end()) { + ++niter; + i++; + } + _vector.insert(niter, row[_model->_colObject]); + break; + } + } + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Move item down")); + + _store->foreach_iter(sigc::bind<int*>(sigc::mem_fun(*this, &OriginalItemArrayParam::_selectIndex), &i)); + } +} + +void OriginalItemArrayParam::on_remove_button_click() +{ + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + remove_link(row[_model->_colObject]); + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Remove item")); + } + +} + +void +OriginalItemArrayParam::on_link_button_click() +{ + Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); + //without second parameter populate all elements filled inside the called function + std::vector<Glib::ustring> itemsid = cm->getElementsOfType(SP_ACTIVE_DESKTOP); + + if (itemsid.empty()) { + return; + } + + bool foundOne = false; + Inkscape::SVGOStringStream os; + for (std::vector<ItemAndActive*>::const_iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + if (foundOne) { + os << "|"; + } else { + foundOne = true; + } + os << (*iter)->href << "," << ((*iter)->actived ? "1" : "0"); + } + for (auto i=itemsid.begin();i!=itemsid.end();++i) { + Glib::ustring itemid = *i; + // add '#' at start to make it an uri. + itemid.insert(itemid.begin(), '#'); + + if (foundOne) { + os << "|"; + } else { + foundOne = true; + } + os << itemid.c_str() << ",1"; + } + param_write_to_repr(os.str().c_str()); + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Link itemarray parameter to item")); +} + +void OriginalItemArrayParam::unlink(ItemAndActive* to) +{ + to->linked_modified_connection.disconnect(); + to->linked_delete_connection.disconnect(); + to->ref.detach(); + if (to->href) { + g_free(to->href); + to->href = NULL; + } +} + +void OriginalItemArrayParam::remove_link(ItemAndActive* to) +{ + unlink(to); + for (std::vector<ItemAndActive*>::iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + if (*iter == to) { + ItemAndActive *w = *iter; + _vector.erase(iter); + delete w; + return; + } + } +} + +void OriginalItemArrayParam::linked_delete(SPObject */*deleted*/, ItemAndActive* /*to*/) +{ + //remove_link(to); + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); +} + +bool OriginalItemArrayParam::_updateLink(const Gtk::TreeIter& iter, ItemAndActive* pd) +{ + Gtk::TreeModel::Row row = *iter; + if (row[_model->_colObject] == pd) { + SPObject *obj = pd->ref.getObject(); + row[_model->_colLabel] = obj && obj->getId() ? ( obj->label() ? obj->label() : obj->getId() ) : pd->href; + return true; + } + return false; +} + +void OriginalItemArrayParam::linked_changed(SPObject */*old_obj*/, SPObject *new_obj, ItemAndActive* to) +{ + to->linked_delete_connection.disconnect(); + to->linked_modified_connection.disconnect(); + to->linked_transformed_connection.disconnect(); + + if (new_obj && SP_IS_ITEM(new_obj)) { + to->linked_delete_connection = new_obj->connectDelete(sigc::bind<ItemAndActive*>(sigc::mem_fun(*this, &OriginalItemArrayParam::linked_delete), to)); + to->linked_modified_connection = new_obj->connectModified(sigc::bind<ItemAndActive*>(sigc::mem_fun(*this, &OriginalItemArrayParam::linked_modified), to)); + to->linked_transformed_connection = SP_ITEM(new_obj)->connectTransformed(sigc::bind<ItemAndActive*>(sigc::mem_fun(*this, &OriginalItemArrayParam::linked_transformed), to)); + + linked_modified(new_obj, SP_OBJECT_MODIFIED_FLAG, to); + } else { + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); + _store->foreach_iter(sigc::bind<ItemAndActive*>(sigc::mem_fun(*this, &OriginalItemArrayParam::_updateLink), to)); + } +} + +void OriginalItemArrayParam::linked_modified(SPObject *linked_obj, guint flags, ItemAndActive* to) +{ + if (!to) { + return; + } + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); + _store->foreach_iter(sigc::bind<ItemAndActive*>(sigc::mem_fun(*this, &OriginalItemArrayParam::_updateLink), to)); +} + +bool OriginalItemArrayParam::param_readSVGValue(const gchar* strvalue) +{ + if (strvalue) { + while (!_vector.empty()) { + ItemAndActive *w = _vector.back(); + unlink(w); + _vector.pop_back(); + delete w; + } + _store->clear(); + + gchar ** strarray = g_strsplit(strvalue, "|", 0); + for (gchar ** iter = strarray; *iter != NULL; iter++) { + if ((*iter)[0] == '#') { + gchar ** substrarray = g_strsplit(*iter, ",", 0); + ItemAndActive* w = new ItemAndActive((SPObject *)param_effect->getLPEObj()); + w->href = g_strdup(*substrarray); + w->actived = *(substrarray+1) != NULL && (*(substrarray+1))[0] == '1'; + w->linked_changed_connection = w->ref.changedSignal().connect(sigc::bind<ItemAndActive *>(sigc::mem_fun(*this, &OriginalItemArrayParam::linked_changed), w)); + w->ref.attach(URI(w->href)); + + _vector.push_back(w); + + Gtk::TreeModel::iterator iter = _store->append(); + Gtk::TreeModel::Row row = *iter; + SPObject *obj = w->ref.getObject(); + + row[_model->_colObject] = w; + row[_model->_colLabel] = obj ? ( obj->label() ? obj->label() : obj->getId() ) : w->href; + row[_model->_colActive] = w->actived; + g_strfreev (substrarray); + } + } + g_strfreev (strarray); + return true; + } + return false; +} + +gchar * OriginalItemArrayParam::param_getSVGValue() const +{ + Inkscape::SVGOStringStream os; + bool foundOne = false; + for (std::vector<ItemAndActive*>::const_iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + if (foundOne) { + os << "|"; + } else { + foundOne = true; + } + os << (*iter)->href << "," << ((*iter)->actived ? "1" : "0"); + } + gchar * str = g_strdup(os.str().c_str()); + return str; +} + +gchar * OriginalItemArrayParam::param_getDefaultSVGValue() const +{ + return g_strdup(""); +} + +void OriginalItemArrayParam::update() +{ + for (std::vector<ItemAndActive*>::iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + SPObject *linked_obj = (*iter)->ref.getObject(); + linked_modified(linked_obj, SP_OBJECT_MODIFIED_FLAG, *iter); + } +} + +} /* namespace LivePathEffect */ + +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/originalitemarray.h b/src/live_effects/parameter/originalitemarray.h new file mode 100644 index 000000000..f93d865ec --- /dev/null +++ b/src/live_effects/parameter/originalitemarray.h @@ -0,0 +1,122 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINALITEMARRAY_H +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINALITEMARRAY_H + +/* + * Inkscape::LivePathEffectParameters + * + * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com> + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <vector> + +#include <gtkmm/box.h> +#include <gtkmm/treeview.h> +#include <gtkmm/treestore.h> +#include <gtkmm/scrolledwindow.h> + +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/item-reference.h" + +#include "svg/svg.h" +#include "svg/stringstream.h" +#include "item-reference.h" +#include "sp-object.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class ItemAndActive { +public: + ItemAndActive(SPObject *owner) + : href(NULL), + ref(owner), + actived(true) + { + + } + gchar *href; + URIReference ref; + bool actived; + + sigc::connection linked_changed_connection; + sigc::connection linked_delete_connection; + sigc::connection linked_modified_connection; + sigc::connection linked_transformed_connection; +}; + +class OriginalItemArrayParam : public Parameter { +public: + class ModelColumns; + + OriginalItemArrayParam( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect); + + virtual ~OriginalItemArrayParam(); + + virtual Gtk::Widget * param_newWidget(); + virtual bool param_readSVGValue(const gchar * strvalue); + virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; + virtual void param_set_default(); + virtual void param_update_default(const gchar * default_value){}; + /** Disable the canvas indicators of parent class by overriding this method */ + virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {}; + /** Disable the canvas indicators of parent class by overriding this method */ + virtual void addCanvasIndicators(SPLPEItem const* /*lpeitem*/, std::vector<Geom::PathVector> & /*hp_vec*/) {}; + + std::vector<ItemAndActive*> _vector; + +protected: + bool _updateLink(const Gtk::TreeIter& iter, ItemAndActive* pd); + bool _selectIndex(const Gtk::TreeIter& iter, int* i); + void unlink(ItemAndActive* to); + void remove_link(ItemAndActive* to); + void setItem(SPObject *linked_obj, guint flags, ItemAndActive* to); + + void linked_changed(SPObject *old_obj, SPObject *new_obj, ItemAndActive* to); + void linked_modified(SPObject *linked_obj, guint flags, ItemAndActive* to); + void linked_transformed(Geom::Affine const *, SPItem *, ItemAndActive*) {} + void linked_delete(SPObject *deleted, ItemAndActive* to); + + ModelColumns *_model; + Glib::RefPtr<Gtk::TreeStore> _store; + Gtk::TreeView _tree; + Gtk::CellRendererText *_text_renderer; + Gtk::CellRendererToggle *_toggle_active; + Gtk::TreeView::Column *_name_column; + Gtk::ScrolledWindow _scroller; + + void on_link_button_click(); + void on_remove_button_click(); + void on_up_button_click(); + void on_down_button_click(); + void on_active_toggled(const Glib::ustring& item); + +private: + void update(); + OriginalItemArrayParam(const OriginalItemArrayParam&); + OriginalItemArrayParam& operator=(const OriginalItemArrayParam&); +}; + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/originalpath.cpp b/src/live_effects/parameter/originalpath.cpp index 62483d7fb..3f833d2ac 100644 --- a/src/live_effects/parameter/originalpath.cpp +++ b/src/live_effects/parameter/originalpath.cpp @@ -36,6 +36,7 @@ OriginalPathParam::OriginalPathParam( const Glib::ustring& label, const Glib::us : PathParam(label, tip, key, wr, effect, "") { oncanvas_editable = false; + _from_original_d = false; } OriginalPathParam::~OriginalPathParam() @@ -90,7 +91,11 @@ OriginalPathParam::linked_modified_callback(SPObject *linked_obj, guint /*flags* { SPCurve *curve = NULL; if (SP_IS_SHAPE(linked_obj)) { - curve = SP_SHAPE(linked_obj)->getCurve(); + if (_from_original_d) { + curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + } else { + curve = SP_SHAPE(linked_obj)->getCurve(); + } } if (SP_IS_TEXT(linked_obj)) { curve = SP_TEXT(linked_obj)->getNormalizedBpath(); diff --git a/src/live_effects/parameter/originalpath.h b/src/live_effects/parameter/originalpath.h index b3feec41f..ec80d1026 100644 --- a/src/live_effects/parameter/originalpath.h +++ b/src/live_effects/parameter/originalpath.h @@ -32,6 +32,7 @@ public: virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {}; /** Disable the canvas indicators of parent class by overriding this method */ virtual void addCanvasIndicators(SPLPEItem const* /*lpeitem*/, std::vector<Geom::PathVector> & /*hp_vec*/) {}; + void setFromOriginalD(bool from_original_d){ _from_original_d = from_original_d; }; protected: virtual void linked_modified_callback(SPObject *linked_obj, guint flags); @@ -40,6 +41,7 @@ protected: void on_select_original_button_click(); private: + bool _from_original_d; OriginalPathParam(const OriginalPathParam&); OriginalPathParam& operator=(const OriginalPathParam&); }; diff --git a/src/live_effects/parameter/originalpatharray.cpp b/src/live_effects/parameter/originalpatharray.cpp index 92859de05..a98c91770 100644 --- a/src/live_effects/parameter/originalpatharray.cpp +++ b/src/live_effects/parameter/originalpatharray.cpp @@ -9,6 +9,10 @@ #endif #include "live_effects/parameter/originalpatharray.h" +#include "live_effects/lpe-spiro.h" +#include "live_effects/lpe-bspline.h" +#include "live_effects/lpeobject.h" +#include "live_effects/lpeobject-reference.h" #include <gtkmm/widget.h> #include <gtkmm/icontheme.h> @@ -19,7 +23,6 @@ #include <glibmm/i18n.h> #include "inkscape.h" -#include "icon-size.h" #include "ui/clipboard.h" #include "svg/svg.h" #include "svg/stringstream.h" @@ -50,12 +53,14 @@ public: add(_colObject); add(_colLabel); add(_colReverse); + add(_colVisible); } virtual ~ModelColumns() {} - Gtk::TreeModelColumn<PathAndDirection*> _colObject; + Gtk::TreeModelColumn<PathAndDirectionAndVisible*> _colObject; Gtk::TreeModelColumn<Glib::ustring> _colLabel; Gtk::TreeModelColumn<bool> _colReverse; + Gtk::TreeModelColumn<bool> _colVisible; }; OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label, @@ -67,7 +72,8 @@ OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label, _vector(), _tree(), _text_renderer(), - _toggle_renderer(), + _toggle_reverse(), + _toggle_visible(), _scroller() { _model = new ModelColumns(); @@ -77,6 +83,22 @@ OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label, _tree.set_reorderable(true); _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Gtk::CellRendererToggle * _toggle_reverse = manage(new Gtk::CellRendererToggle()); + int reverseColNum = _tree.append_column(_("Reverse"), *_toggle_reverse) - 1; + Gtk::TreeViewColumn* col_reverse = _tree.get_column(reverseColNum); + _toggle_reverse->set_activatable(true); + _toggle_reverse->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_reverse_toggled)); + col_reverse->add_attribute(_toggle_reverse->property_active(), _model->_colReverse); + + + Gtk::CellRendererToggle * _toggle_visible = manage(new Gtk::CellRendererToggle()); + int visibleColNum = _tree.append_column(_("Visible"), *_toggle_visible) - 1; + Gtk::TreeViewColumn* col_visible = _tree.get_column(visibleColNum); + _toggle_visible->set_activatable(true); + _toggle_visible->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_visible_toggled)); + col_visible->add_attribute(_toggle_visible->property_active(), _model->_colVisible); + _text_renderer = manage(new Gtk::CellRendererText()); int nameColNum = _tree.append_column(_("Name"), *_text_renderer) - 1; _name_column = _tree.get_column(nameColNum); @@ -85,13 +107,6 @@ OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label, _tree.set_expander_column( *_tree.get_column(nameColNum) ); _tree.set_search_column(_model->_colLabel); - Gtk::CellRendererToggle * _toggle_renderer = manage(new Gtk::CellRendererToggle()); - int toggleColNum = _tree.append_column(_("Reverse"), *_toggle_renderer) - 1; - Gtk::TreeViewColumn* col = _tree.get_column(toggleColNum); - _toggle_renderer->set_activatable(true); - _toggle_renderer->signal_toggled().connect(sigc::mem_fun(*this, &OriginalPathArrayParam::on_reverse_toggled)); - col->add_attribute(_toggle_renderer->property_active(), _model->_colReverse); - //quick little hack -- newer versions of gtk gave the item zero space allotment _scroller.set_size_request(-1, 120); @@ -100,13 +115,15 @@ OriginalPathArrayParam::OriginalPathArrayParam( const Glib::ustring& label, //_scroller.set_shadow_type(Gtk::SHADOW_IN); oncanvas_editable = true; + _from_original_d = false; + _allow_only_bspline_spiro = false; } OriginalPathArrayParam::~OriginalPathArrayParam() { while (!_vector.empty()) { - PathAndDirection *w = _vector.back(); + PathAndDirectionAndVisible *w = _vector.back(); _vector.pop_back(); unlink(w); delete w; @@ -118,7 +135,7 @@ void OriginalPathArrayParam::on_reverse_toggled(const Glib::ustring& path) { Gtk::TreeModel::iterator iter = _store->get_iter(path); Gtk::TreeModel::Row row = *iter; - PathAndDirection *w = row[_model->_colObject]; + PathAndDirectionAndVisible *w = row[_model->_colObject]; row[_model->_colReverse] = !row[_model->_colReverse]; w->reversed = row[_model->_colReverse]; @@ -129,6 +146,21 @@ void OriginalPathArrayParam::on_reverse_toggled(const Glib::ustring& path) _("Link path parameter to path")); } +void OriginalPathArrayParam::on_visible_toggled(const Glib::ustring& path) +{ + Gtk::TreeModel::iterator iter = _store->get_iter(path); + Gtk::TreeModel::Row row = *iter; + PathAndDirectionAndVisible *w = row[_model->_colObject]; + row[_model->_colVisible] = !row[_model->_colVisible]; + w->visibled = row[_model->_colVisible]; + + gchar * full = param_getSVGValue(); + param_write_to_repr(full); + g_free(full); + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Toggle path parameter to path")); +} + void OriginalPathArrayParam::param_set_default() { @@ -217,8 +249,8 @@ void OriginalPathArrayParam::on_up_button_click() Gtk::TreeModel::Row row = *iter; int i = -1; - std::vector<PathAndDirection*>::iterator piter = _vector.begin(); - for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); piter = iter, i++, ++iter) { + std::vector<PathAndDirectionAndVisible*>::iterator piter = _vector.begin(); + for (std::vector<PathAndDirectionAndVisible*>::iterator iter = _vector.begin(); iter != _vector.end(); piter = iter, i++, ++iter) { if (*iter == row[_model->_colObject]) { _vector.erase(iter); _vector.insert(piter, row[_model->_colObject]); @@ -244,9 +276,9 @@ void OriginalPathArrayParam::on_down_button_click() Gtk::TreeModel::Row row = *iter; int i = 0; - for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); i++, ++iter) { + for (std::vector<PathAndDirectionAndVisible*>::iterator iter = _vector.begin(); iter != _vector.end(); i++, ++iter) { if (*iter == row[_model->_colObject]) { - std::vector<PathAndDirection*>::iterator niter = _vector.erase(iter); + std::vector<PathAndDirectionAndVisible*>::iterator niter = _vector.erase(iter); if (niter != _vector.end()) { ++niter; i++; @@ -288,37 +320,40 @@ void OriginalPathArrayParam::on_link_button_click() { Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); - Glib::ustring pathid = cm->getShapeOrTextObjectId(SP_ACTIVE_DESKTOP); - - if (pathid == "") { + std::vector<Glib::ustring> pathsid = cm->getElementsOfType(SP_ACTIVE_DESKTOP, "svg:path"); + std::vector<Glib::ustring> textsid = cm->getElementsOfType(SP_ACTIVE_DESKTOP, "svg:text"); + pathsid.insert(pathsid.end(), textsid.begin(), textsid.end()); + if (pathsid.empty()) { return; } - // add '#' at start to make it an uri. - pathid.insert(pathid.begin(), '#'); - - Inkscape::SVGOStringStream os; bool foundOne = false; - for (std::vector<PathAndDirection*>::const_iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + Inkscape::SVGOStringStream os; + for (std::vector<PathAndDirectionAndVisible*>::const_iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { if (foundOne) { os << "|"; } else { foundOne = true; } - os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0"); + os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0") << "," << ((*iter)->visibled ? "1" : "0"); } - - if (foundOne) { - os << "|"; + for (auto i=pathsid.begin();i!=pathsid.end();++i) { + Glib::ustring pathid = *i; + // add '#' at start to make it an uri. + pathid.insert(pathid.begin(), '#'); + + if (foundOne) { + os << "|"; + } else { + foundOne = true; + } + os << pathid.c_str() << ",0,1"; } - - os << pathid.c_str() << ",0"; - param_write_to_repr(os.str().c_str()); DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, - _("Link path parameter to path")); + _("Link patharray parameter to path")); } -void OriginalPathArrayParam::unlink(PathAndDirection* to) +void OriginalPathArrayParam::unlink(PathAndDirectionAndVisible* to) { to->linked_modified_connection.disconnect(); to->linked_delete_connection.disconnect(); @@ -327,15 +362,15 @@ void OriginalPathArrayParam::unlink(PathAndDirection* to) if (to->href) { g_free(to->href); to->href = NULL; - } + } } -void OriginalPathArrayParam::remove_link(PathAndDirection* to) +void OriginalPathArrayParam::remove_link(PathAndDirectionAndVisible* to) { unlink(to); - for (std::vector<PathAndDirection*>::iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + for (std::vector<PathAndDirectionAndVisible*>::iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { if (*iter == to) { - PathAndDirection *w = *iter; + PathAndDirectionAndVisible *w = *iter; _vector.erase(iter); delete w; return; @@ -343,7 +378,7 @@ void OriginalPathArrayParam::remove_link(PathAndDirection* to) } } -void OriginalPathArrayParam::linked_delete(SPObject */*deleted*/, PathAndDirection* /*to*/) +void OriginalPathArrayParam::linked_delete(SPObject */*deleted*/, PathAndDirectionAndVisible* /*to*/) { //remove_link(to); @@ -352,7 +387,7 @@ void OriginalPathArrayParam::linked_delete(SPObject */*deleted*/, PathAndDirecti g_free(full); } -bool OriginalPathArrayParam::_updateLink(const Gtk::TreeIter& iter, PathAndDirection* pd) +bool OriginalPathArrayParam::_updateLink(const Gtk::TreeIter& iter, PathAndDirectionAndVisible* pd) { Gtk::TreeModel::Row row = *iter; if (row[_model->_colObject] == pd) { @@ -363,35 +398,54 @@ bool OriginalPathArrayParam::_updateLink(const Gtk::TreeIter& iter, PathAndDirec return false; } -void OriginalPathArrayParam::linked_changed(SPObject */*old_obj*/, SPObject *new_obj, PathAndDirection* to) +void OriginalPathArrayParam::linked_changed(SPObject */*old_obj*/, SPObject *new_obj, PathAndDirectionAndVisible* to) { to->linked_delete_connection.disconnect(); to->linked_modified_connection.disconnect(); to->linked_transformed_connection.disconnect(); if (new_obj && SP_IS_ITEM(new_obj)) { - to->linked_delete_connection = new_obj->connectDelete(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_delete), to)); - to->linked_modified_connection = new_obj->connectModified(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_modified), to)); - to->linked_transformed_connection = SP_ITEM(new_obj)->connectTransformed(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_transformed), to)); + to->linked_delete_connection = new_obj->connectDelete(sigc::bind<PathAndDirectionAndVisible*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_delete), to)); + to->linked_modified_connection = new_obj->connectModified(sigc::bind<PathAndDirectionAndVisible*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_modified), to)); + to->linked_transformed_connection = SP_ITEM(new_obj)->connectTransformed(sigc::bind<PathAndDirectionAndVisible*>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_transformed), to)); linked_modified(new_obj, SP_OBJECT_MODIFIED_FLAG, to); } else { to->_pathvector = Geom::PathVector(); SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); - _store->foreach_iter(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to)); + _store->foreach_iter(sigc::bind<PathAndDirectionAndVisible*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to)); } } -void OriginalPathArrayParam::setPathVector(SPObject *linked_obj, guint /*flags*/, PathAndDirection* to) +void OriginalPathArrayParam::setPathVector(SPObject *linked_obj, guint /*flags*/, PathAndDirectionAndVisible* to) { if (!to) { return; } SPCurve *curve = NULL; if (SP_IS_SHAPE(linked_obj)) { - curve = SP_SHAPE(linked_obj)->getCurve(); - } - if (SP_IS_TEXT(linked_obj)) { + SPLPEItem * lpe_item = SP_LPE_ITEM(linked_obj); + if (_from_original_d) { + curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + } else if (_allow_only_bspline_spiro && lpe_item && lpe_item->hasPathEffect()){ + curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + PathEffectList lpelist = lpe_item->getEffectList(); + PathEffectList::iterator i; + for (i = lpelist.begin(); i != lpelist.end(); ++i) { + LivePathEffectObject *lpeobj = (*i)->lpeobject; + if (lpeobj) { + Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe(); + if (dynamic_cast<Inkscape::LivePathEffect::LPEBSpline *>(lpe)) { + LivePathEffect::sp_bspline_do_effect(curve, 0); + } else if (dynamic_cast<Inkscape::LivePathEffect::LPESpiro *>(lpe)) { + LivePathEffect::sp_spiro_do_effect(curve); + } + } + } + } else { + curve = SP_SHAPE(linked_obj)->getCurve(); + } + } else if (SP_IS_TEXT(linked_obj)) { curve = SP_TEXT(linked_obj)->getNormalizedBpath(); } @@ -404,21 +458,21 @@ void OriginalPathArrayParam::setPathVector(SPObject *linked_obj, guint /*flags*/ } } -void OriginalPathArrayParam::linked_modified(SPObject *linked_obj, guint flags, PathAndDirection* to) +void OriginalPathArrayParam::linked_modified(SPObject *linked_obj, guint flags, PathAndDirectionAndVisible* to) { if (!to) { return; } setPathVector(linked_obj, flags, to); SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); - _store->foreach_iter(sigc::bind<PathAndDirection*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to)); + _store->foreach_iter(sigc::bind<PathAndDirectionAndVisible*>(sigc::mem_fun(*this, &OriginalPathArrayParam::_updateLink), to)); } bool OriginalPathArrayParam::param_readSVGValue(const gchar* strvalue) { if (strvalue) { while (!_vector.empty()) { - PathAndDirection *w = _vector.back(); + PathAndDirectionAndVisible *w = _vector.back(); unlink(w); _vector.pop_back(); delete w; @@ -429,11 +483,12 @@ bool OriginalPathArrayParam::param_readSVGValue(const gchar* strvalue) for (gchar ** iter = strarray; *iter != NULL; iter++) { if ((*iter)[0] == '#') { gchar ** substrarray = g_strsplit(*iter, ",", 0); - PathAndDirection* w = new PathAndDirection((SPObject *)param_effect->getLPEObj()); + PathAndDirectionAndVisible* w = new PathAndDirectionAndVisible((SPObject *)param_effect->getLPEObj()); w->href = g_strdup(*substrarray); w->reversed = *(substrarray+1) != NULL && (*(substrarray+1))[0] == '1'; - - w->linked_changed_connection = w->ref.changedSignal().connect(sigc::bind<PathAndDirection *>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_changed), w)); + //Like this to make backwards compatible, new value added in 0.93 + w->visibled = *(substrarray+2) == NULL || (*(substrarray+2))[0] == '1'; + w->linked_changed_connection = w->ref.changedSignal().connect(sigc::bind<PathAndDirectionAndVisible *>(sigc::mem_fun(*this, &OriginalPathArrayParam::linked_changed), w)); w->ref.attach(URI(w->href)); _vector.push_back(w); @@ -445,6 +500,7 @@ bool OriginalPathArrayParam::param_readSVGValue(const gchar* strvalue) row[_model->_colObject] = w; row[_model->_colLabel] = obj ? ( obj->label() ? obj->label() : obj->getId() ) : w->href; row[_model->_colReverse] = w->reversed; + row[_model->_colVisible] = w->visibled; g_strfreev (substrarray); } } @@ -458,18 +514,31 @@ gchar * OriginalPathArrayParam::param_getSVGValue() const { Inkscape::SVGOStringStream os; bool foundOne = false; - for (std::vector<PathAndDirection*>::const_iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + for (std::vector<PathAndDirectionAndVisible*>::const_iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { if (foundOne) { os << "|"; } else { foundOne = true; } - os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0"); + os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0") << "," << ((*iter)->visibled ? "1" : "0"); } gchar * str = g_strdup(os.str().c_str()); return str; } +gchar * OriginalPathArrayParam::param_getDefaultSVGValue() const +{ + return ""; +} + +void OriginalPathArrayParam::update() +{ + for (std::vector<PathAndDirectionAndVisible*>::iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + SPObject *linked_obj = (*iter)->ref.getObject(); + linked_modified(linked_obj, SP_OBJECT_MODIFIED_FLAG, *iter); + } +} + } /* namespace LivePathEffect */ } /* namespace Inkscape */ diff --git a/src/live_effects/parameter/originalpatharray.h b/src/live_effects/parameter/originalpatharray.h index fe9371644..c80d5daf3 100644 --- a/src/live_effects/parameter/originalpatharray.h +++ b/src/live_effects/parameter/originalpatharray.h @@ -28,13 +28,14 @@ namespace Inkscape { namespace LivePathEffect { -class PathAndDirection { +class PathAndDirectionAndVisible { public: - PathAndDirection(SPObject *owner) + PathAndDirectionAndVisible(SPObject *owner) : href(NULL), ref(owner), _pathvector(Geom::PathVector()), - reversed(false) + reversed(false), + visibled(true) { } @@ -42,6 +43,7 @@ public: URIReference ref; Geom::PathVector _pathvector; bool reversed; + bool visibled; sigc::connection linked_changed_connection; sigc::connection linked_delete_connection; @@ -64,31 +66,36 @@ public: virtual Gtk::Widget * param_newWidget(); virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; virtual void param_set_default(); virtual void param_update_default(const gchar * default_value){}; /** Disable the canvas indicators of parent class by overriding this method */ virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {}; /** Disable the canvas indicators of parent class by overriding this method */ virtual void addCanvasIndicators(SPLPEItem const* /*lpeitem*/, std::vector<Geom::PathVector> & /*hp_vec*/) {}; - std::vector<PathAndDirection*> _vector; - + void setFromOriginalD(bool from_original_d){ _from_original_d = from_original_d; update();}; + void allowOnlyBsplineSpiro(bool allow_only_bspline_spiro){ _allow_only_bspline_spiro = allow_only_bspline_spiro; update();}; + + std::vector<PathAndDirectionAndVisible*> _vector; + protected: - bool _updateLink(const Gtk::TreeIter& iter, PathAndDirection* pd); + bool _updateLink(const Gtk::TreeIter& iter, PathAndDirectionAndVisible* pd); bool _selectIndex(const Gtk::TreeIter& iter, int* i); - void unlink(PathAndDirection* to); - void remove_link(PathAndDirection* to); - void setPathVector(SPObject *linked_obj, guint flags, PathAndDirection* to); + void unlink(PathAndDirectionAndVisible* to); + void remove_link(PathAndDirectionAndVisible* to); + void setPathVector(SPObject *linked_obj, guint flags, PathAndDirectionAndVisible* to); - void linked_changed(SPObject *old_obj, SPObject *new_obj, PathAndDirection* to); - void linked_modified(SPObject *linked_obj, guint flags, PathAndDirection* to); - void linked_transformed(Geom::Affine const *, SPItem *, PathAndDirection*) {} - void linked_delete(SPObject *deleted, PathAndDirection* to); + void linked_changed(SPObject *old_obj, SPObject *new_obj, PathAndDirectionAndVisible* to); + void linked_modified(SPObject *linked_obj, guint flags, PathAndDirectionAndVisible* to); + void linked_transformed(Geom::Affine const *, SPItem *, PathAndDirectionAndVisible*) {} + void linked_delete(SPObject *deleted, PathAndDirectionAndVisible* to); ModelColumns *_model; Glib::RefPtr<Gtk::TreeStore> _store; Gtk::TreeView _tree; Gtk::CellRendererText *_text_renderer; - Gtk::CellRendererToggle *_toggle_renderer; + Gtk::CellRendererToggle *_toggle_reverse; + Gtk::CellRendererToggle *_toggle_visible; Gtk::TreeView::Column *_name_column; Gtk::ScrolledWindow _scroller; @@ -97,8 +104,12 @@ protected: void on_up_button_click(); void on_down_button_click(); void on_reverse_toggled(const Glib::ustring& path); + void on_visible_toggled(const Glib::ustring& path); private: + bool _from_original_d; + bool _allow_only_bspline_spiro; + void update(); OriginalPathArrayParam(const OriginalPathArrayParam&); OriginalPathArrayParam& operator=(const OriginalPathArrayParam&); }; diff --git a/src/live_effects/parameter/parameter.cpp b/src/live_effects/parameter/parameter.cpp index 2f73488aa..319ab3fe8 100644 --- a/src/live_effects/parameter/parameter.cpp +++ b/src/live_effects/parameter/parameter.cpp @@ -95,6 +95,15 @@ ScalarParam::param_getSVGValue() const return str; } +gchar * +ScalarParam::param_getDefaultSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << defvalue; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + void ScalarParam::param_set_default() { diff --git a/src/live_effects/parameter/parameter.h b/src/live_effects/parameter/parameter.h index 7ab7e30dd..1586ef346 100644 --- a/src/live_effects/parameter/parameter.h +++ b/src/live_effects/parameter/parameter.h @@ -57,6 +57,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue) = 0; // returns true if new value is valid / accepted. virtual gchar * param_getSVGValue() const = 0; + virtual gchar * param_getDefaultSVGValue() const = 0; virtual void param_widget_is_visible(bool is_visible) {widget_is_visible = is_visible;} void write_to_SVG(); @@ -109,6 +110,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; virtual void param_set_default(); void param_update_default(gdouble default_value); diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp index ec011b855..bd6608737 100644 --- a/src/live_effects/parameter/path.cpp +++ b/src/live_effects/parameter/path.cpp @@ -68,6 +68,7 @@ PathParam::PathParam( const Glib::ustring& label, const Glib::ustring& tip, defvalue = g_strdup(default_value); param_readSVGValue(defvalue); oncanvas_editable = true; + _from_original_d = false; _edit_button = true; _copy_button = true; _paste_button = true; @@ -78,21 +79,24 @@ PathParam::PathParam( const Glib::ustring& label, const Glib::ustring& tip, PathParam::~PathParam() { remove_link(); - using namespace Inkscape::UI; - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) { - if (tools_isactive(desktop, TOOLS_NODES)) { - SPItem * item = SP_ACTIVE_DESKTOP->getSelection()->singleItem(); - if (item != NULL) { - Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(desktop->event_context); - std::set<ShapeRecord> shapes; - ShapeRecord r; - r.item = item; - shapes.insert(r); - nt->_multipath->setItems(shapes); - } - } - } +//TODO: Removed to fix a bug https://bugs.launchpad.net/inkscape/+bug/1716926 +// Maybe wee need to resurrect, not know when this code is added, but seems also not working now in a few test I do. +// in the future and do a deeper fix in multi-path-manipulator +// using namespace Inkscape::UI; +// SPDesktop *desktop = SP_ACTIVE_DESKTOP; +// if (desktop) { +// if (tools_isactive(desktop, TOOLS_NODES)) { +// SPItem * item = SP_ACTIVE_DESKTOP->getSelection()->singleItem(); +// if (item) { +// Inkscape::UI::Tools::NodeTool *nt = static_cast<Inkscape::UI::Tools::NodeTool*>(desktop->event_context); +// std::set<ShapeRecord> shapes; +// ShapeRecord r; +// r.item = item; +// shapes.insert(r); +// nt->_multipath->setItems(shapes); +// } +// } +// } g_free(defvalue); } @@ -169,6 +173,12 @@ PathParam::param_getSVGValue() const } } +gchar * +PathParam::param_getDefaultSVGValue() const +{ + return g_strdup(defvalue); +} + void PathParam::set_buttons(bool edit_button, bool copy_button, bool paste_button, bool link_button) { @@ -444,7 +454,11 @@ PathParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/) { SPCurve *curve = NULL; if (SP_IS_SHAPE(linked_obj)) { - curve = SP_SHAPE(linked_obj)->getCurve(); + if (_from_original_d) { + curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + } else { + curve = SP_SHAPE(linked_obj)->getCurve(); + } } if (SP_IS_TEXT(linked_obj)) { curve = SP_TEXT(linked_obj)->getNormalizedBpath(); diff --git a/src/live_effects/parameter/path.h b/src/live_effects/parameter/path.h index ff5e4f1b8..635056772 100644 --- a/src/live_effects/parameter/path.h +++ b/src/live_effects/parameter/path.h @@ -38,6 +38,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; virtual void param_set_default(); virtual void param_update_default(const gchar * default_value); @@ -50,6 +51,7 @@ public: virtual void addCanvasIndicators(SPLPEItem const* lpeitem, std::vector<Geom::PathVector> &hp_vec); virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/); + void setFromOriginalD(bool from_original_d){ _from_original_d = from_original_d; }; sigc::signal <void> signal_path_pasted; sigc::signal <void> signal_path_changed; @@ -91,6 +93,7 @@ protected: gchar * defvalue; private: + bool _from_original_d; bool _edit_button; bool _copy_button; bool _paste_button; diff --git a/src/live_effects/parameter/point.cpp b/src/live_effects/parameter/point.cpp index 331a86f81..da6edf812 100644 --- a/src/live_effects/parameter/point.cpp +++ b/src/live_effects/parameter/point.cpp @@ -115,6 +115,15 @@ PointParam::param_getSVGValue() const return str; } +gchar * +PointParam::param_getDefaultSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << defvalue; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + void PointParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/) { diff --git a/src/live_effects/parameter/point.h b/src/live_effects/parameter/point.h index a5153ad80..03256f6d0 100644 --- a/src/live_effects/parameter/point.h +++ b/src/live_effects/parameter/point.h @@ -38,6 +38,7 @@ public: bool param_readSVGValue(const gchar * strvalue); gchar * param_getSVGValue() const; + gchar * param_getDefaultSVGValue() const; inline const gchar *handleTip() const { return handle_tip ? handle_tip : param_tooltip.c_str(); } void param_setValue(Geom::Point newpoint, bool write = false); void param_set_default(); diff --git a/src/live_effects/parameter/random.cpp b/src/live_effects/parameter/random.cpp index b1375adda..c2c1b5440 100644 --- a/src/live_effects/parameter/random.cpp +++ b/src/live_effects/parameter/random.cpp @@ -71,6 +71,15 @@ RandomParam::param_getSVGValue() const return str; } +gchar * +RandomParam::param_getDefaultSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << defvalue << ';' << defseed; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + void RandomParam::param_set_default() { diff --git a/src/live_effects/parameter/random.h b/src/live_effects/parameter/random.h index 5fb6027ac..c10473e85 100644 --- a/src/live_effects/parameter/random.h +++ b/src/live_effects/parameter/random.h @@ -31,6 +31,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; virtual void param_set_default(); virtual Gtk::Widget * param_newWidget(); diff --git a/src/live_effects/parameter/text.cpp b/src/live_effects/parameter/text.cpp index f40708917..7e56b2c75 100644 --- a/src/live_effects/parameter/text.cpp +++ b/src/live_effects/parameter/text.cpp @@ -9,7 +9,7 @@ */ #include "ui/widget/registered-widget.h" -#include <glibmm/i18n.h> +#include <gtkmm/alignment.h> #include "live_effects/parameter/text.h" #include "live_effects/effect.h" @@ -18,9 +18,10 @@ #include "inkscape.h" #include "verbs.h" #include "display/canvas-text.h" - #include <2geom/sbasis-geometric.h> +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { @@ -115,6 +116,23 @@ TextParam::param_getSVGValue() const return str; } +gchar * +TextParam::param_getDefaultSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << defvalue; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + +void +TextParam::setTextParam(Inkscape::UI::Widget::RegisteredText *rsu) +{ + Glib::ustring str(rsu->getText()); + param_setValue(str); + write_to_SVG(); +} + Gtk::Widget * TextParam::param_newWidget() { @@ -122,9 +140,16 @@ TextParam::param_newWidget() param_label, param_tooltip, param_key, *param_wr, param_effect->getRepr(), param_effect->getSPDoc())); rsu->setText(value); rsu->setProgrammatically = false; - rsu->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change text parameter")); - return dynamic_cast<Gtk::Widget *> (rsu); + Gtk::Box *text_container = Gtk::manage(new Gtk::Box()); + Gtk::Button *set = Gtk::manage(new Gtk::Button(Glib::ustring("✔"))); + set->signal_clicked() + .connect(sigc::bind<Inkscape::UI::Widget::RegisteredText *>(sigc::mem_fun(*this, &TextParam::setTextParam),rsu)); + text_container->pack_start(*rsu, false, false, 2); + text_container->pack_start(*set, false, false, 2); + Gtk::Widget *return_widg = dynamic_cast<Gtk::Widget *> (text_container); + return_widg->set_halign(Gtk::ALIGN_END); + return return_widg; } void diff --git a/src/live_effects/parameter/text.h b/src/live_effects/parameter/text.h index 137f3ee02..a9de26a52 100644 --- a/src/live_effects/parameter/text.h +++ b/src/live_effects/parameter/text.h @@ -38,9 +38,11 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; void param_setValue(Glib::ustring newvalue); void param_hide_canvas_text(); + void setTextParam(Inkscape::UI::Widget::RegisteredText *rsu); virtual void param_set_default(); virtual void param_update_default(const gchar * default_value); void setPos(Geom::Point pos); diff --git a/src/live_effects/parameter/togglebutton.cpp b/src/live_effects/parameter/togglebutton.cpp index 6aad8b3a6..e26884d6a 100644 --- a/src/live_effects/parameter/togglebutton.cpp +++ b/src/live_effects/parameter/togglebutton.cpp @@ -59,6 +59,13 @@ ToggleButtonParam::param_getSVGValue() const return str; } +gchar * +ToggleButtonParam::param_getDefaultSVGValue() const +{ + gchar * str = g_strdup(defvalue ? "true" : "false"); + return str; +} + void ToggleButtonParam::param_update_default(bool default_value) { @@ -140,21 +147,25 @@ ToggleButtonParam::refresh_button() if(!box_button){ return; } - GList * childs = gtk_container_get_children(GTK_CONTAINER(box_button->gobj())); - guint total_widgets = g_list_length (childs); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(box_button))->get_children(); if (!param_label.empty()) { + Gtk::Label *lab = dynamic_cast<Gtk::Label*>(children[children.size()-1]); + if (!lab) return; if(value || inactive_label.empty()){ - gtk_label_set_text(GTK_LABEL(g_list_nth_data(childs, total_widgets-1)), param_label.c_str()); + lab->set_text(param_label.c_str()); }else{ - gtk_label_set_text(GTK_LABEL(g_list_nth_data(childs, total_widgets-1)), inactive_label.c_str()); + lab->set_text(inactive_label.c_str()); } } if ( _icon_active ) { GdkPixbuf * icon_pixbuf = NULL; + Gtk::Image *im = dynamic_cast<Gtk::Image*>(children[0]); + Gtk::IconSize is(_icon_size); + if (!im) return; if(!value){ - gtk_image_set_from_icon_name (GTK_IMAGE(g_list_nth_data(childs, 0)), _icon_inactive, _icon_size); + im->set_from_icon_name(_icon_inactive, is); } else { - gtk_image_set_from_icon_name (GTK_IMAGE(g_list_nth_data(childs, 0)), _icon_active, _icon_size); + im->set_from_icon_name(_icon_active, is); } } } diff --git a/src/live_effects/parameter/togglebutton.h b/src/live_effects/parameter/togglebutton.h index 02b9d5127..c5f8a3c28 100644 --- a/src/live_effects/parameter/togglebutton.h +++ b/src/live_effects/parameter/togglebutton.h @@ -12,7 +12,6 @@ #include <sigc++/signal.h> #include "live_effects/parameter/parameter.h" -#include "icon-size.h" #include "ui/widget/registered-widget.h" namespace Inkscape { @@ -41,6 +40,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; void param_setValue(bool newvalue); virtual void param_set_default(); diff --git a/src/live_effects/parameter/transformedpoint.cpp b/src/live_effects/parameter/transformedpoint.cpp index 22d5ba3a4..6ec2d0943 100644 --- a/src/live_effects/parameter/transformedpoint.cpp +++ b/src/live_effects/parameter/transformedpoint.cpp @@ -82,6 +82,15 @@ TransformedPointParam::param_getSVGValue() const return str; } +gchar * +TransformedPointParam::param_getDefaultSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << defvalue; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + void TransformedPointParam::param_update_default(Geom::Point default_point) { diff --git a/src/live_effects/parameter/transformedpoint.h b/src/live_effects/parameter/transformedpoint.h index 269cc508e..8b92d81ba 100644 --- a/src/live_effects/parameter/transformedpoint.h +++ b/src/live_effects/parameter/transformedpoint.h @@ -37,6 +37,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; Geom::Point getVector() const { return vector; }; Geom::Point getOrigin() const { return origin; }; diff --git a/src/live_effects/parameter/unit.cpp b/src/live_effects/parameter/unit.cpp index b9b91c1e6..9199e592d 100644 --- a/src/live_effects/parameter/unit.cpp +++ b/src/live_effects/parameter/unit.cpp @@ -48,6 +48,12 @@ UnitParam::param_getSVGValue() const return g_strdup(unit->abbr.c_str()); } +gchar * +UnitParam::param_getDefaultSVGValue() const +{ + return g_strdup(defunit->abbr.c_str()); +} + void UnitParam::param_set_default() { diff --git a/src/live_effects/parameter/unit.h b/src/live_effects/parameter/unit.h index c662b6edc..86e1a24b3 100644 --- a/src/live_effects/parameter/unit.h +++ b/src/live_effects/parameter/unit.h @@ -31,6 +31,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; virtual void param_set_default(); void param_set_value(Inkscape::Util::Unit const &val); virtual void param_update_default(const gchar * default_unit); diff --git a/src/live_effects/parameter/vector.cpp b/src/live_effects/parameter/vector.cpp index 470fa9c2d..6b565536e 100644 --- a/src/live_effects/parameter/vector.cpp +++ b/src/live_effects/parameter/vector.cpp @@ -101,6 +101,15 @@ VectorParam::param_getSVGValue() const return str; } +gchar * +VectorParam::param_getDefaultSVGValue() const +{ + Inkscape::SVGOStringStream os; + os << defvalue; + gchar * str = g_strdup(os.str().c_str()); + return str; +} + Gtk::Widget * VectorParam::param_newWidget() { diff --git a/src/live_effects/parameter/vector.h b/src/live_effects/parameter/vector.h index d270e9f43..8c842e805 100644 --- a/src/live_effects/parameter/vector.h +++ b/src/live_effects/parameter/vector.h @@ -36,6 +36,7 @@ public: virtual bool param_readSVGValue(const gchar * strvalue); virtual gchar * param_getSVGValue() const; + virtual gchar * param_getDefaultSVGValue() const; Geom::Point getVector() const { return vector; }; Geom::Point getOrigin() const { return origin; }; diff --git a/src/main.cpp b/src/main.cpp index 71014ee35..6e559692c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -59,6 +59,7 @@ #include "document.h" #include "layer-model.h" #include "selection.h" +#include "selection-chemistry.h" #include "ui/interface.h" #include "print.h" #include "color.h" @@ -180,7 +181,8 @@ enum { int sp_main_gui(int argc, char const **argv); int sp_main_console(int argc, char const **argv); -static int sp_do_export_png(SPDocument *doc); +static int do_export_png(SPDocument *doc); +static int do_export_svg(SPDocument* doc); static int do_export_ps_pdf(SPDocument* doc, gchar const* uri, char const *mime); static int do_export_emf(SPDocument* doc, gchar const* uri, char const *mime); static int do_export_wmf(SPDocument* doc, gchar const* uri, char const *mime); @@ -294,7 +296,7 @@ static void resetCommandlineGlobals() { #ifdef WIN32 static bool replaceArgs( int& argc, char**& argv ); #endif -static GSList *sp_process_args(poptContext ctx); +static std::vector<gchar *> sp_process_args(poptContext ctx); struct poptOption options[] = { {"version", 'V', POPT_ARG_NONE, NULL, SP_ARG_VERSION, @@ -353,7 +355,7 @@ struct poptOption options[] = { {"export-margin", 0, POPT_ARG_STRING, &sp_export_margin, SP_ARG_EXPORT_MARGIN, - N_("Only for PS/EPS/PDF, sets margin in mm around exported area (default 0)"), + N_("Sets margin around exported area (default 0) in units of page size for SVG and mm for PS/EPS/PDF"), N_("VALUE")}, {"export-area-snap", 0, @@ -700,10 +702,6 @@ main(int argc, char **argv) RegistryTool rt; rt.setPathInfo(); } - - // disable "client side decorations" as they prevent window borders and titlebars to be drawn with native theming - // see also https://bugzilla.gnome.org/show_bug.cgi?id=778791 - g_setenv("GTK_CSD", "0", FALSE); #endif set_extensions_env(); @@ -733,6 +731,7 @@ main(int argc, char **argv) || !strncmp(argv[i], "--export-png", 12) || !strcmp(argv[i], "-l") || !strncmp(argv[i], "--export-plain-svg", 18) + || !strncmp(argv[i], "--export-inkscape-svg", 21) || !strcmp(argv[i], "-i") || !strncmp(argv[i], "--export-area-drawing", 21) || !strcmp(argv[i], "-D") @@ -815,46 +814,19 @@ static void fixupSingleFilename( gchar **orig, gchar **spare ) -static GSList *fixupFilenameEncoding( GSList* fl ) +static void fixupFilenameEncoding( std::vector<gchar*> &filenames) { - GSList *newFl = NULL; - while ( fl ) { - gchar *fn = static_cast<gchar*>(fl->data); - fl = g_slist_remove( fl, fl->data ); + for (int i=0; i<filenames.size(); ++i ) { + gchar *fn = filenames[i]; gchar *newFileName = Inkscape::IO::locale_to_utf8_fallback(fn, -1, NULL, NULL, NULL); if ( newFileName ) { - - if ( 0 ) - { - gchar *safeFn = Inkscape::IO::sanitizeString(fn); - gchar *safeNewFn = Inkscape::IO::sanitizeString(newFileName); - GtkWidget *w = gtk_message_dialog_new( NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, - "Note: Converted '%s' to '%s'", safeFn, safeNewFn ); - gtk_dialog_run (GTK_DIALOG (w)); - gtk_widget_destroy (w); - g_free(safeNewFn); - g_free(safeFn); - } - g_free( fn ); - fn = newFileName; - newFileName = 0; - } - else - if ( 0 ) - { - gchar *safeFn = Inkscape::IO::sanitizeString(fn); - GtkWidget *w = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, "Error: Unable to convert '%s'", safeFn ); - gtk_dialog_run (GTK_DIALOG (w)); - gtk_widget_destroy (w); - g_free(safeFn); + filenames[i] = newFileName; } - newFl = g_slist_append( newFl, fn ); } - return newFl; } -static int sp_common_main( int argc, char const **argv, GSList **flDest ) +static int sp_common_main( int argc, char const **argv, std::vector<gchar*> *flDest ) { #ifdef ENABLE_NLS // temporarily switch gettext encoding to locale, so that help messages can be output properly @@ -866,7 +838,7 @@ static int sp_common_main( int argc, char const **argv, GSList **flDest ) g_return_val_if_fail(ctx != NULL, 1); /* Collect own arguments */ - GSList *fl = sp_process_args(ctx); + std::vector<gchar*> fl = sp_process_args(ctx); poptFreeContext(ctx); #ifdef ENABLE_NLS @@ -877,7 +849,7 @@ static int sp_common_main( int argc, char const **argv, GSList **flDest ) // Now let's see if the file list still holds up if ( needToRecodeParams ) { - fl = fixupFilenameEncoding( fl ); + fixupFilenameEncoding( fl ); } // Check the globals for filename-fixup @@ -916,12 +888,10 @@ static int sp_common_main( int argc, char const **argv, GSList **flDest ) // Return the list if wanted, else free it up. if ( flDest ) { - *flDest = fl; - fl = 0; + flDest->insert(flDest->end(),fl.begin(),fl.end()); } else { - while ( fl ) { - g_free( fl->data ); - fl = g_slist_remove( fl, fl->data ); + for (auto i:fl) { + g_free(i); } } return 0; @@ -931,7 +901,7 @@ namespace Inkscape { namespace UI { namespace Tools { -guint get_group0_keyval(GdkEventKey const* event, guint *consumed_modifiers = NULL); +guint get_latin_keyval(GdkEventKey const* event, guint *consumed_modifiers = NULL); } } @@ -989,7 +959,7 @@ snooper(GdkEvent *event, gpointer /*data*/) { alt_pressed = TRUE && (event->button.state & GDK_MOD1_MASK); break; case GDK_KEY_PRESS: - keyval = Inkscape::UI::Tools::get_group0_keyval(&event->key); + keyval = Inkscape::UI::Tools::get_latin_keyval(&event->key); if (keyval == GDK_KEY_Alt_L) altL_pressed = TRUE; if (keyval == GDK_KEY_Alt_R) altR_pressed = TRUE; alt_pressed = alt_pressed || altL_pressed || altR_pressed; @@ -1000,7 +970,7 @@ snooper(GdkEvent *event, gpointer /*data*/) { event->key.state &= ~GDK_MOD1_MASK; break; case GDK_KEY_RELEASE: - keyval = Inkscape::UI::Tools::get_group0_keyval(&event->key); + keyval = Inkscape::UI::Tools::get_latin_keyval(&event->key); if (keyval == GDK_KEY_Alt_L) altL_pressed = FALSE; if (keyval == GDK_KEY_Alt_R) altR_pressed = FALSE; if (!altL_pressed && !altR_pressed) @@ -1020,7 +990,7 @@ sp_main_gui(int argc, char const **argv) { Gtk::Main main_instance (&argc, const_cast<char ***>(&argv)); - GSList *fl = NULL; + std::vector<gchar *> fl; int retVal = sp_common_main( argc, argv, &fl ); g_return_val_if_fail(retVal == 0, 1); @@ -1036,11 +1006,10 @@ sp_main_gui(int argc, char const **argv) /// \todo FIXME BROKEN - non-UTF-8 sneaks in here. Inkscape::Application::create(argv[0], true); - while (fl) { - if (sp_file_open((gchar *)fl->data,NULL)) { + for (auto i:fl) { + if (sp_file_open(i,NULL)) { create_new=false; } - fl = g_slist_remove(fl, fl->data); } if (create_new) { sp_file_new_default(); @@ -1060,11 +1029,11 @@ sp_main_gui(int argc, char const **argv) /** * Process file list */ -static int sp_process_file_list(GSList *fl) +static int sp_process_file_list(std::vector<gchar*> fl) { int retVal = 0; #ifdef WITH_DBUS - if (!fl) { + if (fl.empty()) { // If we've been asked to listen for D-Bus messages, enter a main loop here // The main loop may be exited by calling "exit" on the D-Bus application interface. if (sp_dbus_listen) { @@ -1074,8 +1043,7 @@ static int sp_process_file_list(GSList *fl) } #endif // WITH_DBUS - while (fl) { - const gchar *filename = (gchar *)fl->data; + for (auto filename:fl) { SPDocument *doc = NULL; try { @@ -1128,51 +1096,10 @@ static int sp_process_file_list(GSList *fl) sp_print_document_to_file(doc, sp_global_printer); } if (sp_export_png || (sp_export_id && sp_export_use_hints)) { - retVal |= sp_do_export_png(doc); + retVal |= do_export_png(doc); } if (sp_export_svg || sp_export_inkscape_svg) { - if (sp_export_text_to_path) { - std::vector<SPItem*> items; - SPRoot *root = doc->getRoot(); - doc->ensureUpToDate(); - for (auto& iter: root->children) { - SPItem* item = (SPItem*) &iter; - if (! (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item) || SP_IS_GROUP(item))) { - continue; - } - - te_update_layout_now_recursive(item); - items.push_back(item); - } - - std::vector<SPItem*> selected; - std::vector<Inkscape::XML::Node*> to_select; - - sp_item_list_to_curves(items, selected, to_select); - - } - if(sp_export_id) { - doc->ensureUpToDate(); - - // "crop" the document to the specified object, cleaning as we go. - SPObject *obj = doc->getObjectById(sp_export_id); - if (sp_export_id_only) { - // If -j then remove all other objects to complete the "crop" - doc->getRoot()->cropToObject(obj); - } - Inkscape::ObjectSet s(doc); - s.set(obj); - s.fitCanvas(false); - } - if (sp_export_svg) { - Inkscape::Extension::save(Inkscape::Extension::db.get("org.inkscape.output.svg.plain"), doc, sp_export_svg, false, - false, false, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY); - } - if (sp_export_inkscape_svg) { - // Export as inkscape SVG. - Inkscape::Extension::save(Inkscape::Extension::db.get("org.inkscape.output.svg.inkscape"), doc, sp_export_inkscape_svg, false, - false, false, Inkscape::Extension::FILE_SAVE_METHOD_INKSCAPE_SVG); - } + retVal |= do_export_svg(doc); } if (sp_export_ps) { retVal |= do_export_ps_pdf(doc, sp_export_ps, "image/x-postscript"); @@ -1201,7 +1128,6 @@ static int sp_process_file_list(GSList *fl) delete doc; } - fl = g_slist_remove(fl, fl->data); } return retVal; } @@ -1258,7 +1184,7 @@ static int sp_main_shell(char const* command_name) poptContext ctx = poptGetContext(NULL, argc, const_cast<const gchar**>(argv), options, 0); poptSetOtherOptionHelp(ctx, _("[OPTIONS...] [FILE...]\n\nAvailable options:")); if ( ctx ) { - GSList *fl = sp_process_args(ctx); + std::vector<gchar *> fl = sp_process_args(ctx); if (sp_process_file_list(fl)) { retval = -1; } @@ -1297,11 +1223,11 @@ int sp_main_console(int argc, char const **argv) char **argv2 = const_cast<char **>(argv); gtk_init_check( &argc, &argv2 ); - GSList *fl = NULL; + std::vector<gchar*> fl; int retVal = sp_common_main( argc, argv, &fl ); g_return_val_if_fail(retVal == 0, 1); - if (fl == NULL && !sp_shell + if (fl.empty() && !sp_shell #ifdef WITH_DBUS && !sp_dbus_listen #endif // WITH_DBUS @@ -1397,8 +1323,13 @@ do_query_all_recurse (SPObject *o) } } +/** + * Perform a PNG export + * + * \param doc Document to export. + */ -static int sp_do_export_png(SPDocument *doc) +static int do_export_png(SPDocument *doc) { Glib::ustring filename; bool filename_from_hint = false; @@ -1607,12 +1538,10 @@ static int sp_do_export_png(SPDocument *doc) path = filename; } - int retcode = 0; //check if specified directory exists - if (!Inkscape::IO::file_directory_exists(filename.c_str())) { g_warning("File path \"%s\" includes directory that doesn't exist.\n", filename.c_str()); - retcode = 1; + return 1; } else { g_print("Background RRGGBBAA: %08x\n", bgcolor); @@ -1626,13 +1555,97 @@ static int sp_do_export_png(SPDocument *doc) g_print("Bitmap saved as: %s\n", filename.c_str()); } else { g_warning("Bitmap failed to save to: %s", filename.c_str()); + return 1; } } else { g_warning("Calculated bitmap dimensions %lu %lu are out of range (1 - %lu). Nothing exported.", width, height, (unsigned long int)PNG_UINT_31_MAX); + return 1; } } - return retcode; + return 0; +} + +/** + * Perform an SVG export + * + * \param doc Document to export. + */ + +static int do_export_svg(SPDocument* doc) +{ + if (sp_export_text_to_path) { + std::vector<SPItem*> items; + SPRoot *root = doc->getRoot(); + doc->ensureUpToDate(); + for (auto& iter: root->children) { + SPItem* item = (SPItem*) &iter; + if (! (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item) || SP_IS_GROUP(item))) { + continue; + } + + te_update_layout_now_recursive(item); + items.push_back(item); + } + + std::vector<SPItem*> selected; + std::vector<Inkscape::XML::Node*> to_select; + + sp_item_list_to_curves(items, selected, to_select); + + } + if (sp_export_margin) { + gdouble margin = g_ascii_strtod(sp_export_margin, NULL); + doc->ensureUpToDate(); + SPNamedView *nv; + Inkscape::XML::Node *nv_repr; + if ((nv = sp_document_namedview(doc, 0)) && (nv_repr = nv->getRepr())) { + sp_repr_set_svg_double(nv_repr, "fit-margin-top", margin); + sp_repr_set_svg_double(nv_repr, "fit-margin-left", margin); + sp_repr_set_svg_double(nv_repr, "fit-margin-right", margin); + sp_repr_set_svg_double(nv_repr, "fit-margin-bottom", margin); + } + } + if(sp_export_area_drawing) { + fit_canvas_to_drawing(doc, sp_export_margin ? true : false); + } + if(sp_export_id) { + doc->ensureUpToDate(); + + // "crop" the document to the specified object, cleaning as we go. + SPObject *obj = doc->getObjectById(sp_export_id); + if (sp_export_id_only) { + // If -j then remove all other objects to complete the "crop" + doc->getRoot()->cropToObject(obj); + } + Inkscape::ObjectSet s(doc); + s.set(obj); + if (!sp_export_area_page) { + s.fitCanvas(sp_export_margin ? true : false); + } + } + + int ret = 0; + if (sp_export_svg) { + try { + Inkscape::Extension::save(Inkscape::Extension::db.get("org.inkscape.output.svg.plain"), doc, sp_export_svg, false, + false, false, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY); + } catch (Inkscape::Extension::Output::save_failed &e) { + g_warning("Failed to save plain SVG to: %s", sp_export_svg); + ret = 1; + } + } + if (sp_export_inkscape_svg) { + // Export as inkscape SVG. + try { + Inkscape::Extension::save(Inkscape::Extension::db.get("org.inkscape.output.svg.inkscape"), doc, sp_export_inkscape_svg, false, + false, false, Inkscape::Extension::FILE_SAVE_METHOD_INKSCAPE_SVG); + } catch (Inkscape::Extension::Output::save_failed &e) { + g_warning("Failed to save Inkscape SVG to: %s", sp_export_inkscape_svg); + ret = 1; + } + } + return ret; } /** @@ -2131,10 +2144,10 @@ bool replaceArgs( int& argc, char**& argv ) } #endif // WIN32 -static GSList * +static std::vector<gchar *> sp_process_args(poptContext ctx) { - GSList *fl = NULL; + std::vector<gchar *> fl; gint a; while ((a = poptGetNextOpt(ctx)) != -1) { @@ -2142,7 +2155,7 @@ sp_process_args(poptContext ctx) case SP_ARG_FILE: { gchar const *fn = poptGetOptArg(ctx); if (fn != NULL) { - fl = g_slist_append(fl, g_strdup(fn)); + fl.push_back(g_strdup(fn)); } break; } @@ -2214,7 +2227,7 @@ sp_process_args(poptContext ctx) gchar const ** const args = poptGetArgs(ctx); if (args != NULL) { for (unsigned i = 0; args[i] != NULL; i++) { - fl = g_slist_append(fl, g_strdup(args[i])); + fl.push_back(g_strdup(args[i])); } } diff --git a/src/object-set.cpp b/src/object-set.cpp index 8fcb4215e..36ddac350 100644 --- a/src/object-set.cpp +++ b/src/object-set.cpp @@ -104,14 +104,18 @@ void ObjectSet::_removeDescendantsFromSet(SPObject *object) { } } -void ObjectSet::_remove(SPObject *object) { +void ObjectSet::_disconnect(SPObject *object) { _releaseConnections[object].disconnect(); _releaseConnections.erase(object); - _container.get<hashed>().erase(object); _remove3DBoxesRecursively(object); _releaseSignals(object); } +void ObjectSet::_remove(SPObject *object) { + _disconnect(object); + _container.get<hashed>().erase(object); +} + void ObjectSet::_add(SPObject *object) { _releaseConnections[object] = object->connectRelease(sigc::hide_return(sigc::mem_fun(*this, &ObjectSet::remove))); _container.push_back(object); @@ -120,9 +124,9 @@ void ObjectSet::_add(SPObject *object) { } void ObjectSet::_clear() { - for (auto object: _container) { - _remove(object); - } + for (auto object: _container) + _disconnect(object); + _container.clear(); } SPObject *ObjectSet::_getMutualAncestor(SPObject *object) { diff --git a/src/object-set.h b/src/object-set.h index 82d2988c7..a8061593a 100644 --- a/src/object-set.h +++ b/src/object-set.h @@ -370,7 +370,7 @@ public: bool unlinkRecursive(const bool skip_undo = false); void relink(); void cloneOriginal(); - void cloneOriginalPathLPE(); + void cloneOriginalPathLPE(bool allow_transforms = false); Inkscape::XML::Node* group(); void popFromGroup(); void ungroup(); @@ -476,6 +476,7 @@ protected: private: BoolOpErrors pathBoolOp(bool_op bop, const bool skip_undo, const unsigned int verb = SP_VERB_NONE, const Glib::ustring description = ""); + void _disconnect(SPObject* object); }; diff --git a/src/path-chemistry.cpp b/src/path-chemistry.cpp index 7840c4ca8..b824d15c7 100644 --- a/src/path-chemistry.cpp +++ b/src/path-chemistry.cpp @@ -237,13 +237,12 @@ ObjectSet::breakApart(bool skip_undo) item->deleteObject(false); - GSList *list = curve->split(); + std::list<SPCurve *> list = curve->split(); curve->unref(); std::vector<Inkscape::XML::Node*> reprs; - for (GSList *l = list; l != NULL; l = l->next) { - curve = (SPCurve *) l->data; + for (auto curve:list) { Inkscape::XML::Node *repr = parent->document()->createElement("svg:path"); repr->setAttribute("style", style); @@ -266,7 +265,7 @@ ObjectSet::breakApart(bool skip_undo) repr->setPosition(pos > 0 ? pos : 0); // if it's the first one, restore id - if (l == list) + if (curve == *(list.begin())) repr->setAttribute("id", id); reprs.push_back(repr); @@ -275,7 +274,6 @@ ObjectSet::breakApart(bool skip_undo) } setReprList(reprs); - g_slist_free(list); g_free(style); g_free(path_effect); } @@ -368,7 +366,12 @@ sp_item_list_to_curves(const std::vector<SPItem*> &items, std::vector<SPItem*>& { continue; } - + //TODO: decide if we want to unlink clones or not, for now keep previous functionality retaining clones as is + SPUse *use = dynamic_cast<SPUse *>(item); + if (use) { + continue; + } + SPPath *path = dynamic_cast<SPPath *>(item); if (path && !path->_curve_before_lpe) { // remove connector attributes @@ -395,9 +398,13 @@ sp_item_list_to_curves(const std::vector<SPItem*> &items, std::vector<SPItem*>& continue; } - + + SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(item); + if (lpeitem) { + lpeitem->removeAllPathEffects(true); + } + if (group) { - group->removeAllPathEffects(true); std::vector<SPItem*> item_list = sp_item_group_item_list(group); std::vector<Inkscape::XML::Node*> item_to_select; @@ -423,6 +430,8 @@ sp_item_list_to_curves(const std::vector<SPItem*> &items, std::vector<SPItem*>& Inkscape::XML::Node *parent = item->getRepr()->parent(); // remember id char const *id = item->getRepr()->attribute("id"); + // remember class + char const *class_attr = item->getRepr()->attribute("class"); // remember title gchar *title = item->title(); // remember description @@ -437,6 +446,8 @@ sp_item_list_to_curves(const std::vector<SPItem*> &items, std::vector<SPItem*>& // restore id repr->setAttribute("id", id); + // restore class + repr->setAttribute("class", class_attr); // add the new repr to the parent parent->appendChild(repr); SPObject* newObj = document->getObjectByRepr(repr); @@ -553,8 +564,6 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/) return g_repr; } - - SP_LPE_ITEM(item)->removeAllPathEffects(true); SPCurve *curve = NULL; { SPShape *shape = dynamic_cast<SPShape *>(item); diff --git a/src/path-prefix.h b/src/path-prefix.h index 1c17ce2d8..d6514d832 100644 --- a/src/path-prefix.h +++ b/src/path-prefix.h @@ -34,6 +34,7 @@ # define INKSCAPE_EXAMPLESDIR BR_DATADIR( INKSCAPE_LIBPREFIX "/share/inkscape/examples" ) # define INKSCAPE_EXTENSIONDIR BR_DATADIR( INKSCAPE_LIBPREFIX "/share/inkscape/extensions" ) # define INKSCAPE_FILTERDIR BR_DATADIR( INKSCAPE_LIBPREFIX "/share/inkscape/filters" ) +# define INKSCAPE_FONTSDIR BR_DATADIR( INKSCAPE_LIBPREFIX "/share/inkscape/fonts" ) # define INKSCAPE_GRADIENTSDIR BR_DATADIR( INKSCAPE_LIBPREFIX "/share/inkscape/gradients" ) # define INKSCAPE_KEYSDIR BR_DATADIR( INKSCAPE_LIBPREFIX "/share/inkscape/keys" ) # define INKSCAPE_PIXMAPDIR BR_DATADIR( INKSCAPE_LIBPREFIX "/share/inkscape/icons" ) @@ -58,6 +59,7 @@ # define INKSCAPE_EXAMPLESDIR WIN32_DATADIR("examples") # define INKSCAPE_EXTENSIONDIR WIN32_DATADIR("extensions") # define INKSCAPE_FILTERDIR WIN32_DATADIR("filters") +# define INKSCAPE_FONTSDIR WIN32_DATADIR("fonts") # define INKSCAPE_GRADIENTSDIR WIN32_DATADIR("gradients") # define INKSCAPE_KEYSDIR WIN32_DATADIR("keys") # define INKSCAPE_PIXMAPDIR WIN32_DATADIR("icons") @@ -81,6 +83,7 @@ # define INKSCAPE_EXAMPLESDIR "Contents/Resources/share/inkscape/examples" # define INKSCAPE_EXTENSIONDIR "Contents/Resources/share/inkscape/extensions" # define INKSCAPE_FILTERDIR "Contents/Resources/share/inkscape/filters" +# define INKSCAPE_FONTSDIR "Contents/Resources/share/inkscape/fonts" # define INKSCAPE_GRADIENTSDIR "Contents/Resources/share/inkscape/gradients" # define INKSCAPE_KEYSDIR "Contents/Resources/share/inkscape/keys" # define INKSCAPE_PIXMAPDIR "Contents/Resources/share/inkscape/icons" @@ -104,6 +107,7 @@ # define INKSCAPE_EXAMPLESDIR INKSCAPE_DATADIR "/inkscape/examples" # define INKSCAPE_EXTENSIONDIR INKSCAPE_DATADIR "/inkscape/extensions" # define INKSCAPE_FILTERDIR INKSCAPE_DATADIR "/inkscape/filters" +# define INKSCAPE_FONTSDIR INKSCAPE_DATADIR "/inkscape/fonts" # define INKSCAPE_GRADIENTSDIR INKSCAPE_DATADIR "/inkscape/gradients" # define INKSCAPE_KEYSDIR INKSCAPE_DATADIR "/inkscape/keys" # define INKSCAPE_PIXMAPDIR INKSCAPE_DATADIR "/inkscape/icons" diff --git a/src/preferences.cpp b/src/preferences.cpp index 4d14afa93..b02e71e46 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -76,7 +76,7 @@ public: _filter(filter) {} virtual ~PrefNodeObserver() {} - virtual void notifyAttributeChanged(XML::Node &node, GQuark name, Util::ptr_shared<char>, Util::ptr_shared<char>); + virtual void notifyAttributeChanged(XML::Node &node, GQuark name, Util::ptr_shared, Util::ptr_shared); private: Observer &_observer; Glib::ustring const _filter; @@ -147,7 +147,7 @@ void Preferences::_load() return; } // create some subdirectories for user stuff - char const *user_dirs[] = {"keys", "templates", "icons", "extensions", "palettes", NULL}; + char const *user_dirs[] = {"extensions", "fonts", "icons", "keys", "palettes", "templates", NULL}; for (int i=0; user_dirs[i]; ++i) { // XXX Why are we doing this here? shouldn't this be an IO load item? char *dir = Inkscape::IO::Resource::profile_path(user_dirs[i]); @@ -393,6 +393,9 @@ std::vector<Glib::ustring> Preferences::getAllDirs(Glib::ustring const &path) Inkscape::XML::Node *node = _getNode(path, false); if (node) { for (Inkscape::XML::NodeSiblingIterator i = node->firstChild(); i; ++i) { + if (i->attribute("id") == NULL) { + continue; + } temp.push_back(path + '/' + i->attribute("id")); } } @@ -561,7 +564,7 @@ Preferences::Observer::~Observer() prefs->removeObserver(*this); } -void Preferences::PrefNodeObserver::notifyAttributeChanged(XML::Node &node, GQuark name, Util::ptr_shared<char>, Util::ptr_shared<char> new_value) +void Preferences::PrefNodeObserver::notifyAttributeChanged(XML::Node &node, GQuark name, Util::ptr_shared, Util::ptr_shared new_value) { // filter out attributes we don't watch gchar const *attr_name = g_quark_to_string(name); @@ -702,6 +705,9 @@ Inkscape::XML::Node *Preferences::_getNode(Glib::ustring const &pref_key, bool c } for (child = node->firstChild(); child; child = child->next()) { + if (child->attribute("id") == NULL) { + continue; + } if (!strcmp(splits[part_i], child->attribute("id"))) { break; } diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index bac924980..0bd611163 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -761,6 +761,10 @@ Inkscape::XML::Node* ObjectSet::group() { group->setPosition(topmost + 1); set(doc->getObjectByRepr(group)); + SPLPEItem *lpeitem = dynamic_cast<SPLPEItem*>(*(items().begin())); + if (lpeitem) { + sp_lpe_item_update_patheffect(lpeitem, true, true); + } DocumentUndo::done(doc, SP_VERB_SELECTION_GROUP, C_("Verb", "Group")); @@ -768,18 +772,12 @@ Inkscape::XML::Node* ObjectSet::group() { } -static gint clone_depth_descending(gconstpointer a, gconstpointer b) { +static bool clone_depth_descending(gconstpointer a, gconstpointer b) { SPUse *use_a = static_cast<SPUse *>(const_cast<gpointer>(a)); SPUse *use_b = static_cast<SPUse *>(const_cast<gpointer>(b)); int depth_a = use_a->cloneDepth(); int depth_b = use_b->cloneDepth(); - if (depth_a < depth_b) { - return 1; - } else if (depth_a == depth_b) { - return 0; - } else { - return -1; - } + return (depth_a==depth_b)?(a<b):(depth_a>depth_b); } void ObjectSet::popFromGroup(){ @@ -822,7 +820,7 @@ static void ungroup_impl(ObjectSet *set) // If any of the clones refer to the groups, unlink them and replace them with successors // in the items list. - GSList *clones_to_unlink = NULL; + std::vector<SPUse*> clones_to_unlink; for (std::vector<SPItem*>::const_iterator item = items.begin(); item != items.end(); ++item) { SPUse *use = dynamic_cast<SPUse *>(*item); @@ -832,21 +830,19 @@ static void ungroup_impl(ObjectSet *set) } if (groups.find(original) != groups.end()) { - clones_to_unlink = g_slist_prepend(clones_to_unlink, *item); + clones_to_unlink.push_back(use); } } // Unlink clones beginning from those with highest clone depth. // This way we can be sure than no additional automatic unlinking happens, // and the items in the list remain valid - clones_to_unlink = g_slist_sort(clones_to_unlink, clone_depth_descending); + std::sort(clones_to_unlink.begin(),clones_to_unlink.end(),clone_depth_descending); - for (GSList *item = clones_to_unlink; item; item = item->next) { - SPUse *use = static_cast<SPUse *>(item->data); - std::vector<SPItem*>::iterator items_node = std::find(items.begin(),items.end(), item->data); + for (auto use:clones_to_unlink) { + std::vector<SPItem*>::iterator items_node = std::find(items.begin(),items.end(), use); *items_node = use->unlink(); } - g_slist_free(clones_to_unlink); // do the actual work for (std::vector<SPItem*>::iterator item = items.begin(); item != items.end(); ++item) { @@ -1666,7 +1662,7 @@ void ObjectSet::applyAffine(Geom::Affine const &affine, bool set_i2d, bool compe for (auto& itm: region.children) { SPUse *use = dynamic_cast<SPUse *>(&itm); if ( use ) { - use->doWriteTransform(use->getRepr(), item->transform.inverse(), NULL, compensate); + use->doWriteTransform(item->transform.inverse(), NULL, compensate); } } } @@ -1710,13 +1706,13 @@ void ObjectSet::applyAffine(Geom::Affine const &affine, bool set_i2d, bool compe if (prefs_parallel) { Geom::Affine move = result * clone_move * t_inv; - item->doWriteTransform(item->getRepr(), move, &move, compensate); + item->doWriteTransform(move, &move, compensate); } else if (prefs_unmoved) { //if (dynamic_cast<SPUse *>(sp_use_get_original(dynamic_cast<SPUse *>(item)))) // clone_move = Geom::identity(); Geom::Affine move = result * clone_move; - item->doWriteTransform(item->getRepr(), move, &t, compensate); + item->doWriteTransform(move, &t, compensate); } } else if (transform_offset_with_source && (prefs_parallel || prefs_unmoved) && affine.isTranslation()){ @@ -1725,23 +1721,23 @@ void ObjectSet::applyAffine(Geom::Affine const &affine, bool set_i2d, bool compe if (prefs_parallel) { Geom::Affine move = result * offset_move * t_inv; - item->doWriteTransform(item->getRepr(), move, &move, compensate); + item->doWriteTransform(move, &move, compensate); } else if (prefs_unmoved) { Geom::Affine move = result * offset_move; - item->doWriteTransform(item->getRepr(), move, &t, compensate); + item->doWriteTransform(move, &t, compensate); } } else { // just apply the result - item->doWriteTransform(item->getRepr(), result, &t, compensate); + item->doWriteTransform(result, &t, compensate); } } else { if (set_i2d) { item->set_i2d_affine(item->i2dt_affine() * (Geom::Affine)affine); } - item->doWriteTransform(item->getRepr(), item->transform, NULL, compensate); + item->doWriteTransform(item->transform, NULL, compensate); } if (adjust_transf_center) { // The transformation center should not be touched in case of pasting or importing, which is allowed by this if clause @@ -2101,8 +2097,6 @@ std::vector<SPItem*> sp_get_same_object_type(SPItem *sel, std::vector<SPItem*> & return matches; } -GSList *sp_get_same_fill_or_stroke_color(SPItem *sel, GSList *src, SPSelectStrokeStyleType type); - /* * Find all items in src list that have the same stroke style as sel by type * Return the list of matching items @@ -2339,14 +2333,15 @@ typedef struct Forward { static Iterator children(SPObject *o) { return o->firstChild(); } static Iterator siblings_after(SPObject *o) { return o->getNext(); } - static void dispose(Iterator /*i*/) {} + static void dispose(Iterator i) {} static SPObject *object(Iterator i) { return i; } static Iterator next(Iterator i) { return i->getNext(); } + static bool isNull(Iterator i) {return (!i);} } Forward; typedef struct ListReverse { - typedef GSList *Iterator; + typedef std::list<SPObject *> *Iterator; static Iterator children(SPObject *o) { return make_list(o, NULL); @@ -2355,23 +2350,24 @@ typedef struct ListReverse { return make_list(o->parent, o); } static void dispose(Iterator i) { - g_slist_free(i); + delete i; } static SPObject *object(Iterator i) { - return reinterpret_cast<SPObject *>(i->data); + return *(i->begin()); } - static Iterator next(Iterator i) { return i->next; } + static Iterator next(Iterator i) { i->pop_front(); return i; } + + static bool isNull(Iterator i) {return i->empty();} private: - static GSList *make_list(SPObject *object, SPObject *limit) { - GSList *list = NULL; + static std::list<SPObject *> *make_list(SPObject *object, SPObject *limit) { + auto list = new std::list<SPObject *>; for (auto &child: object->children) { if (&child == limit) { break; } - list = g_slist_prepend(list, &child); - + list->push_front(&child); } return list; } @@ -2380,7 +2376,7 @@ private: template <typename D> -SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root, +SPItem *next_item(SPDesktop *desktop, std::vector<SPObject *> &path, SPObject *root, bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive) { typename D::Iterator children; @@ -2388,22 +2384,24 @@ SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root, SPItem *found=NULL; - if (path) { - SPObject *object=reinterpret_cast<SPObject *>(path->data); + if (!path.empty()) { + SPObject *object=path.back(); + path.pop_back(); g_assert(object->parent == root); if (desktop->isLayer(object)) { - found = next_item<D>(desktop, path->next, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); + found = next_item<D>(desktop, path, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); } iter = children = D::siblings_after(object); } else { iter = children = D::children(root); } - while ( iter && !found ) { + while ( !D::isNull(iter) && !found ) { SPObject *object=D::object(iter); if (desktop->isLayer(object)) { if (PREFS_SELECTION_LAYER != inlayer) { // recurse into sublayers - found = next_item<D>(desktop, NULL, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); + std::vector<SPObject *> empt; + found = next_item<D>(desktop, empt, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); } } else { SPItem *item = dynamic_cast<SPItem *>(object); @@ -2440,19 +2438,19 @@ SPItem *next_item_from_list(SPDesktop *desktop, std::vector<SPItem*> const &item } } - GSList *path=NULL; + std::vector<SPObject *> path; while ( current != root ) { - path = g_slist_prepend(path, current); + path.push_back(current); current = current->parent; } SPItem *next; // first, try from the current object next = next_item<D>(desktop, path, root, only_in_viewport, inlayer, onlyvisible, onlysensitive); - g_slist_free(path); if (!next) { // if we ran out of objects, start over at the root - next = next_item<D>(desktop, NULL, root, only_in_viewport, inlayer, onlyvisible, onlysensitive); + std::vector<SPObject *> empt; + next = next_item<D>(desktop, empt, root, only_in_viewport, inlayer, onlyvisible, onlysensitive); } return next; @@ -2552,41 +2550,11 @@ void sp_selection_next_patheffect_param(SPDesktop * dt) void ObjectSet::editMask(bool /*clip*/) { return; - /*if (!dt) return; - using namespace Inkscape::UI; - - Inkscape::Selection *selection = dt->getSelection(); - if (!selection || selection->isEmpty()) return; - - GSList const *items = selection->itemList(); - bool has_path = false; - for (GSList *i = const_cast<GSList*>(items); i; i= i->next) { - SPItem *item = SP_ITEM(i->data); - SPObject *search = clip - ? (item->clip_ref ? item->clip_ref->getObject() : NULL) - : item->mask_ref ? item->mask_ref->getObject() : NULL; - has_path |= has_path_recursive(search); - if (has_path) break; - } - if (has_path) { - if (!tools_isactive(dt, TOOLS_NODES)) { - tools_switch(dt, TOOLS_NODES); - } - ink_node_tool_set_mode(INK_NODE_TOOL(dt->event_context), - clip ? NODE_TOOL_EDIT_CLIPPING_PATHS : NODE_TOOL_EDIT_MASKS); - } else if (clip) { - dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, - _("The selection has no applied clip path.")); - } else { - dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, - _("The selection has no applied mask.")); - }*/ } - /** * If \a item is not entirely visible then adjust visible area to centre on the centre on of * \a item. @@ -2849,18 +2817,6 @@ void ObjectSet::cloneOriginal() SPFlowtext *flowtext = dynamic_cast<SPFlowtext *>(item); if (flowtext) { original = flowtext->get_frame(NULL); // first frame only - } else { - SPLPEItem *lpeItem = dynamic_cast<SPLPEItem *>(item); - if (lpeItem) { - // check if the applied LPE is Clone original, if so, go to the refered path - Inkscape::LivePathEffect::Effect* lpe = lpeItem->getPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL); - if (lpe) { - Inkscape::LivePathEffect::Parameter *lpeparam = lpe->getParameter("linkedpath"); - if (Inkscape::LivePathEffect::OriginalPathParam *pathparam = dynamic_cast<Inkscape::LivePathEffect::OriginalPathParam *>(lpeparam)) { - original = pathparam->getObject(); - } - } - } } } } @@ -2915,35 +2871,44 @@ void ObjectSet::cloneOriginal() } /** -* This creates a new path, applies the Original Path LPE, and has it refer to the selection. +* This applies the Fill Between Many LPE, and has it refer to the selection. */ -void ObjectSet::cloneOriginalPathLPE() +void ObjectSet::cloneOriginalPathLPE(bool allow_transforms) { Inkscape::SVGOStringStream os; SPObject * firstItem = NULL; auto items_= items(); + bool multiple = false; for (auto i=items_.begin();i!=items_.end();++i){ if (SP_IS_SHAPE(*i) || SP_IS_TEXT(*i)) { if (firstItem) { os << "|"; + multiple = true; } else { firstItem = SP_ITEM(*i); } - os << '#' << SP_ITEM(*i)->getId() << ",0"; + os << '#' << SP_ITEM(*i)->getId() << ",0,1"; } } if (firstItem) { Inkscape::XML::Document *xml_doc = document()->getReprDoc(); SPObject *parent = firstItem->parent; - // create the LPE Inkscape::XML::Node *lpe_repr = xml_doc->createElement("inkscape:path-effect"); - { + if (multiple) { lpe_repr->setAttribute("effect", "fill_between_many"); lpe_repr->setAttribute("linkedpaths", os.str()); - document()->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to <defs> and assigns the 'id' attribute + lpe_repr->setAttribute("applied", "true"); + } else { + lpe_repr->setAttribute("effect", "clone_original"); + lpe_repr->setAttribute("linkeditem", ((Glib::ustring)"#" + (Glib::ustring)firstItem->getId()).c_str()); } + gchar const *method_str = allow_transforms ? "d" : "bsplinespiro"; + lpe_repr->setAttribute("method", method_str); + gchar const *allow_transforms_str = allow_transforms ? "true" : "false"; + lpe_repr->setAttribute("allow_transforms", allow_transforms_str); + document()->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to <defs> and assigns the 'id' attribute std::string lpe_id_href = std::string("#") + lpe_repr->attribute("id"); Inkscape::GC::release(lpe_repr); @@ -2953,18 +2918,21 @@ void ObjectSet::cloneOriginalPathLPE() clone->setAttribute("d", "M 0 0", false); // add the new clone to the top of the original's parent parent->appendChildRepr(clone); + // select the new object: + set(clone); + Inkscape::GC::release(clone); SPObject *clone_obj = document()->getObjectById(clone->attribute("id")); SPLPEItem *clone_lpeitem = dynamic_cast<SPLPEItem *>(clone_obj); if (clone_lpeitem) { clone_lpeitem->addPathEffect(lpe_id_href, false); } } + if (multiple) { + DocumentUndo::done(document(), SP_VERB_EDIT_CLONE_ORIGINAL_PATH_LPE, _("Fill between many")); + } else { + DocumentUndo::done(document(), SP_VERB_EDIT_CLONE_ORIGINAL_PATH_LPE, _("Clone original")); + } - DocumentUndo::done(document(), SP_VERB_EDIT_CLONE_ORIGINAL_PATH_LPE, _("Fill between many")); - // select the new object: - set(clone); - - Inkscape::GC::release(clone); } else { if(desktop()) desktop()->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select path(s) to fill.")); @@ -3171,7 +3139,7 @@ void ObjectSet::toSymbol() prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); // Remove transform on group, updating clones. - the_group->doWriteTransform(object->getRepr(), Geom::identity()); + the_group->doWriteTransform(Geom::identity()); // restore compensation setting prefs->setInt("/options/clonecompensation/value", saved_compensation); @@ -3483,7 +3451,7 @@ void ObjectSet::untile() if (i) { Geom::Affine transform( i->transform * pat_transform ); - i->doWriteTransform(i->getRepr(), transform); + i->doWriteTransform(transform); new_select.push_back(i); } else { @@ -3871,11 +3839,10 @@ void ObjectSet::setClipGroup() clone->setAttribute("inkscape:transform-center-x", inner->attribute("inkscape:transform-center-x"), false); clone->setAttribute("inkscape:transform-center-y", inner->attribute("inkscape:transform-center-y"), false); - const Geom::Affine maskTransform(Geom::Affine::identity()); std::vector<Inkscape::XML::Node*> templist; templist.push_back(clone); // add the new clone to the top of the original's parent - gchar const *mask_id = SPClipPath::create(templist, doc, &maskTransform); + gchar const *mask_id = SPClipPath::create(templist, doc); outer->setAttribute("clip-path", g_strdup_printf("url(#%s)", mask_id)); @@ -3933,7 +3900,7 @@ void ObjectSet::setClipGroup() clear(); // create a list of duplicates - std::vector<Inkscape::XML::Node*> mask_items; + std::vector<std::pair<Inkscape::XML::Node*, Geom::Affine>> mask_items; std::vector<SPItem*> apply_to_items; std::vector<SPItem*> items_to_delete; std::vector<SPItem*> items_to_select; @@ -3953,12 +3920,8 @@ void ObjectSet::setClipGroup() || (topmost && !apply_to_layer && *i == items_.back()) || apply_to_layer){ - Geom::Affine oldtr=(*i)->transform; - oldtr *= SP_ITEM((*i)->parent)->i2doc_affine().inverse(); - (*i)->doWriteTransform((*i)->getRepr(), (*i)->i2doc_affine()); Inkscape::XML::Node *dup = (*i)->getRepr()->duplicate(xml_doc); - (*i)->doWriteTransform((*i)->getRepr(), oldtr); - mask_items.push_back(dup); + mask_items.push_back(std::make_pair(dup, (*i)->i2doc_affine())); if (remove_original) { items_to_delete.push_back(*i); @@ -4003,11 +3966,15 @@ void ObjectSet::setClipGroup() gchar const *attributeName = apply_clip_path ? "clip-path" : "mask"; for (std::vector<SPItem*>::const_reverse_iterator i = apply_to_items.rbegin(); i != apply_to_items.rend(); ++i) { SPItem *item = reinterpret_cast<SPItem *>(*i); - // inverted object transform should be applied to a mask object, - // as mask is calculated in user space (after applying transform) + std::vector<Inkscape::XML::Node*> mask_items_dup; - for(std::vector<Inkscape::XML::Node*>::const_iterator it=mask_items.begin();it!=mask_items.end();++it) - mask_items_dup.push_back((*it)->duplicate(xml_doc)); + std::map<Inkscape::XML::Node*, Geom::Affine> dup_transf; + for (auto it = mask_items.begin(); it != mask_items.end(); ++it) { + Inkscape::XML::Node *dup = ((*it).first)->duplicate(xml_doc); + mask_items_dup.push_back(dup); + dup_transf[dup] = (*it).second; + } + Inkscape::XML::Node *current = SP_OBJECT(*i)->getRepr(); // Node to apply mask to Inkscape::XML::Node *apply_mask_to = current; @@ -4033,13 +4000,19 @@ void ObjectSet::setClipGroup() Inkscape::GC::release(group); } - Geom::Affine maskTransform(item->i2doc_affine().inverse()); - gchar const *mask_id = NULL; if (apply_clip_path) { - mask_id = SPClipPath::create(mask_items_dup, doc, &maskTransform); + mask_id = SPClipPath::create(mask_items_dup, doc); } else { - mask_id = sp_mask_create(mask_items_dup, doc, &maskTransform); + mask_id = sp_mask_create(mask_items_dup, doc); + } + + // inverted object transform should be applied to a mask object, + // as mask is calculated in user space (after applying transform) + for (auto it = mask_items_dup.begin(); it != mask_items_dup.end(); ++it) { + SPItem *clip_item = SP_ITEM(doc->getObjectByRepr(*it)); + clip_item->doWriteTransform(dup_transf[*it]); + clip_item->doWriteTransform(clip_item->transform * item->i2doc_affine().inverse()); } apply_mask_to->setAttribute(attributeName, Glib::ustring("url(#") + mask_id + ')'); @@ -4084,7 +4057,7 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { std::vector<SPItem*> items_(items().begin(), items().end()); clear(); - GSList *items_to_ungroup = NULL; + std::vector<SPGroup *> items_to_ungroup; std::vector<SPItem*> items_to_select(items_); @@ -4117,7 +4090,7 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { // ungroup only groups we created when setting clip/mask if (group->layerMode() == SPGroup::MASK_HELPER) { - items_to_ungroup = g_slist_prepend(items_to_ungroup, group); + items_to_ungroup.push_back(group); } } @@ -4126,7 +4099,7 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { // restore mask objects into a document for ( std::map<SPObject*,SPItem*>::iterator it = referenced_objects.begin() ; it != referenced_objects.end() ; ++it) { SPObject *obj = (*it).first; // Group containing the clipped paths or masks - GSList *items_to_move = NULL; + std::vector<Inkscape::XML::Node *> items_to_move; for (auto& child: obj->children) { // Collect all clipped paths and masks within a single group Inkscape::XML::Node *copy = child.getRepr()->duplicate(xml_doc); @@ -4134,7 +4107,7 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { { copy->setAttribute("d", copy->attribute("inkscape:original-d")); } - items_to_move = g_slist_prepend(items_to_move, copy); + items_to_move.push_back(copy); } if (!obj->isReferenced()) { @@ -4147,8 +4120,8 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { gint pos = ((*it).second)->getRepr()->position(); // Iterate through all clipped paths / masks - for (GSList *i = items_to_move; NULL != i; i = i->next) { - Inkscape::XML::Node *repr = static_cast<Inkscape::XML::Node *>(i->data); + for (auto i=items_to_move.rbegin();i!=items_to_move.rend();++i) { + Inkscape::XML::Node *repr = *i; // insert into parent, restore pos parent->appendChild(repr); @@ -4160,15 +4133,13 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { // transform mask, so it is moved the same spot where mask was applied Geom::Affine transform(mask_item->transform); transform *= (*it).second->transform; - mask_item->doWriteTransform(mask_item->getRepr(), transform); + mask_item->doWriteTransform(transform); } - - g_slist_free(items_to_move); } // ungroup marked groups added when setting mask - for (GSList *i = items_to_ungroup ; NULL != i ; i = i->next) { - SPGroup *group = dynamic_cast<SPGroup *>(static_cast<SPObject *>(i->data)); + for (auto i=items_to_ungroup.rbegin();i!=items_to_ungroup.rend();++i) { + SPGroup *group = *i; if (group) { items_to_select.erase(std::remove(items_to_select.begin(), items_to_select.end(), group), items_to_select.end()); std::vector<SPItem*> children; @@ -4179,8 +4150,6 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { } } - g_slist_free(items_to_ungroup); - // rebuild selection addList(items_to_select); diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp index 43fe1311d..5044864a4 100644 --- a/src/selection-describer.cpp +++ b/src/selection-describer.cpp @@ -15,6 +15,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif +#include <set> #include <glibmm/i18n.h> #include "xml/quote.h" @@ -33,16 +34,15 @@ // Returns a list of terms for the items to be used in the statusbar char* collect_terms (const std::vector<SPItem*> &items) { - GSList *check = NULL; + std::set<Glib::ustring> check; std::stringstream ss; bool first = true; for ( std::vector<SPItem*>::const_iterator iter=items.begin();iter!=items.end();++iter ) { SPItem *item = *iter; - if (item) { - const char *term = item->displayName(); - if (term != NULL && g_slist_find (check, term) == NULL) { - check = g_slist_prepend (check, (void *) term); + if (item && item->displayName()) { + Glib::ustring term(item->displayName()); + if (term != "" && (check.insert(term).second)) { ss << (first ? "" : ", ") << "<b>" << term << "</b>"; first = false; } @@ -54,14 +54,13 @@ char* collect_terms (const std::vector<SPItem*> &items) // Returns the number of terms in the list static int count_terms (const std::vector<SPItem*> &items) { - GSList *check = NULL; + std::set<Glib::ustring> check; int count=0; for ( std::vector<SPItem*>::const_iterator iter=items.begin();iter!=items.end();++iter ) { SPItem *item = *iter; - if (item) { - const char *term = item->displayName(); - if (term != NULL && g_slist_find (check, term) == NULL) { - check = g_slist_prepend (check, (void *) term); + if (item && item->displayName()) { + Glib::ustring term(item->displayName()); + if (term != "" && (check.insert(term).second)) { count++; } } diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 9e18bbe90..141720371 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -63,7 +63,7 @@ static gboolean sp_sel_trans_handle_event(SPKnot *knot, GdkEvent *event, SPSelTr case GDK_MOTION_NOTIFY: break; case GDK_KEY_PRESS: - if (Inkscape::UI::Tools::get_group0_keyval (&event->key) == GDK_KEY_space) { + if (Inkscape::UI::Tools::get_latin_keyval (&event->key) == GDK_KEY_space) { /* stamping mode: both mode(show content and outline) operation with knot */ if (!SP_KNOT_IS_GRABBED(knot)) { return FALSE; @@ -558,7 +558,7 @@ void Inkscape::SelTrans::stamp() new_affine = &original_item->transform; } - copy_item->doWriteTransform(copy_repr, *new_affine); + copy_item->doWriteTransform(*new_affine); if ( copy_item->isCenterSet() && _center ) { copy_item->setCenter(*_center * _current_relative_affine); @@ -1309,12 +1309,10 @@ gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state) // status text Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(pt[Geom::X], "px"); Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(pt[Geom::Y], "px"); - GString *xs = g_string_new(x_q.string(_desktop->namedview->display_units).c_str()); - GString *ys = g_string_new(y_q.string(_desktop->namedview->display_units).c_str()); - _message_context.setF(Inkscape::NORMAL_MESSAGE, _("Move <b>center</b> to %s, %s"), xs->str, ys->str); - g_string_free(xs, FALSE); - g_string_free(ys, FALSE); - + Glib::ustring xs(x_q.string(_desktop->namedview->display_units)); + Glib::ustring ys(y_q.string(_desktop->namedview->display_units)); + _message_context.setF(Inkscape::NORMAL_MESSAGE, _("Move <b>center</b> to %s, %s"), + xs.c_str(), ys.c_str()); return TRUE; } @@ -1455,11 +1453,11 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) // status text Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(dxy[Geom::X], "px"); Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(dxy[Geom::Y], "px"); - GString *xs = g_string_new(x_q.string(_desktop->namedview->display_units).c_str()); - GString *ys = g_string_new(y_q.string(_desktop->namedview->display_units).c_str()); - _message_context.setF(Inkscape::NORMAL_MESSAGE, _("<b>Move</b> by %s, %s; with <b>Ctrl</b> to restrict to horizontal/vertical; with <b>Shift</b> to disable snapping"), xs->str, ys->str); - g_string_free(xs, TRUE); - g_string_free(ys, TRUE); + Glib::ustring xs(x_q.string(_desktop->namedview->display_units)); + Glib::ustring ys(y_q.string(_desktop->namedview->display_units)); + _message_context.setF(Inkscape::NORMAL_MESSAGE, + _("<b>Move</b> by %s, %s; with <b>Ctrl</b> to restrict to horizontal/vertical; with <b>Shift</b> to disable snapping"), + xs.c_str(), ys.c_str()); } // Given a location of a handle at the visual bounding box, find the corresponding location at the diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp index c1677ca51..0a1e0c4a9 100644 --- a/src/shortcuts.cpp +++ b/src/shortcuts.cpp @@ -153,7 +153,7 @@ guint sp_shortcut_translate_event(GdkEventKey const *event, guint *effective_mod guint remaining_modifiers = 0; guint resulting_modifiers = 0; // remaining modifiers encoded in high-bit mask - keyval = Inkscape::UI::Tools::get_group0_keyval(event, &consumed_modifiers); + keyval = Inkscape::UI::Tools::get_latin_keyval(event, &consumed_modifiers); remaining_modifiers = initial_modifiers & ~consumed_modifiers; resulting_modifiers = ( remaining_modifiers & GDK_SHIFT_MASK ? SP_SHORTCUT_SHIFT_MASK : 0 ) | @@ -485,7 +485,7 @@ void sp_shortcut_file_export_do(char const *exportname) { * Shortcut file consists of pairs of bind elements : * Element (a) is used for shortcut display in menus (display="True") and contains the gdk_keyval_name of the shortcut key * Element (b) is used in shortcut lookup and contains an uppercase version of the gdk_keyval_name, - * or a gdk_keyval_name name and the "Shift" modifier for Shift altered hardware code keys (see get_group0_keyval() for explanation) + * or a gdk_keyval_name name and the "Shift" modifier for Shift altered hardware code keys (see get_latin_keyval() for explanation) */ void sp_shortcut_delete_from_file(char const * /*action*/, unsigned int const shortcut) { diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp index 1829837d8..d3a3810cb 100644 --- a/src/sp-clippath.cpp +++ b/src/sp-clippath.cpp @@ -126,18 +126,13 @@ void SPClipPath::update(SPCtx* ctx, unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for (auto child:l) { if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->updateDisplay(ctx, flags); } @@ -165,22 +160,16 @@ void SPClipPath::modified(unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for (auto child:l) { if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } - sp_object_unref(child); } } @@ -292,7 +281,7 @@ sp_clippath_view_list_remove(SPClipPathView *list, SPClipPathView *view) } // Create a mask element (using passed elements), add it to <defs> -const gchar *SPClipPath::create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, Geom::Affine const* applyTransform) +const gchar *SPClipPath::create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document) { Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); @@ -306,12 +295,7 @@ const gchar *SPClipPath::create (std::vector<Inkscape::XML::Node*> &reprs, SPDoc for (std::vector<Inkscape::XML::Node*>::const_iterator it = reprs.begin(); it != reprs.end(); ++it) { Inkscape::XML::Node *node = (*it); - SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node)); - - if (NULL != applyTransform) { - Geom::Affine transform (item->transform * (*applyTransform)); - item->doWriteTransform(item->getRepr(), transform); - } + clip_path_object->appendChildRepr(node); } Inkscape::GC::release(repr); diff --git a/src/sp-clippath.h b/src/sp-clippath.h index 129f3b7f3..87b5be92c 100644 --- a/src/sp-clippath.h +++ b/src/sp-clippath.h @@ -43,7 +43,7 @@ public: unsigned int clipPathUnits : 1; SPClipPathView *display; - static char const *create(std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, Geom::Affine const* applyTransform); + static char const *create(std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document); //static GType sp_clippath_get_type(void); Inkscape::DrawingItem *show(Inkscape::Drawing &drawing, unsigned int key); diff --git a/src/sp-defs.cpp b/src/sp-defs.cpp index 865c6891e..619a27c0f 100644 --- a/src/sp-defs.cpp +++ b/src/sp-defs.cpp @@ -52,18 +52,13 @@ void SPDefs::modified(unsigned int flags) { } flags &= SP_OBJECT_MODIFIED_CASCADE; - - GSList *l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); + for (auto child:l) { if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } @@ -78,20 +73,17 @@ Inkscape::XML::Node* SPDefs::write(Inkscape::XML::Document *xml_doc, Inkscape::X repr = xml_doc->createElement("svg:defs"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, NULL, flags); if (crepr) { - l = g_slist_prepend(l, crepr); + l.push_back(crepr); } } - - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } - } else { for (auto& child: children) { child.updateRepr(flags); diff --git a/src/sp-dimensions.cpp b/src/sp-dimensions.cpp new file mode 100644 index 000000000..f39b98945 --- /dev/null +++ b/src/sp-dimensions.cpp @@ -0,0 +1,55 @@ +/* + * SVG dimensions implementation + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Edward Flick (EAF) + * Abhishek Sharma + * Jon A. Cruz <jon@joncruz.org> + * + * Copyright (C) 1999-2005 Authors + * Copyright (C) 2000-2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include "sp-dimensions.h" +#include "sp-item.h" + +void SPDimensions::calcDimsFromParentViewport(const SPItemCtx *ictx, bool assign_to_set) +{ +#define ASSIGN(field) { if (assign_to_set) { field._set = true; } } + if (this->x.unit == SVGLength::PERCENT) { + ASSIGN(x); + this->x.computed = this->x.value * ictx->viewport.width(); + } + + if (this->y.unit == SVGLength::PERCENT) { + ASSIGN(y); + this->y.computed = this->y.value * ictx->viewport.height(); + } + + if (this->width.unit == SVGLength::PERCENT) { + ASSIGN(width); + this->width.computed = this->width.value * ictx->viewport.width(); + } + + if (this->height.unit == SVGLength::PERCENT) { + ASSIGN(height); + this->height.computed = this->height.value * ictx->viewport.height(); + } +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/sp-dimensions.h b/src/sp-dimensions.h new file mode 100644 index 000000000..eb76df739 --- /dev/null +++ b/src/sp-dimensions.h @@ -0,0 +1,41 @@ +#ifndef SP_DIMENSIONS_H__ +#define SP_DIMENSIONS_H__ + +/* + * dimensions helper class, common code used by root, image and others + * + * Authors: + * Shlomi Fish + * Copyright (C) 2017 Shlomi Fish, authors + * + * Released under dual Expat and GNU GPL, read the file 'COPYING' for more information + * + */ + +#include "svg/svg-length.h" + +class SPItemCtx; + +class SPDimensions { + +public: + SVGLength x; + SVGLength y; + SVGLength width; + SVGLength height; + void calcDimsFromParentViewport(const SPItemCtx *ictx, bool assign_to_set = false); +}; + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-basic-offset:2 + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=2:tabstop=8:softtabstop=2:fileencoding=utf-8:textwidth=99 : diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index 30c1096ca..166237c8e 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -17,6 +17,8 @@ #include <glibmm.h> #include <glibmm/i18n.h> +#include "live_effects/effect.h" + #include <2geom/angle.h> #include <2geom/circle.h> #include <2geom/ellipse.h> @@ -501,11 +503,18 @@ void SPGenericEllipse::set_shape(bool force) Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform) { - // Allow live effects - if (hasPathEffect() && pathEffectsEnabled()) { + if (hasPathEffect() && pathEffectsEnabled() && + (this->hasPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::BEND_PATH) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::FILL_BETWEEN_MANY) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::FILL_BETWEEN_STROKES) ) ) + { + // if path has this LPE applied, don't write the transform to the pathdata, but write it 'unoptimized' + // also if the effect is type BEND PATH to fix bug #179842 + this->adjust_livepatheffect(xform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return xform; } - /* Calculate ellipse start in parent coords. */ Geom::Point pos(Geom::Point(this->cx.computed, this->cy.computed) * xform); @@ -555,6 +564,9 @@ Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform) // Adjust gradient fill this->adjust_gradient(xform * ret.inverse()); + // Adjust livepatheffect + this->adjust_livepatheffect(xform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return ret; diff --git a/src/sp-filter-primitive.cpp b/src/sp-filter-primitive.cpp index 0fbeed15b..7ced52e11 100644 --- a/src/sp-filter-primitive.cpp +++ b/src/sp-filter-primitive.cpp @@ -139,25 +139,7 @@ void SPFilterPrimitive::update(SPCtx *ctx, guint flags) { SPFilter *parent = SP_FILTER(this->parent); if( parent->primitiveUnits == SP_FILTER_UNITS_USERSPACEONUSE ) { - if (this->x.unit == SVGLength::PERCENT) { - this->x._set = true; - this->x.computed = this->x.value * ictx->viewport.width(); - } - - if (this->y.unit == SVGLength::PERCENT) { - this->y._set = true; - this->y.computed = this->y.value * ictx->viewport.height(); - } - - if (this->width.unit == SVGLength::PERCENT) { - this->width._set = true; - this->width.computed = this->width.value * ictx->viewport.width(); - } - - if (this->height.unit == SVGLength::PERCENT) { - this->height._set = true; - this->height.computed = this->height.value * ictx->viewport.height(); - } + this->calcDimsFromParentViewport(ictx, true); } SPObject::update(ctx, flags); diff --git a/src/sp-filter-primitive.h b/src/sp-filter-primitive.h index d81adbd10..0ecb8af62 100644 --- a/src/sp-filter-primitive.h +++ b/src/sp-filter-primitive.h @@ -15,6 +15,7 @@ */ #include "sp-object.h" +#include "sp-dimensions.h" #include "svg/svg-length.h" #define SP_FILTER_PRIMITIVE(obj) (dynamic_cast<SPFilterPrimitive*>((SPObject*)obj)) @@ -26,16 +27,13 @@ class Filter; class FilterPrimitive; } } -class SPFilterPrimitive : public SPObject { +class SPFilterPrimitive : public SPObject, public SPDimensions { public: SPFilterPrimitive(); virtual ~SPFilterPrimitive(); int image_in, image_out; - /* filter primitive subregion */ - SVGLength x, y, height, width; - protected: virtual void build(SPDocument* doc, Inkscape::XML::Node* repr); virtual void release(); diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp index 052fa7fe2..aa5fe2942 100644 --- a/src/sp-filter.cpp +++ b/src/sp-filter.cpp @@ -213,25 +213,7 @@ void SPFilter::update(SPCtx *ctx, guint flags) { // Note: This only works for root viewport since this routine is not called after // setting a new viewport. A true fix requires a strategy like SPItemView or SPMarkerView. if(this->filterUnits == SP_FILTER_UNITS_USERSPACEONUSE) { - if (this->x.unit == SVGLength::PERCENT) { - this->x._set = true; - this->x.computed = this->x.value * ictx->viewport.width(); - } - - if (this->y.unit == SVGLength::PERCENT) { - this->y._set = true; - this->y.computed = this->y.value * ictx->viewport.height(); - } - - if (this->width.unit == SVGLength::PERCENT) { - this->width._set = true; - this->width.computed = this->width.value * ictx->viewport.width(); - } - - if (this->height.unit == SVGLength::PERCENT) { - this->height._set = true; - this->height.computed = this->height.value * ictx->viewport.height(); - } + this->calcDimsFromParentViewport(ictx, true); } /* do something to trigger redisplay, updates? */ @@ -267,19 +249,18 @@ Inkscape::XML::Node* SPFilter::write(Inkscape::XML::Document *doc, Inkscape::XML repr = doc->createElement("svg:filter"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node *crepr = child.updateRepr(doc, NULL, flags); if (crepr) { - l = g_slist_prepend (l, crepr); + l.push_back(crepr); } } - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove (l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { diff --git a/src/sp-filter.h b/src/sp-filter.h index 1c214c6b7..054562d39 100644 --- a/src/sp-filter.h +++ b/src/sp-filter.h @@ -16,6 +16,7 @@ #include <map> #include "number-opt-number.h" +#include "sp-dimensions.h" #include "sp-object.h" #include "sp-filter-units.h" #include "svg/svg-length.h" @@ -38,7 +39,7 @@ struct ltstr { bool operator()(const char* s1, const char* s2) const; }; -class SPFilter : public SPObject { +class SPFilter : public SPObject, public SPDimensions { public: SPFilter(); virtual ~SPFilter(); @@ -47,14 +48,10 @@ public: unsigned int filterUnits_set : 1; SPFilterUnits primitiveUnits; unsigned int primitiveUnits_set : 1; - SVGLength x; - SVGLength y; - SVGLength width; - SVGLength height; NumberOptNumber filterRes; SPFilterReference *href; sigc::connection modified_connection; - + guint getRefCount(); guint _refcount; diff --git a/src/sp-flowdiv.cpp b/src/sp-flowdiv.cpp index 17b841e37..002fcff85 100644 --- a/src/sp-flowdiv.cpp +++ b/src/sp-flowdiv.cpp @@ -26,18 +26,13 @@ void SPFlowdiv::update(SPCtx *ctx, unsigned int flags) { } childflags &= SP_OBJECT_MODIFIED_CASCADE; - GSList* l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for(auto child:l) { if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM(child)) { SPItem const &chi = *SP_ITEM(child); @@ -64,22 +59,16 @@ void SPFlowdiv::modified(unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for(auto child:l) { if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } - sp_object_unref(child); } } @@ -102,7 +91,7 @@ Inkscape::XML::Node* SPFlowdiv::write(Inkscape::XML::Document *xml_doc, Inkscape repr = xml_doc->createElement("svg:flowDiv"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node* c_repr = NULL; @@ -116,14 +105,12 @@ Inkscape::XML::Node* SPFlowdiv::write(Inkscape::XML::Document *xml_doc, Inkscape } if ( c_repr ) { - l = g_slist_prepend (l, c_repr); + l.push_back(c_repr); } } - - while ( l ) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { @@ -166,19 +153,13 @@ void SPFlowtspan::update(SPCtx *ctx, unsigned int flags) { childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } childflags &= SP_OBJECT_MODIFIED_CASCADE; - - GSList* l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for(auto child:l) { if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM(child)) { SPItem const &chi = *SP_ITEM(child); @@ -204,23 +185,16 @@ void SPFlowtspan::modified(unsigned int flags) { } flags &= SP_OBJECT_MODIFIED_CASCADE; - - GSList *l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for(auto child:l) { if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } - sp_object_unref(child); } } @@ -240,7 +214,7 @@ Inkscape::XML::Node *SPFlowtspan::write(Inkscape::XML::Document *xml_doc, Inksca repr = xml_doc->createElement("svg:flowSpan"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node* c_repr = NULL; @@ -254,14 +228,12 @@ Inkscape::XML::Node *SPFlowtspan::write(Inkscape::XML::Document *xml_doc, Inksca } if ( c_repr ) { - l = g_slist_prepend(l, c_repr); + l.push_back(c_repr); } } - - while ( l ) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { @@ -306,18 +278,13 @@ void SPFlowpara::update(SPCtx *ctx, unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList* l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for(auto child:l) { if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { if (SP_IS_ITEM(child)) { SPItem const &chi = *SP_ITEM(child); @@ -328,7 +295,6 @@ void SPFlowpara::update(SPCtx *ctx, unsigned int flags) { child->updateDisplay(ctx, flags); } } - sp_object_unref(child); } } @@ -342,22 +308,16 @@ void SPFlowpara::modified(unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for(auto child:l) { if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } - sp_object_unref(child); } } @@ -377,7 +337,7 @@ Inkscape::XML::Node *SPFlowpara::write(Inkscape::XML::Document *xml_doc, Inkscap repr = xml_doc->createElement("svg:flowPara"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node* c_repr = NULL; @@ -391,14 +351,13 @@ Inkscape::XML::Node *SPFlowpara::write(Inkscape::XML::Document *xml_doc, Inkscap } if ( c_repr ) { - l = g_slist_prepend(l, c_repr); + l.push_back(c_repr); } } - while ( l ) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp index 4064c12f1..6640d93c2 100644 --- a/src/sp-flowregion.cpp +++ b/src/sp-flowregion.cpp @@ -59,19 +59,15 @@ void SPFlowregion::update(SPCtx *ctx, unsigned int flags) { } childflags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; + std::vector<SPObject*>l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = reinterpret_cast<SPObject *>(l->data); + for (auto child:l) { g_assert(child != NULL); - l = g_slist_remove(l, child); SPItem *item = dynamic_cast<SPItem *>(child); if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { @@ -114,19 +110,15 @@ void SPFlowregion::modified(guint flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; + std::vector<SPObject *>l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = reinterpret_cast<SPObject *>(l->data); + for (auto child:l) { g_assert(child != NULL); - l = g_slist_remove(l, child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); @@ -142,21 +134,20 @@ Inkscape::XML::Node *SPFlowregion::write(Inkscape::XML::Document *xml_doc, Inksc repr = xml_doc->createElement("svg:flowRegion"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { if ( !dynamic_cast<SPTitle *>(&child) && !dynamic_cast<SPDesc *>(&child) ) { Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, NULL, flags); if (crepr) { - l = g_slist_prepend(l, crepr); + l.push_back(crepr); } } } - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i = l.rbegin(); i != l.rend(); ++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } for (auto& child: children) { @@ -216,19 +207,15 @@ void SPFlowregionExclude::update(SPCtx *ctx, unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = reinterpret_cast<SPObject *>(l->data); + for(auto child:l) { g_assert(child != NULL); - l = g_slist_remove(l, child); if (flags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { SPItem *item = dynamic_cast<SPItem *>(child); @@ -268,19 +255,15 @@ void SPFlowregionExclude::modified(guint flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; + std::vector<SPObject*> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = reinterpret_cast<SPObject *>(l->data); + for (auto child:l) { g_assert(child != NULL); - l = g_slist_remove(l, child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); @@ -296,20 +279,19 @@ Inkscape::XML::Node *SPFlowregionExclude::write(Inkscape::XML::Document *xml_doc repr = xml_doc->createElement("svg:flowRegionExclude"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, NULL, flags); if (crepr) { - l = g_slist_prepend(l, crepr); + l.push_back(crepr); } } - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i = l.rbegin(); i != l.rend(); ++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index 741ca7886..2425dada3 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -65,19 +65,14 @@ void SPFlowtext::update(SPCtx* ctx, unsigned int flags) { } childflags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; - + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = reinterpret_cast<SPObject *>(l->data); + for (auto child:l) { g_assert(child != NULL); - l = g_slist_remove(l, child); if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { SPItem *item = dynamic_cast<SPItem *>(child); @@ -216,7 +211,7 @@ Inkscape::XML::Node* SPFlowtext::write(Inkscape::XML::Document* doc, Inkscape::X repr = doc->createElement("svg:flowRoot"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node *c_repr = NULL; @@ -226,14 +221,13 @@ Inkscape::XML::Node* SPFlowtext::write(Inkscape::XML::Document* doc, Inkscape::X } if ( c_repr ) { - l = g_slist_prepend(l, c_repr); + l.push_back(c_repr); } } - while ( l ) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { @@ -714,7 +708,7 @@ Geom::Affine SPFlowtext::set_transform (Geom::Affine const &xform) SPRect *rect = dynamic_cast<SPRect *>(region->firstChild()); if (rect) { rect->set_i2d_affine(xform * rect->i2dt_affine()); - rect->doWriteTransform(rect->getRepr(), rect->transform, NULL, true); + rect->doWriteTransform(rect->transform, NULL, true); } } diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index c1934dd92..feaa04e0f 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -561,23 +561,16 @@ void SPGradient::modified(guint flags) flags &= SP_OBJECT_MODIFIED_CASCADE; // FIXME: climb up the ladder of hrefs - GSList *l = NULL; - + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - - l = g_slist_reverse(l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + + for (auto child:l) { if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } - sp_object_unref(child); } @@ -621,20 +614,19 @@ Inkscape::XML::Node *SPGradient::write(Inkscape::XML::Document *xml_doc, Inkscap SPPaintServer::write(xml_doc, repr, flags); if (flags & SP_OBJECT_WRITE_BUILD) { - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, NULL, flags); if (crepr) { - l = g_slist_prepend(l, crepr); + l.push_back(crepr); } } - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } @@ -877,20 +869,19 @@ sp_gradient_repr_clear_vector(SPGradient *gr) Inkscape::XML::Node *repr = gr->getRepr(); /* Collect stops from original repr */ - GSList *sl = NULL; + std::vector<Inkscape::XML::Node *> l; for (Inkscape::XML::Node *child = repr->firstChild() ; child != NULL; child = child->next() ) { if (!strcmp(child->name(), "svg:stop")) { - sl = g_slist_prepend(sl, child); + l.push_back(child); } } /* Remove all stops */ - while (sl) { + for (auto i=l.rbegin();i!=l.rend();++i) { /** \todo * fixme: This should work, unless we make gradient * into generic group. */ - sp_repr_unparent((Inkscape::XML::Node *)sl->data); - sl = g_slist_remove(sl, sl->data); + sp_repr_unparent(*i); } } @@ -908,7 +899,7 @@ sp_gradient_repr_write_vector(SPGradient *gr) Inkscape::XML::Node *repr = gr->getRepr(); /* We have to be careful, as vector may be our own, so construct repr list at first */ - GSList *cl = NULL; + std::vector<Inkscape::XML::Node *> l; for (guint i = 0; i < gr->vector.stops.size(); i++) { Inkscape::CSSOStringStream os; @@ -919,17 +910,16 @@ sp_gradient_repr_write_vector(SPGradient *gr) os << "stop-color:" << gr->vector.stops[i].color.toString() << ";stop-opacity:" << gr->vector.stops[i].opacity; child->setAttribute("style", os.str().c_str()); /* Order will be reversed here */ - cl = g_slist_prepend(cl, child); + l.push_back(child); } sp_gradient_repr_clear_vector(gr); /* And insert new children from list */ - while (cl) { - Inkscape::XML::Node *child = static_cast<Inkscape::XML::Node *>(cl->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + Inkscape::XML::Node *child = *i; repr->addChild(child, NULL); Inkscape::GC::release(child); - cl = g_slist_remove(cl, child); } } diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index ff0f6cadb..8b4bf121d 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -485,28 +485,25 @@ char* SPGuide::description(bool const verbose) const Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(this->point_on_line[X], "px"); Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(this->point_on_line[Y], "px"); - GString *position_string_x = g_string_new(x_q.string(namedview->display_units).c_str()); - GString *position_string_y = g_string_new(y_q.string(namedview->display_units).c_str()); + Glib::ustring position_string_x = x_q.string(namedview->display_units); + Glib::ustring position_string_y = y_q.string(namedview->display_units); gchar *shortcuts = g_strdup_printf("; %s", _("<b>Shift+drag</b> to rotate, <b>Ctrl+drag</b> to move origin, <b>Del</b> to delete")); if ( are_near(this->normal_to_line, Geom::Point(1., 0.)) || are_near(this->normal_to_line, -Geom::Point(1., 0.)) ) { - descr = g_strdup_printf(_("vertical, at %s"), position_string_x->str); + descr = g_strdup_printf(_("vertical, at %s"), position_string_x.c_str()); } else if ( are_near(this->normal_to_line, Geom::Point(0., 1.)) || are_near(this->normal_to_line, -Geom::Point(0., 1.)) ) { - descr = g_strdup_printf(_("horizontal, at %s"), position_string_y->str); + descr = g_strdup_printf(_("horizontal, at %s"), position_string_y.c_str()); } else { double const radians = this->angle(); double const degrees = Geom::deg_from_rad(radians); int const degrees_int = (int) round(degrees); descr = g_strdup_printf(_("at %d degrees, through (%s,%s)"), - degrees_int, position_string_x->str, position_string_y->str); + degrees_int, position_string_x.c_str(), position_string_y.c_str()); } - - g_string_free(position_string_x, TRUE); - g_string_free(position_string_y, TRUE); - + if (verbose) { gchar *oldDescr = descr; descr = g_strconcat(oldDescr, shortcuts, NULL); diff --git a/src/sp-image.cpp b/src/sp-image.cpp index 1961971cb..6736efdec 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -374,23 +374,8 @@ void SPImage::update(SPCtx *ctx, unsigned int flags) { } } - // Calculate x, y, width, height from parent/initial viewport, see sp-root.cpp - if (this->x.unit == SVGLength::PERCENT) { - this->x.computed = this->x.value * ictx->viewport.width(); - } - - if (this->y.unit == SVGLength::PERCENT) { - this->y.computed = this->y.value * ictx->viewport.height(); - } - - if (this->width.unit == SVGLength::PERCENT) { - this->width.computed = this->width.value * ictx->viewport.width(); - } - - if (this->height.unit == SVGLength::PERCENT) { - this->height.computed = this->height.value * ictx->viewport.height(); - } + this->calcDimsFromParentViewport(ictx); // Image creates a new viewport ictx->viewport= Geom::Rect::from_xywh( this->x.computed, this->y.computed, diff --git a/src/sp-image.h b/src/sp-image.h index 9fa33b5de..9cd5faa8b 100644 --- a/src/sp-image.h +++ b/src/sp-image.h @@ -19,6 +19,7 @@ #include "display/curve.h" #include "sp-item.h" #include "viewbox.h" +#include "sp-dimensions.h" #define SP_IMAGE(obj) (dynamic_cast<SPImage*>((SPObject*)obj)) #define SP_IS_IMAGE(obj) (dynamic_cast<const SPImage*>((SPObject*)obj) != NULL) @@ -26,16 +27,11 @@ #define SP_IMAGE_HREF_MODIFIED_FLAG SP_OBJECT_USER_MODIFIED_FLAG_A namespace Inkscape { class Pixbuf; } -class SPImage : public SPItem, public SPViewBox { +class SPImage : public SPItem, public SPViewBox, public SPDimensions { public: SPImage(); virtual ~SPImage(); - SVGLength x; - SVGLength y; - SVGLength width; - SVGLength height; - Geom::Rect clipbox; double sx, sy; double ox, oy; diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 88b2bb1f9..3d4d7b253 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -32,6 +32,7 @@ #include "attributes.h" #include "sp-item-transform.h" #include "sp-root.h" +#include "sp-rect.h" #include "sp-offset.h" #include "sp-clippath.h" #include "sp-mask.h" @@ -55,11 +56,11 @@ using Inkscape::DocumentUndo; -static void sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write); +static void sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, bool write); SPGroup::SPGroup() : SPLPEItem(), _expanded(false), - _insertBottom(false), + _insert_bottom(false), _layer_mode(SPGroup::GROUP) { } @@ -225,7 +226,7 @@ void SPGroup::modified(guint flags) { Inkscape::XML::Node* SPGroup::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { if (flags & SP_OBJECT_WRITE_BUILD) { - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; if (!repr) { if (dynamic_cast<SPSwitch *>(this)) { @@ -235,22 +236,18 @@ Inkscape::XML::Node* SPGroup::write(Inkscape::XML::Document *xml_doc, Inkscape:: } } - l = NULL; - for (auto& child: children) { if ( !dynamic_cast<SPTitle *>(&child) && !dynamic_cast<SPDesc *>(&child) ) { Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, NULL, flags); if (crepr) { - l = g_slist_prepend (l, crepr); + l.push_back(crepr); } } } - - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove (l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { @@ -509,8 +506,8 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d group->removeAllPathEffects(false); /* Step 1 - generate lists of children objects */ - GSList *items = NULL; - GSList *objects = NULL; + std::vector<Inkscape::XML::Node *> items; + std::vector<Inkscape::XML::Node *> objects; Geom::Affine const g(group->transform); for (auto& child: group->children) { @@ -601,11 +598,11 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d } g_free(affinestr); - items = g_slist_prepend (items, nrepr); + items.push_back(nrepr); } else { Inkscape::XML::Node *nrepr = child.getRepr()->duplicate(prepr->document()); - objects = g_slist_prepend (objects, nrepr); + objects.push_back(nrepr); } } @@ -617,21 +614,20 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d group->deleteObject(true, false); /* Step 3 - add nonitems */ - if (objects) { + if (!objects.empty()) { Inkscape::XML::Node *last_def = defs->getRepr()->lastChild(); - while (objects) { - Inkscape::XML::Node *repr = (Inkscape::XML::Node *) objects->data; + for (auto i=objects.rbegin();i!=objects.rend();++i) { + Inkscape::XML::Node *repr = *i; if (!sp_repr_is_meta_element(repr)) { defs->getRepr()->addChild(repr, last_def); } Inkscape::GC::release(repr); - objects = g_slist_remove (objects, objects->data); } } /* Step 4 - add items */ - while (items) { - Inkscape::XML::Node *repr = (Inkscape::XML::Node *) items->data; + for (auto i=items.rbegin();i!=items.rend();++i) { + Inkscape::XML::Node *repr = *i; // add item prepr->appendChild(repr); // restore position; since the items list was prepended (i.e. reverse), we now add @@ -642,14 +638,13 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d SPItem *item = static_cast<SPItem *>(doc->getObjectByRepr(repr)); if (item) { - item->doWriteTransform(repr, item->transform, NULL, false); + item->doWriteTransform(item->transform, NULL, false); children.insert(children.begin(),item); } else { g_assert_not_reached(); } Inkscape::GC::release(repr); - items = g_slist_remove (items, items->data); } if (do_done) { @@ -712,8 +707,8 @@ void SPGroup::setExpanded(bool isexpanded) { } void SPGroup::setInsertBottom(bool insertbottom) { - if ( _insertBottom != insertbottom) { - _insertBottom = insertbottom; + if ( _insert_bottom != insertbottom) { + _insert_bottom = insertbottom; } } @@ -784,24 +779,24 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p, bo tAff[4] = 0.0; tAff[5] = 0.0; } - item->doWriteTransform(item->getRepr(), tAff, NULL, true); + item->doWriteTransform(tAff, NULL, true); } else { // used for other import - SPItem *subItem = NULL; + SPItem *sub_item = NULL; if (item->clip_ref->getObject()) { - subItem = dynamic_cast<SPItem *>(item->clip_ref->getObject()->firstChild()); + sub_item = dynamic_cast<SPItem *>(item->clip_ref->getObject()->firstChild()); } - if (subItem != NULL) { - subItem->doWriteTransform(subItem->getRepr(), subItem->transform*sc, NULL, true); + if (sub_item != NULL) { + sub_item->doWriteTransform(sub_item->transform*sc, NULL, true); } - subItem = NULL; + sub_item = NULL; if (item->mask_ref->getObject()) { - subItem = dynamic_cast<SPItem *>(item->mask_ref->getObject()->firstChild()); + sub_item = dynamic_cast<SPItem *>(item->mask_ref->getObject()->firstChild()); } - if (subItem != NULL) { - subItem->doWriteTransform(subItem->getRepr(), subItem->transform*sc, NULL, true); + if (sub_item != NULL) { + sub_item->doWriteTransform(sub_item->transform*sc, NULL, true); } - item->doWriteTransform(item->getRepr(), sc.inverse()*item->transform*sc, NULL, true); + item->doWriteTransform(sc.inverse()*item->transform*sc, NULL, true); group->scaleChildItemsRec(sc, p, false); } } else { @@ -812,10 +807,10 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p, bo Geom::Affine final = s.inverse() * sc * s; gchar const *conn_type = NULL; - SPText *textItem = dynamic_cast<SPText *>(item); - bool isTextTextpath = textItem && textItem->firstChild() && dynamic_cast<SPTextPath *>(textItem->firstChild()); - if (isTextTextpath) { - textItem->optimizeTextpathText(); + SPText *text_item = dynamic_cast<SPText *>(item); + bool is_text_path = text_item && text_item->firstChild() && dynamic_cast<SPTextPath *>(text_item->firstChild()); + if (is_text_path) { + text_item->optimizeTextpathText(); } else { SPFlowtext *flowText = dynamic_cast<SPFlowtext *>(item); if (flowText) { @@ -838,24 +833,24 @@ void SPGroup::scaleChildItemsRec(Geom::Scale const &sc, Geom::Point const &p, bo Persp3D *persp = dynamic_cast<Persp3D *>(item); if (persp) { persp3d_apply_affine_transformation(persp, final); - } else if (isTextTextpath && !item->transform.isIdentity()) { + } else if (is_text_path && !item->transform.isIdentity()) { // Save and reset current transform Geom::Affine tmp(item->transform); item->transform = Geom::Affine(); // Apply scale item->set_i2d_affine(item->i2dt_affine() * sc); - item->doWriteTransform(item->getRepr(), item->transform, NULL, true); + item->doWriteTransform(item->transform, NULL, true); // Scale translation and restore original transform tmp[4] *= sc[0]; tmp[5] *= sc[1]; - item->doWriteTransform(item->getRepr(), tmp, NULL, true); + item->doWriteTransform(tmp, NULL, true); } else if (dynamic_cast<SPUse *>(item)) { // calculate the matrix we need to apply to the clone // to cancel its induced transform from its original Geom::Affine move = final.inverse() * item->transform * final; - item->doWriteTransform(item->getRepr(), move, &move, true); + item->doWriteTransform(move, &move, true); } else { - item->doWriteTransform(item->getRepr(), item->transform*sc, NULL, true); + item->doWriteTransform(item->transform*sc, NULL, true); } if (conn_type != NULL) { @@ -907,11 +902,11 @@ void SPGroup::update_patheffect(bool write) { std::vector<SPItem*> const item_list = sp_item_group_item_list(this); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { - SPObject *subitem = *iter; + SPObject *sub_item = *iter; - SPLPEItem *lpeItem = dynamic_cast<SPLPEItem *>(subitem); - if (lpeItem) { - lpeItem->update_patheffect(write); + SPLPEItem *lpe_item = dynamic_cast<SPLPEItem *>(sub_item); + if (lpe_item) { + lpe_item->update_patheffect(write); } } @@ -939,36 +934,54 @@ void SPGroup::update_patheffect(bool write) { } static void -sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write) +sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, bool write) { std::vector<SPItem*> const item_list = sp_item_group_item_list(group); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { - SPObject *subitem = *iter; + SPObject *sub_item = *iter; - SPGroup *subGroup = dynamic_cast<SPGroup *>(subitem); - if (subGroup) { - sp_group_perform_patheffect(subGroup, topgroup, write); + SPGroup *sub_group = dynamic_cast<SPGroup *>(sub_item); + if (sub_group) { + sp_group_perform_patheffect(sub_group, top_group, write); } else { - SPShape *subShape = dynamic_cast<SPShape *>(subitem); - if (subShape) { + SPShape *sub_shape = dynamic_cast<SPShape *>(sub_item); + if (sub_shape) { SPCurve * c = NULL; - - SPPath *subPath = dynamic_cast<SPPath *>(subShape); - if (subPath) { - c = subPath->get_original_curve(); - } else { - c = subShape->getCurve(); + // If item is a SPRect, convert it to path first: + if ( dynamic_cast<SPRect *>(sub_shape) ) { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + Inkscape::Selection *sel = desktop->getSelection(); + if ( sel && !sel->isEmpty() ) { + sel->clear(); + sel->add(SP_ITEM(sub_shape)); + sel->toCurves(); + sub_item = sel->singleItem(); + sub_shape = dynamic_cast<SPShape *>(sub_item); + if (!sub_shape) { + continue; + } + sel->clear(); + sel->add(SP_ITEM(top_group)); + } + } } + c = sub_shape->getCurve(); bool success = false; // only run LPEs when the shape has a curve defined if (c) { - c->transform(i2anc_affine(subitem, topgroup)); - success = topgroup->performPathEffect(c, subShape); - c->transform(i2anc_affine(subitem, topgroup).inverse()); - Inkscape::XML::Node *repr = subitem->getRepr(); + c->transform(i2anc_affine(sub_item, top_group)); + success = top_group->performPathEffect(c, sub_shape); + c->transform(i2anc_affine(sub_item, top_group).inverse()); + Inkscape::XML::Node *repr = sub_item->getRepr(); if (c && success) { - subShape->setCurve(c, TRUE); + SPPath *sub_path = dynamic_cast<SPPath *>(sub_item); + if (!sub_path) { + sub_shape->setCurveInsync( sub_shape->getCurveBeforeLPE(), TRUE); + sub_shape->setCurve(c, TRUE); + sub_shape->setCurveInsync( c, TRUE); + } if (write) { gchar *str = sp_svg_write_path(c->get_pathvector()); repr->setAttribute("d", str); @@ -984,7 +997,7 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write) Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *oldcurve = new (std::nothrow) SPCurve(pv); if (oldcurve) { - subShape->setCurve(oldcurve, TRUE); + sub_shape->setCurve(oldcurve, TRUE); oldcurve->unref(); } } diff --git a/src/sp-item-group.h b/src/sp-item-group.h index 0c74c3dc3..a96d77aa9 100644 --- a/src/sp-item-group.h +++ b/src/sp-item-group.h @@ -36,7 +36,7 @@ public: enum LayerMode { GROUP, LAYER, MASK_HELPER }; bool _expanded; - bool _insertBottom; + bool _insert_bottom; LayerMode _layer_mode; std::map<unsigned int, LayerMode> _display_modes; @@ -46,7 +46,7 @@ public: bool expanded() const { return _expanded; } void setExpanded(bool isexpanded); - bool insertBottom() const { return _insertBottom; } + bool insertBottom() const { return _insert_bottom; } void setInsertBottom(bool insertbottom); LayerMode effectiveLayerMode(unsigned int display_key) const { diff --git a/src/sp-item-notify-moveto.cpp b/src/sp-item-notify-moveto.cpp index dcc91fd0b..28648c03a 100644 --- a/src/sp-item-notify-moveto.cpp +++ b/src/sp-item-notify-moveto.cpp @@ -51,7 +51,7 @@ void sp_item_notify_moveto(SPItem &item, SPGuide const &mv_g, int const snappoin /* Commit repr. */ { - item.doWriteTransform(item.getRepr(), item.transform); + item.doWriteTransform(item.transform); } sp_item_rm_unsatisfied_cns(item); diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp index f1c69cdf6..3675323ca 100644 --- a/src/sp-item-transform.cpp +++ b/src/sp-item-transform.cpp @@ -29,7 +29,7 @@ void sp_item_rotate_rel(SPItem *item, Geom::Rotate const &rotation) // Rotate item. item->set_i2d_affine(item->i2dt_affine() * (Geom::Affine)affine); // Use each item's own transform writer, consistent with sp_selection_apply_affine() - item->doWriteTransform(item->getRepr(), item->transform); + item->doWriteTransform(item->transform); // Restore the center position (it's changed because the bbox center changed) if (item->isCenterSet()) { @@ -44,7 +44,7 @@ void sp_item_scale_rel(SPItem *item, Geom::Scale const &scale) if (bbox) { Geom::Translate const s(bbox->midpoint()); // use getCenter? item->set_i2d_affine(item->i2dt_affine() * s.inverse() * scale * s); - item->doWriteTransform(item->getRepr(), item->transform); + item->doWriteTransform(item->transform); } } @@ -57,7 +57,7 @@ void sp_item_skew_rel(SPItem *item, double skewX, double skewY) Geom::Affine affine = Geom::Affine(s).inverse() * skew * Geom::Affine(s); item->set_i2d_affine(item->i2dt_affine() * affine); - item->doWriteTransform(item->getRepr(), item->transform); + item->doWriteTransform(item->transform); // Restore the center position (it's changed because the bbox center changed) if (item->isCenterSet()) { @@ -70,7 +70,7 @@ void sp_item_move_rel(SPItem *item, Geom::Translate const &tr) { item->set_i2d_affine(item->i2dt_affine() * tr); - item->doWriteTransform(item->getRepr(), item->transform); + item->doWriteTransform(item->transform); } /** diff --git a/src/sp-item.cpp b/src/sp-item.cpp index b4642da5d..3fef28e5b 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -711,19 +711,18 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X // in the case of SP_OBJECT_WRITE_BUILD, the item should always be newly created, // so we need to add any children from the underlying object to the new repr if (flags & SP_OBJECT_WRITE_BUILD) { - GSList *l = NULL; + std::vector<Inkscape::XML::Node *>l; for (auto& child: object->children) { if (dynamic_cast<SPTitle *>(&child) || dynamic_cast<SPDesc *>(&child)) { Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, NULL, flags); if (crepr) { - l = g_slist_prepend (l, crepr); + l.push_back(crepr); } } } - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove (l, l->data); + for (auto i = l.rbegin(); i!= l.rend(); ++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: object->children) { @@ -1407,9 +1406,11 @@ void SPItem::adjust_livepatheffect (Geom::Affine const &postmul, bool set) for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); ++it) { LivePathEffectObject *lpeobj = (*it)->lpeobject; - if (lpeobj && lpeobj->get_lpe()) { - Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe(); - effect->transform_multiply(postmul, set); + if (lpeobj) { + Inkscape::LivePathEffect::Effect * lpe = lpeobj->get_lpe(); + if (lpe && lpe->isReady()) { + lpe->transform_multiply(postmul, set); + } } } } @@ -1422,9 +1423,8 @@ Geom::Affine SPItem::set_transform(Geom::Affine const &transform) { return transform; } -void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv, bool compensate) +void SPItem::doWriteTransform(Geom::Affine const &transform, Geom::Affine const *adv, bool compensate) { - g_return_if_fail(repr != NULL); // calculate the relative transform, if not given by the adv attribute Geom::Affine advertized_transform; if (adv != NULL) { diff --git a/src/sp-item.h b/src/sp-item.h index c4d353a1d..36af02edc 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -330,7 +330,7 @@ public: * stored optimized. Send _transformed_signal. Invoke _write method so that * the repr is updated with the new transform. */ - void doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv = NULL, bool compensate = true); + void doWriteTransform(Geom::Affine const &transform, Geom::Affine const *adv = NULL, bool compensate = true); /** * Sets item private transform (not propagated to repr), without compensating stroke widths, diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index edd572b8b..5be950afa 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -35,6 +35,7 @@ #include "inkscape.h" #include "desktop.h" #include "ui/shape-editor.h" +#include "path-chemistry.h" #include "sp-ellipse.h" #include "display/curve.h" #include "svg/svg.h" @@ -304,8 +305,8 @@ bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip } } if(!SP_IS_GROUP(this) && !is_clip_or_mask && has_clipormask_lpe){ - this->apply_to_clippath(this); - this->apply_to_mask(this); + this->applyToClipPath(this); + this->applyToMask(this); } } return true; @@ -437,8 +438,43 @@ sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths) } repr->setAttribute("inkscape:original-d", NULL); } else { - sp_lpe_item_update_patheffect(lpeitem, true, true); + if (!keep_paths) { + sp_lpe_item_update_patheffect(lpeitem, true, true); + } + } + } else if (SP_IS_SHAPE(lpeitem)) { + Inkscape::XML::Node *repr = lpeitem->getRepr(); + SPMask * mask = lpeitem->mask_ref->getObject(); + if(mask) { + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()), keep_paths); + } + SPClipPath * clip_path = lpeitem->clip_ref->getObject(); + if(clip_path) { + sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()), keep_paths); + } + mask = dynamic_cast<SPMask *>(lpeitem->parent); + clip_path = dynamic_cast<SPClipPath *>(lpeitem->parent); + if ((!lpeitem->hasPathEffectRecursive() && repr->attribute("d")) || + ((mask || clip_path) && !lpeitem->hasPathEffectOnClipOrMaskRecursive() && repr->attribute("d"))) + { + if (!keep_paths) { + repr->setAttribute("d", NULL); + } else { + SPDesktop * desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + std::vector<SPItem*> items; + items.push_back(SP_ITEM(lpeitem)); + std::vector<SPItem*> selected = items; + std::vector<Inkscape::XML::Node*> to_select; + sp_item_list_to_curves(items, selected, to_select, true); + } + } + } else { + if (!keep_paths) { + sp_lpe_item_update_patheffect(lpeitem, true, true); + } } + } } @@ -561,14 +597,16 @@ void SPLPEItem::removeAllPathEffects(bool keep_paths) LivePathEffectObject *lpeobj = (*it)->lpeobject; if (lpeobj) { Inkscape::LivePathEffect::Effect * lpe = lpeobj->get_lpe(); - lpe->keep_paths = keep_paths; - lpe->doOnRemove(this); + if (lpe) { + lpe->keep_paths = keep_paths; + lpe->doOnRemove(this); + } } // unlink and delete all references in the list (*it)->unlink(); - delete *it; - it = this->path_effect_list->erase(it); + ++it; } + this->path_effect_list->clear(); this->getRepr()->setAttribute("inkscape:path-effect", NULL); if (!keep_paths) { @@ -691,53 +729,53 @@ bool SPLPEItem::hasPathEffectRecursive() const } void -SPLPEItem::apply_to_clippath(SPItem *item) +SPLPEItem::applyToClipPath(SPItem *item) { SPClipPath *clip_path = item->clip_ref->getObject(); if(clip_path) { std::vector<SPObject*> clip_path_list = clip_path->childList(true); for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { SPObject * clip_data = *iter; - apply_to_clip_or_mask(SP_ITEM(clip_data), item); + applyToClipPathOrMask(SP_ITEM(clip_data), item); } } if(SP_IS_GROUP(item)){ std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(item)); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { SPObject *subitem = *iter; - apply_to_clippath(SP_ITEM(subitem)); + applyToClipPath(SP_ITEM(subitem)); } } } void -SPLPEItem::apply_to_mask(SPItem *item) +SPLPEItem::applyToMask(SPItem *item) { SPMask *mask = item->mask_ref->getObject(); if(mask) { std::vector<SPObject*> mask_list = mask->childList(true); for ( std::vector<SPObject*>::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) { SPObject * mask_data = *iter; - apply_to_clip_or_mask(SP_ITEM(mask_data), item); + applyToClipPathOrMask(SP_ITEM(mask_data), item); } } if(SP_IS_GROUP(item)){ std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(item)); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { SPObject *subitem = *iter; - apply_to_mask(SP_ITEM(subitem)); + applyToMask(SP_ITEM(subitem)); } } } void -SPLPEItem::apply_to_clip_or_mask(SPItem *clip_mask, SPItem *item) +SPLPEItem::applyToClipPathOrMask(SPItem *clip_mask, SPItem *item) { if (SP_IS_GROUP(clip_mask)) { std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(clip_mask)); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { SPItem *subitem = *iter; - apply_to_clip_or_mask(subitem, item); + applyToClipPathOrMask(subitem, item); } } else if (SP_IS_SHAPE(clip_mask)) { SPCurve * c = NULL; diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h index d5d4e118b..82f3940c1 100644 --- a/src/sp-lpe-item.h +++ b/src/sp-lpe-item.h @@ -94,14 +94,13 @@ public: void removeAllPathEffects(bool keep_paths); void addPathEffect(std::string value, bool reset); void addPathEffect(LivePathEffectObject * new_lpeobj); - void apply_to_mask(SPItem * item); - void apply_to_clippath(SPItem * item); - void apply_to_clip_or_mask(SPItem * clip_mask, SPItem * item); + void applyToMask(SPItem * item); + void applyToClipPath(SPItem * item); + void applyToClipPathOrMask(SPItem * clip_mask, SPItem * item); bool forkPathEffectsIfNecessary(unsigned int nr_of_allowed_users = 1); void editNextParamOncanvas(SPDesktop *dt); }; - void sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool wholetree, bool write); // careful, class already has method with *very* similar name! #endif /* !SP_LPE_ITEM_H_SEEN */ diff --git a/src/sp-marker.cpp b/src/sp-marker.cpp index 43df8525d..01a0d5e61 100644 --- a/src/sp-marker.cpp +++ b/src/sp-marker.cpp @@ -455,7 +455,7 @@ const gchar *generate_marker(std::vector<Inkscape::XML::Node*> &reprs, Geom::Rec dup_transform = Geom::identity(); dup_transform *= move; - copy->doWriteTransform(copy->getRepr(), dup_transform); + copy->doWriteTransform(dup_transform); } Inkscape::GC::release(repr); diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp index a47fab35e..0597d29f7 100644 --- a/src/sp-mask.cpp +++ b/src/sp-mask.cpp @@ -191,7 +191,7 @@ Inkscape::XML::Node* SPMask::write(Inkscape::XML::Document* xml_doc, Inkscape::X // Create a mask element (using passed elements), add it to <defs> const gchar * -sp_mask_create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, Geom::Affine const* applyTransform) +sp_mask_create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document) { Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); @@ -205,12 +205,7 @@ sp_mask_create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, for (std::vector<Inkscape::XML::Node*>::const_iterator it = reprs.begin(); it != reprs.end(); ++it) { Inkscape::XML::Node *node = (*it); - SPItem *item = SP_ITEM(mask_object->appendChildRepr(node)); - - if (NULL != applyTransform) { - Geom::Affine transform (item->transform * (*applyTransform)); - item->doWriteTransform(item->getRepr(), transform); - } + mask_object->appendChildRepr(node); } if (repr != defsrepr->lastChild()) diff --git a/src/sp-mask.h b/src/sp-mask.h index 19786b1fd..02d37b82b 100644 --- a/src/sp-mask.h +++ b/src/sp-mask.h @@ -108,6 +108,6 @@ protected: } }; -const char *sp_mask_create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document, Geom::Affine const* applyTransform); +const char *sp_mask_create (std::vector<Inkscape::XML::Node*> &reprs, SPDocument *document); #endif // SEEN_SP_MASK_H diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp index c89cfcc6f..a8d9e589c 100644 --- a/src/sp-mesh-array.cpp +++ b/src/sp-mesh-array.cpp @@ -936,31 +936,26 @@ void SPMeshNodeArray::write( SPMeshGradient *mg ) { } // First we must delete reprs for old mesh rows and patches. - GSList *descendant_reprs = NULL; - GSList *descendant_objects = NULL; + std::vector<SPObject*> descendant_objects; + std::vector<Inkscape::XML::Node *> descendant_reprs; for (auto& row: mg_array->children) { - descendant_reprs = g_slist_prepend (descendant_reprs, row.getRepr()); - descendant_objects = g_slist_prepend (descendant_objects, &row); + descendant_reprs.push_back(row.getRepr()); + descendant_objects.push_back(&row); for (auto& patch: row.children) { - descendant_reprs = g_slist_prepend (descendant_reprs, patch.getRepr()); - descendant_objects = g_slist_prepend (descendant_objects, &patch); + descendant_reprs.push_back(patch.getRepr()); + descendant_objects.push_back(&patch); for (auto& stop: patch.children) { - descendant_reprs = g_slist_prepend (descendant_reprs, stop.getRepr()); - descendant_objects = g_slist_prepend (descendant_objects, &stop); + descendant_reprs.push_back(stop.getRepr()); + descendant_objects.push_back(&stop); } } } - for ( GSList *i = descendant_objects; i != NULL; i = i->next ) { - SPObject *descendant = SP_OBJECT (i->data); - descendant->deleteObject(); - } - - for ( GSList *i = descendant_reprs; i != NULL; i = i->next ) { - Inkscape::XML::Node *repr = (Inkscape::XML::Node *) i->data; - sp_repr_unparent( repr ); - } + for (auto i:descendant_objects) + i->deleteObject(); + for (auto i:descendant_reprs) + sp_repr_unparent(i); // Now we build new reprs Inkscape::XML::Node *mesh = mg->getRepr(); diff --git a/src/sp-mesh-patch.cpp b/src/sp-mesh-patch.cpp index 9a173a8db..04a121c7a 100644 --- a/src/sp-mesh-patch.cpp +++ b/src/sp-mesh-patch.cpp @@ -94,23 +94,16 @@ void SPMeshpatch::set(unsigned int key, const gchar* value) { void SPMeshpatch::modified(unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; - + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for (auto child:l) { if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } - sp_object_unref(child); } } diff --git a/src/sp-mesh-row.cpp b/src/sp-mesh-row.cpp index 5ac349c27..8204aff65 100644 --- a/src/sp-mesh-row.cpp +++ b/src/sp-mesh-row.cpp @@ -78,23 +78,16 @@ void SPMeshrow::set(unsigned int /*key*/, const gchar* /*value*/) { void SPMeshrow::modified(unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = NULL; - + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child); - l = g_slist_prepend(l, &child); + l.push_back(&child); } - l = g_slist_reverse(l); - - while (l) { - SPObject *child = SP_OBJECT(l->data); - l = g_slist_remove(l, child); - + for (auto child:l) { if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); } - sp_object_unref(child); } } diff --git a/src/sp-object-group.cpp b/src/sp-object-group.cpp index 62c6f7a87..f8ef855e3 100644 --- a/src/sp-object-group.cpp +++ b/src/sp-object-group.cpp @@ -49,19 +49,17 @@ Inkscape::XML::Node *SPObjectGroup::write(Inkscape::XML::Document *xml_doc, Inks repr = xml_doc->createElement("svg:g"); } - GSList *l = 0; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node *crepr = child.updateRepr(xml_doc, NULL, flags); if (crepr) { - l = g_slist_prepend(l, crepr); + l.push_back(crepr); } } - - while (l) { - repr->addChild(static_cast<Inkscape::XML::Node *>(l->data), NULL); - Inkscape::GC::release(static_cast<Inkscape::XML::Node *>(l->data)); - l = g_slist_remove(l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { diff --git a/src/sp-object.cpp b/src/sp-object.cpp index 9f15935ac..bc930a430 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -199,7 +199,7 @@ typedef Debug::SimpleEvent<Debug::Event::REFCOUNT> BaseRefCountEvent; class RefCountEvent : public BaseRefCountEvent { public: - RefCountEvent(SPObject *object, int bias, Util::ptr_shared<char> name) + RefCountEvent(SPObject *object, int bias, Util::ptr_shared name) : BaseRefCountEvent(name) { _addProperty("object", Util::format("%p", object)); @@ -1540,7 +1540,10 @@ char * SPObject::getTitleOrDesc(gchar const *svg_tagname) const char *result = NULL; SPObject *elem = findFirstChild(svg_tagname); if ( elem ) { - result = elem->textualContent(); + //This string copy could be avoided by changing + //the return type of SPObject::getTitleOrDesc + //to std::unique_ptr<Glib::ustring> + result = g_strdup(elem->textualContent().c_str()); } return result; } @@ -1625,24 +1628,22 @@ SPObject* SPObject::findFirstChild(gchar const *tagname) const return nullptr; } -char* SPObject::textualContent() const +Glib::ustring SPObject::textualContent() const { - GString* text = g_string_new(""); + Glib::ustring text; for (auto& child: children) { Inkscape::XML::NodeType child_type = child.repr->type(); if (child_type == Inkscape::XML::ELEMENT_NODE) { - char* new_string = child.textualContent(); - g_string_append(text, new_string); - g_free(new_string); + text += child.textualContent(); } else if (child_type == Inkscape::XML::TEXT_NODE) { - g_string_append(text, child.repr->content()); + text += child.repr->content(); } } - return g_string_free(text, FALSE); + return text; } // For debugging: Print SP tree structure. diff --git a/src/sp-object.h b/src/sp-object.h index d145e966b..08e69f771 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -803,7 +803,7 @@ private: * content except the tags). * Must not be used on anything except elements. */ - char * textualContent() const; + Glib::ustring textualContent() const; /* Real handlers of repr signals */ diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp index e5b1b5d69..82e0b4947 100644 --- a/src/sp-offset.cpp +++ b/src/sp-offset.cpp @@ -63,7 +63,7 @@ class SPDocument; * a change occurs to the offset (change of source or change of radius). * just like the sp-star and other, this path derivative can make control * points, or more precisely one control point, that's enough to define the - * radius (look in object-edit). + * radius (look in shape-editor-knotholders). */ static void refresh_offset_source(SPOffset* offset); @@ -764,7 +764,7 @@ vectors_are_clockwise (Geom::Point A, Geom::Point B, Geom::Point C) } /** - * Distance to the original path; that function is called from object-edit + * Distance to the original path; that function is called from shape-editor-knotholders * to set the radius when the control knot moves. * * The sign of the result is the radius we're going to offset the shape with, @@ -1065,7 +1065,7 @@ static void sp_offset_move_compensate(Geom::Affine const *mp, SPItem */*original // commit the compensation self->transform *= offset_move; - self->doWriteTransform(self->getRepr(), self->transform, &advertized_move); + self->doWriteTransform(self->transform, &advertized_move); self->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } diff --git a/src/sp-offset.h b/src/sp-offset.h index eb3fe227c..117a3308e 100644 --- a/src/sp-offset.h +++ b/src/sp-offset.h @@ -47,7 +47,7 @@ class SPUseReference; * a change occurs to the offset (change of source or change of radius). * just like the sp-star and other, this path derivative can make control * points, or more precisely one control point, that's enough to define the - * radius (look in object-edit). + * radius (look in shape-editor-knotholders). */ class SPOffset : public SPShape { public: diff --git a/src/sp-path.cpp b/src/sp-path.cpp index bb76eb73f..0cf2a5f3e 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -299,6 +299,7 @@ Geom::Affine SPPath::set_transform(Geom::Affine const &transform) { // if path has this LPE applied, don't write the transform to the pathdata, but write it 'unoptimized' // also if the effect is type BEND PATH to fix bug #179842 this->adjust_livepatheffect(transform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return transform; } else { _curve_before_lpe->transform(transform); diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 1e198506b..9ecfe8baa 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -408,7 +408,7 @@ const gchar *SPPattern::produce(const std::vector<Inkscape::XML::Node *> &reprs, dup_transform = Geom::identity(); dup_transform *= move; - copy->doWriteTransform(copy->getRepr(), dup_transform, NULL, false); + copy->doWriteTransform(dup_transform, NULL, false); } Inkscape::GC::release(repr); diff --git a/src/sp-root.cpp b/src/sp-root.cpp index 34047054a..3f31588cc 100644 --- a/src/sp-root.cpp +++ b/src/sp-root.cpp @@ -40,8 +40,7 @@ SPRoot::SPRoot() : SPGroup(), SPViewBox() this->version.inkscape = zero_version; this->original.inkscape = zero_version; - this->x.unset(SVGLength::PERCENT, 0.0, 0.0); // Ignored for root SVG element - this->y.unset(SVGLength::PERCENT, 0.0, 0.0); + this->unset_x_and_y(); this->width.unset(SVGLength::PERCENT, 1.0, 1.0); this->height.unset(SVGLength::PERCENT, 1.0, 1.0); @@ -52,6 +51,12 @@ SPRoot::~SPRoot() { } +void SPRoot::unset_x_and_y() +{ + this->x.unset(SVGLength::PERCENT, 0.0, 0.0); // Ignored for root SVG element + this->y.unset(SVGLength::PERCENT, 0.0, 0.0); +} + void SPRoot::build(SPDocument *document, Inkscape::XML::Node *repr) { //XML Tree being used directly here while it shouldn't be. @@ -206,74 +211,63 @@ void SPRoot::remove_child(Inkscape::XML::Node *child) SPGroup::remove_child(child); } -void SPRoot::update(SPCtx *ctx, guint flags) +void SPRoot::setRootDimensions() { - SPItemCtx const *ictx = (SPItemCtx const *) ctx; - - if( !this->parent ) { + /* + * This is the root SVG element: + * + * x, y, width, and height apply to positioning the SVG element inside a parent. + * For the root SVG in Inkscape there is no parent, thus special rules apply: + * If width, height not set, width = 100%, height = 100% (as always). + * If width and height are in percent, they are percent of viewBox width/height. + * If width, height, and viewBox are not set... pick "random" width/height. + * x, y are ignored. + * initial viewport = (0 0 width height) + */ + if( this->viewBox_set ) { - /* - * This is the root SVG element: - * - * x, y, width, and height apply to positioning the SVG element inside a parent. - * For the root SVG in Inkscape there is no parent, thus special rules apply: - * If width, height not set, width = 100%, height = 100% (as always). - * If width and height are in percent, they are percent of viewBox width/height. - * If width, height, and viewBox are not set... pick "random" width/height. - * x, y are ignored. - * initial viewport = (0 0 width height) - */ - if( this->viewBox_set ) { - - if( this->width._set ) { - // Check if this is necessary - if (this->width.unit == SVGLength::PERCENT) { - this->width.computed = this->width.value * this->viewBox.width(); - } - } else { - this->width.set( SVGLength::PX, this->viewBox.width(), this->viewBox.width() ); + if( this->width._set ) { + // Check if this is necessary + if (this->width.unit == SVGLength::PERCENT) { + this->width.computed = this->width.value * this->viewBox.width(); } + } else { + this->width.set( SVGLength::PX, this->viewBox.width(), this->viewBox.width() ); + } - if( this->height._set ) { - if (this->height.unit == SVGLength::PERCENT) { - this->height.computed = this->height.value * this->viewBox.height(); - } - } else { - this->height.set(SVGLength::PX, this->viewBox.height(), this->viewBox.height() ); + if( this->height._set ) { + if (this->height.unit == SVGLength::PERCENT) { + this->height.computed = this->height.value * this->viewBox.height(); } - } else { + this->height.set(SVGLength::PX, this->viewBox.height(), this->viewBox.height() ); + } - if( !this->width._set ) { - this->width.set( SVGLength::PX, 100, 100 ); // Random default - } + } else { - if( !this->height._set ) { - this->height.set( SVGLength::PX, 100, 100 ); // Random default - } + if( !this->width._set || this->width.unit == SVGLength::PERCENT) { + this->width.set( SVGLength::PX, 300, 300 ); // CSS/SVG default } - // Ignore x, y values for root element - this->x.unset(SVGLength::PERCENT, 0.0, 0.0); - this->y.unset(SVGLength::PERCENT, 0.0, 0.0); + if( !this->height._set || this->height.unit == SVGLength::PERCENT) { + this->height.set( SVGLength::PX, 150, 150 ); // CSS/SVG default + } } - // Calculate x, y, width, height from parent/initial viewport - if (this->x.unit == SVGLength::PERCENT) { - this->x.computed = this->x.value * ictx->viewport.width(); - } + // Ignore x, y values for root element + this->unset_x_and_y(); +} - if (this->y.unit == SVGLength::PERCENT) { - this->y.computed = this->y.value * ictx->viewport.height(); - } +void SPRoot::update(SPCtx *ctx, guint flags) +{ + SPItemCtx const *ictx = (SPItemCtx const *) ctx; - if (this->width.unit == SVGLength::PERCENT) { - this->width.computed = this->width.value * ictx->viewport.width(); + if( !this->parent ) { + this->setRootDimensions(); } - if (this->height.unit == SVGLength::PERCENT) { - this->height.computed = this->height.value * ictx->viewport.height(); - } + // Calculate x, y, width, height from parent/initial viewport + this->calcDimsFromParentViewport(ictx); // std::cout << "SPRoot::update: final:" // << " x: " << x.computed @@ -355,9 +349,7 @@ Inkscape::XML::Node *SPRoot::write(Inkscape::XML::Document *xml_doc, Inkscape::X Inkscape::DrawingItem *SPRoot::show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) { - Inkscape::DrawingItem *ai = 0; - - ai = SPGroup::show(drawing, key, flags); + Inkscape::DrawingItem *ai = SPGroup::show(drawing, key, flags); if (ai) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(ai); @@ -366,10 +358,10 @@ Inkscape::DrawingItem *SPRoot::show(Inkscape::Drawing &drawing, unsigned int key // Uncomment to print out XML tree // getRepr()->recursivePrintTree(0); - + // Uncomment to print out SP Object tree // recursivePrintTree(0); - + // Uncomment to print out Display Item tree // ai->recursivePrintTree(0); diff --git a/src/sp-root.h b/src/sp-root.h index 2776ae887..4a37840d9 100644 --- a/src/sp-root.h +++ b/src/sp-root.h @@ -18,6 +18,7 @@ #include "svg/svg-length.h" #include "sp-item-group.h" #include "viewbox.h" +#include "sp-dimensions.h" #define SP_ROOT(obj) (dynamic_cast<SPRoot*>((SPObject*)obj)) #define SP_IS_ROOT(obj) (dynamic_cast<const SPRoot*>((SPObject*)obj) != NULL) @@ -25,7 +26,7 @@ class SPDefs; /** \<svg\> element */ -class SPRoot : public SPGroup, public SPViewBox { +class SPRoot : public SPGroup, public SPViewBox, public SPDimensions { public: SPRoot(); virtual ~SPRoot(); @@ -35,11 +36,6 @@ public: Inkscape::Version inkscape; } version, original; - SVGLength x; - SVGLength y; - SVGLength width; - SVGLength height; - char *onload; /** @@ -63,6 +59,9 @@ public: virtual Inkscape::DrawingItem* show(Inkscape::Drawing &drawing, unsigned int key, unsigned int flags); virtual void print(SPPrintContext *ctx); virtual const char* displayName() const; +private: + void unset_x_and_y(); + void setRootDimensions(); }; #endif /* !SP_ROOT_H_SEEN */ diff --git a/src/sp-script.cpp b/src/sp-script.cpp index bd1ab512b..144c8d76a 100644 --- a/src/sp-script.cpp +++ b/src/sp-script.cpp @@ -73,47 +73,6 @@ Inkscape::XML::Node* SPScript::write(Inkscape::XML::Document* /*doc*/, Inkscape: return repr; } -//static Inkscape::XML::Node *sp_script_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) -//{ -/* -TODO: - code copied from sp-defs - decide what to do here! - - if (flags & SP_OBJECT_WRITE_BUILD) { - - if (!repr) { - repr = xml_doc->createElement("svg:script"); - } - - GSList *l = NULL; - for ( SPObject *child = object->firstChild() ; child; child = child->getNext() ) { - Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags); - if (crepr) { - l = g_slist_prepend(l, crepr); - } - } - - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); - } - - } else { - for ( SPObject *child = object->firstChild() ; child; child = child->getNext() ) { - child->updateRepr(flags); - } - } - - if (((SPObjectClass *) (parent_class))->write) { - (* ((SPObjectClass *) (parent_class))->write)(object, xml_doc, repr, flags); - } -*/ -// -// return ((SPScript*)object)->cscript->onWrite(xml_doc, repr, flags); -//} - /* Local Variables: mode:c++ diff --git a/src/sp-spiral.cpp b/src/sp-spiral.cpp index d75db3daa..a84fc6041 100644 --- a/src/sp-spiral.cpp +++ b/src/sp-spiral.cpp @@ -14,7 +14,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ - +#include "live_effects/effect.h" #include "svg/svg.h" #include "attributes.h" #include <2geom/bezier-utils.h> @@ -429,13 +429,25 @@ void SPSpiral::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape */ Geom::Affine SPSpiral::set_transform(Geom::Affine const &xform) { - // Only set transform with proportional scaling - if (!xform.withoutTranslation().isUniformScale()) { + if (hasPathEffect() && pathEffectsEnabled() && + (this->hasPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::BEND_PATH) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::FILL_BETWEEN_MANY) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::FILL_BETWEEN_STROKES) ) ) + { + // if path has this LPE applied, don't write the transform to the pathdata, but write it 'unoptimized' + // also if the effect is type BEND PATH to fix bug #179842 + this->adjust_livepatheffect(xform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return xform; } - - // Allow live effects - if (hasPathEffect() && pathEffectsEnabled()) { + // Only set transform with proportional scaling + if (!xform.withoutTranslation().isUniformScale()) { + // Adjust livepatheffect + if (hasPathEffect() && pathEffectsEnabled()) { + this->adjust_livepatheffect(xform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + } return xform; } @@ -476,6 +488,9 @@ Geom::Affine SPSpiral::set_transform(Geom::Affine const &xform) // Adjust gradient fill this->adjust_gradient(xform * ret.inverse()); + // Adjust livepatheffect + this->adjust_livepatheffect(xform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return ret; diff --git a/src/sp-star.cpp b/src/sp-star.cpp index d7ee352c7..9844df98a 100644 --- a/src/sp-star.cpp +++ b/src/sp-star.cpp @@ -20,7 +20,7 @@ #include <cstring> #include <string> #include <glib.h> -#include <glibmm/i18n.h> +#include "live_effects/effect.h" #include "svg/svg.h" #include "attributes.h" @@ -29,6 +29,7 @@ #include "document.h" #include "sp-star.h" +#include <glibmm/i18n.h> SPStar::SPStar() : SPPolygon() , sides(5), @@ -511,13 +512,26 @@ void SPStar::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape:: Geom::Affine SPStar::set_transform(Geom::Affine const &xform) { bool opt_trans = (randomized == 0); - // Only set transform with proportional scaling - if (!xform.withoutTranslation().isUniformScale()) { + // Allow live effects + if (hasPathEffect() && pathEffectsEnabled() && + (this->hasPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::FILL_BETWEEN_MANY) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::BEND_PATH) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::FILL_BETWEEN_STROKES) ) ) + { + // if path has this LPE applied, don't write the transform to the pathdata, but write it 'unoptimized' + this->adjust_livepatheffect(xform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return xform; } - // Allow live effects - if (hasPathEffect() && pathEffectsEnabled()) { + // Only set transform with proportional scaling + if (!xform.withoutTranslation().isUniformScale()) { + // Adjust livepatheffect + if (hasPathEffect() && pathEffectsEnabled()) { + this->adjust_livepatheffect(xform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + } return xform; } @@ -558,6 +572,9 @@ Geom::Affine SPStar::set_transform(Geom::Affine const &xform) // Adjust gradient fill this->adjust_gradient(xform * ret.inverse()); + // Adjust livepatheffect + this->adjust_livepatheffect(xform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return ret; diff --git a/src/sp-style-elem.cpp b/src/sp-style-elem.cpp index c87b5436d..da02d4ef1 100644 --- a/src/sp-style-elem.cpp +++ b/src/sp-style-elem.cpp @@ -12,6 +12,9 @@ #include <iostream> #include <fstream> +// For font-rule +#include "libnrtype/FontFactory.h" + using Inkscape::XML::TEXT_NODE; SPStyleElem::SPStyleElem() : SPObject() { @@ -106,14 +109,14 @@ Inkscape::XML::Node* SPStyleElem::write(Inkscape::XML::Document* xml_doc, Inksca /** Returns the concatenation of the content of the text children of the specified object. */ -static GString * +static Glib::ustring concat_children(Inkscape::XML::Node const &repr) { - GString *ret = g_string_sized_new(0); - // effic: 0 is just to catch bugs. Increase to something reasonable. + Glib::ustring ret; + // effic: Initialising ret to a reasonable starting size could speed things up. for (Inkscape::XML::Node const *rch = repr.firstChild(); rch != NULL; rch = rch->next()) { if ( rch->type() == TEXT_NODE ) { - ret = g_string_append(ret, rch->content()); + ret += rch->content(); } } return ret; @@ -176,6 +179,10 @@ import_style_cb (CRDocHandler *a_handler, std::cerr << "import_style_cb: No document!" << std::endl; return; } + if (!document->style_sheet) { + std::cerr << "import_style_cb: No document style sheet!" << std::endl; + return; + } if (!document->getURI()) { std::cerr << "import_style_cb: Document URI is NULL" << std::endl; return; @@ -277,8 +284,10 @@ start_font_face_cb(CRDocHandler *a_handler, static_cast<void *>(parse_tmp.currStmt), unsigned(parse_tmp.stmtType)); // fixme: Check whether we need to unref currStmt if non-NULL. } + CRStatement *font_face_rule = cr_statement_new_at_font_face_rule (parse_tmp.stylesheet, NULL); + g_return_if_fail(font_face_rule && font_face_rule->type == AT_FONT_FACE_RULE_STMT); parse_tmp.stmtType = FONT_FACE_STMT; - parse_tmp.currStmt = NULL; + parse_tmp.currStmt = font_face_rule; } static void @@ -287,13 +296,76 @@ end_font_face_cb(CRDocHandler *a_handler) g_return_if_fail(a_handler->app_data != NULL); ParseTmp &parse_tmp = *static_cast<ParseTmp *>(a_handler->app_data); g_return_if_fail(parse_tmp.hasMagic()); - if (parse_tmp.stmtType != FONT_FACE_STMT || parse_tmp.currStmt != NULL) { - g_warning("Expecting currStmt==NULL and stmtType==1 (FONT_FACE_STMT) at end of @font-face, but found currStmt=%p, stmtType=%u", - static_cast<void *>(parse_tmp.currStmt), unsigned(parse_tmp.stmtType)); - // fixme: Check whether we need to unref currStmt if non-NULL. - parse_tmp.currStmt = NULL; + + CRStatement *const font_face_rule = parse_tmp.currStmt; + if (parse_tmp.stmtType == FONT_FACE_STMT + && font_face_rule + && font_face_rule->type == AT_FONT_FACE_RULE_STMT) + { + parse_tmp.stylesheet->statements = cr_statement_append(parse_tmp.stylesheet->statements, + font_face_rule); + } else { + g_warning("Found stmtType=%u, stmt=%p, stmt.type=%u.", + unsigned(parse_tmp.stmtType), + font_face_rule, + unsigned(font_face_rule->type)); } + + std::cout << "end_font_face_cb: font face rule limited support." << std::endl; + cr_declaration_dump (font_face_rule->kind.font_face_rule->decl_list, stdout, 2, TRUE); + printf ("\n"); + + // Get document + SPDocument* document = parse_tmp.document; + if (!document) { + std::cerr << "end_font_face_cb: No document!" << std::endl; + return; + } + if (!document->getURI()) { + std::cerr << "end_font_face_cb: Document URI is NULL" << std::endl; + return; + } + + // Add ttf or otf fonts. + CRDeclaration const *cur = NULL; + for (cur = font_face_rule->kind.font_face_rule->decl_list; cur; cur = cur->next) { + if (cur->property && + cur->property->stryng && + cur->property->stryng->str && + strcmp(cur->property->stryng->str, "src") == 0 ) { + + if (cur->value && + cur->value->content.str && + cur->value->content.str->stryng && + cur->value->content.str->stryng->str) { + + Glib::ustring value = cur->value->content.str->stryng->str; + std::size_t found = value.find_last_of("ttf"); + + if (value.rfind("ttf") == (value.length() - 3) || + value.rfind("otf") == (value.length() - 3)) { + + // Get file + Glib::ustring ttf_file = + Inkscape::IO::Resource::get_filename (document->getURI(), value); + + if (!ttf_file.empty()) { + font_factory *factory = font_factory::Default(); + factory->AddFontFile( ttf_file.c_str() ); + std::cout << "end_font_face_cb: Added font: " << ttf_file << std::endl; + + // FIX ME: Need to refresh font list. + } else { + std::cout << "end_font_face_cb: Failed to add: " << value << std::endl; + } + } + } + } + } + + parse_tmp.currStmt = NULL; parse_tmp.stmtType = NO_STMT; + } static void @@ -301,26 +373,38 @@ property_cb(CRDocHandler *const a_handler, CRString *const a_name, CRTerm *const a_value, gboolean const a_important) { + // std::cout << "property_cb: Entrance: " << a_name->stryng->str << ": " << cr_term_to_string(a_value) << std::endl; g_return_if_fail(a_handler && a_name); g_return_if_fail(a_handler->app_data != NULL); ParseTmp &parse_tmp = *static_cast<ParseTmp *>(a_handler->app_data); g_return_if_fail(parse_tmp.hasMagic()); - if (parse_tmp.stmtType == FONT_FACE_STMT) { - if (parse_tmp.currStmt != NULL) { - g_warning("Found non-NULL currStmt %p though stmtType==FONT_FACE_STMT.", parse_tmp.currStmt); - } - /* We currently ignore @font-face descriptors. */ - return; - } + CRStatement *const ruleset = parse_tmp.currStmt; - g_return_if_fail(ruleset - && ruleset->type == RULESET_STMT - && parse_tmp.stmtType == NORMAL_RULESET_STMT); - CRDeclaration *const decl = cr_declaration_new(ruleset, cr_string_dup(a_name), a_value); + g_return_if_fail(ruleset); + + CRDeclaration *const decl = cr_declaration_new (ruleset, cr_string_dup(a_name), a_value); g_return_if_fail(decl); decl->important = a_important; - CRStatus const append_status = cr_statement_ruleset_append_decl(ruleset, decl); - g_return_if_fail(append_status == CR_OK); + + switch (parse_tmp.stmtType) { + + case NORMAL_RULESET_STMT: { + g_return_if_fail (ruleset->type == RULESET_STMT); + CRStatus const append_status = cr_statement_ruleset_append_decl (ruleset, decl); + g_return_if_fail (append_status == CR_OK); + break; + } + case FONT_FACE_STMT: { + g_return_if_fail (ruleset->type == AT_FONT_FACE_RULE_STMT); + CRDeclaration *new_decls = cr_declaration_append (ruleset->kind.font_face_rule->decl_list, decl); + g_return_if_fail (new_decls); + ruleset->kind.font_face_rule->decl_list = new_decls; + break; + } + default: + g_warning ("property_cb: Unhandled stmtType: %u", parse_tmp.stmtType); + return; + } } CRParser* @@ -364,10 +448,6 @@ void SPStyleElem::read_content() { // style element would correspond to document->style_sheet, while // laters ones are chained on using style_sheet->next). - if (document->style_sheet != NULL) { - cr_stylesheet_destroy (document->style_sheet); - document->style_sheet = NULL; - } document->style_sheet = cr_stylesheet_new (NULL); CRParser *parser = parser_init(document->style_sheet, document); @@ -376,17 +456,20 @@ void SPStyleElem::read_content() { ParseTmp *parse_tmp = reinterpret_cast<ParseTmp *>(sac_handler->app_data); //XML Tree being used directly here while it shouldn't be. - GString *const text = concat_children(*getRepr()); + Glib::ustring const text = concat_children(*getRepr()); CRStatus const parse_status = - cr_parser_parse_buf (parser, reinterpret_cast<guchar *>(text->str), text->len, CR_UTF_8); + cr_parser_parse_buf (parser, reinterpret_cast<const guchar *>(text.c_str()), text.bytes(), CR_UTF_8); // std::cout << "SPStyeElem::read_content: result:" << std::endl; // const gchar* string = cr_stylesheet_to_string (document->style_sheet); // std::cout << (string?string:"Null") << std::endl; if (parse_status == CR_OK) { - cr_cascade_set_sheet(document->style_cascade, document->style_sheet, ORIGIN_AUTHOR); + // Also destroys old style sheet: + cr_cascade_set_sheet (document->style_cascade, document->style_sheet, ORIGIN_AUTHOR); } else { + cr_stylesheet_destroy (document->style_sheet); + document->style_sheet = NULL; if (parse_status != CR_PARSING_ERROR) { g_printerr("parsing error code=%u\n", unsigned(parse_status)); /* Better than nothing. TODO: Improve libcroco's error handling. At a minimum, add a @@ -402,6 +485,7 @@ void SPStyleElem::read_content() { // If style sheet has changed, we need to cascade the entire object tree, top down // Get root, read style, loop through children update_style_recursively( (SPObject *)document->getRoot() ); + // cr_stylesheet_dump (document->style_sheet, stdout); } /** diff --git a/src/sp-tag.h b/src/sp-tag.h index 927bb45d1..36459a04b 100644 --- a/src/sp-tag.h +++ b/src/sp-tag.h @@ -3,7 +3,7 @@ /** \file * SVG <inkscape:tag> implementation - * + * * Authors: * Theodore Janeczko * @@ -25,19 +25,19 @@ class SPTag : public SPObject { public: SPTag() {} virtual ~SPTag() {} - + virtual void build(SPDocument * doc, Inkscape::XML::Node *repr); //virtual void release(); virtual void set(unsigned key, const gchar* value); virtual void update(SPCtx * ctx, unsigned flags); - + virtual Inkscape::XML::Node* write(Inkscape::XML::Document* doc, Inkscape::XML::Node* repr, guint flags); - + bool expanded() const { return _expanded; } void setExpanded(bool isexpanded); void moveTo(SPObject *target, gboolean intoafter); - + private: bool _expanded; }; diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 2a88c5009..3d9a41fe3 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -28,6 +28,7 @@ #include <libnrtype/font-instance.h> #include <glibmm/i18n.h> +#include <glibmm/regex.h> #include "svg/svg.h" #include "display/drawing-text.h" #include "attributes.h" @@ -72,10 +73,6 @@ void SPText::build(SPDocument *doc, Inkscape::XML::Node *repr) { this->readAttr( "textLength" ); this->readAttr( "lengthAdjust" ); - // SVG 2 Auto wrapped text - this->readAttr( "width" ); - this->readAttr( "height" ); - SPItem::build(doc, repr); this->readAttr( "sodipodi:linespacing" ); // has to happen after the styles are read @@ -107,22 +104,6 @@ void SPText::set(unsigned int key, const gchar* value) { this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_TEXT_LAYOUT_MODIFIED_FLAG); break; - case SP_ATTR_WIDTH: - if (!this->width.read(value) || this->width.value < 0.0) { - this->width.unset(); - } - - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - - case SP_ATTR_HEIGHT: - if (!this->height.read(value) || this->height.value < 0.0) { - this->height.unset(); - } - - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - default: SPItem::set(key, value); break; @@ -144,30 +125,24 @@ void SPText::remove_child(Inkscape::XML::Node *rch) { void SPText::update(SPCtx *ctx, guint flags) { + unsigned childflags = (flags & SP_OBJECT_MODIFIED_CASCADE); if (flags & SP_OBJECT_MODIFIED_FLAG) { childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } // Create temporary list of children - GSList *l = NULL; - + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child, this); - l = g_slist_prepend (l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = reinterpret_cast<SPObject*>(l->data); // We just built this list, so cast is safe. - l = g_slist_remove (l, child); - + for (auto child:l) { if (childflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { /* fixme: Do we need transform? */ child->updateDisplay(ctx, childflags); } - sp_object_unref(child, this); } @@ -188,6 +163,18 @@ void SPText::update(SPCtx *ctx, guint flags) { attributes.update( em, ex, w, h ); + // Set inline_size computed value if necessary (i.e. if unit is %). + if (style->inline_size.set) { + if (style->inline_size.unit == SP_CSS_UNIT_PERCENT) { + if (style->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB || + style->writing_mode.computed == SP_CSS_WRITING_MODE_RL_TB) { + style->inline_size.computed = style->inline_size.value * ictx->viewport.width(); + } else { + style->inline_size.computed = style->inline_size.value * ictx->viewport.height(); + } + } + } + /* fixme: It is not nice to have it here, but otherwise children content changes does not work */ /* fixme: Even now it may not work, as we are delayed */ /* fixme: So check modification flag everywhere immediate state is used */ @@ -230,23 +217,16 @@ void SPText::modified(guint flags) { } // Create temporary list of children - GSList *l = NULL; - + std::vector<SPObject *> l; for (auto& child: children) { sp_object_ref(&child, this); - l = g_slist_prepend (l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - - while (l) { - SPObject *child = reinterpret_cast<SPObject*>(l->data); // We just built this list, so cast is safe. - l = g_slist_remove (l, child); - + for (auto child:l) { if (cflags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(cflags); } - sp_object_unref(child, this); } } @@ -257,7 +237,7 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X repr = xml_doc->createElement("svg:text"); } - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { if (SP_IS_TITLE(&child) || SP_IS_DESC(&child)) { @@ -273,14 +253,13 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X } if (crepr) { - l = g_slist_prepend (l, crepr); + l.push_back(crepr); } } - while (l) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove (l, l->data); + for (auto i=l.rbegin();i!=l.rend();++i) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { @@ -299,14 +278,6 @@ Inkscape::XML::Node *SPText::write(Inkscape::XML::Document *xml_doc, Inkscape::X this->attributes.writeTo(repr); this->rebuildLayout(); // copied from update(), see LP Bug 1339305 - // SVG 2 Auto-wrapped text - if( this->width.computed > 0.0 ) { - sp_repr_set_svg_double(repr, "width", this->width.computed); - } - if( this->height.computed > 0.0 ) { - sp_repr_set_svg_double(repr, "height", this->height.computed); - } - SPItem::write(xml_doc, repr, flags); return repr; @@ -359,7 +330,7 @@ gchar* SPText::description() const { int unit = prefs->getInt("/options/font/unitType", SP_CSS_UNIT_PT); Inkscape::Util::Quantity q = Inkscape::Util::Quantity(style->font_size.computed, "px"); q.quantity *= this->i2doc_affine().descrim(); - GString *xs = g_string_new(q.string(sp_style_get_css_unit_string(unit)).c_str()); + Glib::ustring xs = q.string(sp_style_get_css_unit_string(unit)); char const *trunc = ""; Inkscape::Text::Layout const *layout = te_get_layout((SPItem *) this); @@ -369,8 +340,8 @@ gchar* SPText::description() const { } char *ret = ( SP_IS_TEXT_TEXTPATH(this) - ? g_strdup_printf(_("on path%s (%s, %s)"), trunc, n, xs->str) - : g_strdup_printf(_("%s (%s, %s)"), trunc, n, xs->str) ); + ? g_strdup_printf(_("on path%s (%s, %s)"), trunc, n, xs.c_str()) + : g_strdup_printf(_("%s (%s, %s)"), trunc, n, xs.c_str()) ); return ret; } @@ -465,60 +436,133 @@ unsigned SPText::_buildLayoutInput(SPObject *root, Inkscape::Text::Layout::Optio int child_attrs_offset = 0; Inkscape::Text::Layout::OptionalTextTagAttrs optional_attrs; - // Test SVG 2 text in shape implementation // To do: follow SPItem clip_ref/mask_ref code if (style->shape_inside.set ) { - // Extract out id - Glib::ustring shape_url = style->shape_inside.value; - if ( shape_url.compare(0,5,"url(#") != 0 || shape_url.compare(shape_url.size()-1,1,")") != 0 ){ - std::cerr << "SPText::_buildLayoutInput(): Invalid shape-inside value: " << shape_url << std::endl; - } else { - shape_url.erase(0,5); - shape_url.erase(shape_url.size()-1,1); - // std::cout << "SPText::_buildLayoutInput(): shape-inside: " << shape_url << std::endl; - SPShape *shape = dynamic_cast<SPShape *>(document->getObjectById( shape_url )); - if ( shape ) { - - // This code adapted from sp-flowregion.cpp: GetDest() - if (!(shape->_curve)) { - shape->set_shape(); - } - SPCurve *curve = shape->getCurve(); + // Find union of all exclusion shapes + Shape *exclusion_shape; + if(style->shape_subtract.set) { + exclusion_shape = _buildExclusionShape(); + } - if ( curve ) { - Path *temp = new Path; - Path *padded = new Path; - temp->LoadPathVector( curve->get_pathvector(), shape->transform, true ); - if( style->shape_padding.set ) { - // std::cout << " padding: " << style->shape_padding.computed << std::endl; - temp->OutsideOutline ( padded, style->shape_padding.computed, join_round, butt_straight, 20.0 ); + // Extract out shapes (a comma separated list of urls) + Glib::ustring shapeInside_value = style->shape_inside.value; + std::vector<Glib::ustring> shapes_url = Glib::Regex::split_simple(" ", shapeInside_value); + for (int i=0; i<shapes_url.size(); ++i) { + Glib::ustring shape_url = shapes_url.at(i); + if ( shape_url.compare(0,5,"url(#") != 0 || shape_url.compare(shape_url.size()-1,1,")") != 0 ){ + std::cerr << "SPText::_buildLayoutInput(): Invalid shape-inside value: " << shape_url << std::endl; + } else { + shape_url.erase(0,5); + shape_url.erase(shape_url.size()-1,1); + std::cout << "SPText::_buildLayoutInput(): shape-inside: " << shape_url << std::endl; + SPShape *shape = dynamic_cast<SPShape *>(document->getObjectById( shape_url )); + if ( shape ) { + + // This code adapted from sp-flowregion.cpp: GetDest() + if (!(shape->_curve)) { + shape->set_shape(); + } + SPCurve *curve = shape->getCurve(); + + if ( curve ) { + Path *temp = new Path; + Path *padded = new Path; + temp->LoadPathVector( curve->get_pathvector(), shape->transform, true ); + if( style->shape_padding.set ) { + // std::cout << " padding: " << style->shape_padding.computed << std::endl; + temp->OutsideOutline ( padded, style->shape_padding.computed, join_round, butt_straight, 20.0 ); + } else { + // std::cout << " no padding" << std::endl; + padded->Copy( temp ); + } + padded->Convert( 0.25 ); // Convert to polyline + Shape* sh = new Shape; + padded->Fill( sh, 0 ); + // for( unsigned i = 0; i < temp->pts.size(); ++i ) { + // std::cout << " ........ " << temp->pts[i].p << std::endl; + // } + // std::cout << " ...... shape: " << sh->numberOfPoints() << std::endl; + Shape *uncross = new Shape; + uncross->ConvertToShape( sh ); + + // Subtract exclusion shape + if(style->shape_subtract.set) { + Shape *copy = new Shape; + if (exclusion_shape && exclusion_shape->hasEdges()) { + copy->Booleen(uncross, const_cast<Shape*>(exclusion_shape), bool_op_diff); + } else { + copy->Copy(uncross); + } + layout.appendWrapShape( copy ); + //delete exclusion_shape; + continue; + } + + layout.appendWrapShape( uncross ); + + delete temp; + delete padded; + delete sh; + // delete uncross; } else { - // std::cout << " no padding" << std::endl; - padded->Copy( temp ); + std::cerr << "SPText::_buildLayoutInput(): Failed to get curve." << std::endl; } - padded->Convert( 0.25 ); // Convert to polyline - Shape* sh = new Shape; - padded->Fill( sh, 0 ); - // for( unsigned i = 0; i < temp->pts.size(); ++i ) { - // std::cout << " ........ " << temp->pts[i].p << std::endl; - // } - // std::cout << " ...... shape: " << sh->numberOfPoints() << std::endl; - Shape *uncross = new Shape; - uncross->ConvertToShape( sh ); - layout.appendWrapShape( uncross ); - - delete temp; - delete padded; - delete sh; - // delete uncross; } else { - std::cerr << "SPText::_buildLayoutInput(): Failed to get curve." << std::endl; + std::cerr << "SPText::_buildLayoutInput(): Failed to find shape." << std::endl; } - } else { - std::cerr << "SPText::_buildLayoutInput(): Failed to find shape." << std::endl; } } + } else if (style->inline_size.set) { + // If both shape_inside and inline_size are set, shape_inside wins out. + + // We construct a rectange with one dimension set by the computed value of 'inline-size' + // and the other dimension set to infinity. Text is layed out starting at the 'x' and 'y' + // attribute values. This is handled elsewhere. + + double inline_size = style->inline_size.computed; + unsigned mode = style->writing_mode.computed; + unsigned anchor = style->text_anchor.computed; + unsigned direction = style->direction.computed; + + Geom::Rect frame; + if (mode == SP_CSS_WRITING_MODE_LR_TB || + mode == SP_CSS_WRITING_MODE_RL_TB) { + // horizontal + frame = Geom::Rect::from_xywh(attributes.firstXY()[Geom::X], -100000, inline_size, 200000); + if (anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) { + frame *= Geom::Translate (-inline_size/2.0, 0 ); + } else if ( (direction == SP_CSS_DIRECTION_LTR && anchor == SP_CSS_TEXT_ANCHOR_END ) || + (direction == SP_CSS_DIRECTION_RTL && anchor == SP_CSS_TEXT_ANCHOR_START) ) { + frame *= Geom::Translate (-inline_size, 0); + } + } else { + // vertical + frame = Geom::Rect::from_xywh(-100000, attributes.firstXY()[Geom::Y], 200000, inline_size); + if (anchor == SP_CSS_TEXT_ANCHOR_MIDDLE) { + frame *= Geom::Translate (0, -inline_size/2.0); + } else if (anchor == SP_CSS_TEXT_ANCHOR_END) { + frame *= Geom::Translate (0, -inline_size); + } + } + // std::cout << " inline_size frame: " << frame << std::endl; + + Shape *shape = new Shape; + shape->Reset(); + int v0 = shape->AddPoint(frame.corner(0)); + int v1 = shape->AddPoint(frame.corner(1)); + int v2 = shape->AddPoint(frame.corner(2)); + int v3 = shape->AddPoint(frame.corner(3)); + shape->AddEdge(v0, v1); + shape->AddEdge(v1, v2); + shape->AddEdge(v2, v3); + shape->AddEdge(v3, v0); + Shape *uncross = new Shape; + uncross->ConvertToShape( shape ); + + layout.appendWrapShape( uncross ); + + delete shape; } if (SP_IS_TEXT(root)) { @@ -526,6 +570,8 @@ unsigned SPText::_buildLayoutInput(SPObject *root, Inkscape::Text::Layout::Optio layout.strut.reset(); if (style) { + + // Strut font_instance *font = font_factory::Default()->FaceFromStyle( style ); if (font) { font->FontMetrics(layout.strut.ascent, layout.strut.descent, layout.strut.xheight); @@ -541,6 +587,32 @@ unsigned SPText::_buildLayoutInput(SPObject *root, Inkscape::Text::Layout::Optio layout.strut.computeEffective( style->line_height.computed/style->font_size.computed ); } } + + // SVG 2 Text wrapping + if (style->shape_inside.set) { + // 'x' and 'y' attributes are always ignored. + optional_attrs.x.clear(); + optional_attrs.y.clear(); + } + else if (style->inline_size.set) { + // For horizontal text: + // 'x' is used to calculate the left/right edges of the rectangle but is not + // needed later. If not deleted here, it will cause an incorrect positioning + // of the first line. + // 'y' is used to determine where the first line box is located and is needed + // during the output stage. + // For vertical text: + // Follow above but exchange 'x' and 'y'. + if (style->writing_mode.computed == SP_CSS_WRITING_MODE_LR_TB || + style->writing_mode.computed == SP_CSS_WRITING_MODE_RL_TB) { + // Horizontal text + optional_attrs.x.clear(); + } else { + // Vertical text + optional_attrs.y.clear(); + } + } + } // set textLength on the entire layout, see note in TNG-Layout.h @@ -610,6 +682,63 @@ unsigned SPText::_buildLayoutInput(SPObject *root, Inkscape::Text::Layout::Optio return length; } +Shape* SPText::_buildExclusionShape() const +{ + Shape *result = new Shape(); // Union of all exlusion shapes + Shape *shape_temp = new Shape(); + + Glib::ustring shapeSubtract_value = style->shape_subtract.value; + + // Extract out shapes (a comma separated list of urls) + std::vector<Glib::ustring> shapes_url = Glib::Regex::split_simple(" ", shapeSubtract_value); + + for(int i=0; i<shapes_url.size(); i++) { + Glib::ustring shape_url = shapes_url.at(i); + if ( shape_url.compare(0,5,"url(#") != 0 || shape_url.compare(shape_url.size()-1,1,")") != 0 ){ + std::cerr << "SPText::_buildLayoutInput(): Invalid shape-inside value: " << shape_url << std::endl; + } else { + shape_url.erase(0,5); + shape_url.erase(shape_url.size()-1,1); + // std::cout << "SPText::_buildLayoutInput(): shape-inside: " << shape_url << std::endl; + SPShape *shape = dynamic_cast<SPShape *>(document->getObjectById( shape_url )); + if ( shape ) { + // This code adapted from sp-flowregion.cpp: GetDest() + if (!(shape->_curve)) { + shape->set_shape(); + } + SPCurve *curve = shape->getCurve(); + + if ( curve ) { + Path *temp = new Path; + Path *margin = new Path; + temp->LoadPathVector( curve->get_pathvector(), shape->transform, true ); + + if( shape->style->shape_margin.set ) { + temp->OutsideOutline ( margin, -shape->style->shape_margin.computed, join_round, butt_straight, 20.0 ); + } else { + margin->Copy( temp ); + } + + margin->Convert( 0.25 ); // Convert to polyline + Shape* sh = new Shape; + margin->Fill( sh, 0 ); + + Shape *uncross = new Shape; + uncross->ConvertToShape( sh ); + + if (result->hasEdges()) { + shape_temp->Booleen(result, uncross, bool_op_union); + std::swap(result, shape_temp); + } else { + result->Copy(uncross); + } + } + } + } + } + return result; +} + void SPText::rebuildLayout() { layout.clear(); diff --git a/src/sp-text.h b/src/sp-text.h index be48d7fcb..67613d043 100644 --- a/src/sp-text.h +++ b/src/sp-text.h @@ -42,14 +42,10 @@ public: /** Completely recalculates the layout. */ void rebuildLayout(); -//semiprivate: (need to be accessed by the C-style functions still) + //semiprivate: (need to be accessed by the C-style functions still) TextTagAttributes attributes; Inkscape::Text::Layout layout; - // SVG 2 Auto-wrapped text - SVGLength width; - SVGLength height; - /** when the object is transformed it's nicer to change the font size and coordinates when we can, rather than just applying a matrix transform. is_root is used to indicate to the function that it should @@ -72,6 +68,9 @@ private: that we don't get a spurious extra one at the end of the flow. */ unsigned _buildLayoutInput(SPObject *root, Inkscape::Text::Layout::OptionalTextTagAttrs const &parent_optional_attrs, unsigned parent_attrs_offset, bool in_textpath); + /** Union all exlusion shapes. */ + Shape* _buildExclusionShape() const; + public: /** Optimize textpath text on next set_transform. */ void optimizeTextpathText() diff --git a/src/sp-tref-reference.cpp b/src/sp-tref-reference.cpp index dfb8dd60b..d683e34ed 100644 --- a/src/sp-tref-reference.cpp +++ b/src/sp-tref-reference.cpp @@ -75,8 +75,8 @@ void SPTRefReference::notifyChildOrderChanged(Inkscape::XML::Node &/*node*/, Ink void SPTRefReference::notifyContentChanged(Inkscape::XML::Node &/*node*/, - Inkscape::Util::ptr_shared<char> /*old_content*/, - Inkscape::Util::ptr_shared<char> /*new_content*/) + Inkscape::Util::ptr_shared /*old_content*/, + Inkscape::Util::ptr_shared /*new_content*/) { SPObject *owner = getOwner(); @@ -87,8 +87,8 @@ void SPTRefReference::notifyContentChanged(Inkscape::XML::Node &/*node*/, void SPTRefReference::notifyAttributeChanged(Inkscape::XML::Node &/*node*/, GQuark /*name*/, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> /*new_value*/) + Inkscape::Util::ptr_shared /*old_value*/, + Inkscape::Util::ptr_shared /*new_value*/) { // Do nothing - tref only cares about textual content } diff --git a/src/sp-tref-reference.h b/src/sp-tref-reference.h index b555ace2d..516e125c1 100644 --- a/src/sp-tref-reference.h +++ b/src/sp-tref-reference.h @@ -52,11 +52,11 @@ public: virtual void notifyChildOrderChanged(Inkscape::XML::Node &node, Inkscape::XML::Node &child, Inkscape::XML::Node *old_prev, Inkscape::XML::Node *new_prev); virtual void notifyContentChanged(Inkscape::XML::Node &node, - Inkscape::Util::ptr_shared<char> old_content, - Inkscape::Util::ptr_shared<char> new_content); + Inkscape::Util::ptr_shared old_content, + Inkscape::Util::ptr_shared new_content); virtual void notifyAttributeChanged(Inkscape::XML::Node &node, GQuark name, - Inkscape::Util::ptr_shared<char> old_value, - Inkscape::Util::ptr_shared<char> new_value); + Inkscape::Util::ptr_shared old_value, + Inkscape::Util::ptr_shared new_value); ///////////////////////////////////////////////////////////////////// protected: diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp index 014876478..2655e219b 100644 --- a/src/sp-tref.cpp +++ b/src/sp-tref.cpp @@ -502,16 +502,12 @@ sp_tref_convert_to_tspan(SPObject *obj) // RECURSIVE CASE //////////////////// else { - GSList *l = NULL; + std::vector<SPObject *> l; for (auto& child: obj->children) { sp_object_ref(&child, obj); - l = g_slist_prepend (l, &child); + l.push_back(&child); } - l = g_slist_reverse (l); - while (l) { - SPObject *child = reinterpret_cast<SPObject *>(l->data); // We just built this list, so cast is safe. - l = g_slist_remove (l, child); - + for(auto child:l) { // Note that there may be more than one conversion happening here, so if it's not a // tref being passed into this function, the returned value can't be specifically known new_tspan = sp_tref_convert_to_tspan(child); diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp index 2e169ad77..d8c655c06 100644 --- a/src/sp-tspan.cpp +++ b/src/sp-tspan.cpp @@ -171,7 +171,7 @@ Inkscape::XML::Node* SPTSpan::write(Inkscape::XML::Document *xml_doc, Inkscape:: this->attributes.writeTo(repr); if ( flags&SP_OBJECT_WRITE_BUILD ) { - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node* c_repr=NULL; @@ -185,14 +185,13 @@ Inkscape::XML::Node* SPTSpan::write(Inkscape::XML::Document *xml_doc, Inkscape:: } if ( c_repr ) { - l = g_slist_prepend(l, c_repr); + l.push_back(c_repr); } } - while ( l ) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for (auto i = l.rbegin(); i!= l.rend(); ++i) { + repr->addChild((*i), NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { @@ -395,7 +394,7 @@ Inkscape::XML::Node* SPTextPath::write(Inkscape::XML::Document *xml_doc, Inkscap } if ( flags & SP_OBJECT_WRITE_BUILD ) { - GSList *l = NULL; + std::vector<Inkscape::XML::Node *> l; for (auto& child: children) { Inkscape::XML::Node* c_repr=NULL; @@ -409,14 +408,13 @@ Inkscape::XML::Node* SPTextPath::write(Inkscape::XML::Document *xml_doc, Inkscap } if ( c_repr ) { - l = g_slist_prepend(l, c_repr); + l.push_back(c_repr); } } - while ( l ) { - repr->addChild((Inkscape::XML::Node *) l->data, NULL); - Inkscape::GC::release((Inkscape::XML::Node *) l->data); - l = g_slist_remove(l, l->data); + for( auto i = l.rbegin(); i != l.rend(); ++i ) { + repr->addChild(*i, NULL); + Inkscape::GC::release(*i); } } else { for (auto& child: children) { @@ -462,24 +460,23 @@ void sp_textpath_to_text(SPObject *tp) xy *= tp->document->getDocumentScale().inverse(); // Convert to user-units. // make a list of textpath children - GSList *tp_reprs = NULL; + std::vector<Inkscape::XML::Node *> tp_reprs; for (auto& o: tp->children) { - tp_reprs = g_slist_prepend(tp_reprs, o.getRepr()); + tp_reprs.push_back(o.getRepr()); } - for ( GSList *i = tp_reprs ; i ; i = i->next ) { + for (auto i = tp_reprs.rbegin(); i != tp_reprs.rend(); ++i) { // make a copy of each textpath child - Inkscape::XML::Node *copy = ((Inkscape::XML::Node *) i->data)->duplicate(text->getRepr()->document()); + Inkscape::XML::Node *copy = (*i)->duplicate(text->getRepr()->document()); // remove the old repr from under textpath - tp->getRepr()->removeChild((Inkscape::XML::Node *) i->data); + tp->getRepr()->removeChild(*i); // put its copy under text text->getRepr()->addChild(copy, NULL); // fixme: copy id } //remove textpath tp->deleteObject(); - g_slist_free(tp_reprs); // set x/y on text (to be near where it was when on path) /* fixme: Yuck, is this really the right test? */ diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 648852961..61e8002bb 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -43,11 +43,8 @@ SPUse::SPUse() : SPItem(), + SPDimensions(), child(NULL), - x(), - y(), - width(), - height(), href(NULL), ref(new SPUseReference(this)), _delete_connection(), @@ -356,22 +353,21 @@ Geom::Affine SPUse::get_root_transform() { //track the ultimate source of a chain of uses SPObject *orig = this->child; - GSList *chain = NULL; - chain = g_slist_prepend(chain, this); + std::vector<SPItem*> chain; + chain.push_back(this); while (dynamic_cast<SPUse *>(orig)) { - chain = g_slist_prepend(chain, orig); + chain.push_back(dynamic_cast<SPItem *>(orig)); orig = dynamic_cast<SPUse *>(orig)->child; } - chain = g_slist_prepend(chain, orig); - + chain.push_back(dynamic_cast<SPItem *>(orig)); // calculate the accummulated transform, starting from the original Geom::Affine t(Geom::identity()); - for (GSList *i = chain; i != NULL; i = i->next) { - SPItem *i_tem = reinterpret_cast<SPItem *>(i->data); + for (auto i=chain.rbegin(); i!=chain.rend(); ++i) { + SPItem *i_tem = *i; // "An additional transformation translate(x,y) is appended to the end (i.e., // right-side) of the transform attribute on the generated 'g', where x and y @@ -385,8 +381,6 @@ Geom::Affine SPUse::get_root_transform() { t *= i_tem->transform; } - - g_slist_free(chain); return t; } @@ -442,7 +436,7 @@ void SPUse::move_compensate(Geom::Affine const *mp) { if(item){ item->transform *= m; Geom::Affine identity; - item->doWriteTransform(clip.getRepr(),item->transform, &identity); + item->doWriteTransform(item->transform, &identity); } } } @@ -452,7 +446,7 @@ void SPUse::move_compensate(Geom::Affine const *mp) { if(item){ item->transform *= m; Geom::Affine identity; - item->doWriteTransform(mask.getRepr(),item->transform, &identity); + item->doWriteTransform(item->transform, &identity); } } } @@ -482,7 +476,7 @@ void SPUse::move_compensate(Geom::Affine const *mp) { if(item){ item->transform *= clone_move.inverse(); Geom::Affine identity; - item->doWriteTransform(clip.getRepr(),item->transform, &identity); + item->doWriteTransform(item->transform, &identity); } } } @@ -492,7 +486,7 @@ void SPUse::move_compensate(Geom::Affine const *mp) { if(item){ item->transform *= clone_move.inverse(); Geom::Affine identity; - item->doWriteTransform(mask.getRepr(),item->transform, &identity); + item->doWriteTransform(item->transform, &identity); } } } @@ -500,7 +494,7 @@ void SPUse::move_compensate(Geom::Affine const *mp) { // commit the compensation this->transform *= clone_move; - this->doWriteTransform(this->getRepr(), this->transform, &advertized_move); + this->doWriteTransform(this->transform, &advertized_move); this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } @@ -584,21 +578,7 @@ void SPUse::update(SPCtx *ctx, unsigned flags) { childflags &= SP_OBJECT_MODIFIED_CASCADE; /* Set up child viewport */ - if (this->x.unit == SVGLength::PERCENT) { - this->x.computed = this->x.value * ictx->viewport.width(); - } - - if (this->y.unit == SVGLength::PERCENT) { - this->y.computed = this->y.value * ictx->viewport.height(); - } - - if (this->width.unit == SVGLength::PERCENT) { - this->width.computed = this->width.value * ictx->viewport.width(); - } - - if (this->height.unit == SVGLength::PERCENT) { - this->height.computed = this->height.value * ictx->viewport.height(); - } + this->calcDimsFromParentViewport(ictx); childflags &= ~SP_OBJECT_USER_MODIFIED_FLAG_B; @@ -742,7 +722,7 @@ SPItem *SPUse::unlink() { { Geom::Affine nomove(Geom::identity()); // Advertise ourselves as not moving. - item->doWriteTransform(item->getRepr(), t, &nomove); + item->doWriteTransform(t, &nomove); } return item; diff --git a/src/sp-use.h b/src/sp-use.h index 81e4391aa..bcf0a8513 100644 --- a/src/sp-use.h +++ b/src/sp-use.h @@ -19,12 +19,13 @@ #include <sigc++/sigc++.h> #include "svg/svg-length.h" +#include "sp-dimensions.h" #include "sp-item.h" #include "enums.h" class SPUseReference; -class SPUse : public SPItem { +class SPUse : public SPItem, public SPDimensions { public: SPUse(); virtual ~SPUse(); @@ -34,10 +35,6 @@ public: SPItem *child; // SVG attrs - SVGLength x; - SVGLength y; - SVGLength width; - SVGLength height; char *href; // the reference to the original object diff --git a/src/splivarot.cpp b/src/splivarot.cpp index c594a6426..3410a2635 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -867,7 +867,7 @@ void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Affine //There is a special group to markers whith this reverse the order in clussion m_repr->setPosition(0); SPItem *marker_item = (SPItem *) doc->getObjectByRepr(m_repr); - marker_item->doWriteTransform(m_repr, tr); + marker_item->doWriteTransform(tr); if (!legacy) { sp_item_path_outline(marker_item, desktop, legacy); } @@ -1414,7 +1414,7 @@ sp_item_path_outline(SPItem *item, SPDesktop *desktop, bool legacy) // restore title, description, id, transform g_repr->setAttribute("id", id); SPItem *newitem = (SPItem *) doc->getObjectByRepr(g_repr); - newitem->doWriteTransform(g_repr, transform); + newitem->doWriteTransform(transform); if (title) { newitem->setTitle(title); } @@ -1768,7 +1768,7 @@ void sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool Geom::Affine const transform(item->transform); - item->doWriteTransform(item->getRepr(), Geom::identity()); + item->doWriteTransform(Geom::identity()); //XML Tree being used directly here while it shouldn't be... gchar *style = g_strdup(item->getRepr()->attribute("style")); @@ -1869,7 +1869,7 @@ void sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool if ( updating ) { //XML Tree being used directly here while it shouldn't be - item->doWriteTransform(item->getRepr(), transform); + item->doWriteTransform(transform); char const *id = item->getRepr()->attribute("id"); char const *uri = g_strdup_printf("#%s", id); repr->setAttribute("xlink:href", uri); @@ -1893,7 +1893,7 @@ void sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool const char *n_id = item->getRepr()->attribute("id"); item->deleteObject(false); repr->setAttribute("id", n_id); - nitem->doWriteTransform(repr, transform); + nitem->doWriteTransform(transform); } // The object just created from a temporary repr is only a seed. @@ -1961,7 +1961,7 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset) Geom::Affine const transform(item->transform); - item->doWriteTransform(item->getRepr(), Geom::identity()); + item->doWriteTransform(Geom::identity()); gchar *style = g_strdup(item->getRepr()->attribute("style")); @@ -2103,7 +2103,7 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset) SPItem *newitem = (SPItem *) desktop->getDocument()->getObjectByRepr(repr); // reapply the transform - newitem->doWriteTransform(repr, transform); + newitem->doWriteTransform(transform); repr->setAttribute("id", id); @@ -2173,7 +2173,7 @@ sp_selected_path_simplify_item(SPDesktop *desktop, this is necessary so that the item is transformed twice back and forth, allowing all compensations to cancel out regardless of the preferences */ - item->doWriteTransform(item->getRepr(), Geom::identity()); + item->doWriteTransform(Geom::identity()); gchar *style = g_strdup(item->getRepr()->attribute("style")); gchar *mask = g_strdup(item->getRepr()->attribute("mask")); @@ -2246,7 +2246,7 @@ sp_selected_path_simplify_item(SPDesktop *desktop, SPItem *newitem = (SPItem *) desktop->getDocument()->getObjectByRepr(repr); // reapply the transform - newitem->doWriteTransform(repr, transform); + newitem->doWriteTransform(transform); // restore title & description if (title) { diff --git a/src/style-internal.cpp b/src/style-internal.cpp index 5c2f5697f..666bd75c6 100644 --- a/src/style-internal.cpp +++ b/src/style-internal.cpp @@ -101,7 +101,7 @@ SPIFloat::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase con return (name + ":inherit;"); } else { Inkscape::CSSOStringStream os; - os << name << ":" << this->value << ";"; + os << name << ":" << this->value << important_str() << ";"; return os.str(); } } @@ -175,7 +175,7 @@ SPIScale24::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase c return (name + ":inherit;"); } else { Inkscape::CSSOStringStream os; - os << name << ":" << SP_SCALE24_TO_FLOAT(this->value) << ";"; + os << name << ":" << SP_SCALE24_TO_FLOAT(this->value) << important_str() << ";"; return os.str(); } } @@ -327,39 +327,41 @@ SPILength::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase co Inkscape::CSSOStringStream os; switch (this->unit) { case SP_CSS_UNIT_NONE: - os << name << ":" << this->computed << ";"; + os << name << ":" << this->computed; break; case SP_CSS_UNIT_PX: - os << name << ":" << this->computed << "px;"; + os << name << ":" << this->computed << "px"; break; case SP_CSS_UNIT_PT: - os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "pt") << "pt;"; + os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "pt") << "pt"; break; case SP_CSS_UNIT_PC: - os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "pc") << "pc;"; + os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "pc") << "pc"; break; case SP_CSS_UNIT_MM: - os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "mm") << "mm;"; + os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "mm") << "mm"; break; case SP_CSS_UNIT_CM: - os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "cm") << "cm;"; + os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "cm") << "cm"; break; case SP_CSS_UNIT_IN: - os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "in") << "in;"; + os << name << ":" << Inkscape::Util::Quantity::convert(this->computed, "px", "in") << "in"; break; case SP_CSS_UNIT_EM: - os << name << ":" << this->value << "em;"; + os << name << ":" << this->value << "em"; break; case SP_CSS_UNIT_EX: - os << name << ":" << this->value << "ex;"; + os << name << ":" << this->value << "ex"; break; case SP_CSS_UNIT_PERCENT: - os << name << ":" << (this->value * 100.0) << "%;"; + os << name << ":" << (this->value * 100.0) << "%"; break; default: /* Invalid */ break; } + os << important_str(); + os << ";"; return os.str(); } } @@ -477,7 +479,7 @@ SPILengthOrNormal::write( guint const flags, SPStyleSrc const &style_src_req, SP bool src = (style_src_req == style_src || !(flags & SP_STYLE_FLAG_IFSRC)); if (should_write(flags, set, dfp, src)) { if (this->normal) { - return (name + ":normal;"); + return (name + ":normal" + important_str() + ";"); } else { return SPILength::write(flags, style_src_req, base); } @@ -571,13 +573,15 @@ SPIFontVariationSettings::write( guint const flags, SPStyleSrc const &style_src_ bool src = (style_src_req == style_src || !(flags & SP_STYLE_FLAG_IFSRC)); if (should_write(flags, set, dfp, src)) { if (this->normal) { - return (name + ":normal;"); + return (name + ":normal" + important_str() + ";"); } else { Inkscape::CSSOStringStream os; for (std::map<char*,float>::const_iterator it=axes.begin(); it!=axes.end(); ++it){ os << "\"" << it->first << "\" " << it->second << " "; // FIXME: can we avoid the last space char ? } + os << important_str(); + os << ";"; return os.str(); } } @@ -645,11 +649,11 @@ SPIEnum::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase cons bool src = (style_src_req == style_src || !(flags & SP_STYLE_FLAG_IFSRC)); if (should_write(flags, set, dfp, src)) { if (this->inherit) { - return (name + ":inherit;"); + return (name + ":inherit" + important_str() + ";" ); } for (unsigned i = 0; enums[i].key; ++i) { if (enums[i].value == static_cast< gint > (this->value) ) { - return (name + ":" + enums[i].key + ";"); + return (name + ":" + enums[i].key + important_str() + ";"); } } } @@ -782,10 +786,10 @@ SPIEnumBits::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase bool src = (style_src_req == style_src || !(flags & SP_STYLE_FLAG_IFSRC)); if (should_write(flags, set, dfp, src)) { if (this->inherit) { - return (name + ":inherit;"); + return (name + ":inherit" + important_str() + ";" ); } if (this->value == 0 ) { - return (name + ":normal"); + return (name + ":normal" + important_str() + ";" ); } Glib::ustring return_string = name + ":"; unsigned j = 1; @@ -796,6 +800,8 @@ SPIEnumBits::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase } j *= 2; } + return_string += important_str(); + return_string += ";"; return return_string; } return Glib::ustring(""); @@ -851,13 +857,13 @@ SPILigatures::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase bool src = (style_src_req == style_src || !(flags & SP_STYLE_FLAG_IFSRC)); if (should_write(flags, set, dfp, src)) { if (this->inherit) { - return (name + ":inherit;"); + return (name + ":inherit" + important_str() + ";"); } if (value == SP_CSS_FONT_VARIANT_LIGATURES_NONE ) { - return (name + ":none;"); + return (name + ":none" + important_str() + ";" ); } if (value == SP_CSS_FONT_VARIANT_LIGATURES_NORMAL ) { - return (name + ":normal;"); + return (name + ":normal" + important_str() + ";"); } Glib::ustring return_string = name + ":"; @@ -870,6 +876,7 @@ SPILigatures::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase if ( !(value & SP_CSS_FONT_VARIANT_LIGATURES_CONTEXTUAL) ) return_string += "no-contextual "; return_string.erase( return_string.size() - 1 ); + return_string += important_str(); return_string += ";"; return return_string; } @@ -950,10 +957,10 @@ SPINumeric::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase c bool src = (style_src_req == style_src || !(flags & SP_STYLE_FLAG_IFSRC)); if (should_write(flags, set, dfp, src)) { if (this->inherit) { - return (name + ":inherit;"); + return (name + ":inherit" + important_str() + ";"); } if (value == SP_CSS_FONT_VARIANT_NUMERIC_NORMAL ) { - return (name + ":normal;"); + return (name + ":normal" + important_str() + ";"); } Glib::ustring return_string = name + ":"; @@ -974,6 +981,7 @@ SPINumeric::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase c if ( value & SP_CSS_FONT_VARIANT_NUMERIC_SLASHED_ZERO ) return_string += "slashed-zero "; return_string.erase( return_string.size() - 1 ); + return_string += important_str(); return_string += ";"; return return_string; } @@ -1019,19 +1027,19 @@ SPIString::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase co bool src = (style_src_req == style_src || !(flags & SP_STYLE_FLAG_IFSRC)); if (should_write(flags, set, dfp, src)) { if (this->inherit) { - return (name + ":inherit;"); + return (name + ":inherit" + important_str() + ";"); } else { if( this->value ) { if( name.compare( "font-family" ) == 0 ) { Glib::ustring font_family( this->value ); css_font_family_quote( font_family ); - return (name + ":" + font_family + ";"); + return (name + ":" + font_family + important_str() + ";"); } else if( name.compare( "-inkscape-font-specification" ) == 0 ) { Glib::ustring font_spec( this->value ); css_quote( font_spec ); - return (name + ":" + font_spec + ";"); + return (name + ":" + font_spec + important_str() + ";"); } else { - return (name + ":" + this->value + ";"); + return (name + ":" + this->value + important_str() + ";"); } } } @@ -1154,7 +1162,7 @@ SPIColor::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase con } if ( !css.str().empty() ) { - return (name + ":" + css.str() + ";"); + return (name + ":" + css.str() + important_str() + ";"); } } @@ -1419,7 +1427,7 @@ SPIPaint::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase con } if ( !css.str().empty() ) { - return (name + ":" + css.str() + ";"); + return (name + ":" + css.str() + important_str() + ";"); } } @@ -1654,7 +1662,7 @@ SPIPaintOrder::write( guint const flags, SPStyleSrc const &style_src_req, SPIBas } } } - return (name + ":" + css.str() + ";"); + return (name + ":" + css.str() + important_str() + ";"); } return Glib::ustring(""); } @@ -1773,10 +1781,10 @@ const Glib::ustring SPIFilter::write( guint const flags, SPStyleSrc const &style bool src = (style_src_req == style_src || !(flags & SP_STYLE_FLAG_IFSRC)); if (should_write(flags, set, dfp, src)) { if (this->inherit) { - return (name + ":inherit;"); + return (name + ":inherit" + important_str() + ";"); } else if(this->href && this->href->getURI()) { gchar *uri = this->href->getURI()->toString(); - Glib::ustring retval = name + ":url(" + uri + ");"; + Glib::ustring retval = name + ":url(" + uri + ")" + important_str() + ";"; g_free(uri); return retval; } @@ -1922,6 +1930,7 @@ SPIDashArray::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase } os << this->values[i]; } + os << important_str(); os << ";"; return os.str(); } @@ -2044,7 +2053,7 @@ SPIFontSize::write( guint const flags, SPStyleSrc const &style_src_req, SPIBase } else if (this->type == SP_FONT_SIZE_PERCENTAGE) { css << (this->value * 100.0) << "%"; } - return (name + ":" + css.str() + ";"); + return (name + ":" + css.str() + important_str() + ";"); } return Glib::ustring(""); } @@ -2412,7 +2421,7 @@ SPIBaselineShift::write( guint const flags, SPStyleSrc const &style_src_req, SPI } else if (this->type == SP_BASELINE_SHIFT_PERCENTAGE) { css << (this->value * 100.0) << "%"; } - return (name + ":" + css.str() + ";"); + return (name + ":" + css.str() + important_str() + ";"); } return Glib::ustring(""); } @@ -2593,6 +2602,7 @@ SPITextDecorationLine::write( guint const flags, SPStyleSrc const &style_src_req } else { os << "none"; } + os << important_str(); os << ";"; return ( os.str() ); } @@ -2729,6 +2739,7 @@ SPITextDecorationStyle::write( guint const flags, SPStyleSrc const &style_src_re std::cerr << "SPITextDecorationStyle::write(): No valid value for property" << std::endl; return Glib::ustring(""); } + os << important_str(); os << ";"; return ( os.str() ); } @@ -2883,6 +2894,7 @@ SPITextDecoration::write( guint const flags, SPStyleSrc const &style_src_req, SP } else { os << "none"; } + os << important_str(); os << ";"; return ( os.str() ); } diff --git a/src/style-internal.h b/src/style-internal.h index c0b2f3e72..d8d2a37bc 100644 --- a/src/style-internal.h +++ b/src/style-internal.h @@ -59,6 +59,10 @@ enum SPStyleSrc { * reading in the properties backwards. If a property is already set, it * prevents an earlier property from being read. * + * A declaration with an "!important" rule overrides any other declarations (except those that + * also have an "!important" rule). Attributes can not use the "!important" rule and the rule + * is not inherited. + * * In order for cascading to work, each element in the tree must be read in from top to bottom * (parent before child). At each step, if a style property is not explicitly set, the property * value is taken from the parent. Some properties have "computed" values that depend on: @@ -122,6 +126,7 @@ public: inherits(inherits), set(false), inherit(false), + important(false), style_src(SP_STYLE_SRC_STYLE_PROP), // Default to property, see bug 1662285. style(NULL) {} @@ -131,14 +136,43 @@ public: virtual void read( gchar const *str ) = 0; virtual void readIfUnset( gchar const *str, SPStyleSrc const &source = SP_STYLE_SRC_STYLE_PROP ) { - if ( !set ) { - read( str ); + if (!str) return; + + bool has_important = false; + Glib::ustring stripped = strip_important(str, has_important); // Sets 'has_important' + + // '!important' is invalid on attributes, don't read. + if (source == SP_STYLE_SRC_ATTRIBUTE && has_important){ + return; + } + + if ( !set || (has_important && !important) ) { + read( stripped.c_str() ); if ( set ) { style_src = source; + if (has_important) { + important = true; + } } } } + Glib::ustring important_str() const { + return Glib::ustring(important ? " !important" : ""); + } + + Glib::ustring strip_important( gchar const *str, bool &important ) { + assert (str != NULL); + Glib::ustring string = Glib::ustring(str); + auto pos = string.rfind( " !important" ); + important = false; + if (pos != std::string::npos) { + important = true; + string.erase(pos); + } + return string; + } + virtual void readAttribute( Inkscape::XML::Node *repr ) { readIfUnset( repr->attribute( name.c_str() ), SP_STYLE_SRC_ATTRIBUTE ); } @@ -147,7 +181,7 @@ public: SPStyleSrc const &style_src_req = SP_STYLE_SRC_STYLE_PROP, SPIBase const *const base = NULL ) const = 0; virtual void clear() { - set = false, inherit = false; + set = false, inherit = false, important = false; } virtual void cascade( const SPIBase* const parent ) = 0; @@ -162,6 +196,7 @@ public: name = rhs.name; inherits = rhs.inherits; set = rhs.set; + important = rhs.important; inherit = rhs.inherit; style_src = rhs.style_src; style = rhs.style; @@ -183,6 +218,7 @@ public: unsigned inherits : 1; // Property inherits by default from parent. unsigned set : 1; // Property has been explicitly set (vs. inherited). unsigned inherit : 1; // Property value set to 'inherit'. + unsigned important : 1; // Property rule 'important' has been explicitly set. SPStyleSrc style_src : 2; // Source (attribute, style attribute, style-sheet). // To do: make private after g_asserts removed diff --git a/src/style.cpp b/src/style.cpp index 36d669301..608cca1e6 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -134,9 +134,10 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) : // SVG 2 Text Wrapping shape_inside( "shape-inside" ), // SPIString - //shape_outside( "shape-outside" ), // SPIString + shape_subtract( "shape-subtract" ), // SPIString shape_padding( "shape-padding", 0.0 ), // SPILength for now - //shape_margin( "shape-margin", 0.0 ), // SPILength for now + shape_margin( "shape-margin", 0.0 ), // SPILength for now + inline_size( "inline-size", 0.0 ), // SPILength for now text_decoration(), text_decoration_line(), @@ -252,6 +253,8 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) : stroke_width.setStylePointer( this ); stroke_dashoffset.setStylePointer( this ); shape_padding.setStylePointer( this ); + shape_margin.setStylePointer( this ); + inline_size.setStylePointer( this ); // Properties that depend on 'color' text_decoration_color.setStylePointer( this ); @@ -323,7 +326,10 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) : _properties.push_back( &white_space ); _properties.push_back( &shape_inside ); + _properties.push_back( &shape_subtract ); _properties.push_back( &shape_padding ); + _properties.push_back( &shape_margin ); + _properties.push_back( &inline_size ); _properties.push_back( &clip_rule ); _properties.push_back( &display ); @@ -799,9 +805,18 @@ SPStyle::readIfUnset( gint id, gchar const *val, SPStyleSrc const &source ) { case SP_PROP_SHAPE_INSIDE: shape_inside.readIfUnset( val, source ); break; + case SP_PROP_SHAPE_SUBTRACT: + shape_subtract.readIfUnset( val, source ); + break; case SP_PROP_SHAPE_PADDING: shape_padding.readIfUnset( val, source ); break; + case SP_PROP_SHAPE_MARGIN: + shape_margin.readIfUnset( val, source ); + break; + case SP_PROP_INLINE_SIZE: + inline_size.readIfUnset( val, source ); + break; case SP_PROP_DOMINANT_BASELINE: dominant_baseline.readIfUnset( val, source ); break; @@ -1155,7 +1170,13 @@ SPStyle::_mergeDecl( CRDeclaration const *const decl, SPStyleSrc const &source */ guchar *const str_value_unsigned = cr_term_to_string(decl->value); gchar *const str_value = reinterpret_cast<gchar *>(str_value_unsigned); - readIfUnset( prop_idx, str_value, source ); + + // Add "!important" rule if necessary as this is not handled by cr_term_to_string(). + gchar const * important = decl->important ? " !important" : ""; + Inkscape::CSSOStringStream os; + os << str_value << important; + + readIfUnset( prop_idx, os.str().c_str(), source ); g_free(str_value); } } @@ -1713,9 +1734,18 @@ sp_style_unset_property_attrs(SPObject *o) if (style->shape_inside.set) { repr->setAttribute("shape-inside", NULL); } + if (style->shape_subtract.set) { + repr->setAttribute("shape-subtract", NULL); + } if (style->shape_padding.set) { repr->setAttribute("shape-padding", NULL); } + if (style->shape_margin.set) { + repr->setAttribute("shape-margin", NULL); + } + if (style->inline_size.set) { + repr->setAttribute("inline-size", NULL); + } if (style->writing_mode.set) { repr->setAttribute("writing-mode", NULL); } @@ -1808,7 +1838,10 @@ sp_css_attr_unset_text(SPCSSAttr *css) sp_repr_css_set_property(css, "text-anchor", NULL); sp_repr_css_set_property(css, "white-space", NULL); sp_repr_css_set_property(css, "shape-inside", NULL); + sp_repr_css_set_property(css, "shape-subtract", NULL); sp_repr_css_set_property(css, "shape-padding", NULL); + sp_repr_css_set_property(css, "shape-margin", NULL); + sp_repr_css_set_property(css, "inline-size", NULL); sp_repr_css_set_property(css, "kerning", NULL); // not implemented yet sp_repr_css_set_property(css, "dominant-baseline", NULL); // not implemented yet sp_repr_css_set_property(css, "alignment-baseline", NULL); // not implemented yet diff --git a/src/style.h b/src/style.h index 85d07b9ef..1b6ee2f47 100644 --- a/src/style.h +++ b/src/style.h @@ -166,9 +166,10 @@ public: /** SVG2 Text Wrapping */ SPIString shape_inside; - // SPIString shape_outside; + SPIString shape_subtract; SPILength shape_padding; - // SPILength shape_margin; + SPILength shape_margin; + SPILength inline_size; /* Text Decoration ----------------------- */ diff --git a/src/svg/makefile.in b/src/svg/makefile.in deleted file mode 100644 index a906fc7c4..000000000 --- a/src/svg/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) svg/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) svg/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/svg/svg-color.cpp b/src/svg/svg-color.cpp index 89a5636a8..60cbff3dc 100644 --- a/src/svg/svg-color.cpp +++ b/src/svg/svg-color.cpp @@ -398,7 +398,7 @@ guint32 sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 dfl) * this check wrapper. */ gchar const *end = str; guint32 const ret = internal_sp_svg_read_color(str, &end, dfl); - assert(((ret == dfl) && (end == str)) + g_assert(((ret == dfl) && (end == str)) || (((ret & 0xff) == 0) && (str < end))); if (str < end) { @@ -407,7 +407,7 @@ guint32 sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 dfl) buf[end - str] = '\0'; gchar const *buf_end = buf; guint32 const check = internal_sp_svg_read_color(buf, &buf_end, 1); - assert(check == ret + g_assert(check == ret && buf_end - buf == end - str); g_free(buf); @@ -425,7 +425,7 @@ guint32 sp_svg_read_color(gchar const *str, gchar const **end_ptr, guint32 dfl) */ static void rgb24_to_css(char *const buf, unsigned const rgb24) { - assert(rgb24 < (1u << 24)); + g_assert(rgb24 < (1u << 24)); /* SVG 1.1 Full allows additional colour names not supported by SVG Tiny, but we don't bother * with them: it's good for these colours to be copyable to non-SVG CSS stylesheets and for diff --git a/src/text-chemistry.cpp b/src/text-chemistry.cpp index 2b731c75d..2c84a00f3 100644 --- a/src/text-chemistry.cpp +++ b/src/text-chemistry.cpp @@ -119,7 +119,7 @@ text_put_on_path() parent->appendChild(repr); SPItem *new_item = (SPItem *) desktop->getDocument()->getObjectByRepr(repr); - new_item->doWriteTransform(repr, text->transform); + new_item->doWriteTransform(text->transform); new_item->updateRepr(); Inkscape::GC::release(repr); @@ -140,9 +140,9 @@ text_put_on_path() text->getRepr()->setAttribute("transform", NULL); // make a list of text children - GSList *text_reprs = NULL; + std::vector<Inkscape::XML::Node *> text_reprs; for(auto& o: text->children) { - text_reprs = g_slist_prepend(text_reprs, o.getRepr()); + text_reprs.push_back(o.getRepr()); } // create textPath and put it into the text @@ -158,9 +158,9 @@ text_put_on_path() } text->getRepr()->addChild(textpath, NULL); - for ( GSList *i = text_reprs ; i ; i = i->next ) { + for (auto i=text_reprs.rbegin();i!=text_reprs.rend();++i) { // Make a copy of each text child - Inkscape::XML::Node *copy = ((Inkscape::XML::Node *) i->data)->duplicate(xml_doc); + Inkscape::XML::Node *copy = (*i)->duplicate(xml_doc); // We cannot have multiline in textpath, so remove line attrs from tspans if (!strcmp(copy->name(), "svg:tspan")) { copy->setAttribute("sodipodi:role", NULL); @@ -168,7 +168,7 @@ text_put_on_path() copy->setAttribute("y", NULL); } // remove the old repr from under text - text->getRepr()->removeChild(reinterpret_cast<Inkscape::XML::Node *>(i->data)); + text->getRepr()->removeChild(*i); // put its copy into under textPath textpath->addChild(copy, NULL); // fixme: copy id } @@ -179,7 +179,6 @@ text_put_on_path() DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_TEXT, _("Put text on path")); - g_slist_free(text_reprs); } void @@ -393,7 +392,7 @@ text_unflow () } std::vector<SPItem*> new_objs; - GSList *old_objs = NULL; + std::vector<SPItem *> old_objs; auto items = selection->items(); for(auto i=items.begin();i!=items.end();++i){ @@ -444,7 +443,7 @@ text_unflow () text->_adjustFontsizeRecursive(text, ex); new_objs.push_back((SPItem*)text_object); - old_objs = g_slist_prepend (old_objs, flowtext); + old_objs.push_back(flowtext); Inkscape::GC::release(rtext); Inkscape::GC::release(rtspan); @@ -454,12 +453,10 @@ text_unflow () selection->clear(); reverse(new_objs.begin(),new_objs.end()); selection->setList(new_objs); - for (GSList *i = old_objs; i; i = i->next) { - SP_OBJECT(i->data)->deleteObject (true); + for (auto i:old_objs) { + i->deleteObject (true); } - g_slist_free (old_objs); - DocumentUndo::done(doc, SP_VERB_CONTEXT_TEXT, _("Unflow flowed text")); } @@ -505,7 +502,7 @@ flowtext_to_text() parent->addChild(repr, item->getRepr()); SPItem *new_item = reinterpret_cast<SPItem *>(desktop->getDocument()->getObjectByRepr(repr)); - new_item->doWriteTransform(repr, item->transform); + new_item->doWriteTransform(item->transform); new_item->updateRepr(); Inkscape::GC::release(repr); diff --git a/src/trace/makefile.in b/src/trace/makefile.in deleted file mode 100644 index 8c2bfd912..000000000 --- a/src/trace/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) trace/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) trace/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp index 52e99886a..b93d8358f 100644 --- a/src/trace/trace.cpp +++ b/src/trace/trace.cpp @@ -527,7 +527,7 @@ void Tracer::traceThread() if (reprobj) { SPItem *newItem = SP_ITEM(reprobj); - newItem->doWriteTransform(pathRepr, tf, NULL); + newItem->doWriteTransform(tf); } if (nrPaths == 1) { diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index efdb279b4..be13d9b1b 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -5,10 +5,10 @@ set(ui_SRC dialog-events.cpp draw-anchor.cpp interface.cpp - object-edit.cpp previewholder.cpp selected-color.cpp shape-editor.cpp + shape-editor-knotholders.cpp tool-factory.cpp tools-switch.cpp uxmanager.cpp @@ -185,7 +185,6 @@ set(ui_SRC event-debug.h icon-names.h interface.h - object-edit.h previewable.h previewfillable.h previewholder.h diff --git a/src/ui/cache/makefile.in b/src/ui/cache/makefile.in deleted file mode 100644 index af45adb0f..000000000 --- a/src/ui/cache/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd ../.. && $(MAKE) ui/cache/all - -clean %.a %.$(OBJEXT): - cd ../.. && $(MAKE) ui/cache/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 3cc8ac098..33ad4401c 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -105,6 +105,7 @@ public: virtual bool pastePathEffect(ObjectSet *set); virtual Glib::ustring getPathParameter(SPDesktop* desktop); virtual Glib::ustring getShapeOrTextObjectId(SPDesktop *desktop); + virtual std::vector<Glib::ustring> getElementsOfType(SPDesktop *desktop, gchar const *type); virtual const gchar *getFirstObjectID(); ClipboardManagerImpl(); @@ -653,6 +654,54 @@ Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop) } /** + * Get all objects id from the clipboard. + * @return A vector containing all IDs or empty if no shape or text item was found. + * type. Set to "*" to retrive all elements of the types vector inside, feel free to populate more + */ +std::vector<Glib::ustring> ClipboardManagerImpl::getElementsOfType(SPDesktop *desktop, gchar const* type) +{ + std::vector<Glib::ustring> result; + SPDocument *tempdoc = _retrieveClipboard(); // any target will do here + if ( tempdoc == NULL ) { + _userWarn(desktop, _("Nothing on the clipboard.")); + return result; + } + Inkscape::XML::Node *root = tempdoc->getReprRoot(); + + // 1293979: strip out the defs of the document + root->removeChild(tempdoc->getDefs()->getRepr()); + std::vector<Inkscape::XML::Node const *> reprs; + if (strcmp(type, "*") == 0){ + //TODO:Fill vector with all posible elements + std::vector<Glib::ustring> types; + types.push_back((Glib::ustring)"svg:path"); + types.push_back((Glib::ustring)"svg:circle"); + types.push_back((Glib::ustring)"svg:rect"); + types.push_back((Glib::ustring)"svg:ellipse"); + types.push_back((Glib::ustring)"svg:text"); + types.push_back((Glib::ustring)"svg:g"); + types.push_back((Glib::ustring)"svg:image"); + for (auto i=types.begin();i!=types.end();++i) { + Glib::ustring type_elem = *i; + std::vector<Inkscape::XML::Node const *> reprs_found = sp_repr_lookup_name_many(root, type_elem.c_str(), -1); // unlimited search depth + reprs.insert(reprs.end(), reprs_found.begin(), reprs_found.end()); + } + } else { + reprs = sp_repr_lookup_name_many(root, type, -1); // unlimited search depth + } + for (auto i=reprs.begin();i!=reprs.end();++i) { + Inkscape::XML::Node const * node = *i; + result.push_back(node->attribute("id")); + } + if ( result.empty() ) { + _userWarn(desktop, ((Glib::ustring)_("Clipboard does not contain any.") + (Glib::ustring)type).c_str()); + tempdoc->doUnref(); + return result; + } + return result; +} + +/** * Iterate over a list of items and copy them to the clipboard. */ void ClipboardManagerImpl::_copySelection(ObjectSet *selection) diff --git a/src/ui/clipboard.h b/src/ui/clipboard.h index 32a49867c..390830bba 100644 --- a/src/ui/clipboard.h +++ b/src/ui/clipboard.h @@ -51,6 +51,7 @@ public: virtual bool pastePathEffect(ObjectSet *set) = 0; virtual Glib::ustring getPathParameter(SPDesktop* desktop) = 0; virtual Glib::ustring getShapeOrTextObjectId(SPDesktop *desktop) = 0; + virtual std::vector<Glib::ustring> getElementsOfType(SPDesktop *desktop, gchar const* type = "*") = 0; virtual const gchar *getFirstObjectID() = 0; static ClipboardManager *get(); diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index 1bc87574e..3ca752c82 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -253,7 +253,7 @@ context_menu_item_on_my_deselect(void */*object*/, SPAction *action) // TODO: Update this to allow radio items to be used -void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb)//, SPDesktop *view)//, bool radio, GSList *group) +void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb) { SPAction *action; SPDesktop *view = _desktop; diff --git a/src/ui/control-manager.cpp b/src/ui/control-manager.cpp index d0285e467..d0106bfcd 100644 --- a/src/ui/control-manager.cpp +++ b/src/ui/control-manager.cpp @@ -330,10 +330,12 @@ void ControlManagerImpl::setSelected(SPCanvasItem *item, bool selected) if (selected && _resizeOnSelect.count(item->ctrlType)) { item->ctrlResize = 2; + } else { + item->ctrlResize = 0; } // TODO refresh colors - double targetSize = _sizeTable[item->ctrlType][_size - 1] + _resize; + double targetSize = _sizeTable[item->ctrlType][_size - 1] + item->ctrlResize; g_object_set(item, "size", targetSize, NULL); } } diff --git a/src/ui/control-manager.h b/src/ui/control-manager.h index 3f090d0bd..418591991 100644 --- a/src/ui/control-manager.h +++ b/src/ui/control-manager.h @@ -76,11 +76,7 @@ public: private: ControlManager(); -#if __cplusplus <= 199711L - std::auto_ptr<ControlManagerImpl> _impl; -#else std::unique_ptr<ControlManagerImpl> _impl; -#endif friend class ControlManagerImpl; }; diff --git a/src/ui/dialog-events.cpp b/src/ui/dialog-events.cpp index d7d56fa50..cf11490f3 100644 --- a/src/ui/dialog-events.cpp +++ b/src/ui/dialog-events.cpp @@ -100,7 +100,7 @@ sp_dialog_event_handler (GtkWindow *win, GdkEvent *event, gpointer data) case GDK_KEY_PRESS: - switch (Inkscape::UI::Tools::get_group0_keyval (&event->key)) { + switch (Inkscape::UI::Tools::get_latin_keyval (&event->key)) { case GDK_KEY_Escape: sp_dialog_defocus (win); ret = TRUE; diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index ad13ed8c4..71edcf259 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -1993,18 +1993,16 @@ void CloneTiler::remove(bool do_undo/* = true*/) SPObject *parent = obj->parent; // remove old tiling - GSList *to_delete = NULL; + std::vector<SPObject *> to_delete; for (auto& child: parent->children) { if (is_a_clone_of (&child, obj)) { - to_delete = g_slist_prepend (to_delete, &child); + to_delete.push_back(&child); } } - for (GSList *i = to_delete; i; i = i->next) { - SPObject *obj = reinterpret_cast<SPObject *>(i->data); + for (auto obj:to_delete) { g_assert(obj != NULL); obj->deleteObject(); } - g_slist_free (to_delete); change_selection (selection); @@ -2639,11 +2637,10 @@ void CloneTiler::reset_recursive(GtkWidget *w) } if (GTK_IS_CONTAINER(w)) { - GList *ch = gtk_container_get_children (GTK_CONTAINER(w)); - for (GList *i = ch; i != NULL; i = i->next) { - reset_recursive (GTK_WIDGET(i->data)); + std::vector<Gtk::Widget*> c = Glib::wrap(GTK_CONTAINER(w))->get_children(); + for ( auto i : c ) { + reset_recursive(i->gobj()); } - g_list_free (ch); } } diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index 9037e8377..e50824c7b 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -257,7 +257,7 @@ bool Dialog::_onEvent(GdkEvent *event) switch (event->type) { case GDK_KEY_PRESS: { - switch (Inkscape::UI::Tools::get_group0_keyval (&event->key)) { + switch (Inkscape::UI::Tools::get_latin_keyval (&event->key)) { case GDK_KEY_Escape: { _defocus(); ret = true; diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 56f3a29c0..d878b50a4 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -27,10 +27,6 @@ #include <gtkmm/grid.h> #include <gtkmm/spinbutton.h> -#ifdef WITH_GNOME_VFS -# include <libgnomevfs/gnome-vfs-init.h> // gnome_vfs_initialized -#endif - #include <glibmm/i18n.h> #include <glibmm/miscutils.h> @@ -1300,11 +1296,7 @@ void Export::onBrowse () _("_Save"), GTK_RESPONSE_ACCEPT, NULL ); -#ifdef WITH_GNOME_VFS - if (gnome_vfs_initialized()) { - gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(fs), false); - } -#endif + gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(fs), false); sp_transientize (fs); diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index b69e9ce97..64f6c98c6 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -31,10 +31,6 @@ #include "path-prefix.h" #include "preferences.h" -#ifdef WITH_GNOME_VFS -#include <libgnomevfs/gnome-vfs.h> -#endif - #include <gtkmm/expander.h> #include <glibmm/convert.h> @@ -663,11 +659,9 @@ void FileDialogBaseGtk::_updatePreviewCallback() Glib::ustring fileName = get_preview_filename(); bool enabled = previewCheckbox.get_active(); -#ifdef WITH_GNOME_VFS - if (fileName.empty() && gnome_vfs_initialized()) { + if (fileName.empty()) { fileName = get_preview_uri(); } -#endif if (enabled && !fileName.empty()) { svgPreview.set(fileName, _dialogType); @@ -698,11 +692,7 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window &parentWindow, const Gl set_select_multiple(true); } -#ifdef WITH_GNOME_VFS - if (gnome_vfs_initialized()) { - set_local_only(false); - } -#endif + set_local_only(false); /* Initalize to Autodetect */ extension = NULL; @@ -883,10 +873,11 @@ bool FileOpenDialogImplGtk::show() extension = extensionMap[gtk_file_filter_get_name(filter)]; } myFilename = get_filename(); -#ifdef WITH_GNOME_VFS - if (myFilename.empty() && gnome_vfs_initialized()) + + if (myFilename.empty()) { myFilename = get_uri(); -#endif + } + cleanup(true); return true; } else { @@ -928,10 +919,10 @@ std::vector<Glib::ustring> FileOpenDialogImplGtk::getFilenames() for (auto it : result_tmp) result.push_back(it); -#ifdef WITH_GNOME_VFS - if (result.empty() && gnome_vfs_initialized()) + if (result.empty()) { result = get_uris(); -#endif + } + return result; } @@ -963,11 +954,7 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow, const Gl /* One file at a time */ set_select_multiple(false); -#ifdef WITH_GNOME_VFS - if (gnome_vfs_initialized()) { - set_local_only(false); - } -#endif + set_local_only(false); /* Initalize to Autodetect */ extension = NULL; @@ -1310,11 +1297,11 @@ void FileSaveDialogImplGtk::updateNameAndExtension() { // Pick up any changes the user has typed in. Glib::ustring tmp = get_filename(); -#ifdef WITH_GNOME_VFS - if (tmp.empty() && gnome_vfs_initialized()) { + + if (tmp.empty()) { tmp = get_uri(); } -#endif + if (!tmp.empty()) { myFilename = tmp; } @@ -1449,11 +1436,7 @@ FileExportDialogImpl::FileExportDialogImpl(Gtk::Window &parentWindow, const Glib /* One file at a time */ set_select_multiple(false); -#ifdef WITH_GNOME_VFS - if (gnome_vfs_initialized()) { - set_local_only(false); - } -#endif + set_local_only(false); /* Initalize to Autodetect */ extension = NULL; @@ -1634,11 +1617,10 @@ bool FileExportDialogImpl::show() extension = type.extension; } myFilename = get_filename(); -#ifdef WITH_GNOME_VFS - if (myFilename.empty() && gnome_vfs_initialized()) { + + if (myFilename.empty()) { myFilename = get_uri(); } -#endif /* diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index 4fb8089ee..7f0bf58c5 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -1781,6 +1781,7 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread() ofn.lpstrFilter = _filter; ofn.nFilterIndex = _filter_index; ofn.lpfnHook = GetSaveFileName_hookproc; + ofn.lpstrDefExt = L"svg\0"; ofn.lCustData = (LPARAM)this; _result = GetSaveFileNameW(&ofn) != 0; diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp index 3cbc1b6e9..c16e60c5f 100644 --- a/src/ui/dialog/grid-arrange-tab.cpp +++ b/src/ui/dialog/grid-arrange-tab.cpp @@ -298,15 +298,14 @@ g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_h std::vector<SPItem*>::iterator it = sorted.begin(); for (row_cnt=0; ((it != sorted.end()) && (row_cnt<NoOfRows)); ++row_cnt) { - GSList *current_row = NULL; + std::vector<SPItem *> current_row; col_cnt = 0; for(;it!=sorted.end()&&col_cnt<NoOfCols;++it) { - current_row = g_slist_append (current_row, *it); + current_row.push_back(*it); col_cnt++; } - for (; current_row != NULL; current_row = current_row->next) { - SPItem *item=SP_ITEM(current_row->data); + for (auto item:current_row) { Inkscape::XML::Node *repr = item->getRepr(); Geom::OptRect b = item->documentVisualBounds(); Geom::Point min; @@ -329,11 +328,10 @@ g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_h Geom::Point move = Geom::Point(new_x - min[Geom::X], min[Geom::Y] - new_y); Geom::Affine const affine = Geom::Affine(Geom::Translate(move)); item->set_i2d_affine(item->i2dt_affine() * affine); - item->doWriteTransform(repr, item->transform, NULL); - SP_OBJECT (current_row->data)->updateRepr(); + item->doWriteTransform(item->transform); + item->updateRepr(); cnt +=1; } - g_slist_free (current_row); } DocumentUndo::done(desktop->getDocument(), SP_VERB_SELECTION_ARRANGE, diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index 991139aa8..f9cd8929a 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -18,7 +18,6 @@ #endif #include <gtkmm/buttonbox.h> -#include <boost/scoped_ptr.hpp> #include <glibmm/i18n.h> #include <glibmm/timer.h> diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 2ccffd7bc..4aaa0cbe4 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -22,6 +22,8 @@ #include <glibmm/miscutils.h> #include <glibmm/markup.h> #include <gtkmm/main.h> +#include <gtkmm/recentmanager.h> +#include <gtkmm/recentinfo.h> #include "preferences.h" #include "verbs.h" @@ -498,11 +500,20 @@ void InkscapePreferences::initPageTools() _page_text.add_group_header( _("Text units")); _font_unit_type.init( "/options/font/unitType", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), SP_CSS_UNIT_PT ); - _page_text.add_line( false, _("Text size unit type:"), _font_unit_type, "", + _page_text.add_line( true, _("Text size unit type:"), _font_unit_type, "", _("Set the type of unit used in the text toolbar and text dialogs"), false); _font_output_px.init ( _("Always output text size in pixels (px)"), "/options/font/textOutputPx", true); // _page_text.add_line( false, "", _font_output_px, "", _("Always convert the text size units above into pixels (px) before saving to file")); + _page_text.add_group_header( _("Font directories")); + _font_fontsdir_system.init( _("Use Inkscape's fonts directory"), "/options/font/use_fontsdir_system", true); + _page_text.add_line( true, "", _font_fontsdir_system, "", _("Load additional fonts from \"fonts\" directory located in Inkscape's global \"share\" directory")); + _font_fontsdir_user.init( _("Use user's fonts directory"), "/options/font/use_fontsdir_user", true); + _page_text.add_line( true, "", _font_fontsdir_user, "", _("Load additional fonts from \"fonts\" directory located in Inkscape's user configuration directory")); + _font_fontdirs_custom.init("/options/font/custom_fontdirs", 50); + _page_text.add_line(true, _("Additional font directories"), _font_fontdirs_custom, "", _("Load additional fonts from custom locations (one path per line)"), true); + + this->AddNewObjectsStyle(_page_text, "/tools/text"); //Spray @@ -1959,12 +1970,7 @@ void InkscapePreferences::initPageSpellcheck() static void appendList( Glib::ustring& tmp, const gchar* const*listing ) { - bool first = true; for (const gchar* const* ptr = listing; *ptr; ptr++) { - if (!first) { - tmp += " "; - } - first = false; tmp += *ptr; tmp += "\n"; } @@ -1980,77 +1986,64 @@ void InkscapePreferences::initPageSystem() _page_system.add_line( false, "", _misc_namedicon_delay, "", _("When on, named icons will be rendered before displaying the ui. This is for working around bugs in GTK+ named icon notification"), true); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - { - // TRANSLATORS: following strings are paths in Inkscape preferences - Misc - System info - - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - _page_system.add_group_header( _("System info")); - - _sys_user_config.set_text((char const *)Inkscape::IO::Resource::profile_path("")); - _sys_user_config.set_editable(false); - _page_system.add_line(true, _("User config: "), _sys_user_config, "", _("Location of users configuration"), true); - - _sys_user_prefs.set_text(prefs->getPrefsFilename()); - _sys_user_prefs.set_editable(false); - _page_system.add_line(true, _("User preferences: "), _sys_user_prefs, "", _("Location of the users preferences file"), true); + _page_system.add_group_header( _("System info")); - _sys_user_extension_dir.set_text((char const *)IO::Resource::get_path(IO::Resource::USER, IO::Resource::EXTENSIONS, "")); - _sys_user_extension_dir.set_editable(false); - _page_system.add_line(true, _("User extensions: "), _sys_user_extension_dir, "", _("Location of the users extensions"), true); + _sys_user_config.set_text((char const *)Inkscape::IO::Resource::profile_path("")); + _sys_user_config.set_editable(false); + _page_system.add_line(true, _("User config: "), _sys_user_config, "", _("Location of users configuration"), true); - _sys_user_cache.set_text(g_get_user_cache_dir()); - _sys_user_cache.set_editable(false); - _page_system.add_line(true, _("User cache: "), _sys_user_cache, "", _("Location of users cache"), true); + _sys_user_prefs.set_text(prefs->getPrefsFilename()); + _sys_user_prefs.set_editable(false); + _page_system.add_line(true, _("User preferences: "), _sys_user_prefs, "", _("Location of the users preferences file"), true); - Glib::ustring tmp_dir = prefs->getString("/options/autosave/path"); - if (tmp_dir.empty()) { - tmp_dir = Glib::get_tmp_dir(); - } - _sys_tmp_files.set_text(tmp_dir); - _sys_tmp_files.set_editable(false); - _page_system.add_line(true, _("Temporary files: "), _sys_tmp_files, "", _("Location of the temporary files used for autosave"), true); - - _sys_data.set_text( INKSCAPE_DATADIR ); - _sys_data.set_editable(false); - _page_system.add_line(true, _("Inkscape data: "), _sys_data, "", _("Location of Inkscape data"), true); - - _sys_extension_dir.set_text(INKSCAPE_EXTENSIONDIR); - _sys_extension_dir.set_editable(false); - _page_system.add_line(true, _("Inkscape extensions: "), _sys_extension_dir, "", _("Location of the Inkscape extensions"), true); - - Glib::ustring tmp; - appendList( tmp, g_get_system_data_dirs() ); - _sys_systemdata.get_buffer()->insert(_sys_systemdata.get_buffer()->end(), tmp); - _sys_systemdata.set_editable(false); - _sys_systemdata_scroll.add(_sys_systemdata); - _sys_systemdata_scroll.set_size_request(0, 80); - _sys_systemdata_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - _page_system.add_line(true, _("System data: "), _sys_systemdata_scroll, "", _("Locations of system data"), true); + _sys_user_extension_dir.set_text((char const *)IO::Resource::get_path(IO::Resource::USER, IO::Resource::EXTENSIONS, "")); + _sys_user_extension_dir.set_editable(false); + _page_system.add_line(true, _("User extensions: "), _sys_user_extension_dir, "", _("Location of the users extensions"), true); - { - tmp = ""; - gchar** paths = 0; - gint count = 0; - gtk_icon_theme_get_search_path(gtk_icon_theme_get_default(), &paths, &count); - if (count > 0) { - tmp += paths[0]; - tmp += "\n"; - for (int i = 1; i < count; i++) { - tmp += " "; - tmp += paths[i]; - tmp += "\n"; - } - } - } + _sys_user_cache.set_text(g_get_user_cache_dir()); + _sys_user_cache.set_editable(false); + _page_system.add_line(true, _("User cache: "), _sys_user_cache, "", _("Location of users cache"), true); - _sys_icon.get_buffer()->insert(_sys_icon.get_buffer()->end(), tmp); + Glib::ustring tmp_dir = prefs->getString("/options/autosave/path"); + if (tmp_dir.empty()) { + tmp_dir = Glib::get_tmp_dir(); } + _sys_tmp_files.set_text(tmp_dir); + _sys_tmp_files.set_editable(false); + _page_system.add_line(true, _("Temporary files: "), _sys_tmp_files, "", _("Location of the temporary files used for autosave"), true); + + _sys_data.set_text( INKSCAPE_DATADIR ); + _sys_data.set_editable(false); + _page_system.add_line(true, _("Inkscape data: "), _sys_data, "", _("Location of Inkscape data"), true); + + _sys_extension_dir.set_text(INKSCAPE_EXTENSIONDIR); + _sys_extension_dir.set_editable(false); + _page_system.add_line(true, _("Inkscape extensions: "), _sys_extension_dir, "", _("Location of the Inkscape extensions"), true); + + Glib::ustring tmp; + appendList( tmp, g_get_system_data_dirs() ); + _sys_systemdata.get_buffer()->insert(_sys_systemdata.get_buffer()->end(), tmp); + _sys_systemdata.set_editable(false); + _sys_systemdata_scroll.add(_sys_systemdata); + _sys_systemdata_scroll.set_size_request(100, 80); + _sys_systemdata_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + _sys_systemdata_scroll.set_shadow_type(Gtk::SHADOW_IN); + _page_system.add_line(true, _("System data: "), _sys_systemdata_scroll, "", _("Locations of system data"), true); + + tmp = ""; + gchar** paths = 0; + gint count = 0; + gtk_icon_theme_get_search_path(gtk_icon_theme_get_default(), &paths, &count); + appendList( tmp, paths ); + g_strfreev(paths); + _sys_icon.get_buffer()->insert(_sys_icon.get_buffer()->end(), tmp); _sys_icon.set_editable(false); _sys_icon_scroll.add(_sys_icon); - _sys_icon_scroll.set_size_request(0, 80); + _sys_icon_scroll.set_size_request(100, 80); _sys_icon_scroll.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + _sys_icon_scroll.set_shadow_type(Gtk::SHADOW_IN); _page_system.add_line(true, _("Icon theme: "), _sys_icon_scroll, "", _("Locations of icon themes"), true); this->AddPage(_page_system, _("System"), PREFS_PAGE_SYSTEM); @@ -2097,21 +2090,15 @@ bool InkscapePreferences::PresentPage(const Gtk::TreeModel::iterator& iter) void InkscapePreferences::on_reset_open_recent_clicked() { - GtkRecentManager* manager = gtk_recent_manager_get_default(); - GList* recent_list = gtk_recent_manager_get_items(manager); - GList* element; - GError* error; + Glib::RefPtr<Gtk::RecentManager> manager = Gtk::RecentManager::get_default(); + std::vector< Glib::RefPtr< Gtk::RecentInfo > > recent_list = manager->get_items(); //Remove only elements that were added by Inkscape - for (element = g_list_first(recent_list); element; element = g_list_next(element)){ - error = NULL; - GtkRecentInfo* info = (GtkRecentInfo*) element->data; - if (gtk_recent_info_has_application(info, g_get_prgname())){ - gtk_recent_manager_remove_item(manager, gtk_recent_info_get_uri(info), &error); + for (auto e : recent_list) { + if (e->has_application(g_get_prgname())) { + manager->remove_item(e->get_uri()); } - gtk_recent_info_unref (info); } - g_list_free(recent_list); } void InkscapePreferences::on_pagelist_selection_changed() diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 50465a9ec..a197a8e65 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -328,6 +328,9 @@ protected: UI::Widget::PrefCheckButton _font_dialog; UI::Widget::PrefCombo _font_unit_type; UI::Widget::PrefCheckButton _font_output_px; + UI::Widget::PrefCheckButton _font_fontsdir_system; + UI::Widget::PrefCheckButton _font_fontsdir_user; + UI::Widget::PrefMultiEntry _font_fontdirs_custom; UI::Widget::PrefCheckButton _misc_comment; UI::Widget::PrefCheckButton _misc_default_metadata; diff --git a/src/ui/dialog/knot-properties.cpp b/src/ui/dialog/knot-properties.cpp index b094dc0e7..29e1cb2bb 100644 --- a/src/ui/dialog/knot-properties.cpp +++ b/src/ui/dialog/knot-properties.cpp @@ -151,7 +151,7 @@ KnotPropertiesDialog::_close() bool KnotPropertiesDialog::_handleKeyEvent(GdkEventKey * /*event*/) { - /*switch (get_group0_keyval(event)) { + /*switch (get_latin_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: { _apply(); diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp index 562484022..4ab6e130e 100644 --- a/src/ui/dialog/layer-properties.cpp +++ b/src/ui/dialog/layer-properties.cpp @@ -290,7 +290,7 @@ SPObject* LayerPropertiesDialog::_selectedLayer() bool LayerPropertiesDialog::_handleKeyEvent(GdkEventKey *event) { - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_latin_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: { _strategy->perform(*this); diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index 3c99d1461..6223bd627 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -542,7 +542,7 @@ void LayersPanel::_toggled( Glib::ustring const& str, int targetCol ) bool LayersPanel::_handleKeyEvent(GdkEventKey *event) { - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_latin_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_F2: { @@ -713,12 +713,12 @@ void LayersPanel::_doTreeMove( ) { if (_dnd_source && _dnd_source->getRepr() ) { if(!_dnd_target){ - _dnd_source->doWriteTransform(_dnd_source->getRepr(), _dnd_source->i2doc_affine() * _dnd_source->document->getRoot()->i2doc_affine().inverse()); + _dnd_source->doWriteTransform(_dnd_source->i2doc_affine() * _dnd_source->document->getRoot()->i2doc_affine().inverse()); }else{ SPItem* parent = _dnd_into ? _dnd_target : dynamic_cast<SPItem*>(_dnd_target->parent); if(parent){ Geom::Affine move = _dnd_source->i2doc_affine() * parent->i2doc_affine().inverse(); - _dnd_source->doWriteTransform(_dnd_source->getRepr(), move); + _dnd_source->doWriteTransform(move); } } _dnd_source->moveTo(_dnd_target, _dnd_into); diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index 98789f7b2..28a42929b 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -206,9 +206,11 @@ LivePathEffectEditor::showParams(LivePathEffect::Effect& effect) if (defaultswidget) { Gtk::Expander * expander = NULL; std::vector<Gtk::Widget *> childs = dynamic_cast<Gtk::Box *> (effectwidget)->get_children(); - std::vector<Gtk::Widget *> childs_default = dynamic_cast<Gtk::Box *> (childs[childs.size()-1])->get_children(); - if ((expander = dynamic_cast<Gtk::Expander *>(childs_default[childs_default.size()-1]))){ - expanderopen = expander->get_expanded(); + if (childs.size()) { + std::vector<Gtk::Widget *> childs_default = dynamic_cast<Gtk::Box *> (childs[childs.size()-1])->get_children(); + if ((expander = dynamic_cast<Gtk::Expander *>(childs_default[childs_default.size()-1]))){ + expanderopen = expander->get_expanded(); + } } } effectcontrol_vbox.remove(*effectwidget); @@ -473,7 +475,7 @@ LivePathEffectEditor::onAdd() item = NULL; // run sp_selection_clone_original_path_lpe - sel->cloneOriginalPathLPE(); + sel->cloneOriginalPathLPE(true); SPItem *new_item = sel->singleItem(); // Check that the cloning was successful. We don't want to change the ID of the original referenced path! diff --git a/src/ui/dialog/lpe-powerstroke-properties.cpp b/src/ui/dialog/lpe-powerstroke-properties.cpp index 9bd98c7c0..e66229dcd 100644 --- a/src/ui/dialog/lpe-powerstroke-properties.cpp +++ b/src/ui/dialog/lpe-powerstroke-properties.cpp @@ -146,7 +146,7 @@ PowerstrokePropertiesDialog::_close() bool PowerstrokePropertiesDialog::_handleKeyEvent(GdkEventKey * /*event*/) { - /*switch (get_group0_keyval(event)) { + /*switch (get_latin_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: { _apply(); diff --git a/src/ui/dialog/makefile.in b/src/ui/dialog/makefile.in deleted file mode 100644 index 805c48aef..000000000 --- a/src/ui/dialog/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd ../.. && $(MAKE) ui/dialog/all - -clean %.a %.$(OBJEXT): - cd ../.. && $(MAKE) ui/dialog/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 1e0ab9604..b50d68239 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -148,8 +148,8 @@ public: _pnl->_objectsChanged( _obj ); } } - virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {} - virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) { + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { if ( _pnl && _obj ) { if ( name == _lockedAttr || name == _labelAttr || name == _highlightAttr || name == _groupAttr || name == _styleAttr || name == _clipAttr || name == _maskAttr ) { _pnl->_updateObject(_obj, name == _highlightAttr); @@ -735,7 +735,7 @@ bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event) // handle events for the treeview bool empty = _desktop->selection->isEmpty(); - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_latin_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: { diff --git a/src/ui/dialog/objects.h b/src/ui/dialog/objects.h index b7fd1b4f8..8ad1b15ef 100644 --- a/src/ui/dialog/objects.h +++ b/src/ui/dialog/objects.h @@ -16,7 +16,6 @@ # include <config.h> #endif -#include <boost/scoped_ptr.hpp> #include <gtkmm/box.h> #include <gtkmm/treeview.h> #include <gtkmm/treestore.h> @@ -168,7 +167,7 @@ private: Gtk::Box _blur_vbox; Gtk::Dialog _colorSelectorDialog; - boost::scoped_ptr<Inkscape::UI::SelectedColor> _selectedColor; + std::unique_ptr<Inkscape::UI::SelectedColor> _selectedColor; //Methods: diff --git a/src/ui/dialog/polar-arrange-tab.cpp b/src/ui/dialog/polar-arrange-tab.cpp index 2b4550d20..75e1a56b8 100644 --- a/src/ui/dialog/polar-arrange-tab.cpp +++ b/src/ui/dialog/polar-arrange-tab.cpp @@ -140,7 +140,7 @@ static void rotateAround(SPItem *item, Geom::Point center, Geom::Rotate const &r center = item->getCenter(); item->set_i2d_affine(item->i2dt_affine() * affine); - item->doWriteTransform(item->getRepr(), item->transform); + item->doWriteTransform(item->transform); if(item->isCenterSet()) { diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index 4d248fd09..532a8c364 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -26,7 +26,6 @@ #include "util/units.h" #include "helper/png-write.h" #include "svg/svg-color.h" -#include "io/sys.h" #include <glibmm/i18n.h> @@ -52,7 +51,7 @@ static void draw_page(GtkPrintOperation *, std::string tmp_base = "inkscape-print-png-XXXXXX"; int tmp_fd; - if ( (tmp_fd = Inkscape::IO::file_open_tmp (tmp_png, tmp_base)) >= 0) { + if ( (tmp_fd = Glib::file_open_tmp(tmp_png, tmp_base)) >= 0) { close(tmp_fd); guint32 bgcolor = 0x00000000; diff --git a/src/ui/dialog/prototype.cpp b/src/ui/dialog/prototype.cpp index b3bf60aab..b7c9f7abf 100644 --- a/src/ui/dialog/prototype.cpp +++ b/src/ui/dialog/prototype.cpp @@ -22,6 +22,8 @@ namespace Inkscape { namespace UI { namespace Dialog { +// Note that in order for a dialog to be restored, it must be listed in SPDesktop::show_dialogs(). + Prototype::Prototype() : // UI::Widget::Panel("Prototype Label", "/dialogs/prototype", SP_VERB_DIALOG_PROTOTYPE, // "Prototype Apply Label", true), diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index 4f7657f4f..3318b5e6b 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -50,8 +50,6 @@ namespace Dialog { SpellCheck::SpellCheck (void) : UI::Widget::Panel ("", "/dialogs/spellcheck/", SP_VERB_DIALOG_SPELLCHECK), - _rects(NULL), - _seen_objects(NULL), _text(NULL), _layout(NULL), _stops(0), @@ -196,12 +194,11 @@ void SpellCheck::setTargetDesktop(SPDesktop *desktop) void SpellCheck::clearRects() { - for (GSList *it = _rects; it; it = it->next) { - sp_canvas_item_hide(SP_CANVAS_ITEM(it->data)); - sp_canvas_item_destroy(SP_CANVAS_ITEM(it->data)); + for(auto t : _rects) { + sp_canvas_item_hide(t); + sp_canvas_item_destroy(t); } - g_slist_free(_rects); - _rects = NULL; + _rects.clear(); } void SpellCheck::disconnect() @@ -214,47 +211,39 @@ void SpellCheck::disconnect() } } -GSList *SpellCheck::allTextItems (SPObject *r, GSList *l, bool hidden, bool locked) +void SpellCheck::allTextItems (SPObject *r, std::vector<SPItem *> &l, bool hidden, bool locked) { if (!desktop) - return l; // no desktop to check + return; // no desktop to check if (SP_IS_DEFS(r)) - return l; // we're not interested in items in defs + return; // we're not interested in items in defs if (!strcmp(r->getRepr()->name(), "svg:metadata")) { - return l; // we're not interested in metadata + return; // we're not interested in metadata } for (auto& child: r->children) { if (SP_IS_ITEM (&child) && !child.cloned && !desktop->isLayer(SP_ITEM(&child))) { if ((hidden || !desktop->itemIsHidden(SP_ITEM(&child))) && (locked || !SP_ITEM(&child)->isLocked())) { if (SP_IS_TEXT(&child) || SP_IS_FLOWTEXT(&child)) - l = g_slist_prepend (l, &child); + l.push_back(static_cast<SPItem*>(&child)); } } - l = allTextItems (&child, l, hidden, locked); + allTextItems (&child, l, hidden, locked); } - return l; + return; } bool SpellCheck::textIsValid (SPObject *root, SPItem *text) { - GSList *l = NULL; - l = allTextItems (root, l, false, true); - for (GSList *i = l; i; i = i->next) { - SPItem *item = static_cast<SPItem *>(i->data); - if (item == text) { - g_slist_free (l); - return true; - } - } - g_slist_free (l); - return false; + std::vector<SPItem*> l; + allTextItems (root, l, false, true); + return (std::find(l.begin(), l.end(), text) != l.end()); } -gint SpellCheck::compareTextBboxes (gconstpointer a, gconstpointer b) +bool SpellCheck::compareTextBboxes (gconstpointer a, gconstpointer b)//returns a<b { SPItem *i1 = SP_ITEM(a); SPItem *i2 = SP_ITEM(b); @@ -262,41 +251,28 @@ gint SpellCheck::compareTextBboxes (gconstpointer a, gconstpointer b) Geom::OptRect bbox1 = i1->desktopVisualBounds(); Geom::OptRect bbox2 = i2->desktopVisualBounds(); if (!bbox1 || !bbox2) { - return 0; + return false; } // vector between top left corners Geom::Point diff = Geom::Point(bbox2->min()[Geom::X], bbox2->max()[Geom::Y]) - Geom::Point(bbox1->min()[Geom::X], bbox1->max()[Geom::Y]); - // sort top to bottom, left to right, but: - // if i2 is higher only 0.2 or less times it is righter than i1, put i1 first - if (diff[Geom::Y] > 0.2 * diff[Geom::X]) - return 1; - else - return -1; - - return 0; + return diff[Geom::Y] == 0 ? (diff[Geom::X] < 0) : (diff[Geom::Y] < 0); } // We regenerate and resort the list every time, because user could have changed it while the // dialog was waiting SPItem *SpellCheck::getText (SPObject *root) { - GSList *l = NULL; - l = allTextItems (root, l, false, true); - l = g_slist_sort(l, (GCompareFunc)SpellCheck::compareTextBboxes); - - for (GSList *i = l; i; i = i->next) { - SPItem *item = static_cast<SPItem *>(i->data); - if (!g_slist_find (_seen_objects, item)) { - _seen_objects = g_slist_prepend(_seen_objects, item); - g_slist_free(l); + std::vector<SPItem*> l; + allTextItems (root, l, false, true); + std::sort(l.begin(),l.end(),SpellCheck::compareTextBboxes); + + for (auto item:l) { + if(_seen_objects.insert(item).second) return item; - } } - - g_slist_free(l); return NULL; } @@ -402,8 +378,7 @@ SpellCheck::init(SPDesktop *d) _root = desktop->getDocument()->getRoot(); // empty the list of objects we've checked - g_slist_free (_seen_objects); - _seen_objects = NULL; + _seen_objects.clear(); // grab first text nextText(); @@ -456,8 +431,7 @@ SpellCheck::finished () g_free(label); } - g_slist_free(_seen_objects); - _seen_objects = NULL; + _seen_objects.clear(); desktop = NULL; _root = NULL; @@ -615,7 +589,7 @@ SpellCheck::nextWord() curve->lineto(area.corner(0)); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(rect), curve); sp_canvas_item_show(rect); - _rects = g_slist_prepend(_rects, rect); + _rects.push_back(rect); // scroll to make it all visible Geom::Point const center = desktop->get_display_area().midpoint(); @@ -707,10 +681,10 @@ SpellCheck::nextWord() void SpellCheck::deleteLastRect () { - if (_rects) { - sp_canvas_item_hide(SP_CANVAS_ITEM(_rects->data)); - sp_canvas_item_destroy(SP_CANVAS_ITEM(_rects->data)); - _rects = _rects->next; // pop latest-prepended rect + if (!_rects.empty()) { + sp_canvas_item_hide(_rects.back()); + sp_canvas_item_destroy(_rects.back()); + _rects.pop_back(); // pop latest-prepended rect } } @@ -861,7 +835,6 @@ SpellCheck::onStart () } } - /* Local Variables: mode:c++ diff --git a/src/ui/dialog/spellcheck.h b/src/ui/dialog/spellcheck.h index 834f23c24..e7563ad1e 100644 --- a/src/ui/dialog/spellcheck.h +++ b/src/ui/dialog/spellcheck.h @@ -16,6 +16,9 @@ # include <config.h> #endif +#include <vector> +#include <set> + #include <gtkmm/box.h> #include <gtkmm/button.h> #include <gtkmm/buttonbox.h> @@ -68,7 +71,7 @@ private: /** * Returns a list of all the text items in the SPObject */ - GSList *allTextItems (SPObject *r, GSList *l, bool hidden, bool locked); + void allTextItems (SPObject *r, std::vector<SPItem *> &l, bool hidden, bool locked); /** * Is text inside the SPOject's tree @@ -78,7 +81,7 @@ private: /** * Compare the visual bounds of 2 SPItems referred to by a and b */ - static gint compareTextBboxes (gconstpointer a, gconstpointer b); + static bool compareTextBboxes (gconstpointer a, gconstpointer b); SPItem *getText (SPObject *root); void nextText (); @@ -165,12 +168,12 @@ private: /** * list of canvasitems (currently just rects) that mark misspelled things on canvas */ - GSList *_rects; + std::vector<SPCanvasItem *> _rects; /** * list of text objects we have already checked in this session */ - GSList *_seen_objects; + std::set<SPItem *> _seen_objects; /** * the object currently being checked diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index aa453e8e8..60138fa89 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -56,8 +56,8 @@ public: }; virtual void notifyContentChanged(Inkscape::XML::Node &node, - Inkscape::Util::ptr_shared<char> old_content, - Inkscape::Util::ptr_shared<char> new_content); + Inkscape::Util::ptr_shared old_content, + Inkscape::Util::ptr_shared new_content); StyleDialog * _styleDialog; }; @@ -66,8 +66,8 @@ public: void StyleDialog::NodeObserver::notifyContentChanged( Inkscape::XML::Node &/*node*/, - Inkscape::Util::ptr_shared<char> /*old_content*/, - Inkscape::Util::ptr_shared<char> /*new_content*/ ) { + Inkscape::Util::ptr_shared /*old_content*/, + Inkscape::Util::ptr_shared /*new_content*/ ) { #ifdef DEBUG_STYLEDIALOG std::cout << "StyleDialog::NodeObserver::notifyContentChanged" << std::endl; @@ -111,8 +111,8 @@ public: virtual void notifyAttributeChanged( Inkscape::XML::Node &node, GQuark qname, - Util::ptr_shared<char> /*old_value*/, - Util::ptr_shared<char> /*new_value*/ ) { + Util::ptr_shared /*old_value*/, + Util::ptr_shared /*new_value*/ ) { if ( _styleDialog && _repr ) { // For the moment only care about attributes that are directly used in selectors. diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index b876fa98c..558b0b19e 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -617,52 +617,48 @@ void SymbolsDialog::get_symbols() { } } -GSList* SymbolsDialog::symbols_in_doc_recursive (SPObject *r, GSList *l) +void SymbolsDialog::symbols_in_doc_recursive (SPObject *r, std::vector<SPSymbol*> &l) { - g_return_val_if_fail(r != NULL, l); + if(!r) return; // Stop multiple counting of same symbol if ( dynamic_cast<SPUse *>(r) ) { - return l; + return; } if ( dynamic_cast<SPSymbol *>(r) ) { - l = g_slist_prepend (l, r); + l.push_back(dynamic_cast<SPSymbol *>(r)); } for (auto& child: r->children) { - l = symbols_in_doc_recursive( &child, l ); + symbols_in_doc_recursive( &child, l ); } - - return l; } -GSList* SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) { +std::vector<SPSymbol*> SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) +{ - GSList *l = NULL; - l = symbols_in_doc_recursive (symbolDocument->getRoot(), l ); - l = g_slist_reverse( l ); + std::vector<SPSymbol*> l; + symbols_in_doc_recursive (symbolDocument->getRoot(), l ); return l; } -GSList* SymbolsDialog::use_in_doc_recursive (SPObject *r, GSList *l) +void SymbolsDialog::use_in_doc_recursive (SPObject *r, std::vector<SPUse*> &l) { if ( dynamic_cast<SPUse *>(r) ) { - l = g_slist_prepend (l, r); + l.push_back(dynamic_cast<SPUse *>(r)); } for (auto& child: r->children) { - l = use_in_doc_recursive( &child, l ); + use_in_doc_recursive( &child, l ); } - - return l; } -GSList* SymbolsDialog::use_in_doc( SPDocument* useDocument ) { +std::vector<SPUse*> SymbolsDialog::use_in_doc( SPDocument* useDocument ) { - GSList *l = NULL; - l = use_in_doc_recursive (useDocument->getRoot(), l ); + std::vector<SPUse*> l; + use_in_doc_recursive (useDocument->getRoot(), l); return l; } @@ -671,10 +667,8 @@ GSList* SymbolsDialog::use_in_doc( SPDocument* useDocument ) { gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* document) { gchar const* style = 0; - GSList* l = use_in_doc( document ); - for( ; l != NULL; l = l->next ) { - SPObject *obj = reinterpret_cast<SPObject *>(l->data); - SPUse *use = dynamic_cast<SPUse *>(obj); + std::vector<SPUse*> l = use_in_doc( document ); + for( auto use:l ) { if ( use ) { gchar const *href = use->getRepr()->attribute("xlink:href"); if( href ) { @@ -693,10 +687,8 @@ gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* documen void SymbolsDialog::add_symbols( SPDocument* symbolDocument ) { - GSList* l = symbols_in_doc( symbolDocument ); - for( ; l != NULL; l = l->next ) { - SPObject *obj = reinterpret_cast<SPObject *>(l->data); - SPSymbol *symbol = dynamic_cast<SPSymbol *>(obj); + std::vector<SPSymbol*> l = symbols_in_doc( symbolDocument ); + for(auto symbol:l) { if (symbol) { add_symbol( symbol ); } diff --git a/src/ui/dialog/symbols.h b/src/ui/dialog/symbols.h index 5dc1e3cad..747e5c6c9 100644 --- a/src/ui/dialog/symbols.h +++ b/src/ui/dialog/symbols.h @@ -14,10 +14,10 @@ #define INKSCAPE_UI_DIALOG_SYMBOLS_H #include "display/drawing.h" - #include "ui/dialog/desktop-tracker.h" - #include "ui/widget/panel.h" +#include "sp-symbol.h" +#include "sp-use.h" #include <vector> @@ -85,10 +85,10 @@ private: void add_symbol( SPObject* symbol_document ); SPDocument* symbols_preview_doc(); - GSList* symbols_in_doc_recursive(SPObject *r, GSList *l); - GSList* symbols_in_doc( SPDocument* document ); - GSList* use_in_doc_recursive(SPObject *r, GSList *l); - GSList* use_in_doc( SPDocument* document ); + void symbols_in_doc_recursive(SPObject *r, std::vector<SPSymbol*> &l); + std::vector<SPSymbol*> symbols_in_doc( SPDocument* document ); + void use_in_doc_recursive(SPObject *r, std::vector<SPUse*> &l); + std::vector<SPUse*> use_in_doc( SPDocument* document ); gchar const* style_from_use( gchar const* id, SPDocument* document); Glib::RefPtr<Gdk::Pixbuf> draw_symbol(SPObject *symbol); diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp index 176719995..ae45654a7 100644 --- a/src/ui/dialog/tags.cpp +++ b/src/ui/dialog/tags.cpp @@ -106,8 +106,8 @@ public: _pnl->_objectsChanged( _obj ); } } - virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {} - virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) { + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { if ( _pnl && _obj ) { if ( name == _labelAttr ) { _pnl->_updateObject( _obj); @@ -522,7 +522,7 @@ void TagsPanel::_checkTreeSelection() bool TagsPanel::_handleKeyEvent(GdkEventKey *event) { - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_latin_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_F2: { @@ -1103,14 +1103,6 @@ void TagsPanel::setDesktop( SPDesktop* desktop ) setDocument(_desktop, _desktop->doc()); } } -/* - GSList const *layers = _desktop->doc()->getResourceList( "layer" ); - g_message( "layers list starts at %p", layers ); - for ( GSList const *iter=layers ; iter ; iter = iter->next ) { - SPObject *layer=static_cast<SPObject *>(iter->data); - g_message(" {%s} [%s]", layer->id, layer->label() ); - } -*/ deskTrack.setBase(desktop); } diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index 5ad1b9ec5..8713e6ddc 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -727,7 +727,7 @@ void Transformation::applyPageScale(Inkscape::Selection *selection) Geom::Affine scaler = get_scale_transform_for_variable_stroke (*bbox_pref, *bbox_geom, transform_stroke, preserve, x0, y0, x1, y1); item->set_i2d_affine(item->i2dt_affine() * scaler); - item->doWriteTransform(item->getRepr(), item->transform); + item->doWriteTransform(item->transform); } } } else { diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp index 83c0de45b..c245890bc 100644 --- a/src/ui/dialog/xml-tree.cpp +++ b/src/ui/dialog/xml-tree.cpp @@ -856,7 +856,7 @@ void XmlTree::on_document_uri_set(gchar const * /*uri*/, SPDocument * /*document gboolean XmlTree::quit_on_esc (GtkWidget *w, GdkEventKey *event, GObject */*tbl*/) { - switch (Inkscape::UI::Tools::get_group0_keyval (event)) { + switch (Inkscape::UI::Tools::get_latin_keyval (event)) { case GDK_KEY_Escape: // defocus gtk_widget_destroy(w); return TRUE; diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index 0223b2b3b..4f1e5cd6f 100644 --- a/src/ui/interface.cpp +++ b/src/ui/interface.cpp @@ -25,6 +25,8 @@ #include "ui/dialog/dialog-manager.h" #include <gtkmm/icontheme.h> +#include <gtkmm/radiomenuitem.h> +#include <gtkmm/separatormenuitem.h> #include "file.h" #include <glibmm/miscutils.h> @@ -51,7 +53,6 @@ #include "sp-namedview.h" #include "sp-root.h" #include "helper/action.h" -#include "helper/gnome-utils.h" #include "helper/window.h" #include "io/sys.h" #include "ui/dialog-events.h" @@ -109,8 +110,7 @@ static GtkTargetEntry *completeDropTargets = 0; static int completeDropTargetsCount = 0; static bool temporarily_block_actions = false; -#define ENTRIES_SIZE(n) sizeof(n)/sizeof(n[0]) -static guint nui_drop_target_entries = ENTRIES_SIZE(ui_drop_target_entries); +static guint nui_drop_target_entries = G_N_ELEMENTS(ui_drop_target_entries); static void sp_ui_import_files(gchar *buffer); static void sp_ui_import_one_file(char const *filename); static void sp_ui_import_one_file_with_check(gpointer filename, gpointer unused); @@ -221,19 +221,14 @@ sp_create_window(SPViewWidget *vw, bool editable) if ( completeDropTargets == 0 || completeDropTargetsCount == 0 ) { - std::vector<gchar*> types; - - GSList *list = gdk_pixbuf_get_formats(); - while ( list ) { - int i = 0; - GdkPixbufFormat *one = (GdkPixbufFormat*)list->data; - gchar** typesXX = gdk_pixbuf_format_get_mime_types(one); - for ( i = 0; typesXX[i]; i++ ) { - types.push_back(g_strdup(typesXX[i])); - } - g_strfreev(typesXX); + std::vector<Glib::ustring> types; - list = g_slist_next(list); + std::vector<Gdk::PixbufFormat> list = Gdk::Pixbuf::get_formats(); + for (auto one:list) { + std::vector<Glib::ustring> typesXX = one.get_mime_types(); + for (auto i:typesXX) { + types.push_back(i); + } } completeDropTargetsCount = nui_drop_target_entries + types.size(); completeDropTargets = new GtkTargetEntry[completeDropTargetsCount]; @@ -242,8 +237,8 @@ sp_create_window(SPViewWidget *vw, bool editable) } int pos = nui_drop_target_entries; - for (std::vector<gchar*>::iterator it = types.begin() ; it != types.end() ; ++it) { - completeDropTargets[pos].target = *it; + for (std::vector<Glib::ustring>::iterator it = types.begin() ; it != types.end() ; ++it) { + completeDropTargets[pos].target = g_strdup((*it).c_str()); completeDropTargets[pos].flags = 0; completeDropTargets[pos].info = IMAGE_DATA; pos++; @@ -452,14 +447,14 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *men Inkscape::UI::View::View *view, bool show_icon = false, bool radio = false, - GSList *group = NULL) + Gtk::RadioMenuItem::Group *group = NULL) { - GtkWidget *item; + Gtk::Widget *item; // Just create a menu separator if this isn't a real action. // Otherwise, create a real menu item if (verb->get_code() == SP_VERB_NONE) { - item = gtk_separator_menu_item_new(); + item = new Gtk::SeparatorMenuItem(); } else { SPAction *action = verb->get_action(Inkscape::ActionContext(view)); @@ -468,9 +463,9 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *men // Create the menu item itself, either as a radio menu item, or just // a regular menu item depending on whether the "radio" flag is set if (radio) { - item = gtk_radio_menu_item_new(group); + item = new Gtk::RadioMenuItem(*group); } else { - item = gtk_menu_item_new(); + item = new Gtk::MenuItem(); } // Create a box to contain all the widgets (icon, label, accelerator) @@ -491,8 +486,8 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *men GtkAccelGroup *accel_group = sp_shortcut_get_accel_group(); gtk_menu_set_accel_group(menu, accel_group); - sp_shortcut_add_accelerator(item, sp_shortcut_get_primary(verb)); - gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(label), item); + sp_shortcut_add_accelerator(item->gobj(), sp_shortcut_get_primary(verb)); + gtk_accel_label_set_accel_widget(GTK_ACCEL_LABEL(label), item->gobj()); GtkWidget *icon; @@ -509,33 +504,34 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *men gtk_box_pack_start(GTK_BOX(box), label, TRUE, TRUE, 0); // Finally, pack all the widgets into the menu item - gtk_container_add(GTK_CONTAINER(item), box); + gtk_container_add(GTK_CONTAINER(item->gobj()), box); action->signal_set_sensitive.connect( sigc::bind<0>( sigc::ptr_fun(>k_widget_set_sensitive), - item)); + item->gobj())); action->signal_set_name.connect( sigc::bind<0>( sigc::ptr_fun(&sp_ui_menu_item_set_name), - item)); + item->gobj())); if (!action->sensitive) { - gtk_widget_set_sensitive(item, FALSE); + item->set_sensitive(false); } - gtk_widget_set_events(item, GDK_KEY_PRESS_MASK); - g_object_set_data(G_OBJECT(item), "view", (gpointer) view); - g_signal_connect( G_OBJECT(item), "activate", G_CALLBACK(sp_ui_menu_activate), action ); - g_signal_connect( G_OBJECT(item), "select", G_CALLBACK(sp_ui_menu_select_action), action ); - g_signal_connect( G_OBJECT(item), "deselect", G_CALLBACK(sp_ui_menu_deselect_action), action ); + gtk_widget_set_events(item->gobj(), GDK_KEY_PRESS_MASK); + + g_object_set_data(G_OBJECT(item->gobj()), "view", (gpointer) view); + g_signal_connect( G_OBJECT(item->gobj()), "activate", G_CALLBACK(sp_ui_menu_activate), action ); + g_signal_connect( G_OBJECT(item->gobj()), "select", G_CALLBACK(sp_ui_menu_select_action), action ); + g_signal_connect( G_OBJECT(item->gobj()), "deselect", G_CALLBACK(sp_ui_menu_deselect_action), action ); } - gtk_widget_show_all(item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + item->show_all(); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item->gobj()); - return item; + return item->gobj(); } // end of sp_ui_menu_append_item_from_verb @@ -770,25 +766,24 @@ static void addTaskMenuItems(GtkMenu *menu, Inkscape::UI::View::View *view) 0, 0 }; - GSList *group = 0; + Gtk::RadioMenuItem::Group group; int count = 0; gint active = Inkscape::UI::UXManager::getInstance()->getDefaultTask( dynamic_cast<SPDesktop*>(view) ); for (gchar const **strs = data; strs[0]; strs += 2, count++) { - GtkWidget *item = gtk_radio_menu_item_new_with_label( group, strs[0] ); - group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(item) ); + Gtk::RadioMenuItem *item = new Gtk::RadioMenuItem(group,Glib::ustring(strs[0])); if ( count == active ) { - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(item), TRUE ); + item->set_active(); } - g_object_set_data( G_OBJECT(item), "view", view ); - g_signal_connect( G_OBJECT(item), "toggled", reinterpret_cast<GCallback>(taskToggled), GINT_TO_POINTER(count) ); - g_signal_connect( G_OBJECT(item), "select", G_CALLBACK(sp_ui_menu_select), const_cast<gchar*>(strs[1]) ); - g_signal_connect( G_OBJECT(item), "deselect", G_CALLBACK(sp_ui_menu_deselect), 0 ); + g_object_set_data( G_OBJECT(item->gobj()), "view", view ); + g_signal_connect( G_OBJECT(item->gobj()), "toggled", reinterpret_cast<GCallback>(taskToggled), GINT_TO_POINTER(count) ); + g_signal_connect( G_OBJECT(item->gobj()), "select", G_CALLBACK(sp_ui_menu_select), const_cast<gchar*>(strs[1]) ); + g_signal_connect( G_OBJECT(item->gobj()), "deselect", G_CALLBACK(sp_ui_menu_deselect), 0 ); - gtk_widget_show( item ); - gtk_menu_shell_append( GTK_MENU_SHELL(menu), item ); + item->show(); + gtk_menu_shell_append( GTK_MENU_SHELL(menu), GTK_WIDGET(item->gobj()) ); } } @@ -832,7 +827,7 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I { if (menus == NULL) return; if (menu == NULL) return; - GSList *group = NULL; + Gtk::RadioMenuItem::Group group; for (Inkscape::XML::Node *menu_pntr = menus; menu_pntr != NULL; @@ -864,8 +859,7 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I if (verb != NULL) { if (menu_pntr->attribute("radio") != NULL) { - GtkWidget *item = sp_ui_menu_append_item_from_verb (GTK_MENU(menu), verb, view, show_icon, true, group); - group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(item)); + GtkWidget *item = sp_ui_menu_append_item_from_verb (GTK_MENU(menu), verb, view, show_icon, true, &group); if (menu_pntr->attribute("default") != NULL) { gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE); } @@ -881,7 +875,8 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I } } else { sp_ui_menu_append_item_from_verb(GTK_MENU(menu), verb, view, show_icon); - group = NULL; + Gtk::RadioMenuItem::Group group2; + group = group2; } } else { gchar string[120]; @@ -1339,12 +1334,13 @@ static void sp_ui_drag_leave( GtkWidget */*widget*/, static void sp_ui_import_files(gchar *buffer) { - GList *list = gnome_uri_list_extract_filenames(buffer); - if (!list) - return; - g_list_foreach(list, sp_ui_import_one_file_with_check, NULL); - g_list_foreach(list, (GFunc) g_free, NULL); - g_list_free(list); + gchar** l = g_uri_list_extract_uris(buffer); + for (int i = 0; i< g_strv_length (l); i++) { + gchar *f = g_filename_from_uri (l[i], NULL, NULL); + sp_ui_import_one_file_with_check(f, NULL); + g_free(f); + } + g_strfreev(l); } static void @@ -1436,14 +1432,12 @@ sp_ui_menu_item_set_name(GtkWidget *data, Glib::ustring const &name) if (GTK_IS_LABEL(child)) { gtk_label_set_markup_with_mnemonic(GTK_LABEL (child), name.c_str()); } else if (GTK_IS_BOX(child)) { - GList *children = gtk_container_get_children(GTK_CONTAINER(child)); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(child))->get_children(); // Label is second child in list - GtkWidget *label = GTK_WIDGET(children->next->data); - - gtk_label_set_markup_with_mnemonic( - GTK_LABEL (label), - name.c_str()); + Gtk::Label *label = dynamic_cast<Gtk::Label*>(children[1]); + if(!label) return; + label->set_markup_with_mnemonic(name); }//else sp_ui_menu_append_item_from_verb has been modified and can set //a menu item in yet another way... } diff --git a/src/ui/makefile.in b/src/ui/makefile.in deleted file mode 100644 index f8a407592..000000000 --- a/src/ui/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) ui/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) ui/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/ui/object-edit.h b/src/ui/object-edit.h deleted file mode 100644 index 75f3ce12b..000000000 --- a/src/ui/object-edit.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef OBJECT_EDIT_H_SEEN -#define OBJECT_EDIT_H_SEEN - -/* - * Node editing extension to objects - * - * Authors: - * Lauris Kaplinski <lauris@kaplinski.com> - * Mitsuru Oka - * Jon A. Cruz <jon@joncruz.org> - * - * Licensed under GNU GPL - */ - -#include "knotholder.h" - -namespace Inkscape { -namespace UI { - -KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop); - -} -} - -class RectKnotHolder : public KnotHolder { -public: - RectKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); - virtual ~RectKnotHolder() {}; -}; - -class Box3DKnotHolder : public KnotHolder { -public: - Box3DKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); - virtual ~Box3DKnotHolder() {}; -}; - -class ArcKnotHolder : public KnotHolder { -public: - ArcKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); - virtual ~ArcKnotHolder() {}; -}; - -class StarKnotHolder : public KnotHolder { -public: - StarKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); - virtual ~StarKnotHolder() {}; -}; - -class SpiralKnotHolder : public KnotHolder { -public: - SpiralKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); - virtual ~SpiralKnotHolder() {}; -}; - -class OffsetKnotHolder : public KnotHolder { -public: - OffsetKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); - virtual ~OffsetKnotHolder() {}; -}; - -class FlowtextKnotHolder : public KnotHolder { -public: - FlowtextKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); - virtual ~FlowtextKnotHolder() {}; -}; - -class MiscKnotHolder : public KnotHolder { -public: - MiscKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); - virtual ~MiscKnotHolder() {}; -}; - -#endif // OBJECT_EDIT_H_SEEN - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/object-edit.cpp b/src/ui/shape-editor-knotholders.cpp index a2b6a2de0..b2e41bac4 100644 --- a/src/ui/object-edit.cpp +++ b/src/ui/shape-editor-knotholders.cpp @@ -31,11 +31,59 @@ #include "live_effects/effect.h" #include "sp-pattern.h" #include <glibmm/i18n.h> -#include "ui/object-edit.h" +#include "knotholder.h" #include "knot-holder-entity.h" #define sp_round(v,m) (((v) < 0.0) ? ((ceil((v) / (m) - 0.5)) * (m)) : ((floor((v) / (m) + 0.5)) * (m))) +class RectKnotHolder : public KnotHolder { +public: + RectKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); + virtual ~RectKnotHolder() {}; +}; + +class Box3DKnotHolder : public KnotHolder { +public: + Box3DKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); + virtual ~Box3DKnotHolder() {}; +}; + +class ArcKnotHolder : public KnotHolder { +public: + ArcKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); + virtual ~ArcKnotHolder() {}; +}; + +class StarKnotHolder : public KnotHolder { +public: + StarKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); + virtual ~StarKnotHolder() {}; +}; + +class SpiralKnotHolder : public KnotHolder { +public: + SpiralKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); + virtual ~SpiralKnotHolder() {}; +}; + +class OffsetKnotHolder : public KnotHolder { +public: + OffsetKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); + virtual ~OffsetKnotHolder() {}; +}; + +class FlowtextKnotHolder : public KnotHolder { +public: + FlowtextKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); + virtual ~FlowtextKnotHolder() {}; +}; + +class MiscKnotHolder : public KnotHolder { +public: + MiscKnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler); + virtual ~MiscKnotHolder() {}; +}; + namespace { static KnotHolder *sp_lpe_knot_holder(SPLPEItem *item, SPDesktop *desktop) diff --git a/src/ui/shape-editor.cpp b/src/ui/shape-editor.cpp index 6a8f5e931..4851c413f 100644 --- a/src/ui/shape-editor.cpp +++ b/src/ui/shape-editor.cpp @@ -20,21 +20,23 @@ #include "sp-shape.h" #include "sp-path.h" #include "inkscape.h" -#include "ui/object-edit.h" #include "ui/shape-editor.h" #include "xml/node-event-vector.h" -//using Inkscape::createKnotHolder; namespace Inkscape { namespace UI { +KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop); + bool ShapeEditor::_blockSetItem = false; -ShapeEditor::ShapeEditor(SPDesktop *dt) { - this->desktop = dt; - this->knotholder = NULL; - this->knotholder_listener_attached_for = NULL; +ShapeEditor::ShapeEditor(SPDesktop *dt, Geom::Affine edit_transform) : + desktop(dt), + knotholder(nullptr), + knotholder_listener_attached_for(nullptr), + _edit_transform(edit_transform) +{ } ShapeEditor::~ShapeEditor() { @@ -76,14 +78,6 @@ void ShapeEditor::decrement_local_change() { } } -const SPItem *ShapeEditor::get_item() { - const SPItem *item = NULL; - if (this->has_knotholder()) { - item = this->knotholder->getItem(); - } - return item; -} - void ShapeEditor::event_attr_changed(Inkscape::XML::Node * node, gchar const *name, gchar const *, gchar const *, bool, void *data) { g_assert(data); @@ -129,6 +123,7 @@ void ShapeEditor::set_item(SPItem *item, bool keep_knotholder) { this->knotholder = createKnotHolder(item, desktop); } if (this->knotholder) { + this->knotholder->setEditTransform(_edit_transform); this->knotholder->update_knots(); // setting new listener repr = this->knotholder->repr; diff --git a/src/ui/shape-editor.h b/src/ui/shape-editor.h index 7f435efca..e30b2d60b 100644 --- a/src/ui/shape-editor.h +++ b/src/ui/shape-editor.h @@ -23,7 +23,7 @@ namespace UI { class ShapeEditor { public: - ShapeEditor(SPDesktop *desktop); + ShapeEditor(SPDesktop *desktop, Geom::Affine edit_transform = Geom::identity()); ~ShapeEditor(); void set_item(SPItem *item, bool keep_knotholder = false); @@ -42,11 +42,11 @@ public: char const * /*new_value*/, bool /*is_interactive*/, void *data); private: void reset_item (bool keep_knotholder = true); - const SPItem *get_item(); static bool _blockSetItem; SPDesktop *desktop; Inkscape::XML::Node *knotholder_listener_attached_for; + Geom::Affine _edit_transform; }; } // namespace UI diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index f122a468d..ec845b1b3 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -20,7 +20,6 @@ #include <2geom/forward.h> #include <2geom/point.h> #include <2geom/rect.h> -#include "util/accumulators.h" #include "util/unordered-containers.h" #include "ui/tool/commit-events.h" #include "ui/tool/manipulator.h" diff --git a/src/ui/tool/control-point.cpp b/src/ui/tool/control-point.cpp index d9374c790..8ab9fcbd7 100644 --- a/src/ui/tool/control-point.cpp +++ b/src/ui/tool/control-point.cpp @@ -380,7 +380,7 @@ bool ControlPoint::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, G // update tips on modifier state change // TODO add ESC keybinding as drag cancel case GDK_KEY_PRESS: - switch (Inkscape::UI::Tools::get_group0_keyval(&event->key)) + switch (Inkscape::UI::Tools::get_latin_keyval(&event->key)) { case GDK_KEY_Escape: { // ignore Escape if this is not a drag diff --git a/src/ui/tool/control-point.h b/src/ui/tool/control-point.h index 4a01b9f21..bc1f060cd 100644 --- a/src/ui/tool/control-point.h +++ b/src/ui/tool/control-point.h @@ -18,7 +18,6 @@ #include <2geom/point.h> #include "ui/control-types.h" -#include "util/accumulators.h" #include "display/sodipodi-ctrl.h" #include "enums.h" @@ -76,8 +75,6 @@ namespace UI { */ class ControlPoint : boost::noncopyable, public sigc::trackable { public: - typedef Inkscape::Util::ReverseInterruptible RInt; - typedef Inkscape::Util::Interruptible Int; /** * Enumeration representing the possible states of the control point, used to determine @@ -162,15 +159,6 @@ public: void transferGrab(ControlPoint *from, GdkEventMotion *event); /// @} - /// @name Receive notifications about control point events - /// @{ - /*sigc::signal<void, Geom::Point const &, Geom::Point &, GdkEventMotion*> signal_dragged; - sigc::signal<bool, GdkEventButton*>::accumulated<RInt> signal_clicked; - sigc::signal<bool, GdkEventButton*>::accumulated<RInt> signal_doubleclicked; - sigc::signal<bool, GdkEventMotion*>::accumulated<Int> signal_grabbed; - sigc::signal<void, GdkEventButton*> signal_ungrabbed;*/ - /// @} - /// @name Inspect the state of the control point /// @{ State state() const { return _state; } diff --git a/src/ui/tool/manipulator.h b/src/ui/tool/manipulator.h index 07e01a656..66b47ce98 100644 --- a/src/ui/tool/manipulator.h +++ b/src/ui/tool/manipulator.h @@ -17,7 +17,6 @@ #include <sigc++/sigc++.h> #include <glib.h> #include <gdk/gdk.h> -#include <boost/shared_ptr.hpp> #include "ui/tools/tool-base.h" class SPDesktop; @@ -76,14 +75,14 @@ template <typename T> class MultiManipulator : public PointManipulator { public: //typedef typename T::ItemType ItemType; - typedef typename std::pair<void*, boost::shared_ptr<T> > MapPair; - typedef typename std::map<void*, boost::shared_ptr<T> > MapType; + typedef typename std::pair<void*, std::shared_ptr<T> > MapPair; + typedef typename std::map<void*, std::shared_ptr<T> > MapType; MultiManipulator(SPDesktop *d, ControlPointSelection &sel) : PointManipulator(d, sel) {} void addItem(void *item) { - boost::shared_ptr<T> m(_createManipulator(item)); + std::shared_ptr<T> m(_createManipulator(item)); _mmap.insert(MapPair(item, m)); } void removeItem(void *item) { @@ -98,16 +97,17 @@ public: bool empty() { return _mmap.empty(); } - void setItems(GSList const *list) { + + void setItems(std::vector<gpointer> list) { // this function is not called anywhere ... delete ? std::set<void*> to_remove; for (typename MapType::iterator mi = _mmap.begin(); mi != _mmap.end(); ++mi) { to_remove.insert(mi->first); } - for (GSList *i = const_cast<GSList*>(list); i; i = i->next) { - if (_isItemType(i->data)) { + for (auto i:list) { + if (_isItemType(i)) { // erase returns the number of items removed // if nothing was removed, it means this item did not have a manipulator - add it - if (!to_remove.erase(i->data)) addItem(i->data); + if (!to_remove.erase(i)) addItem(i); } } typedef typename std::set<void*>::iterator RmIter; diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index f30c7e349..9cfa4ed31 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -10,7 +10,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <boost/shared_ptr.hpp> #include "node.h" #include <glibmm/i18n.h> #include "desktop.h" @@ -161,7 +160,7 @@ void MultiPathManipulator::setItems(std::set<ShapeRecord> const &s) if (sr.edit_transform != sr_new.edit_transform || sr.role != sr_new.role) { - boost::shared_ptr<PathManipulator> hold(i->second); + std::shared_ptr<PathManipulator> hold(i->second); if (sr.edit_transform != sr_new.edit_transform) hold->setControlsTransform(sr_new.edit_transform); if (sr.role != sr_new.role) { @@ -179,7 +178,7 @@ void MultiPathManipulator::setItems(std::set<ShapeRecord> const &s) for (std::set<ShapeRecord>::iterator i = shapes.begin(); i != shapes.end(); ++i) { ShapeRecord const &r = *i; if (!SP_IS_PATH(r.item) && !IS_LIVEPATHEFFECT(r.item)) continue; - boost::shared_ptr<PathManipulator> newpm(new PathManipulator(*this, (SPPath*) r.item, + std::shared_ptr<PathManipulator> newpm(new PathManipulator(*this, (SPPath*) r.item, r.edit_transform, _getOutlineColor(r.role, r.item), r.lpe_key)); newpm->showHandles(_show_handles); // always show outlines for clips and masks diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h index 4f152e0a2..742c6d421 100644 --- a/src/ui/tool/multi-path-manipulator.h +++ b/src/ui/tool/multi-path-manipulator.h @@ -77,8 +77,8 @@ public: sigc::signal<void> signal_coords_changed; /// Emitted whenever the coordinates /// shown in the status bar need updating private: - typedef std::pair<ShapeRecord, boost::shared_ptr<PathManipulator> > MapPair; - typedef std::map<ShapeRecord, boost::shared_ptr<PathManipulator> > MapType; + typedef std::pair<ShapeRecord, std::shared_ptr<PathManipulator> > MapPair; + typedef std::map<ShapeRecord, std::shared_ptr<PathManipulator> > MapType; template <typename R> void invokeForAll(R (PathManipulator::*method)()) { @@ -88,11 +88,11 @@ private: // be a valid iterator and then assign i to it. MapType::iterator next_i = i; ++next_i; - // i->second is a boost::shared_ptr so try to hold on to it so + // i->second is a std::shared_ptr so try to hold on to it so // it won't get freed prematurely by the WriteXML() method or // whatever. See https://bugs.launchpad.net/inkscape/+bug/1617615 // Applicable to empty paths. - boost::shared_ptr<PathManipulator> hold(i->second); + std::shared_ptr<PathManipulator> hold(i->second); ((hold.get())->*method)(); i = next_i; } diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index d6e491ac3..4f42400d4 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -559,14 +559,11 @@ Glib::ustring Handle::_getDragTip(GdkEventMotion */*event*/) const Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(dist[Geom::X], "px"); Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(dist[Geom::Y], "px"); Inkscape::Util::Quantity len_q = Inkscape::Util::Quantity(length(), "px"); - GString *x = g_string_new(x_q.string(_desktop->namedview->display_units).c_str()); - GString *y = g_string_new(y_q.string(_desktop->namedview->display_units).c_str()); - GString *len = g_string_new(len_q.string(_desktop->namedview->display_units).c_str()); + Glib::ustring x = x_q.string(_desktop->namedview->display_units); + Glib::ustring y = y_q.string(_desktop->namedview->display_units); + Glib::ustring len = len_q.string(_desktop->namedview->display_units); Glib::ustring ret = format_tip(C_("Path handle tip", - "Move handle by %s, %s; angle %.2f°, length %s"), x->str, y->str, angle, len->str); - g_string_free(x, TRUE); - g_string_free(y, TRUE); - g_string_free(len, TRUE); + "Move handle by %s, %s; angle %.2f°, length %s"), x.c_str(), y.c_str(), angle, len.c_str()); return ret; } @@ -1458,11 +1455,9 @@ Glib::ustring Node::_getDragTip(GdkEventMotion */*event*/) const Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(dist[Geom::X], "px"); Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(dist[Geom::Y], "px"); - GString *x = g_string_new(x_q.string(_desktop->namedview->display_units).c_str()); - GString *y = g_string_new(y_q.string(_desktop->namedview->display_units).c_str()); - Glib::ustring ret = format_tip(C_("Path node tip", "Move node by %s, %s"), x->str, y->str); - g_string_free(x, TRUE); - g_string_free(y, TRUE); + Glib::ustring x = x_q.string(_desktop->namedview->display_units); + Glib::ustring y = y_q.string(_desktop->namedview->display_units); + Glib::ustring ret = format_tip(C_("Path node tip", "Move node by %s, %s"), x.c_str(), y.c_str()); return ret; } diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h index a05f0e3b9..2964b66ca 100644 --- a/src/ui/tool/node.h +++ b/src/ui/tool/node.h @@ -22,8 +22,6 @@ #include <cstddef> #include <functional> -#include <boost/enable_shared_from_this.hpp> -#include <boost/shared_ptr.hpp> #include "ui/tool/selectable-control-point.h" #include "snapped-point.h" #include "ui/tool/node-types.h" @@ -357,7 +355,7 @@ private: friend class NodeList; }; -class NodeList : ListNode, boost::noncopyable, public boost::enable_shared_from_this<NodeList> { +class NodeList : ListNode, boost::noncopyable { public: typedef std::size_t size_type; typedef Node &reference; @@ -465,9 +463,9 @@ private: * List of node lists. Represents an editable path. * Editable path composed of one or more subpaths. */ -class SubpathList : public std::list< boost::shared_ptr<NodeList> > { +class SubpathList : public std::list< std::shared_ptr<NodeList> > { public: - typedef std::list< boost::shared_ptr<NodeList> > list_type; + typedef std::list< std::shared_ptr<NodeList> > list_type; SubpathList(PathManipulator &pm) : _path_manipulator(pm) {} PathManipulator &pm() { return _path_manipulator; } diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index f2899dd01..2c99e7fc8 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -68,7 +68,7 @@ public: } virtual void notifyAttributeChanged(Inkscape::XML::Node &/*node*/, GQuark attr, - Util::ptr_shared<char>, Util::ptr_shared<char>) + Util::ptr_shared, Util::ptr_shared) { // do nothing if blocked if (_blocked) return; diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h index 283cb610a..5fa24c23b 100644 --- a/src/ui/tool/path-manipulator.h +++ b/src/ui/tool/path-manipulator.h @@ -15,8 +15,6 @@ #include <memory> #include <2geom/pathvector.h> #include <2geom/affine.h> -#include <boost/shared_ptr.hpp> -#include <boost/weak_ptr.hpp> #include "ui/tool/node.h" #include "ui/tool/manipulator.h" #include "live_effects/lpe-bspline.h" @@ -105,7 +103,7 @@ public: static bool is_item_type(void *item); private: typedef NodeList Subpath; - typedef boost::shared_ptr<NodeList> SubpathPtr; + typedef std::shared_ptr<NodeList> SubpathPtr; void _createControlPointsFromGeometry(); diff --git a/src/ui/tools/arc-tool.cpp b/src/ui/tools/arc-tool.cpp index b501962fb..33f323eb3 100644 --- a/src/ui/tools/arc-tool.cpp +++ b/src/ui/tools/arc-tool.cpp @@ -227,7 +227,7 @@ bool ArcTool::root_handler(GdkEvent* event) { break; case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: @@ -385,8 +385,8 @@ void ArcTool::drag(Geom::Point pt, guint state) { Inkscape::Util::Quantity rdimx_q = Inkscape::Util::Quantity(rdimx, "px"); Inkscape::Util::Quantity rdimy_q = Inkscape::Util::Quantity(rdimy, "px"); - GString *xs = g_string_new(rdimx_q.string(desktop->namedview->display_units).c_str()); - GString *ys = g_string_new(rdimy_q.string(desktop->namedview->display_units).c_str()); + Glib::ustring xs = rdimx_q.string(desktop->namedview->display_units); + Glib::ustring ys = rdimy_q.string(desktop->namedview->display_units); if (state & GDK_CONTROL_MASK) { int ratio_x, ratio_y; @@ -399,13 +399,10 @@ void ArcTool::drag(Geom::Point pt, guint state) { ratio_y = (int) rint (rdimy / rdimx); } - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Ellipse</b>: %s × %s (constrained to ratio %d:%d); with <b>Shift</b> to draw around the starting point"), xs->str, ys->str, ratio_x, ratio_y); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Ellipse</b>: %s × %s (constrained to ratio %d:%d); with <b>Shift</b> to draw around the starting point"), xs.c_str(), ys.c_str(), ratio_x, ratio_y); } else { - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Ellipse</b>: %s × %s; with <b>Ctrl</b> to make square or integer-ratio ellipse; with <b>Shift</b> to draw around the starting point"), xs->str, ys->str); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Ellipse</b>: %s × %s; with <b>Ctrl</b> to make square or integer-ratio ellipse; with <b>Shift</b> to draw around the starting point"), xs.c_str(), ys.c_str()); } - - g_string_free(xs, FALSE); - g_string_free(ys, FALSE); } void ArcTool::finishItem() { @@ -418,7 +415,7 @@ void ArcTool::finishItem() { } this->arc->updateRepr(); - this->arc->doWriteTransform(this->arc->getRepr(), this->arc->transform, NULL, true); + this->arc->doWriteTransform(this->arc->transform, NULL, true); desktop->canvas->endForcedFullRedraws(); diff --git a/src/ui/tools/box3d-tool.cpp b/src/ui/tools/box3d-tool.cpp index 276385335..09ee2cda9 100644 --- a/src/ui/tools/box3d-tool.cpp +++ b/src/ui/tools/box3d-tool.cpp @@ -335,7 +335,7 @@ bool Box3dTool::root_handler(GdkEvent* event) { break; case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Up: case GDK_KEY_Down: case GDK_KEY_KP_Up: @@ -529,9 +529,9 @@ void Box3dTool::drag(guint /*state*/) { side->setAttribute("style", cur_style.data()); } else { // use default style - GString *pstring = g_string_new(""); - g_string_printf (pstring, "/tools/shapes/3dbox/%s", box3d_side_axes_string(side)); - desktop->applyCurrentOrToolStyle (side, pstring->str, false); + Glib::ustring tool_path = Glib::ustring::compose("/tools/shapes/3dbox/%1", + box3d_side_axes_string(side)); + desktop->applyCurrentOrToolStyle (side, tool_path, false); } side->updateRepr(); // calls box3d_side_write() and updates, e.g., the axes string description diff --git a/src/ui/tools/calligraphic-tool.cpp b/src/ui/tools/calligraphic-tool.cpp index 266375caa..2a29b25b0 100644 --- a/src/ui/tools/calligraphic-tool.cpp +++ b/src/ui/tools/calligraphic-tool.cpp @@ -421,10 +421,9 @@ void CalligraphicTool::cancel() { sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0); /* Remove all temporary line segments */ - while (this->segments) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->segments->data)); - this->segments = g_slist_remove(this->segments, this->segments->data); - } + for (auto i:this->segments) + sp_canvas_item_destroy(SP_CANVAS_ITEM(i)); + this->segments.clear(); /* reset accumulated curve */ this->accumulated->reset(); @@ -731,10 +730,9 @@ bool CalligraphicTool::root_handler(GdkEvent* event) { this->apply(motion_dt); /* Remove all temporary line segments */ - while (this->segments) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->segments->data)); - this->segments = g_slist_remove(this->segments, this->segments->data); - } + for (auto i:this->segments) + sp_canvas_item_destroy(SP_CANVAS_ITEM(i)); + this->segments.clear(); /* Create object */ this->fit_and_split(true); @@ -779,7 +777,7 @@ bool CalligraphicTool::root_handler(GdkEvent* event) { } case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Up: case GDK_KEY_KP_Up: if (!MOD__CTRL_ONLY(event)) { @@ -860,7 +858,7 @@ bool CalligraphicTool::root_handler(GdkEvent* event) { break; case GDK_KEY_RELEASE: - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Control_L: case GDK_KEY_Control_R: this->message_context->clear(); @@ -947,7 +945,7 @@ void CalligraphicTool::set_to_accumulated(bool unionize, bool subtract) { result = desktop->getSelection()->singleItem(); } - result->doWriteTransform(result->getRepr(), result->transform, NULL, true); + result->doWriteTransform(result->transform, NULL, true); } else { if (this->repr) { sp_repr_unparent(this->repr); @@ -1089,7 +1087,7 @@ void CalligraphicTool::fit_and_split(bool release) { this->currentcurve->curveto(bp2[2], bp2[1], bp2[0]); } // FIXME: dc->segments is always NULL at this point?? - if (!this->segments) { // first segment + if (this->segments.empty()) { // first segment add_cap(this->currentcurve, b2[0], b1[0], this->cap_rounding); } this->currentcurve->closepath(); @@ -1143,8 +1141,8 @@ void CalligraphicTool::fit_and_split(bool release) { sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cbp), 0x00000000, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); /* fixme: Cannot we cascade it to root more clearly? */ g_signal_connect(G_OBJECT(cbp), "event", G_CALLBACK(sp_desktop_root_handler), desktop); - - this->segments = g_slist_prepend(this->segments, cbp); + + this->segments.push_back(cbp); } this->point1[0] = this->point1[this->npoints - 1]; diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp index 6d2682089..b9d36706f 100644 --- a/src/ui/tools/connector-tool.cpp +++ b/src/ui/tools/connector-tool.cpp @@ -434,7 +434,7 @@ bool ConnectorTool::root_handler(GdkEvent* event) { break; case GDK_KEY_PRESS: - ret = this->_handleKeyPress(get_group0_keyval (&event->key)); + ret = this->_handleKeyPress(get_latin_keyval (&event->key)); break; default: @@ -904,7 +904,7 @@ void ConnectorTool::_flushWhite(SPCurve *gc) { this->newconn->updateRepr(); } - this->newconn->doWriteTransform(this->newconn->getRepr(), this->newconn->transform, NULL, true); + this->newconn->doWriteTransform(this->newconn->transform, NULL, true); // Only set the selection after we are finished with creating the attributes of // the connector. Otherwise, the selection change may alter the defaults for diff --git a/src/ui/tools/dropper-tool.cpp b/src/ui/tools/dropper-tool.cpp index 53a99e481..7bde1b698 100644 --- a/src/ui/tools/dropper-tool.cpp +++ b/src/ui/tools/dropper-tool.cpp @@ -345,7 +345,7 @@ bool DropperTool::root_handler(GdkEvent* event) { break; case GDK_KEY_PRESS: - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Up: case GDK_KEY_Down: case GDK_KEY_KP_Up: diff --git a/src/ui/tools/dynamic-base.cpp b/src/ui/tools/dynamic-base.cpp index bb4989333..1026c26c6 100644 --- a/src/ui/tools/dynamic-base.cpp +++ b/src/ui/tools/dynamic-base.cpp @@ -21,7 +21,6 @@ namespace Tools { DynamicBase::DynamicBase(gchar const *const *cursor_shape) : ToolBase(cursor_shape) , accumulated(NULL) - , segments(NULL) , currentshape(NULL) , currentcurve(NULL) , cal1(NULL) @@ -62,10 +61,10 @@ DynamicBase::~DynamicBase() { this->accumulated = 0; } - while (this->segments) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->segments->data)); - this->segments = g_slist_remove(this->segments, this->segments->data); + for (auto i:segments) { + sp_canvas_item_destroy(SP_CANVAS_ITEM(i)); } + segments.clear(); if (this->currentcurve) { this->currentcurve = this->currentcurve->unref(); diff --git a/src/ui/tools/dynamic-base.h b/src/ui/tools/dynamic-base.h index e270052f3..b9ffd71ce 100644 --- a/src/ui/tools/dynamic-base.h +++ b/src/ui/tools/dynamic-base.h @@ -20,6 +20,7 @@ */ #include "ui/tools/tool-base.h" +#include "display/sp-canvas-item.h" struct SPCanvasItem; class SPCurve; @@ -48,7 +49,7 @@ protected: SPCurve *accumulated; /** canvas items for "committed" segments */ - GSList *segments; + std::vector<SPCanvasItem*> segments; /** canvas item for red "leading" segment */ SPCanvasItem *currentshape; diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp index b4246b9cc..7892e865b 100644 --- a/src/ui/tools/eraser-tool.cpp +++ b/src/ui/tools/eraser-tool.cpp @@ -360,10 +360,9 @@ void EraserTool::cancel() { this->is_drawing = false; sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0); /* Remove all temporary line segments */ - while (this->segments) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->segments->data)); - this->segments = g_slist_remove(this->segments, this->segments->data); - } + for (auto i : this->segments) + sp_canvas_item_destroy(SP_CANVAS_ITEM(i)); + this->segments.clear(); /* reset accumulated curve */ this->accumulated->reset(); this->clear_current(); @@ -464,10 +463,9 @@ bool EraserTool::root_handler(GdkEvent* event) { this->apply(motion_dt); /* Remove all temporary line segments */ - while (this->segments) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->segments->data)); - this->segments = g_slist_remove(this->segments, this->segments->data); - } + for (auto i : this->segments) + sp_canvas_item_destroy(SP_CANVAS_ITEM(i)); + this->segments.clear(); /* Create object */ this->fit_and_split(true); @@ -494,7 +492,7 @@ bool EraserTool::root_handler(GdkEvent* event) { } case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { // case GDK_KEY_Up: // case GDK_KEY_KP_Up: // if (!MOD__CTRL_ONLY(event)) { @@ -598,7 +596,7 @@ bool EraserTool::root_handler(GdkEvent* event) { break; case GDK_KEY_RELEASE: - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Control_L: case GDK_KEY_Control_R: this->message_context->clear(); @@ -780,7 +778,7 @@ void EraserTool::set_to_accumulated() { if (dup_clip) { SPItem * dup_clip_obj = SP_ITEM(item_repr->parent->appendChildRepr(dup_clip)); if (dup_clip_obj) { - dup_clip_obj->doWriteTransform(dup_clip, item->transform); + dup_clip_obj->doWriteTransform(item->transform); sp_object_ref(clip_path, 0); clip_path->deleteObject(true); sp_object_unref(clip_path); @@ -1015,7 +1013,7 @@ void EraserTool::fit_and_split(bool release) { } // FIXME: this->segments is always NULL at this point?? - if (!this->segments) { // first segment + if (this->segments.empty()) { // first segment add_cap(this->currentcurve, b2[1], b2[0], b1[0], b1[1], this->cap_rounding); } @@ -1072,7 +1070,7 @@ void EraserTool::fit_and_split(bool release) { /* fixme: Cannot we cascade it to root more clearly? */ g_signal_connect(G_OBJECT(cbp), "event", G_CALLBACK(sp_desktop_root_handler), desktop); - this->segments = g_slist_prepend(this->segments, cbp); + this->segments.push_back(cbp); if (eraser_mode == ERASER_MODE_DELETE) { sp_canvas_item_hide(cbp); diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp index f6f9b4355..401b50c1c 100644 --- a/src/ui/tools/flood-tool.cpp +++ b/src/ui/tools/flood-tool.cpp @@ -444,7 +444,7 @@ static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *deskto SPObject *reprobj = document->getObjectByRepr(pathRepr); if (reprobj) { - SP_ITEM(reprobj)->doWriteTransform(pathRepr, transform, NULL); + SP_ITEM(reprobj)->doWriteTransform(transform); // premultiply the item transform by the accumulated parent transform in the paste layer Geom::Affine local (SP_GROUP(desktop->currentLayer())->i2doc_affine()); @@ -1189,7 +1189,7 @@ bool FloodTool::root_handler(GdkEvent* event) { } break; case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Up: case GDK_KEY_Down: case GDK_KEY_KP_Up: diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index 32f2bdde1..064a83a5a 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -81,13 +81,10 @@ FreehandBase::FreehandBase(gchar const *const *cursor_shape) , red_curve(NULL) , blue_bpath(NULL) , blue_curve(NULL) - , green_bpaths(NULL) , green_curve(NULL) , green_anchor(NULL) , green_closed(false) , white_item(NULL) - , white_curves(NULL) - , white_anchors(NULL) , overwrite_curve(NULL) , sa(NULL) , ea(NULL) @@ -178,7 +175,7 @@ bool FreehandBase::root_handler(GdkEvent* event) { switch (event->type) { case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Up: case GDK_KEY_Down: case GDK_KEY_KP_Up: @@ -619,22 +616,20 @@ static void spdc_attach_selection(FreehandBase *dc, Inkscape::Selection */*sel*/ SPCurve *norm = SP_PATH(item)->get_curve_for_edit(); norm->transform((dc->white_item)->i2dt_affine()); g_return_if_fail( norm != NULL ); - dc->white_curves = g_slist_reverse(norm->split()); + dc->white_curves = norm->split(); norm->unref(); // Anchor list - for (GSList *l = dc->white_curves; l != NULL; l = l->next) { - SPCurve *c; - c = static_cast<SPCurve*>(l->data); + for (auto c:dc->white_curves) { g_return_if_fail( c->get_segment_count() > 0 ); if ( !c->is_closed() ) { SPDrawAnchor *a; a = sp_draw_anchor_new(dc, c, TRUE, *(c->first_point())); if (a) - dc->white_anchors = g_slist_prepend(dc->white_anchors, a); + dc->white_anchors.push_back(a); a = sp_draw_anchor_new(dc, c, FALSE, *(c->last_point())); if (a) - dc->white_anchors = g_slist_prepend(dc->white_anchors, a); + dc->white_anchors.push_back(a); } } // fixme: recalculate active anchor? @@ -706,10 +701,9 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); // Green dc->green_curve = new SPCurve(); - while (dc->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(dc->green_bpaths->data)); - dc->green_bpaths = g_slist_remove(dc->green_bpaths, dc->green_bpaths->data); - } + for (auto i : dc->green_bpaths) + sp_canvas_item_destroy(i); + dc->green_bpaths.clear(); // Blue c->append_continuous(dc->blue_curve, 0.0625); @@ -759,8 +753,8 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed) c->unref(); dc->overwrite_curve->closepath_current(); if(dc->sa){ - dc->white_curves = g_slist_remove(dc->white_curves, dc->sa->curve); - dc->white_curves = g_slist_append(dc->white_curves, dc->overwrite_curve); + dc->white_curves.erase(std::find(dc->white_curves.begin(),dc->white_curves.end(), dc->sa->curve)); + dc->white_curves.push_back(dc->overwrite_curve); } }else{ dc->sa->curve->append_continuous(c, 0.0625); @@ -774,7 +768,7 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed) // Step C - test start if (dc->sa) { SPCurve *s = dc->sa->curve; - dc->white_curves = g_slist_remove(dc->white_curves, s); + dc->white_curves.erase(std::find(dc->white_curves.begin(),dc->white_curves.end(), s)); if(prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1 || prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2){ s = dc->overwrite_curve; @@ -787,7 +781,7 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed) c = s; } else /* Step D - test end */ if (dc->ea) { SPCurve *e = dc->ea->curve; - dc->white_curves = g_slist_remove(dc->white_curves, e); + dc->white_curves.erase(std::find(dc->white_curves.begin(),dc->white_curves.end(), e)); if (!dc->ea->start) { e = reverse_then_unref(e); } @@ -827,11 +821,10 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed) static void spdc_flush_white(FreehandBase *dc, SPCurve *gc) { SPCurve *c; - if (dc->white_curves) { + if (! dc->white_curves.empty()) { g_assert(dc->white_item); c = SPCurve::concat(dc->white_curves); - g_slist_free(dc->white_curves); - dc->white_curves = NULL; + dc->white_curves.clear(); if (gc) { c->append(gc, FALSE); } @@ -883,7 +876,7 @@ static void spdc_flush_white(FreehandBase *dc, SPCurve *gc) Inkscape::GC::release(repr); item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); item->updateRepr(); - item->doWriteTransform(item->getRepr(), item->transform, NULL, true); + item->doWriteTransform(item->transform, NULL, true); spdc_check_for_and_apply_waiting_LPE(dc, item, c, false); dc->selection->set(repr); if(previous_shape_type == BEND_CLIPBOARD){ @@ -917,8 +910,8 @@ SPDrawAnchor *spdc_test_inside(FreehandBase *dc, Geom::Point p) active = sp_draw_anchor_test(dc->green_anchor, p, TRUE); } - for (GSList *l = dc->white_anchors; l != NULL; l = l->next) { - SPDrawAnchor *na = sp_draw_anchor_test(static_cast<SPDrawAnchor*>(l->data), p, !active); + for (auto i:dc->white_anchors) { + SPDrawAnchor *na = sp_draw_anchor_test(i, p, !active); if ( !active && na ) { active = na; } @@ -932,14 +925,12 @@ static void spdc_reset_white(FreehandBase *dc) // We do not hold refcount dc->white_item = NULL; } - while (dc->white_curves) { - reinterpret_cast<SPCurve *>(dc->white_curves->data)->unref(); - dc->white_curves = g_slist_remove(dc->white_curves, dc->white_curves->data); - } - while (dc->white_anchors) { - sp_draw_anchor_destroy(static_cast<SPDrawAnchor*>(dc->white_anchors->data)); - dc->white_anchors = g_slist_remove(dc->white_anchors, dc->white_anchors->data); - } + for (auto i: dc->white_curves) + i->unref(); + dc->white_curves.clear(); + for (auto i:dc->white_anchors) + sp_draw_anchor_destroy(i); + dc->white_anchors.clear(); } static void spdc_free_colors(FreehandBase *dc) @@ -963,10 +954,9 @@ static void spdc_free_colors(FreehandBase *dc) } // Green - while (dc->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(dc->green_bpaths->data)); - dc->green_bpaths = g_slist_remove(dc->green_bpaths, dc->green_bpaths->data); - } + for (auto i : dc->green_bpaths) + sp_canvas_item_destroy(i); + dc->green_bpaths.clear(); if (dc->green_curve) { dc->green_curve = dc->green_curve->unref(); } @@ -979,14 +969,12 @@ static void spdc_free_colors(FreehandBase *dc) // We do not hold refcount dc->white_item = NULL; } - while (dc->white_curves) { - reinterpret_cast<SPCurve *>(dc->white_curves->data)->unref(); - dc->white_curves = g_slist_remove(dc->white_curves, dc->white_curves->data); - } - while (dc->white_anchors) { - sp_draw_anchor_destroy(static_cast<SPDrawAnchor *>(dc->white_anchors->data)); - dc->white_anchors = g_slist_remove(dc->white_anchors, dc->white_anchors->data); - } + for (auto i: dc->white_curves) + i->unref(); + dc->white_curves.clear(); + for (auto i:dc->white_anchors) + sp_draw_anchor_destroy(i); + dc->white_anchors.clear(); } void spdc_create_single_dot(ToolBase *ec, Geom::Point const &pt, char const *tool, guint event_state) { diff --git a/src/ui/tools/freehand-base.h b/src/ui/tools/freehand-base.h index 8759e6647..02d0a9982 100644 --- a/src/ui/tools/freehand-base.h +++ b/src/ui/tools/freehand-base.h @@ -66,15 +66,15 @@ public: SPCurve *blue_curve; // Green - GSList *green_bpaths; + std::vector<SPCanvasItem*> green_bpaths; SPCurve *green_curve; SPDrawAnchor *green_anchor; gboolean green_closed; // a flag meaning we hit the green anchor, so close the path on itself // White SPItem *white_item; - GSList *white_curves; - GSList *white_anchors; + std::list<SPCurve *> white_curves; + std::vector<SPDrawAnchor*> white_anchors; // Alternative curve to use on continuing the exisiting curve in case of // bspline or spirolive, because using anchor curves gives random memory diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp index 95d940bd6..1735a78df 100644 --- a/src/ui/tools/gradient-tool.cpp +++ b/src/ui/tools/gradient-tool.cpp @@ -219,7 +219,7 @@ sp_gradient_context_is_over_line (GradientTool *rc, SPItem *item, Geom::Point ev } static std::vector<Geom::Point> -sp_gradient_context_get_stop_intervals (GrDrag *drag, GSList **these_stops, GSList **next_stops) +sp_gradient_context_get_stop_intervals (GrDrag *drag, std::vector<SPStop *> &these_stops, std::vector<SPStop *> &next_stops) { std::vector<Geom::Point> coords; @@ -285,15 +285,15 @@ sp_gradient_context_get_stop_intervals (GrDrag *drag, GSList **these_stops, GSLi } // if both adjacent draggers selected, - if (!g_slist_find(*these_stops, this_stop) && dnext && dnext->isSelected()) { + if ((std::find(these_stops.begin(),these_stops.end(),this_stop)==these_stops.end()) && dnext && dnext->isSelected()) { // remember the coords of the future dragger to select it coords.push_back(0.5*(dragger->point + dnext->point)); // do not insert a stop now, it will confuse the loop; // just remember the stops - *these_stops = g_slist_prepend (*these_stops, this_stop); - *next_stops = g_slist_prepend (*next_stops, next_stop); + these_stops.push_back(this_stop); + next_stops.push_back(next_stop); } } } @@ -307,12 +307,12 @@ sp_gradient_context_add_stops_between_selected_stops (GradientTool *rc) SPDocument *doc = NULL; GrDrag *drag = rc->_grdrag; - GSList *these_stops = NULL; - GSList *next_stops = NULL; + std::vector<SPStop *> these_stops; + std::vector<SPStop *> next_stops; - std::vector<Geom::Point> coords = sp_gradient_context_get_stop_intervals (drag, &these_stops, &next_stops); + std::vector<Geom::Point> coords = sp_gradient_context_get_stop_intervals (drag, these_stops, next_stops); - if (g_slist_length(these_stops) == 0 && drag->numSelected() == 1) { + if (these_stops.empty() && drag->numSelected() == 1) { // if a single stop is selected, add between that stop and the next one GrDragger *dragger = *(drag->selected.begin()); for (std::vector<GrDraggable *>::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end(); ++j) { @@ -330,47 +330,42 @@ sp_gradient_context_add_stops_between_selected_stops (GradientTool *rc) if (this_stop) { SPStop *next_stop = this_stop->getNextStop(); if (next_stop) { - these_stops = g_slist_prepend (these_stops, this_stop); - next_stops = g_slist_prepend (next_stops, next_stop); + these_stops.push_back(this_stop); + next_stops.push_back(next_stop); } } } } // now actually create the new stops - GSList *i = these_stops; - GSList *j = next_stops; - GSList *new_stops = NULL; + auto i = these_stops.rbegin(); + auto j = next_stops.rbegin(); + std::vector<SPStop *> new_stops; - for (; i != NULL && j != NULL; i = i->next, j = j->next) { - SPStop *this_stop = (SPStop *) i->data; - SPStop *next_stop = (SPStop *) j->data; + for (;i != these_stops.rend() && j != next_stops.rend(); ++i, ++j ) { + SPStop *this_stop = *i; + SPStop *next_stop = *j; gfloat offset = 0.5*(this_stop->offset + next_stop->offset); SPObject *parent = this_stop->parent; if (SP_IS_GRADIENT (parent)) { doc = parent->document; SPStop *new_stop = sp_vector_add_stop (SP_GRADIENT (parent), this_stop, next_stop, offset); - new_stops = g_slist_prepend (new_stops, new_stop); + new_stops.push_back(new_stop); SP_GRADIENT(parent)->ensureVector(); } } - if (g_slist_length(these_stops) > 0 && doc) { + if (!these_stops.empty() && doc) { DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT, _("Add gradient stop")); drag->updateDraggers(); // so that it does not automatically update draggers in idle loop, as this would deselect drag->local_change = true; // select the newly created stops - for (GSList *s = new_stops; s != NULL; s = s->next) { - drag->selectByStop((SPStop *)s->data); + for (auto i:new_stops) { + drag->selectByStop(i); } - } - - g_slist_free (these_stops); - g_slist_free (next_stops); - g_slist_free (new_stops); } static double sqr(double x) {return x*x;} @@ -381,26 +376,25 @@ sp_gradient_simplify(GradientTool *rc, double tolerance) SPDocument *doc = NULL; GrDrag *drag = rc->_grdrag; - GSList *these_stops = NULL; - GSList *next_stops = NULL; + std::vector<SPStop *> these_stops; + std::vector<SPStop *> next_stops; - std::vector<Geom::Point> coords = sp_gradient_context_get_stop_intervals (drag, &these_stops, &next_stops); + std::vector<Geom::Point> coords = sp_gradient_context_get_stop_intervals (drag, these_stops, next_stops); - GSList *todel = NULL; + std::set<SPStop *> todel; - GSList *i = these_stops; - GSList *j = next_stops; - for (; i != NULL && j != NULL; i = i->next, j = j->next) { - SPStop *stop0 = (SPStop *) i->data; - SPStop *stop1 = (SPStop *) j->data; + auto i = these_stops.begin(); + auto j = next_stops.end(); + for (; i != these_stops.end() && j != next_stops.end(); ++i, ++j) { + SPStop *stop0 = *i; + SPStop *stop1 = *j; - gint i1 = g_slist_index(these_stops, stop1); - if (i1 != -1) { - GSList *next_next = g_slist_nth (next_stops, i1); - if (next_next) { - SPStop *stop2 = (SPStop *) next_next->data; + auto i1 = std::find(these_stops.begin(), these_stops.end(), stop1); + if (i1 != these_stops.end()) { + if (next_stops.size()>(i1-these_stops.begin())) { + SPStop *stop2 = *(next_stops.begin() + (i1-these_stops.begin())); - if (g_slist_find(todel, stop0) || g_slist_find(todel, stop2)) + if (todel.find(stop0)!=todel.end() || todel.find(stop2) != todel.end()) continue; guint32 const c0 = stop0->get_rgba32(); @@ -416,28 +410,23 @@ sp_gradient_simplify(GradientTool *rc, double tolerance) sqr(SP_RGBA32_A_F(c1) - SP_RGBA32_A_F(c1r)); if (diff < tolerance) - todel = g_slist_prepend (todel, stop1); + todel.insert(stop1); } } } - for (i = todel; i != NULL; i = i->next) { - SPStop *stop = (SPStop*) i->data; + for (auto stop : todel) { doc = stop->document; Inkscape::XML::Node * parent = stop->getRepr()->parent(); parent->removeChild( stop->getRepr() ); } - if (g_slist_length(todel) > 0) { + if (!todel.empty()) { DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT, _("Simplify gradient")); drag->local_change = true; drag->updateDraggers(); drag->selectByCoords(coords); } - - g_slist_free (todel); - g_slist_free (these_stops); - g_slist_free (next_stops); } @@ -676,7 +665,7 @@ bool GradientTool::root_handler(GdkEvent* event) { break; case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: @@ -730,7 +719,7 @@ bool GradientTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_4: if (!MOD__CTRL(event)) { // not ctrl gint mul = 1 + gobble_key_events( - get_group0_keyval(&event->key), 0); // with any mask + get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { drag->selected_move_screen(mul*-10, 0); // shift @@ -753,7 +742,7 @@ bool GradientTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_8: if (!MOD__CTRL(event)) { // not ctrl gint mul = 1 + gobble_key_events( - get_group0_keyval(&event->key), 0); // with any mask + get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { drag->selected_move_screen(0, mul*10); // shift @@ -777,7 +766,7 @@ bool GradientTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_6: if (!MOD__CTRL(event)) { // not ctrl gint mul = 1 + gobble_key_events( - get_group0_keyval(&event->key), 0); // with any mask + get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -802,7 +791,7 @@ bool GradientTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_2: if (!MOD__CTRL(event)) { // not ctrl gint mul = 1 + gobble_key_events( - get_group0_keyval(&event->key), 0); // with any mask + get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -859,7 +848,7 @@ bool GradientTool::root_handler(GdkEvent* event) { break; case GDK_KEY_RELEASE: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: diff --git a/src/ui/tools/lpe-tool.cpp b/src/ui/tools/lpe-tool.cpp index 35e6d14a0..ad3964f4a 100644 --- a/src/ui/tools/lpe-tool.cpp +++ b/src/ui/tools/lpe-tool.cpp @@ -225,14 +225,14 @@ bool LpeTool::root_handler(GdkEvent* event) { case GDK_KEY_PRESS: /** - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { } break; **/ case GDK_KEY_RELEASE: /** - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_Control_L: case GDK_Control_R: dc->_message_context->clear(); diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 0da883891..24295e7cf 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -1005,7 +1005,7 @@ void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsi text_item_box->transform *= Geom::Translate(pos); text_item_box->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); text_item_box->updateRepr(); - text_item_box->doWriteTransform(text_item_box->getRepr(), text_item_box->transform, NULL, true); + text_item_box->doWriteTransform(text_item_box->transform, NULL, true); Inkscape::XML::Node *rlabel = text_item_box->getRepr(); text_item_box->deleteObject(); measure_repr->addChild(rlabel, NULL); @@ -1014,7 +1014,7 @@ void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsi text_item->transform *= Geom::Rotate(angle); text_item->transform *= Geom::Translate(pos); text_item->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true); + text_item->doWriteTransform(text_item->transform, NULL, true); } } diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index d79741270..fdfae84df 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -170,68 +170,6 @@ void MeshTool::selection_changed(Inkscape::Selection* /*sel*/) { // FIXME // We need to update mesh gradient handles. // Get gradient this drag belongs too.. - // std::cout << "mesh_selection_changed: selection: objects: " << n_obj << std::endl; - // GSList *itemList = (GSList *) selection->itemList(); - // while( itemList ) { - - // SPItem *item = SP_ITEM( itemList->data ); - // // std::cout << " item: " << SP_OBJECT(item)->getId() << std::endl; - - // SPStyle *style = item->style; - // if (style && (style->fill.isPaintserver())) { - - // SPPaintServer *server = item->style->getFillPaintServer(); - // if ( SP_IS_MESHGRADIENT(server) ) { - - // SPMeshGradient *mg = SP_MESHGRADIENT(server); - - // guint rows = 0;//mg->array.patches.size(); - // for ( guint i = 0; i < rows; ++i ) { - // guint columns = 0;//mg->array.patches[0].size(); - // for ( guint j = 0; j < columns; ++j ) { - // } - // } - // } - // } - // itemList = itemList->next; - // } - - // GList* dragger_ptr = drag->draggers; // Points to GrDragger class (group of GrDraggable) - // guint count = 0; - // while( dragger_ptr ) { - - // std::cout << "mesh_selection_changed: dragger: " << ++count << std::endl; - // GSList* draggable_ptr = ((GrDragger *) dragger_ptr->data)->draggables; - - // while( draggable_ptr ) { - - // std::cout << "mesh_selection_changed: draggable: " << draggable_ptr << std::endl; - // GrDraggable *draggable = (GrDraggable *) draggable_ptr->data; - - // gint point_type = draggable->point_type; - // gint point_i = draggable->point_i; - // bool fill_or_stroke = draggable->fill_or_stroke; - - // if( point_type == POINT_MG_CORNER ) { - - // //std::cout << "mesh_selection_changed: POINT_MG_CORNER: " << point_i << std::endl; - // // Now we must create or destroy corresponding handles. - - // if( g_list_find( drag->selected, dragger_ptr->data ) ) { - // //std::cout << "gradient_selection_changed: Selected: " << point_i << std::endl; - // // Which meshes does this point belong to? - - // } else { - // //std::cout << "mesh_selection_changed: Not Selected: " << point_i << std::endl; - // } - // } - - // draggable_ptr = draggable_ptr->next; - - // } - - // dragger_ptr = dragger_ptr->next; - // } } void MeshTool::setup() { @@ -887,7 +825,7 @@ bool MeshTool::root_handler(GdkEvent* event) { #endif // FIXME: tip - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: @@ -926,7 +864,7 @@ bool MeshTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_Left: case GDK_KEY_KP_4: if (!MOD__CTRL(event)) { // not ctrl - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -950,7 +888,7 @@ bool MeshTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_Up: case GDK_KEY_KP_8: if (!MOD__CTRL(event)) { // not ctrl - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -974,7 +912,7 @@ bool MeshTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_Right: case GDK_KEY_KP_6: if (!MOD__CTRL(event)) { // not ctrl - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -998,7 +936,7 @@ bool MeshTool::root_handler(GdkEvent* event) { case GDK_KEY_KP_Down: case GDK_KEY_KP_2: if (!MOD__CTRL(event)) { // not ctrl - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -1096,7 +1034,7 @@ bool MeshTool::root_handler(GdkEvent* event) { #ifdef DEBUG_MESH std::cout << "sp_mesh_context_root_handler: GDK_KEY_RELEASE" << std::endl; #endif - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index d508a16f2..2b3de5203 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -358,6 +358,7 @@ void NodeTool::set(const Inkscape::Preferences::Entry& value) { } /** Recursively collect ShapeRecords */ +static void gather_items(NodeTool *nt, SPItem *base, SPObject *obj, Inkscape::UI::ShapeRole role, std::set<Inkscape::UI::ShapeRecord> &s) { @@ -437,7 +438,7 @@ void NodeTool::selection_changed(Inkscape::Selection *sel) { if ((SP_IS_SHAPE(r.item) || SP_IS_TEXT(r.item) || SP_IS_GROUP(r.item) || SP_IS_OBJECTGROUP(r.item)) && this->_shape_editors.find(r.item) == this->_shape_editors.end()) { - ShapeEditor *si = new ShapeEditor(this->desktop); + ShapeEditor *si = new ShapeEditor(this->desktop, r.edit_transform); si->set_item(r.item); this->_shape_editors.insert(const_cast<SPItem*&>(r.item), si); } @@ -549,7 +550,7 @@ bool NodeTool::root_handler(GdkEvent* event) { // otherwise some features cease to work case GDK_KEY_PRESS: - switch (get_group0_keyval(&event->key)) + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Escape: // deselect everything if (this->_selected_nodes->empty()) { diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp index dcdbe1220..16cdf63b5 100644 --- a/src/ui/tools/pen-tool.cpp +++ b/src/ui/tools/pen-tool.cpp @@ -861,18 +861,18 @@ bool PenTool::_handle2ButtonPress(GdkEventButton const &bevent) { void PenTool::_redrawAll() { // green - if (this->green_bpaths) { + if (! this->green_bpaths.empty()) { // remove old piecewise green canvasitems - while (this->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data)); - this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data); + for (auto i : this->green_bpaths){ + sp_canvas_item_destroy(i); } + this->green_bpaths.clear(); // one canvas bpath for all of green_curve SPCanvasItem *canvas_shape = sp_canvas_bpath_new(this->desktop->getSketch(), this->green_curve, true); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvas_shape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(canvas_shape), 0, SP_WIND_RULE_NONZERO); - this->green_bpaths = g_slist_prepend(this->green_bpaths, canvas_shape); + this->green_bpaths.push_back(canvas_shape); } if (this->green_anchor) { SP_CTRL(this->green_anchor->ctrl)->moveto(this->green_anchor->dp); @@ -1063,7 +1063,7 @@ bool PenTool::_handleKeyPress(GdkEvent *event) { } } - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Left: // move last point left case GDK_KEY_KP_Left: if (!MOD__CTRL(event)) { // not ctrl @@ -1254,10 +1254,10 @@ void PenTool::_resetColors() { this->blue_curve->reset(); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->blue_bpath), NULL, true); // Green - while (this->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data)); - this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data); + for (auto i:this->green_bpaths) { + sp_canvas_item_destroy(i); } + this->green_bpaths.clear(); this->green_curve->reset(); if (this->green_anchor) { this->green_anchor = sp_draw_anchor_destroy(this->green_anchor); @@ -1292,7 +1292,7 @@ void PenTool::_setAngleDistanceStatusMessage(Geom::Point const p, int pc_point_t Geom::Point rel = p - this->p[pc_point_to_compare]; Inkscape::Util::Quantity q = Inkscape::Util::Quantity(Geom::L2(rel), "px"); - GString *dist = g_string_new(q.string(desktop->namedview->display_units).c_str()); + Glib::ustring dist = q.string(desktop->namedview->display_units); double angle = atan2(rel[Geom::Y], rel[Geom::X]) * 180 / M_PI; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/options/compassangledisplay/value", 0) != 0) { @@ -1302,8 +1302,7 @@ void PenTool::_setAngleDistanceStatusMessage(Geom::Point const p, int pc_point_t } } - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, message, angle, dist->str); - g_string_free(dist, false); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, message, angle, dist.c_str()); } // this function changes the colors red, green and blue making them transparent or not, depending on if spiro is being used. @@ -1334,17 +1333,17 @@ void PenTool::_bsplineSpiroColor() } //We erase all the "green_bpaths" to recreate them after with the colour //transparency recently modified - if (this->green_bpaths) { + if (!this->green_bpaths.empty()) { // remove old piecewise green canvasitems - while (this->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data)); - this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data); + for (auto i:this->green_bpaths) { + sp_canvas_item_destroy(i); } + this->green_bpaths.clear(); // one canvas bpath for all of green_curve SPCanvasItem *canvas_shape = sp_canvas_bpath_new(this->desktop->getSketch(), this->green_curve, true); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvas_shape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(canvas_shape), 0, SP_WIND_RULE_NONZERO); - this->green_bpaths = g_slist_prepend(this->green_bpaths, canvas_shape); + this->green_bpaths.push_back(canvas_shape); } sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(this->red_bpath), this->red_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); } @@ -1557,18 +1556,18 @@ void PenTool::_bsplineSpiroMotion(guint const state){ this->overwrite_curve = tmp_curve->copy(); } } - if (this->green_bpaths) { + if (!this->green_bpaths.empty()) { this->green_curve = tmp_curve->copy(); // remove old piecewise green canvasitems - while (this->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data)); - this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data); + for (auto i: this->green_bpaths) { + sp_canvas_item_destroy(i); } + this->green_bpaths.clear(); // one canvas bpath for all of green_curve SPCanvasItem *canvas_shape = sp_canvas_bpath_new(this->desktop->getSketch(), this->green_curve, true); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvas_shape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_bpath_set_fill(SP_CANVAS_BPATH(canvas_shape), 0, SP_WIND_RULE_NONZERO); - this->green_bpaths = g_slist_prepend(this->green_bpaths, canvas_shape); + this->green_bpaths.push_back(canvas_shape); } } if (cubic) { @@ -1929,7 +1928,7 @@ void PenTool::_finishSegment(Geom::Point const p, guint const state) { curve->unref(); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(canvas_shape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); - this->green_bpaths = g_slist_prepend(this->green_bpaths, canvas_shape); + this->green_bpaths.push_back(canvas_shape); this->p[0] = this->p[3]; this->p[1] = this->p[4]; @@ -1955,11 +1954,9 @@ bool PenTool::_undoLastPoint() { // Reset red curve this->red_curve->reset(); // Destroy topmost green bpath - if (this->green_bpaths) { - if (this->green_bpaths->data) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data)); - } - this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data); + if (!this->green_bpaths.empty()) { + sp_canvas_item_destroy(this->green_bpaths.back()); + this->green_bpaths.pop_back(); } // Get last segment if ( this->green_curve->is_unset() ) { @@ -1987,11 +1984,9 @@ bool PenTool::_undoLastPoint() { // delete the last segment of the green curve if (this->green_curve->get_segment_count() == 1) { this->npoints = 5; - if (this->green_bpaths) { - if (this->green_bpaths->data) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data)); - } - this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data); + if (!this->green_bpaths.empty()) { + sp_canvas_item_destroy(this->green_bpaths.back()); + this->green_bpaths.pop_back(); } this->green_curve->reset(); } else { diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp index 3705d0f43..6f64e8e26 100644 --- a/src/ui/tools/pencil-tool.cpp +++ b/src/ui/tools/pencil-tool.cpp @@ -475,10 +475,10 @@ void PencilTool::_cancel() { this->red_curve->reset(); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->red_bpath), NULL); - while (this->green_bpaths) { - sp_canvas_item_destroy(SP_CANVAS_ITEM(this->green_bpaths->data)); - this->green_bpaths = g_slist_remove(this->green_bpaths, this->green_bpaths->data); + for (auto i:this->green_bpaths) { + sp_canvas_item_destroy(i); } + this->green_bpaths.clear(); this->green_curve->reset(); if (this->green_anchor) { this->green_anchor = sp_draw_anchor_destroy(this->green_anchor); @@ -493,7 +493,7 @@ void PencilTool::_cancel() { bool PencilTool::_handleKeyPress(GdkEventKey const &event) { bool ret = false; - switch (get_group0_keyval(&event)) { + switch (get_latin_keyval(&event)) { case GDK_KEY_Up: case GDK_KEY_Down: case GDK_KEY_KP_Up: @@ -546,7 +546,7 @@ bool PencilTool::_handleKeyPress(GdkEventKey const &event) { bool PencilTool::_handleKeyRelease(GdkEventKey const &event) { bool ret = false; - switch (get_group0_keyval(&event)) { + switch (get_latin_keyval(&event)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Meta_L: @@ -1067,7 +1067,7 @@ void PencilTool::_fitAndSplit() { } sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cshape), this->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); - this->green_bpaths = g_slist_prepend(this->green_bpaths, cshape); + this->green_bpaths.push_back(cshape); this->red_curve_is_valid = false; } diff --git a/src/ui/tools/rect-tool.cpp b/src/ui/tools/rect-tool.cpp index 9ebf51e76..655650ef4 100644 --- a/src/ui/tools/rect-tool.cpp +++ b/src/ui/tools/rect-tool.cpp @@ -258,7 +258,7 @@ bool RectTool::root_handler(GdkEvent* event) { } break; case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: @@ -326,7 +326,7 @@ bool RectTool::root_handler(GdkEvent* event) { } break; case GDK_KEY_RELEASE: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: @@ -397,8 +397,8 @@ void RectTool::drag(Geom::Point const pt, guint state) { Inkscape::Util::Quantity rdimx_q = Inkscape::Util::Quantity(rdimx, "px"); Inkscape::Util::Quantity rdimy_q = Inkscape::Util::Quantity(rdimy, "px"); - GString *xs = g_string_new(rdimx_q.string(desktop->namedview->display_units).c_str()); - GString *ys = g_string_new(rdimy_q.string(desktop->namedview->display_units).c_str()); + Glib::ustring xs = rdimx_q.string(desktop->namedview->display_units); + Glib::ustring ys = rdimy_q.string(desktop->namedview->display_units); if (state & GDK_CONTROL_MASK) { int ratio_x, ratio_y; @@ -421,20 +421,25 @@ void RectTool::drag(Geom::Point const pt, guint state) { } if (!is_golden_ratio) { - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Rectangle</b>: %s × %s (constrained to ratio %d:%d); with <b>Shift</b> to draw around the starting point"), xs->str, ys->str, ratio_x, ratio_y); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, + _("<b>Rectangle</b>: %s × %s (constrained to ratio %d:%d); with <b>Shift</b> to draw around the starting point"), + xs.c_str(), ys.c_str(), ratio_x, ratio_y); } else { if (ratio_y == 1) { - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Rectangle</b>: %s × %s (constrained to golden ratio 1.618 : 1); with <b>Shift</b> to draw around the starting point"), xs->str, ys->str); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, + _("<b>Rectangle</b>: %s × %s (constrained to golden ratio 1.618 : 1); with <b>Shift</b> to draw around the starting point"), + xs.c_str(), ys.c_str()); } else { - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Rectangle</b>: %s × %s (constrained to golden ratio 1 : 1.618); with <b>Shift</b> to draw around the starting point"), xs->str, ys->str); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, + _("<b>Rectangle</b>: %s × %s (constrained to golden ratio 1 : 1.618); with <b>Shift</b> to draw around the starting point"), + xs.c_str(), ys.c_str()); } } } else { - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Rectangle</b>: %s × %s; with <b>Ctrl</b> to make square or integer-ratio rectangle; with <b>Shift</b> to draw around the starting point"), xs->str, ys->str); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, + _("<b>Rectangle</b>: %s × %s; with <b>Ctrl</b> to make square or integer-ratio rectangle; with <b>Shift</b> to draw around the starting point"), + xs.c_str(), ys.c_str()); } - - g_string_free(xs, FALSE); - g_string_free(ys, FALSE); } void RectTool::finishItem() { @@ -447,7 +452,7 @@ void RectTool::finishItem() { } this->rect->updateRepr(); - this->rect->doWriteTransform(this->rect->getRepr(), this->rect->transform, NULL, true); + this->rect->doWriteTransform(this->rect->transform, NULL, true); this->desktop->canvas->endForcedFullRedraws(); diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index fca2173ca..3dfb764bb 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -344,18 +344,18 @@ bool SelectTool::item_handler(SPItem* item, GdkEvent* event) { break; case GDK_KEY_PRESS: - if (get_group0_keyval (&event->key) == GDK_KEY_space) { + if (get_latin_keyval (&event->key) == GDK_KEY_space) { if (this->dragging && this->grabbed) { /* stamping mode: show content mode moving */ _seltrans->stamp(); ret = TRUE; } - } else if (get_group0_keyval (&event->key) == GDK_KEY_Tab) { + } else if (get_latin_keyval (&event->key) == GDK_KEY_Tab) { if (this->dragging && this->grabbed) { _seltrans->getNextClosestPoint(false); ret = TRUE; } - } else if (get_group0_keyval (&event->key) == GDK_KEY_ISO_Left_Tab) { + } else if (get_latin_keyval (&event->key) == GDK_KEY_ISO_Left_Tab) { if (this->dragging && this->grabbed) { _seltrans->getNextClosestPoint(true); ret = TRUE; @@ -854,7 +854,7 @@ bool SelectTool::root_handler(GdkEvent* event) { case GDK_KEY_PRESS: // keybindings for select context { { - guint keyval = get_group0_keyval(&event->key); + guint keyval = get_latin_keyval(&event->key); bool alt = ( MOD__ALT(event) || (keyval == GDK_KEY_Alt_L) @@ -896,11 +896,11 @@ bool SelectTool::root_handler(GdkEvent* event) { gdouble const offset = prefs->getDoubleLimited("/options/defaultscale/value", 2, 0, 1000, "px"); int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12); - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Left: // move selection left case GDK_KEY_KP_Left: if (!MOD__CTRL(event)) { // not ctrl - gint mul = 1 + gobble_key_events( get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events( get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -923,7 +923,7 @@ bool SelectTool::root_handler(GdkEvent* event) { case GDK_KEY_Up: // move selection up case GDK_KEY_KP_Up: if (!MOD__CTRL(event)) { // not ctrl - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -946,7 +946,7 @@ bool SelectTool::root_handler(GdkEvent* event) { case GDK_KEY_Right: // move selection right case GDK_KEY_KP_Right: if (!MOD__CTRL(event)) { // not ctrl - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -969,7 +969,7 @@ bool SelectTool::root_handler(GdkEvent* event) { case GDK_KEY_Down: // move selection down case GDK_KEY_KP_Down: if (!MOD__CTRL(event)) { // not ctrl - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask if (MOD__ALT(event)) { // alt if (MOD__SHIFT(event)) { @@ -1024,7 +1024,7 @@ bool SelectTool::root_handler(GdkEvent* event) { case GDK_KEY_bracketleft: if (MOD__ALT(event)) { - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask selection->rotateScreen(mul*1); } else if (MOD__CTRL(event)) { selection->rotate(90); @@ -1037,7 +1037,7 @@ bool SelectTool::root_handler(GdkEvent* event) { case GDK_KEY_bracketright: if (MOD__ALT(event)) { - gint mul = 1 + gobble_key_events(get_group0_keyval(&event->key), 0); // with any mask + gint mul = 1 + gobble_key_events(get_latin_keyval(&event->key), 0); // with any mask selection->rotateScreen(-1*mul); } else if (MOD__CTRL(event)) { selection->rotate(-90); @@ -1097,7 +1097,7 @@ bool SelectTool::root_handler(GdkEvent* event) { break; } case GDK_KEY_RELEASE: { - guint keyval = get_group0_keyval(&event->key); + guint keyval = get_latin_keyval(&event->key); if (key_is_a_modifier (keyval)) { this->defaultMessageContext()->clear(); } diff --git a/src/ui/tools/spiral-tool.cpp b/src/ui/tools/spiral-tool.cpp index b681aec38..bb8ce6356 100644 --- a/src/ui/tools/spiral-tool.cpp +++ b/src/ui/tools/spiral-tool.cpp @@ -232,7 +232,7 @@ bool SpiralTool::root_handler(GdkEvent* event) { break; case GDK_KEY_PRESS: - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Alt_R: case GDK_KEY_Control_L: case GDK_KEY_Control_R: @@ -291,7 +291,7 @@ bool SpiralTool::root_handler(GdkEvent* event) { break; case GDK_KEY_RELEASE: - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: @@ -372,11 +372,10 @@ void SpiralTool::drag(Geom::Point const &p, guint state) { /* status text */ Inkscape::Util::Quantity q = Inkscape::Util::Quantity(rad, "px"); - GString *rads = g_string_new(q.string(desktop->namedview->display_units).c_str()); + Glib::ustring rads = q.string(desktop->namedview->display_units); this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Spiral</b>: radius %s, angle %5g°; with <b>Ctrl</b> to snap angle"), - rads->str, sp_round((arg + 2.0*M_PI*this->spiral->revo)*180/M_PI, 0.0001)); - g_string_free(rads, FALSE); + rads.c_str(), sp_round((arg + 2.0*M_PI*this->spiral->revo)*180/M_PI, 0.0001)); } void SpiralTool::finishItem() { @@ -390,7 +389,7 @@ void SpiralTool::finishItem() { spiral->set_shape(); spiral->updateRepr(SP_OBJECT_WRITE_EXT); - spiral->doWriteTransform(spiral->getRepr(), spiral->transform, NULL, true); + spiral->doWriteTransform(spiral->transform, NULL, true); this->desktop->canvas->endForcedFullRedraws(); diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp index f3e7e6d3c..5593ceb34 100644 --- a/src/ui/tools/spray-tool.cpp +++ b/src/ui/tools/spray-tool.cpp @@ -120,7 +120,7 @@ static void sp_spray_rotate_rel(Geom::Point c, SPDesktop */*desktop*/, SPItem *i // Rotate item. item->set_i2d_affine(item->i2dt_affine() * affine); // Use each item's own transform writer, consistent with sp_selection_apply_affine() - item->doWriteTransform(item->getRepr(), item->transform); + item->doWriteTransform(item->transform); // Restore the center position (it's changed because the bbox center changed) if (item->isCenterSet()) { item->setCenter(c); @@ -133,7 +133,7 @@ static void sp_spray_scale_rel(Geom::Point c, SPDesktop */*desktop*/, SPItem *it { Geom::Translate const s(c); item->set_i2d_affine(item->i2dt_affine() * s.inverse() * scale * s); - item->doWriteTransform(item->getRepr(), item->transform); + item->doWriteTransform(item->transform); } SprayTool::SprayTool() @@ -1375,7 +1375,7 @@ bool SprayTool::root_handler(GdkEvent* event) { } case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_j: case GDK_KEY_J: if (MOD__SHIFT_ONLY(event)) { @@ -1487,7 +1487,7 @@ bool SprayTool::root_handler(GdkEvent* event) { case GDK_KEY_RELEASE: { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: this->update_cursor(false); diff --git a/src/ui/tools/star-tool.cpp b/src/ui/tools/star-tool.cpp index 32f0e6d92..ed25503c4 100644 --- a/src/ui/tools/star-tool.cpp +++ b/src/ui/tools/star-tool.cpp @@ -246,7 +246,7 @@ bool StarTool::root_handler(GdkEvent* event) { break; case GDK_KEY_PRESS: - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Alt_R: case GDK_KEY_Control_L: case GDK_KEY_Control_R: @@ -306,7 +306,7 @@ bool StarTool::root_handler(GdkEvent* event) { break; case GDK_KEY_RELEASE: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Alt_L: case GDK_KEY_Alt_R: case GDK_KEY_Control_L: @@ -389,14 +389,12 @@ void StarTool::drag(Geom::Point p, guint state) /* status text */ Inkscape::Util::Quantity q = Inkscape::Util::Quantity(r1, "px"); - GString *rads = g_string_new(q.string(desktop->namedview->display_units).c_str()); + Glib::ustring rads = q.string(desktop->namedview->display_units); this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, ( this->isflatsided? _("<b>Polygon</b>: radius %s, angle %5g°; with <b>Ctrl</b> to snap angle") : _("<b>Star</b>: radius %s, angle %5g°; with <b>Ctrl</b> to snap angle") ), - rads->str, sp_round((arg1) * 180 / M_PI, 0.0001)); - - g_string_free(rads, FALSE); + rads.c_str(), sp_round((arg1) * 180 / M_PI, 0.0001)); } void StarTool::finishItem() { @@ -415,7 +413,7 @@ void StarTool::finishItem() { this->star->setCenter(this->center); this->star->set_shape(); this->star->updateRepr(SP_OBJECT_WRITE_EXT); - this->star->doWriteTransform(this->star->getRepr(), this->star->transform, NULL, true); + this->star->doWriteTransform(this->star->transform, NULL, true); desktop->canvas->endForcedFullRedraws(); diff --git a/src/ui/tools/text-tool.cpp b/src/ui/tools/text-tool.cpp index 9091b455e..692b65c44 100644 --- a/src/ui/tools/text-tool.cpp +++ b/src/ui/tools/text-tool.cpp @@ -417,7 +417,7 @@ static void sp_text_context_setup_text(TextTool *tc) text_item->transform = SP_ITEM(ec->desktop->currentLayer())->i2doc_affine().inverse(); text_item->updateRepr(); - text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true); + text_item->doWriteTransform(text_item->transform, NULL, true); DocumentUndo::done(ec->desktop->getDocument(), SP_VERB_CONTEXT_TEXT, _("Create text")); } @@ -575,13 +575,9 @@ bool TextTool::root_handler(GdkEvent* event) { // status text Inkscape::Util::Quantity x_q = Inkscape::Util::Quantity(fabs((p - this->p0)[Geom::X]), "px"); Inkscape::Util::Quantity y_q = Inkscape::Util::Quantity(fabs((p - this->p0)[Geom::Y]), "px"); - GString *xs = g_string_new(x_q.string(desktop->namedview->display_units).c_str()); - GString *ys = g_string_new(y_q.string(desktop->namedview->display_units).c_str()); - this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Flowed text frame</b>: %s × %s"), xs->str, ys->str); - - g_string_free(xs, FALSE); - g_string_free(ys, FALSE); - + Glib::ustring xs = x_q.string(desktop->namedview->display_units); + Glib::ustring ys = y_q.string(desktop->namedview->display_units); + this->message_context->setF(Inkscape::IMMEDIATE_MESSAGE, _("<b>Flowed text frame</b>: %s × %s"), xs.c_str(), ys.c_str()); } else if (!this->sp_event_context_knot_mouseover()) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); @@ -657,7 +653,7 @@ bool TextTool::root_handler(GdkEvent* event) { } break; case GDK_KEY_PRESS: { - guint const group0_keyval = get_group0_keyval(&event->key); + guint const group0_keyval = get_latin_keyval(&event->key); if (group0_keyval == GDK_KEY_KP_Add || group0_keyval == GDK_KEY_KP_Subtract) { @@ -965,7 +961,7 @@ bool TextTool::root_handler(GdkEvent* event) { if (this->text) { if (MOD__ALT(event)) { gint mul = 1 + gobble_key_events( - get_group0_keyval(&event->key), 0); // with any mask + get_latin_keyval(&event->key), 0); // with any mask if (MOD__SHIFT(event)) sp_te_adjust_kerning_screen(this->text, this->text_sel_start, this->text_sel_end, desktop, Geom::Point(mul*-10, 0)); else @@ -989,7 +985,7 @@ bool TextTool::root_handler(GdkEvent* event) { if (this->text) { if (MOD__ALT(event)) { gint mul = 1 + gobble_key_events( - get_group0_keyval(&event->key), 0); // with any mask + get_latin_keyval(&event->key), 0); // with any mask if (MOD__SHIFT(event)) sp_te_adjust_kerning_screen(this->text, this->text_sel_start, this->text_sel_end, desktop, Geom::Point(mul*10, 0)); else @@ -1013,7 +1009,7 @@ bool TextTool::root_handler(GdkEvent* event) { if (this->text) { if (MOD__ALT(event)) { gint mul = 1 + gobble_key_events( - get_group0_keyval(&event->key), 0); // with any mask + get_latin_keyval(&event->key), 0); // with any mask if (MOD__SHIFT(event)) sp_te_adjust_kerning_screen(this->text, this->text_sel_start, this->text_sel_end, desktop, Geom::Point(0, mul*-10)); else @@ -1037,7 +1033,7 @@ bool TextTool::root_handler(GdkEvent* event) { if (this->text) { if (MOD__ALT(event)) { gint mul = 1 + gobble_key_events( - get_group0_keyval(&event->key), 0); // with any mask + get_latin_keyval(&event->key), 0); // with any mask if (MOD__SHIFT(event)) sp_te_adjust_kerning_screen(this->text, this->text_sel_start, this->text_sel_end, desktop, Geom::Point(0, mul*10)); else diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp index 12c3a3675..7b4f67da9 100644 --- a/src/ui/tools/tool-base.cpp +++ b/src/ui/tools/tool-base.cpp @@ -71,6 +71,10 @@ static guint32 scroll_event_time = 0; static gdouble scroll_multiply = 1; static guint scroll_keyval = 0; +// globals for key processing +static bool latin_keys_group_valid = FALSE; +static gint latin_keys_group; + namespace Inkscape { namespace UI { @@ -598,7 +602,7 @@ bool ToolBase::root_handler(GdkEvent* event) { int const key_scroll = prefs->getIntLimited("/options/keyscroll/value", 10, 0, 1000); - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { // GDK insists on stealing these keys (F1 for no idea what, tab for cycling widgets // in the editing window). So we resteal them back and run our regular shortcut // invoker on them. @@ -638,7 +642,7 @@ bool ToolBase::root_handler(GdkEvent* event) { int i = (int) floor(key_scroll * accelerate_scroll(event, acceleration, desktop->getCanvas())); - gobble_key_events(get_group0_keyval(&event->key), GDK_CONTROL_MASK); + gobble_key_events(get_latin_keyval(&event->key), GDK_CONTROL_MASK); this->desktop->scroll_relative(Geom::Point(i, 0)); ret = TRUE; } else { @@ -653,7 +657,7 @@ bool ToolBase::root_handler(GdkEvent* event) { int i = (int) floor(key_scroll * accelerate_scroll(event, acceleration, desktop->getCanvas())); - gobble_key_events(get_group0_keyval(&event->key), GDK_CONTROL_MASK); + gobble_key_events(get_latin_keyval(&event->key), GDK_CONTROL_MASK); this->desktop->scroll_relative(Geom::Point(0, i)); ret = TRUE; } else { @@ -668,7 +672,7 @@ bool ToolBase::root_handler(GdkEvent* event) { int i = (int) floor(key_scroll * accelerate_scroll(event, acceleration, desktop->getCanvas())); - gobble_key_events(get_group0_keyval(&event->key), GDK_CONTROL_MASK); + gobble_key_events(get_latin_keyval(&event->key), GDK_CONTROL_MASK); this->desktop->scroll_relative(Geom::Point(-i, 0)); ret = TRUE; } else { @@ -683,7 +687,7 @@ bool ToolBase::root_handler(GdkEvent* event) { int i = (int) floor(key_scroll * accelerate_scroll(event, acceleration, desktop->getCanvas())); - gobble_key_events(get_group0_keyval(&event->key), GDK_CONTROL_MASK); + gobble_key_events(get_latin_keyval(&event->key), GDK_CONTROL_MASK); this->desktop->scroll_relative(Geom::Point(0, -i)); ret = TRUE; } else { @@ -752,7 +756,7 @@ bool ToolBase::root_handler(GdkEvent* event) { gdk_window_set_cursor(gtk_widget_get_window (w), this->cursor); } - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_space: if (within_tolerance) { // Space was pressed, but not panned @@ -1138,7 +1142,7 @@ void sp_event_root_menu_popup(SPDesktop *desktop, SPItem *item, GdkEvent *event) void sp_event_show_modifier_tip(Inkscape::MessageContext *message_context, GdkEvent *event, gchar const *ctrl_tip, gchar const *shift_tip, gchar const *alt_tip) { - guint keyval = get_group0_keyval(&event->key); + guint keyval = get_latin_keyval(&event->key); bool ctrl = ctrl_tip && (MOD__CTRL(event) || (keyval == GDK_KEY_Control_L) || (keyval == GDK_KEY_Control_R)); @@ -1159,19 +1163,48 @@ void sp_event_show_modifier_tip(Inkscape::MessageContext *message_context, } /** - * Return the keyval corresponding to the key event in group 0, i.e., - * in the main (English) layout. + * Try to determine the keys group of Latin layout. + * Check available keymap entries for Latin 'a' key and find the minimal integer value. + */ +static void update_latin_keys_group() { + GdkKeymapKey* keys; + gint n_keys; + + latin_keys_group_valid = FALSE; + if (gdk_keymap_get_entries_for_keyval(gdk_keymap_get_default(), GDK_KEY_a, &keys, &n_keys)) { + for (gint i = 0; i < n_keys; i++) { + if (!latin_keys_group_valid || keys[i].group < latin_keys_group) { + latin_keys_group = keys[i].group; + latin_keys_group_valid = TRUE; + } + } + g_free(keys); + } +} + +/** + * Initialize Latin keys group handling. + */ +void init_latin_keys_group() { + g_signal_connect(G_OBJECT(gdk_keymap_get_default()), + "keys-changed", G_CALLBACK(update_latin_keys_group), NULL); + update_latin_keys_group(); +} + +/** + * Return the keyval corresponding to the key event in Latin group. * * Use this instead of simply event->keyval, so that your keyboard shortcuts * work regardless of layouts (e.g., in Cyrillic). */ -guint get_group0_keyval(GdkEventKey const *event, guint *consumed_modifiers /*= NULL*/) { +guint get_latin_keyval(GdkEventKey const *event, guint *consumed_modifiers /*= NULL*/) { guint keyval = 0; GdkModifierType modifiers; + gint group = latin_keys_group_valid ? latin_keys_group : event->group; gdk_keymap_translate_keyboard_state( gdk_keymap_get_for_display(gdk_display_get_default()), - event->hardware_keycode, (GdkModifierType) event->state, 0 /*event->group*/, + event->hardware_keycode, (GdkModifierType) event->state, group, &keyval, NULL, NULL, &modifiers); if (consumed_modifiers) { diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h index 09a9db660..7185b787e 100644 --- a/src/ui/tools/tool-base.h +++ b/src/ui/tools/tool-base.h @@ -251,7 +251,8 @@ gint gobble_motion_events(gint mask); void sp_event_show_modifier_tip(Inkscape::MessageContext *message_context, GdkEvent *event, gchar const *ctrl_tip, gchar const *shift_tip, gchar const *alt_tip); -guint get_group0_keyval(GdkEventKey const *event, guint *consumed_modifiers = NULL); +void init_latin_keys_group(); +guint get_latin_keyval(GdkEventKey const *event, guint *consumed_modifiers = NULL); SPItem *sp_event_context_find_item (SPDesktop *desktop, Geom::Point const &p, bool select_under, bool into_groups); SPItem *sp_event_context_over_item (SPDesktop *desktop, SPItem *item, Geom::Point const &p); diff --git a/src/ui/tools/tweak-tool.cpp b/src/ui/tools/tweak-tool.cpp index dcd9413fb..9348ef842 100644 --- a/src/ui/tools/tweak-tool.cpp +++ b/src/ui/tools/tweak-tool.cpp @@ -374,23 +374,20 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P } if (dynamic_cast<SPGroup *>(item) && !dynamic_cast<SPBox3D *>(item)) { - GSList *children = NULL; + std::vector<SPItem *> children; for (auto& child: item->children) { - if (dynamic_cast<SPItem *>(static_cast<SPObject *>(&child))) { - children = g_slist_prepend(children, &child); + if (dynamic_cast<SPItem *>(&child)) { + children.push_back(dynamic_cast<SPItem *>(&child)); } } - for (GSList *i = children; i; i = i->next) { - SPItem *child = dynamic_cast<SPItem *>(static_cast<SPObject *>(i->data)); + for (auto i = children.rbegin(); i!= children.rend(); ++i) { + SPItem *child = *i; g_assert(child != NULL); if (sp_tweak_dilate_recursive (selection, child, p, vector, mode, radius, force, fidelity, reverse)) { did = true; } } - - g_slist_free(children); - } else { if (mode == TWEAK_MODE_MOVE) { @@ -1287,7 +1284,7 @@ bool TweakTool::root_handler(GdkEvent* event) { } case GDK_KEY_PRESS: { - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_m: case GDK_KEY_M: case GDK_KEY_0: @@ -1482,7 +1479,7 @@ bool TweakTool::root_handler(GdkEvent* event) { } case GDK_KEY_RELEASE: { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - switch (get_group0_keyval(&event->key)) { + switch (get_latin_keyval(&event->key)) { case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: this->update_cursor(false); diff --git a/src/ui/tools/zoom-tool.cpp b/src/ui/tools/zoom-tool.cpp index 8ba0c17b3..6f7fca242 100644 --- a/src/ui/tools/zoom-tool.cpp +++ b/src/ui/tools/zoom-tool.cpp @@ -168,7 +168,7 @@ bool ZoomTool::root_handler(GdkEvent* event) { break; } case GDK_KEY_PRESS: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Escape: if (!Inkscape::Rubberband::get(desktop)->is_started()) { Inkscape::SelectionHelper::selectNone(desktop); @@ -206,7 +206,7 @@ bool ZoomTool::root_handler(GdkEvent* event) { } break; case GDK_KEY_RELEASE: - switch (get_group0_keyval (&event->key)) { + switch (get_latin_keyval (&event->key)) { case GDK_KEY_Shift_L: case GDK_KEY_Shift_R: this->cursor_shape = cursor_zoom_xpm; diff --git a/src/ui/view/makefile.in b/src/ui/view/makefile.in deleted file mode 100644 index 0fe15637a..000000000 --- a/src/ui/view/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd ../.. && $(MAKE) ui/view/all - -clean %.a %.$(OBJEXT): - cd ../.. && $(MAKE) ui/view/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/ui/widget/color-notebook.cpp b/src/ui/widget/color-notebook.cpp index a4df8187f..ba333d0ed 100644 --- a/src/ui/widget/color-notebook.cpp +++ b/src/ui/widget/color-notebook.cpp @@ -22,6 +22,7 @@ #include <glibmm/i18n.h> #include <gtkmm/label.h> #include <gtkmm/notebook.h> +#include <gtkmm/radiobutton.h> #include "preferences.h" #include "widgets/spw-utilities.h" @@ -325,8 +326,8 @@ void ColorNotebook::_addPage(Page &page) _buttons[page_num] = gtk_radio_button_new_with_label(NULL, mode_name.c_str()); gtk_toggle_button_set_mode(GTK_TOGGLE_BUTTON(_buttons[page_num]), FALSE); if (page_num > 0) { - GSList *group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(_buttons[0])); - gtk_radio_button_set_group(GTK_RADIO_BUTTON(_buttons[page_num]), group); + auto g = Glib::wrap(GTK_RADIO_BUTTON(_buttons[0]))->get_group(); + Glib::wrap(GTK_RADIO_BUTTON(_buttons[page_num]))->set_group(g); } gtk_widget_show(_buttons[page_num]); gtk_box_pack_start(GTK_BOX(_buttonbox), _buttons[page_num], TRUE, TRUE, 0); diff --git a/src/ui/widget/color-preview.cpp b/src/ui/widget/color-preview.cpp index c9b6e56d2..54b2991f0 100644 --- a/src/ui/widget/color-preview.cpp +++ b/src/ui/widget/color-preview.cpp @@ -11,6 +11,7 @@ #include "ui/widget/color-preview.h" #include "display/cairo-utils.h" +#include <cairo.h> #define SPCP_DEFAULT_WIDTH 32 #define SPCP_DEFAULT_HEIGHT 12 @@ -70,45 +71,45 @@ ColorPreview::setRgba32 (guint32 rgba) bool ColorPreview::on_draw(const Cairo::RefPtr<Cairo::Context>& cr) { - GdkRectangle warea, carea; - gint w2; - + double x, y, width, height; const Gtk::Allocation& allocation = get_allocation(); - warea.x = allocation.get_x(); - warea.y = allocation.get_y(); - warea.width = allocation.get_width(); - warea.height = allocation.get_height(); + x = 0; + y = 0; + width = allocation.get_width()/2.0; + height = allocation.get_height(); + + double radius = height / 7.5; + double degrees = M_PI / 180.0; + cairo_new_sub_path (cr->cobj()); + cairo_line_to(cr->cobj(), width, 0); + cairo_line_to(cr->cobj(), width, height); + cairo_arc (cr->cobj(), x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees); + cairo_arc (cr->cobj(), x + radius, y + radius, radius, 180 * degrees, 270 * degrees); + cairo_close_path (cr->cobj()); /* Transparent area */ - w2 = warea.width / 2; - - carea.x = warea.x; - carea.y = warea.y; - carea.width = w2; - carea.height = warea.height; - cairo_pattern_t *checkers = ink_cairo_pattern_create_checkerboard(); - cr->rectangle(carea.x, carea.y, carea.width, carea.height); cairo_set_source(cr->cobj(), checkers); cr->fill_preserve(); ink_cairo_set_source_rgba32(cr->cobj(), _rgba); cr->fill(); - cairo_pattern_destroy(checkers); /* Solid area */ - carea.x = warea.x + w2; - carea.y = warea.y; - carea.width = warea.width - w2; - carea.height = warea.height; + x = width; - cr->rectangle(carea.x, carea.y, carea.width, carea.height); + cairo_new_sub_path (cr->cobj()); + cairo_arc (cr->cobj(), x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees); + cairo_arc (cr->cobj(), x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees); + cairo_line_to(cr->cobj(), x, height); + cairo_line_to(cr->cobj(), x, y); + cairo_close_path (cr->cobj()); ink_cairo_set_source_rgba32(cr->cobj(), _rgba | 0xff); cr->fill(); - + return true; } diff --git a/src/ui/widget/makefile.in b/src/ui/widget/makefile.in deleted file mode 100644 index e479d7031..000000000 --- a/src/ui/widget/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd ../.. && $(MAKE) ui/widget/all - -clean %.a %.$(OBJEXT): - cd ../.. && $(MAKE) ui/widget/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp index eb0e45f14..7427ad4e2 100644 --- a/src/ui/widget/page-sizer.cpp +++ b/src/ui/widget/page-sizer.cpp @@ -355,13 +355,12 @@ PageSizer::PageSizer(Registry & _wr) _fitPageMarginExpander.set_vexpand(); _customDimTable.attach(_fitPageMarginExpander, 0, 2, 2, 1); - _dimTabOrderGList = NULL; - _dimTabOrderGList = g_list_append(_dimTabOrderGList, _dimensionWidth.gobj()); - _dimTabOrderGList = g_list_append(_dimTabOrderGList, _dimensionHeight.gobj()); - _dimTabOrderGList = g_list_append(_dimTabOrderGList, _dimensionUnits.gobj()); - _dimTabOrderGList = g_list_append(_dimTabOrderGList, _fitPageMarginExpander.gobj()); - Glib::ListHandle<Widget *> dimFocusChain(_dimTabOrderGList, Glib::OWNERSHIP_NONE); - _customDimTable.set_focus_chain(dimFocusChain); + _dimTabOrderList.clear(); + _dimTabOrderList.push_back(&_dimensionWidth); + _dimTabOrderList.push_back(&_dimensionHeight); + _dimTabOrderList.push_back(&_dimensionUnits); + _dimTabOrderList.push_back(&_fitPageMarginExpander); + _customDimTable.set_focus_chain(_dimTabOrderList); //## Set up fit page expander _fitPageMarginExpander.set_use_underline(); @@ -454,7 +453,6 @@ PageSizer::PageSizer(Registry & _wr) */ PageSizer::~PageSizer() { - g_list_free(_dimTabOrderGList); } diff --git a/src/ui/widget/page-sizer.h b/src/ui/widget/page-sizer.h index f84f96782..329ecfc6d 100644 --- a/src/ui/widget/page-sizer.h +++ b/src/ui/widget/page-sizer.h @@ -220,7 +220,7 @@ protected: RegisteredUnitMenu _dimensionUnits; RegisteredScalarUnit _dimensionWidth; RegisteredScalarUnit _dimensionHeight; - GList * _dimTabOrderGList; + std::vector<Widget*> _dimTabOrderList; //### Fit Page options Gtk::Expander _fitPageMarginExpander; diff --git a/src/ui/widget/panel.cpp b/src/ui/widget/panel.cpp index 9332fe0f9..aea9b7e8e 100644 --- a/src/ui/widget/panel.cpp +++ b/src/ui/widget/panel.cpp @@ -24,7 +24,6 @@ #include <glibmm/i18n.h> #include "panel.h" -#include "icon-size.h" #include "preferences.h" #include "desktop.h" diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp index 2981316c0..8b8e663a5 100644 --- a/src/ui/widget/preferences-widget.cpp +++ b/src/ui/widget/preferences-widget.cpp @@ -34,6 +34,7 @@ #include <glibmm/i18n.h> #include <glibmm/convert.h> +#include <glibmm/regex.h> #ifdef WIN32 #include <windows.h> @@ -78,6 +79,7 @@ void DialogPage::add_line(bool indent, auto hb = Gtk::manage(new Gtk::Box()); hb->set_spacing(12); + hb->set_hexpand(true); hb->pack_start(widget, expand_widget, expand_widget); // Pack an additional widget into a box with the widget if desired @@ -859,6 +861,35 @@ void PrefEntry::on_changed() } } +void PrefMultiEntry::init(Glib::ustring const &prefs_path, int height) +{ + // TODO: Figure out if there's a way to specify height in lines instead of px + // and how to obtain a reasonable default width if 'expand_widget' is not used + set_size_request(100, height); + set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + set_shadow_type(Gtk::SHADOW_IN); + + add(_text); + + _prefs_path = prefs_path; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring value = prefs->getString(_prefs_path); + value = Glib::Regex::create("\\|")->replace_literal(value, 0, "\n", (Glib::RegexMatchFlags)0); + _text.get_buffer()->set_text(value); + _text.get_buffer()->signal_changed().connect(sigc::mem_fun(*this, &PrefMultiEntry::on_changed)); +} + +void PrefMultiEntry::on_changed() +{ + if (get_visible()) //only take action if user changed value + { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring value = _text.get_buffer()->get_text(); + value = Glib::Regex::create("\\n")->replace_literal(value, 0, "|", (Glib::RegexMatchFlags)0); + prefs->setString(_prefs_path, value); + } +} + void PrefColorPicker::init(Glib::ustring const &label, Glib::ustring const &prefs_path, guint32 default_rgba) { diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h index 142793509..2578be533 100644 --- a/src/ui/widget/preferences-widget.h +++ b/src/ui/widget/preferences-widget.h @@ -28,6 +28,8 @@ #include <sigc++/sigc++.h> #include <gtkmm/checkbutton.h> #include <gtkmm/radiobutton.h> +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/textview.h> #include <gtkmm/comboboxtext.h> #include <gtkmm/drawingarea.h> #include <gtkmm/grid.h> @@ -195,6 +197,16 @@ protected: void on_changed(); }; +class PrefMultiEntry : public Gtk::ScrolledWindow +{ +public: + void init(Glib::ustring const &prefs_path, int height); +protected: + Glib::ustring _prefs_path; + Gtk::TextView _text; + void on_changed(); +}; + class PrefEntryButtonHBox : public Gtk::HBox { public: diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp index 639bd4161..a88413347 100644 --- a/src/ui/widget/registered-widget.cpp +++ b/src/ui/widget/registered-widget.cpp @@ -412,9 +412,12 @@ RegisteredColorPicker::on_changed (guint32 rgba) local_repr = dt->getNamedView()->getRepr(); local_doc = dt->getDocument(); } - gchar c[32]; - sp_svg_write_color(c, sizeof(c), rgba); + if (_akey == _ckey + "_opacity_LPE") { //For LPE parameter we want stored with alpha + sprintf(c, "#%08x", rgba); + } else { + sp_svg_write_color(c, sizeof(c), rgba); + } bool saved = DocumentUndo::getUndoSensitive(local_doc); DocumentUndo::setUndoSensitive(local_doc, false); local_repr->setAttribute(_ckey.c_str(), c); diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index 68acddfcc..d9b93f6db 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -107,8 +107,7 @@ static const GtkTargetEntry ui_drop_target_entries [] = { {"application/x-color", 0, APP_X_COLOR} }; -#define ENTRIES_SIZE(n) sizeof(n)/sizeof(n[0]) -static guint nui_drop_target_entries = ENTRIES_SIZE(ui_drop_target_entries); +static guint nui_drop_target_entries = G_N_ELEMENTS(ui_drop_target_entries); /* convenience function */ static Dialog::FillAndStroke *get_fill_and_stroke_panel(SPDesktop *desktop); @@ -139,7 +138,6 @@ SelectedStyle::SelectedStyle(bool /*layout*/) _opacity_blocked (false), - _unit_mis(NULL), _sw_unit(NULL) { set_name("SelectedStyle"); @@ -336,7 +334,7 @@ SelectedStyle::SelectedStyle(bool /*layout*/) while(iter != m.end()) { Gtk::RadioMenuItem *mi = Gtk::manage(new Gtk::RadioMenuItem(_sw_group)); mi->add(*(new Gtk::Label(iter->first, Gtk::ALIGN_START))); - _unit_mis = g_slist_append(_unit_mis, mi); + _unit_mis.push_back(mi); Inkscape::Util::Unit const *u = unit_table.getUnit(iter->first); mi->signal_activate().connect(sigc::bind<Inkscape::Util::Unit const *>(sigc::mem_fun(*this, &SelectedStyle::on_popup_units), u)); _popup_sw.attach(*mi, 0,1, row, row+1); @@ -449,6 +447,7 @@ SelectedStyle::~SelectedStyle() delete selection_modified_connection; subselection_changed_connection->disconnect(); delete subselection_changed_connection; + _unit_mis.clear(); for (int i = SS_FILL; i <= SS_STROKE; i++) { delete _color_preview[i]; @@ -488,9 +487,7 @@ SelectedStyle::setDesktop(SPDesktop *desktop) _sw_unit = desktop->getNamedView()->display_units; // Set the doc default unit active in the units list - gint length = g_slist_length(_unit_mis); - for (int i = 0; i < length; i++) { - Gtk::RadioMenuItem *mi = (Gtk::RadioMenuItem *) g_slist_nth_data(_unit_mis, i); + for ( auto mi:_unit_mis ) { if (mi && mi->get_label() == _sw_unit->abbr) { mi->set_active(); break; diff --git a/src/ui/widget/selected-style.h b/src/ui/widget/selected-style.h index 065d745f0..b7f3d5dda 100644 --- a/src/ui/widget/selected-style.h +++ b/src/ui/widget/selected-style.h @@ -267,7 +267,7 @@ protected: Gtk::Menu _popup_sw; Gtk::RadioButtonGroup _sw_group; - GSList *_unit_mis; + std::vector<Gtk::RadioMenuItem*> _unit_mis; void on_popup_units(Inkscape::Util::Unit const *u); void on_popup_preset(int i); Gtk::MenuItem _popup_sw_remove; diff --git a/src/ui/widget/spinbutton.cpp b/src/ui/widget/spinbutton.cpp index d1776e630..0c082d3ce 100644 --- a/src/ui/widget/spinbutton.cpp +++ b/src/ui/widget/spinbutton.cpp @@ -71,7 +71,7 @@ bool SpinButton::on_my_focus_in_event(GdkEventFocus* /*event*/) bool SpinButton::on_my_key_press_event(GdkEventKey* event) { - switch (Inkscape::UI::Tools::get_group0_keyval (event)) { + switch (Inkscape::UI::Tools::get_latin_keyval (event)) { case GDK_KEY_Escape: undo(); return true; // I consumed the event diff --git a/src/ui/widget/unit-tracker.cpp b/src/ui/widget/unit-tracker.cpp index a1501c229..d36220b74 100644 --- a/src/ui/widget/unit-tracker.cpp +++ b/src/ui/widget/unit-tracker.cpp @@ -14,7 +14,7 @@ #include "style-internal.h" #include "unit-tracker.h" -#include "widgets/ege-select-one-action.h" +//#include "widgets/ege-select-one-action.h" #define COLUMN_STRING 0 @@ -31,9 +31,6 @@ UnitTracker::UnitTracker(UnitType unit_type) : _activeUnit(NULL), _activeUnitInitialized(false), _store(0), - _unitList(0), - _actionList(0), - _adjList(0), _priorValues() { _store = gtk_list_store_new(1, G_TYPE_STRING); @@ -58,17 +55,17 @@ UnitTracker::UnitTracker(UnitType unit_type) : UnitTracker::~UnitTracker() { // Unhook weak references to GtkActions - while (_actionList) { - g_signal_handlers_disconnect_by_func(G_OBJECT(_actionList->data), (gpointer) _unitChangedCB, this); - g_object_weak_unref(G_OBJECT(_actionList->data), _actionFinalizedCB, this); - _actionList = g_slist_delete_link(_actionList, _actionList); + for (auto i : _actionList) { + g_signal_handlers_disconnect_by_func(G_OBJECT(i), (gpointer) _unitChangedCB, this); + g_object_weak_unref(G_OBJECT(i), _actionFinalizedCB, this); } + _actionList.clear(); // Unhook weak references to GtkAdjustments - while (_adjList) { - g_object_weak_unref(G_OBJECT(_adjList->data), _adjustmentFinalizedCB, this); - _adjList = g_slist_delete_link(_adjList, _adjList); + for (auto i : _adjList) { + g_object_weak_unref(G_OBJECT(i), _adjustmentFinalizedCB, this); } + _adjList.clear(); } bool UnitTracker::isUpdating() const @@ -109,9 +106,9 @@ void UnitTracker::setActiveUnitByAbbr(gchar const *abbr) void UnitTracker::addAdjustment(GtkAdjustment *adj) { - if (!g_slist_find(_adjList, adj)) { + if (std::find(_adjList.begin(),_adjList.end(),adj)!=_adjList.end()) { g_object_weak_ref(G_OBJECT(adj), _adjustmentFinalizedCB, this); - _adjList = g_slist_append(_adjList, adj); + _adjList.push_back(adj); } } @@ -147,7 +144,7 @@ GtkAction *UnitTracker::createAction(gchar const *name, gchar const *label, gcha ege_select_one_action_set_appearance(act1, "minimal"); g_object_weak_ref(G_OBJECT(act1), _actionFinalizedCB, this); g_signal_connect(G_OBJECT(act1), "changed", G_CALLBACK(_unitChangedCB), this); - _actionList = g_slist_append(_actionList, act1); + _actionList.push_back(act1); return GTK_ACTION(act1); } @@ -180,9 +177,10 @@ void UnitTracker::_adjustmentFinalizedCB(gpointer data, GObject *where_the_objec void UnitTracker::_actionFinalized(GObject *where_the_object_was) { - GSList *target = g_slist_find(_actionList, where_the_object_was); - if (target) { - _actionList = g_slist_remove(_actionList, where_the_object_was); + EgeSelectOneAction* act = (EgeSelectOneAction*)(where_the_object_was); + auto it = std::find(_actionList.begin(),_actionList.end(), act); + if (it != _actionList.end()) { + _actionList.erase(it); } else { g_warning("Received a finalization callback for unknown object %p", where_the_object_was); } @@ -190,9 +188,10 @@ void UnitTracker::_actionFinalized(GObject *where_the_object_was) void UnitTracker::_adjustmentFinalized(GObject *where_the_object_was) { - GSList *target = g_slist_find(_adjList, where_the_object_was); - if (target) { - _adjList = g_slist_remove(_adjList, where_the_object_was); + GtkAdjustment* adj = (GtkAdjustment*)(where_the_object_was); + auto it = std::find(_adjList.begin(),_adjList.end(), adj); + if (it != _adjList.end()) { + _adjList.erase(it); } else { g_warning("Received a finalization callback for unknown object %p", where_the_object_was); } @@ -217,7 +216,7 @@ void UnitTracker::_setActive(gint active) Inkscape::Util::Unit const *newUnit = unit_table.getUnit(newAbbr); _activeUnit = newUnit; - if (_adjList) { + if (!_adjList.empty()) { _fixupAdjustments(unit, newUnit); } @@ -230,11 +229,8 @@ void UnitTracker::_setActive(gint active) _active = active; - for ( GSList *cur = _actionList ; cur ; cur = g_slist_next(cur) ) { - if (IS_EGE_SELECT_ONE_ACTION(cur->data)) { - EgeSelectOneAction *act = EGE_SELECT_ONE_ACTION(cur->data); - ege_select_one_action_set_active(act, active); - } + for (auto act:_actionList) { + ege_select_one_action_set_active(act, active); } _activeUnitInitialized = true; @@ -244,8 +240,7 @@ void UnitTracker::_setActive(gint active) void UnitTracker::_fixupAdjustments(Inkscape::Util::Unit const *oldUnit, Inkscape::Util::Unit const *newUnit) { _isUpdating = true; - for ( GSList *cur = _adjList ; cur ; cur = g_slist_next(cur) ) { - GtkAdjustment *adj = GTK_ADJUSTMENT(cur->data); + for ( auto adj : _adjList ) { gdouble oldVal = gtk_adjustment_get_value(adj); gdouble val = oldVal; diff --git a/src/ui/widget/unit-tracker.h b/src/ui/widget/unit-tracker.h index 8fa9ff304..643ac4e51 100644 --- a/src/ui/widget/unit-tracker.h +++ b/src/ui/widget/unit-tracker.h @@ -17,6 +17,7 @@ #include <map> #include "util/units.h" +#include "widgets/ege-select-one-action.h" using Inkscape::Util::Unit; using Inkscape::Util::UnitType; @@ -65,9 +66,8 @@ private: Inkscape::Util::Unit const *_activeUnit; bool _activeUnitInitialized; GtkListStore *_store; - GSList *_unitList; - GSList *_actionList; - GSList *_adjList; + std::vector<EgeSelectOneAction*> _actionList; + std::vector<GtkAdjustment*> _adjList; std::map <GtkAdjustment *, gdouble> _priorValues; }; diff --git a/src/unclump.cpp b/src/unclump.cpp index 5ec5cfce4..55825cdd6 100644 --- a/src/unclump.cpp +++ b/src/unclump.cpp @@ -298,7 +298,7 @@ unclump_push (SPItem *from, SPItem *what, double dist) //g_print ("push %s at %g,%g from %g,%g by %g,%g, dist %g\n", what->getId(), it[Geom::X],it[Geom::Y], p[Geom::X],p[Geom::Y], by[Geom::X],by[Geom::Y], dist); what->set_i2d_affine(what->i2dt_affine() * move); - what->doWriteTransform(what->getRepr(), what->transform, NULL); + what->doWriteTransform(what->transform); } /** @@ -321,7 +321,7 @@ unclump_pull (SPItem *to, SPItem *what, double dist) //g_print ("pull %s at %g,%g to %g,%g by %g,%g, dist %g\n", what->getId(), it[Geom::X],it[Geom::Y], p[Geom::X],p[Geom::Y], by[Geom::X],by[Geom::Y], dist); what->set_i2d_affine(what->i2dt_affine() * move); - what->doWriteTransform(what->getRepr(), what->transform, NULL); + what->doWriteTransform(what->transform); } diff --git a/src/uri.cpp b/src/uri.cpp index 9178c8ae8..219792b6e 100644 --- a/src/uri.cpp +++ b/src/uri.cpp @@ -159,7 +159,7 @@ const std::string URI::getFullPath(std::string const &base) const { path = Glib::build_filename(base, path); } // Check the existance of the file - if(! g_file_test(path.c_str(), G_FILE_TEST_EXISTS) + if(! g_file_test(path.c_str(), G_FILE_TEST_EXISTS) || g_file_test(path.c_str(), G_FILE_TEST_IS_DIR) ) { path.clear(); } @@ -207,13 +207,11 @@ URI URI::fromUtf8( gchar const* path ) { tmp += (gunichar)one; } else { gchar scratch[4]; - g_snprintf( scratch, 4, "%c%02X", '%', one ); + g_snprintf( scratch, 4, "%%%02X", one ); tmp.append( scratch ); } } - const gchar *uri = tmp.data(); - URI result(uri); - return result; + return URI( tmp.data() ); } /* TODO !!! proper error handling */ diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index 9680b6377..b8c61e2fe 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -10,8 +10,6 @@ set(util_SRC # ------- # Headers - accumulators.h - compose.hpp copy.h ege-appear-time-tracker.h ege-tags.h diff --git a/src/util/accumulators.h b/src/util/accumulators.h deleted file mode 100644 index 2cd51b101..000000000 --- a/src/util/accumulators.h +++ /dev/null @@ -1,113 +0,0 @@ -/** @file - * Frequently used accumulators for use with libsigc++ - */ -/* Authors: - * Krzysztof KosiÅ„ski <tweenk.pl@gmail.com> - * - * Copyright (C) 2009 Authors - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifndef SEEN_UTIL_ACCUMULATORS_H -#define SEEN_UTIL_ACCUMULATORS_H - -#include <iterator> - -namespace Inkscape { -namespace Util { - -/** - * Accumulator which evaluates slots in reverse connection order. - * The slot that was connected last is evaluated first. - */ -struct Reverse { - typedef void result_type; - template <typename T_iterator> - result_type operator()(T_iterator first, T_iterator last) const { - while (first != last) *(--last); - } -}; - -/** - * Accumulator type for interruptible signals. Slots return a boolean value; emission - * is stopped when true is returned from a slot. - */ -struct Interruptible { - typedef bool result_type; - template <typename T_iterator> - result_type operator()(T_iterator first, T_iterator last) const { - for (; first != last; ++first) - if (*first) return true; - return false; - } -}; - -/** - * Same as Interruptible, but the slots are called in reverse order of connection, - * e.g. the slot that was connected last is evaluated first. - */ -struct ReverseInterruptible { - typedef bool result_type; - template <typename T_iterator> - result_type operator()(T_iterator first, T_iterator last) const { - while (first != last) { - if (*(--last)) return true; - } - return false; - } -}; - -/** - * The template parameter specifies how many slots from the beginning of the list - * should be evaluated after other slots. Useful for signals which invoke other signals - * once complete. Undefined results if the signal does not have at least @c num_chained - * slots before first emission. - * - * For example, if template param = 3, the execution order is as follows: - * @verbatim - 8. 1. 2. 3. 4. 5. 6. 7. - S1 S2 S3 S4 S5 S6 S7 S8 @endverbatim - */ -template <unsigned num_chained = 1> -struct Chained { - typedef void result_type; - template <typename T_iterator> - result_type operator()(T_iterator first, T_iterator last) const { - T_iterator save_first = first; - // ARGH, iterator_traits is not defined for slot iterators! - //std::advance(first, num_chained); - for (unsigned i = 0; i < num_chained && first != last; ++i) ++first; - for (; first != last; ++first) *first; - for (unsigned i = 0; i < num_chained && save_first != last; ++i, ++save_first) - *save_first; - } -}; - -/** - * Executes a logical OR on the results from slots. - */ -struct LogicalOr { - typedef bool result_type; - template <typename T_iterator> - result_type operator()(T_iterator first, T_iterator last) const { - bool ret = false; - for (; first != last; ++first) ret |= *first; - return ret; - } -}; - -} // namespace Util -} // namespace Inkscape - -#endif - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/util/compose.hpp b/src/util/compose.hpp deleted file mode 100644 index b3f410c8e..000000000 --- a/src/util/compose.hpp +++ /dev/null @@ -1,393 +0,0 @@ -/* Defines String::compose(fmt, arg...) for easy, i18n-friendly - * composition of strings. - * - * Version 1.0. - * - * Copyright (c) 2002 Ole Laursen <olau@hardworking.dk>. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA. - */ - -// -// Basic usage is like -// -// std::cout << String::compose("This is a %1x%2 matrix.", rows, cols); -// -// See http://www.cs.aau.dk/~olau/compose/ or the included README.compose for -// more details. -// - -#ifndef STRING_COMPOSE_H -#define STRING_COMPOSE_H - -#include <sstream> -#include <string> -#include <list> -#include <map> // for multimap - -namespace StringPrivate -{ - // the actual composition class - using string::compose is cleaner, so we - // hide it here - class Composition - { - public: - // initialize and prepare format string on the form "text %1 text %2 etc." - explicit Composition(std::string fmt); - - // supply an replacement argument starting from %1 - template <typename T> - Composition &arg(const T &obj); - - // compose and return string - std::string str() const; - - private: - std::ostringstream os; - int arg_no; - - // we store the output as a list - when the output string is requested, the - // list is concatenated to a string; this way we can keep iterators into - // the list instead of into a string where they're possibly invalidated on - // inserting a specification string - typedef std::list<std::string> output_list; - output_list output; - - // the initial parse of the format string fills in the specification map - // with positions for each of the various %?s - typedef std::multimap<int, output_list::iterator> specification_map; - specification_map specs; - }; - - // helper for converting spec string numbers - inline int char_to_int(char c) - { - switch (c) { - case '0': return 0; - case '1': return 1; - case '2': return 2; - case '3': return 3; - case '4': return 4; - case '5': return 5; - case '6': return 6; - case '7': return 7; - case '8': return 8; - case '9': return 9; - default: return -1000; - } - } - - inline bool is_number(int n) - { - switch (n) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return true; - - default: - return false; - } - } - - - // implementation of class Composition - template <typename T> - inline Composition &Composition::arg(const T &obj) - { - os << obj; - - std::string rep = os.str(); - - if (!rep.empty()) { // manipulators don't produce output - for (specification_map::const_iterator i = specs.lower_bound(arg_no), - end = specs.upper_bound(arg_no); i != end; ++i) { - output_list::iterator pos = i->second; - ++pos; - - output.insert(pos, rep); - } - - os.str(std::string()); - //os.clear(); - ++arg_no; - } - - return *this; - } - - inline Composition::Composition(std::string fmt) - : arg_no(1) - { - std::string::size_type b = 0, i = 0; - - // fill in output with the strings between the %1 %2 %3 etc. and - // fill in specs with the positions - while (i < fmt.length()) { - if (fmt[i] == '%' && i + 1 < fmt.length()) { - if (fmt[i + 1] == '%') { // catch %% - fmt.replace(i, 2, "%"); - ++i; - } - else if (is_number(fmt[i + 1])) { // aha! a spec! - // save string - output.push_back(fmt.substr(b, i - b)); - - int n = 1; // number of digits - int spec_no = 0; - - do { - spec_no += char_to_int(fmt[i + n]); - spec_no *= 10; - ++n; - } while (i + n < fmt.length() && is_number(fmt[i + n])); - - spec_no /= 10; - output_list::iterator pos = output.end(); - --pos; // safe since we have just inserted a string> - - specs.insert(specification_map::value_type(spec_no, pos)); - - // jump over spec string - i += n; - b = i; - } - else - ++i; - } - else - ++i; - } - - if (i - b > 0) // add the rest of the string - output.push_back(fmt.substr(b, i - b)); - } - - inline std::string Composition::str() const - { - // assemble string - std::string str; - - for (output_list::const_iterator i = output.begin(), end = output.end(); - i != end; ++i) - str += *i; - - return str; - } -} - -// now for the real thing(s) -namespace String -{ - // a series of functions which accept a format string on the form "text %1 - // more %2 less %3" and a number of templated parameters and spits out the - // composited string - template <typename T1> - inline std::string compose(const std::string &fmt, const T1 &o1) - { - StringPrivate::Composition c(fmt); - c.arg(o1); - return c.str(); - } - - template <typename T1, typename T2> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2); - return c.str(); - } - - template <typename T1, typename T2, typename T3> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7, const T8 &o8) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7, const T8 &o8, const T9 &o9) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9, typename T10> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7, const T8 &o8, const T9 &o9, - const T10 &o10) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) - .arg(o10); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7, const T8 &o8, const T9 &o9, - const T10 &o10, const T11 &o11) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) - .arg(o10).arg(o11); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11, typename T12> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7, const T8 &o8, const T9 &o9, - const T10 &o10, const T11 &o11, const T12 &o12) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) - .arg(o10).arg(o11).arg(o12); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11, typename T12, typename T13> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7, const T8 &o8, const T9 &o9, - const T10 &o10, const T11 &o11, const T12 &o12, - const T13 &o13) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) - .arg(o10).arg(o11).arg(o12).arg(o13); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11, typename T12, typename T13, typename T14> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7, const T8 &o8, const T9 &o9, - const T10 &o10, const T11 &o11, const T12 &o12, - const T13 &o13, const T14 &o14) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) - .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14); - return c.str(); - } - - template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6, typename T7, typename T8, typename T9, typename T10, - typename T11, typename T12, typename T13, typename T14, - typename T15> - inline std::string compose(const std::string &fmt, - const T1 &o1, const T2 &o2, const T3 &o3, - const T4 &o4, const T5 &o5, const T6 &o6, - const T7 &o7, const T8 &o8, const T9 &o9, - const T10 &o10, const T11 &o11, const T12 &o12, - const T13 &o13, const T14 &o14, const T15 &o15) - { - StringPrivate::Composition c(fmt); - c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) - .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15); - return c.str(); - } -} - - -#endif // STRING_COMPOSE_H diff --git a/src/util/format.h b/src/util/format.h index 690121254..d2fe2d0ef 100644 --- a/src/util/format.h +++ b/src/util/format.h @@ -20,20 +20,20 @@ namespace Inkscape { namespace Util { -inline ptr_shared<char> vformat(char const *format, va_list args) { +inline ptr_shared vformat(char const *format, va_list args) { char *temp=g_strdup_vprintf(format, args); - ptr_shared<char> result=share_string(temp); + ptr_shared result=share_string(temp); g_free(temp); return result; } // needed since G_GNUC_PRINTF can only be used on a declaration - ptr_shared<char> format(char const *format, ...) G_GNUC_PRINTF(1,2); -inline ptr_shared<char> format(char const *format, ...) { + ptr_shared format(char const *format, ...) G_GNUC_PRINTF(1,2); +inline ptr_shared format(char const *format, ...) { va_list args; va_start(args, format); - ptr_shared<char> result=vformat(format, args); + ptr_shared result=vformat(format, args); va_end(args); return result; diff --git a/src/util/makefile.in b/src/util/makefile.in deleted file mode 100644 index fc4870075..000000000 --- a/src/util/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) util/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) util/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/util/share.cpp b/src/util/share.cpp index 3cb289b10..d5d93fc75 100644 --- a/src/util/share.cpp +++ b/src/util/share.cpp @@ -1,5 +1,6 @@ /* - * Inkscape::Util::ptr_shared<T> - like T const *, but stronger + * Inkscape::Util::ptr_shared<T> - like T const *, but stronger. + * Used to hold c-style strings for objects that are managed by the gc. * * Authors: * MenTaLguY <mental@rydia.net> @@ -15,13 +16,13 @@ namespace Inkscape { namespace Util { -ptr_shared<char> share_string(char const *string) { - g_return_val_if_fail(string != NULL, share_unsafe<char>(NULL)); +ptr_shared share_string(char const *string) { + g_return_val_if_fail(string != NULL, share_unsafe(NULL)); return share_string(string, std::strlen(string)); } -ptr_shared<char> share_string(char const *string, std::size_t length) { - g_return_val_if_fail(string != NULL, share_unsafe<char>(NULL)); +ptr_shared share_string(char const *string, std::size_t length) { + g_return_val_if_fail(string != NULL, share_unsafe(NULL)); char *new_string=new (GC::ATOMIC) char[length+1]; std::memcpy(new_string, string, length); new_string[length] = 0; diff --git a/src/util/share.h b/src/util/share.h index 8f1e7045a..6e5a24d71 100644 --- a/src/util/share.h +++ b/src/util/share.h @@ -1,5 +1,6 @@ /* - * Inkscape::Util::ptr_shared<T> - like T const *, but stronger + * Inkscape::Util::ptr_shared<T> - like T const *, but stronger. + * Used to hold c-style strings for objects that are managed by the gc. * * Authors: * MenTaLguY <mental@rydia.net> @@ -19,120 +20,84 @@ namespace Inkscape { namespace Util { -template <typename T> class ptr_shared { public: - ptr_shared() : _obj(NULL) {} - template <typename T1> - ptr_shared(ptr_shared<T1> const &other) : _obj(other._obj) {} + ptr_shared() : _string(NULL) {} + ptr_shared(ptr_shared const &other) : _string(other._string) {} - T const *pointer() const { return _obj; } + operator char const *() const { return _string; } + operator bool() const { return _string; } - template <typename T1> - operator T1 const *() const { return _obj; } + char const *pointer() const { return _string; } + char const &operator[](int i) const { return _string[i]; } - operator bool() const { return _obj; } - - T const &operator*() const { return *_obj; } - T const *operator->() const { return _obj; } - T const &operator[](int i) const { return _obj[i]; } - - ptr_shared<T> operator+(int i) const { - return share_unsafe(_obj+i); + ptr_shared operator+(int i) const { + return share_unsafe(_string+i); } - ptr_shared<T> operator-(int i) const { - return share_unsafe(_obj-i); + ptr_shared operator-(int i) const { + return share_unsafe(_string-i); } - - ptr_shared<T> &operator+=(int i) const { - _obj += i; + //WARNING: No bounds checking in += and -= functions. Moving the pointer + //past the end of the string and then back could probably cause the garbage + //collector to deallocate the string inbetween, as there's temporary no + //valid reference pointing into the allocated space. + ptr_shared &operator+=(int i) { + _string += i; return *this; } - ptr_shared<T> &operator-=(int i) const { - _obj -= i; + ptr_shared &operator-=(int i) { + _string -= i; return *this; } - - template <typename T1> - std::ptrdiff_t operator-(ptr_shared<T1> const &other) { - return _obj - other._obj; + std::ptrdiff_t operator-(ptr_shared const &other) { + return _string - other._string; } - template <typename T1> - ptr_shared<T> &operator=(ptr_shared<T1> const &other) { - _obj = other._obj; + ptr_shared &operator=(ptr_shared const &other) { + _string = other._string; return *this; } - template <typename T1> - bool operator==(ptr_shared<T1> const &other) const { - return _obj == other._obj; + bool operator==(ptr_shared const &other) const { + return _string == other._string; } - - template <typename T1> - bool operator!=(ptr_shared<T1> const &other) const { - return _obj != other._obj; + bool operator!=(ptr_shared const &other) const { + return _string != other._string; } - - template <typename T1> - bool operator>(ptr_shared<T1> const &other) const { - return _obj > other._obj; + bool operator>(ptr_shared const &other) const { + return _string > other._string; } - - template <typename T1> - bool operator<(ptr_shared<T1> const &other) const { - return _obj < other._obj; - } - - static ptr_shared<T> share_unsafe(T const *obj) { - return ptr_shared<T>(obj); + bool operator<(ptr_shared const &other) const { + return _string < other._string; } -protected: - explicit ptr_shared(T const *obj) : _obj(obj) {} + friend ptr_shared share_unsafe(char const *string); private: - T const *_obj; -}; - -template <typename T> -inline ptr_shared<T> share(T const *obj) { - return share_unsafe(obj ? new T(*obj) : NULL); -} + ptr_shared(char const *string) : _string(string) {} + static ptr_shared share_unsafe(char const *string) { + return ptr_shared(string); + } -ptr_shared<char> share_string(char const *string); -ptr_shared<char> share_string(char const *string, std::size_t length); + //This class (and code usign it) assumes that it never has to free this + //pointer, and that the memory it points to will not be freed as long as a + //ptr_shared pointing to it exists. + char const *_string; +}; -template <typename T> -inline ptr_shared<T> reshare(T const *obj) { - return ptr_shared<T>::share_unsafe(obj); -} +ptr_shared share_string(char const *string); +ptr_shared share_string(char const *string, std::size_t length); -template <typename T> -inline ptr_shared<T> share_unsafe(T const *obj) { - return ptr_shared<T>::share_unsafe(obj); +inline ptr_shared share_unsafe(char const *string) { + return ptr_shared::share_unsafe(string); } -inline ptr_shared<char> share_static_string(char const *string) { +//TODO: Do we need this function? +inline ptr_shared share_static_string(char const *string) { return share_unsafe(string); } -template <typename T1, typename T2> -inline ptr_shared<T1> static_cast_shared(ptr_shared<T2> const &ref) { - return reshare(static_cast<T1 const *>(ref.pointer())); -} - -template <typename T1, typename T2> -inline ptr_shared<T1> dynamic_cast_shared(ptr_shared<T2> const &ref) { - return reshare(dynamic_cast<T1 const *>(ref.pointer())); -} - -template <typename T1, typename T2> -inline ptr_shared<T1> reinterpret_cast_shared(ptr_shared<T2> const &ref) { - return reshare(reinterpret_cast<T1 const *>(ref.pointer())); -} - } } diff --git a/src/vanishing-point.h b/src/vanishing-point.h index ae2a88d6e..f396225df 100644 --- a/src/vanishing-point.h +++ b/src/vanishing-point.h @@ -176,7 +176,7 @@ public: std::vector<SPCtrlLine *> lines; void printDraggers(); // convenience for debugging - /* + /* * FIXME: Should the following functions be merged? * Also, they should make use of the info in a VanishingPoint structure (regarding boxes * and perspectives) rather than each time iterating over the whole list of selected items? diff --git a/src/verbs.cpp b/src/verbs.cpp index 4827ba631..c1c108415 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -3114,7 +3114,7 @@ Verb *Verb::_base_verbs[] = { new DialogVerb(SP_VERB_DIALOG_CLONETILER, "DialogClonetiler", N_("Create Tiled Clones..."), N_("Create multiple clones of selected object, arranging them into a pattern or scattering"), INKSCAPE_ICON("dialog-tile-clones")), new DialogVerb(SP_VERB_DIALOG_ATTR, "DialogObjectAttributes", N_("_Object attributes..."), - N_("Edit the object attributes..."), INKSCAPE_ICON("dialog-object-attributes")), + N_("Edit the object attributes..."), INKSCAPE_ICON("dialog-object-properties")), new DialogVerb(SP_VERB_DIALOG_ITEM, "DialogObjectProperties", N_("_Object Properties..."), N_("Edit the ID, locked and visible status, and other object properties"), INKSCAPE_ICON("dialog-object-properties")), new DialogVerb(SP_VERB_DIALOG_INPUT, "DialogInput", N_("_Input Devices..."), diff --git a/src/widgets/button.h b/src/widgets/button.h index 94a956de3..680ccb79d 100644 --- a/src/widgets/button.h +++ b/src/widgets/button.h @@ -18,7 +18,6 @@ #include <gtk/gtk.h> #include <sigc++/connection.h> -#include "icon-size.h" struct SPAction; diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 1d0b31a6e..571f920bf 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -1077,8 +1077,8 @@ SPDesktopWidget::shutdown() doc->getName()); // fix for bug lp:168809 GtkWidget *ma = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog)); - GList *ma_labels = gtk_container_get_children(GTK_CONTAINER(ma)); - GtkWidget *label = GTK_WIDGET(g_list_first(ma_labels)->data); + std::vector<Gtk::Widget*> ma_labels = Glib::wrap(GTK_CONTAINER(ma))->get_children(); + GtkWidget *label = GTK_WIDGET(ma_labels[0]->gobj()); gtk_widget_set_can_focus(label, FALSE); GtkWidget *close_button; @@ -1136,8 +1136,8 @@ SPDesktopWidget::shutdown() doc->getName() ? doc->getName() : "Unnamed"); // fix for bug lp:168809 GtkWidget *ma = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog)); - GList *ma_labels = gtk_container_get_children(GTK_CONTAINER(ma)); - GtkWidget *label = GTK_WIDGET(g_list_first(ma_labels)->data); + std::vector<Gtk::Widget*> ma_labels = Glib::wrap(GTK_CONTAINER(ma))->get_children(); + GtkWidget *label = GTK_WIDGET(ma_labels[0]->gobj()); gtk_widget_set_can_focus(label, FALSE); GtkWidget *close_button; @@ -1734,22 +1734,22 @@ void SPDesktopWidget::namedviewModified(SPObject *obj, guint flags) * This should solve: https://bugs.launchpad.net/inkscape/+bug/362995 */ if (GTK_IS_CONTAINER(aux_toolbox)) { - GList *ch = gtk_container_get_children (GTK_CONTAINER(aux_toolbox)); - for (GList *i = ch; i != NULL; i = i->next) { - if (GTK_IS_CONTAINER(i->data)) { - GList *grch = gtk_container_get_children (GTK_CONTAINER(i->data)); - for (GList *j = grch; j != NULL; j = j->next) { + std::vector<Gtk::Widget*> ch = Glib::wrap(GTK_CONTAINER(aux_toolbox))->get_children(); + for (auto i:ch) { + if (GTK_IS_CONTAINER(i->gobj())) { + std::vector<Gtk::Widget*> grch = dynamic_cast<Gtk::Container*>(i)->get_children(); + for (auto j:grch) { - if (!GTK_IS_WIDGET(j->data)) // wasn't a widget + if (!GTK_IS_WIDGET(j->gobj())) // wasn't a widget continue; // Don't apply to text toolbar. We want to be able to // use different units for text. (Bug 1562217) - const gchar* name = gtk_widget_get_name( (GTK_WIDGET(j->data)) ); - if (strcmp( name, "TextToolbar") == 0) + const Glib::ustring name = j->get_name(); + if ( name == "TextToolbar") continue; - gpointer t = sp_search_by_data_recursive(GTK_WIDGET(j->data), (gpointer) "tracker"); + gpointer t = sp_search_by_data_recursive(GTK_WIDGET(j->gobj()), (gpointer) "tracker"); if (t == NULL) // didn't find any tracker data continue; @@ -1941,12 +1941,10 @@ static void sp_dtw_zoom_populate_popup (GtkEntry */*entry*/, GtkMenu *menu, gpointer data) { SPDesktop *dt = SP_DESKTOP_WIDGET (data)->desktop; - - GList* children = gtk_container_get_children (GTK_CONTAINER (menu)); - for ( auto iter = children ; iter ; iter = g_list_next (iter)) { - gtk_container_remove (GTK_CONTAINER (menu), GTK_WIDGET (iter->data)); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(menu))->get_children(); + for ( auto iter : children) { + Glib::wrap(GTK_CONTAINER(menu))->remove(*iter); } - g_list_free (children); GtkWidget *item; @@ -2129,11 +2127,10 @@ sp_dtw_rotation_populate_popup (GtkEntry */*entry*/, GtkMenu *menu, gpointer dat { SPDesktopWidget *dtw = static_cast<SPDesktopWidget*>(data); - GList* children = gtk_container_get_children (GTK_CONTAINER (menu)); - for ( auto iter = children ; iter ; iter = g_list_next (iter)) { - gtk_container_remove (GTK_CONTAINER (menu), GTK_WIDGET (iter->data)); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(menu))->get_children(); + for ( auto iter : children) { + Glib::wrap(GTK_CONTAINER(menu))->remove(*iter); } - g_list_free (children); GtkWidget *item; diff --git a/src/widgets/ege-adjustment-action.cpp b/src/widgets/ege-adjustment-action.cpp index e4f041bd1..597c697cb 100644 --- a/src/widgets/ege-adjustment-action.cpp +++ b/src/widgets/ege-adjustment-action.cpp @@ -41,10 +41,13 @@ #include <cmath> #include <string.h> +#include <vector> +#include <algorithm> +#include <gtkmm/container.h> +#include <gtkmm/radiomenuitem.h> #include <gdk/gdkkeysyms.h> -#include "icon-size.h" #include "widgets/ege-adjustment-action.h" #include "gimp/gimpspinscale.h" #include "ui/icon-names.h" @@ -111,7 +114,7 @@ struct _EgeAdjustmentActionPrivate gdouble page; gint appearanceMode; gboolean transferFocus; - GList* descriptions; + std::vector<EgeAdjustmentDescr*> descriptions; gchar* appearance; gchar* iconId; GtkIconSize iconSize; @@ -268,7 +271,7 @@ static void ege_adjustment_action_init( EgeAdjustmentAction* action ) action->private_data->page = 0.0; action->private_data->appearanceMode = APPEARANCE_NONE; action->private_data->transferFocus = FALSE; - action->private_data->descriptions = 0; + //action->private_data->descriptions = 0; action->private_data->appearance = 0; action->private_data->iconId = 0; action->private_data->iconSize = GTK_ICON_SIZE_SMALL_TOOLBAR; @@ -514,11 +517,13 @@ static void egeAct_free_description( gpointer data, gpointer user_data ) { static void egeAct_free_all_descriptions( EgeAdjustmentAction* action ) { - if ( action->private_data->descriptions ) { - g_list_foreach( action->private_data->descriptions, egeAct_free_description, 0 ); - g_list_free( action->private_data->descriptions ); - action->private_data->descriptions = 0; + for(auto i:action->private_data->descriptions) { + egeAct_free_description(i,0); } + for(auto i:action->private_data->descriptions) { + g_free(i); + } + action->private_data->descriptions.clear(); } static gint egeAct_compare_descriptions( gconstpointer a, gconstpointer b ) @@ -551,7 +556,8 @@ void ege_adjustment_action_set_descriptions( EgeAdjustmentAction* action, gchar EgeAdjustmentDescr* descr = g_new0( EgeAdjustmentDescr, 1 ); descr->descr = descriptions[i] ? g_strdup( descriptions[i] ) : 0; descr->value = values[i]; - action->private_data->descriptions = g_list_insert_sorted( action->private_data->descriptions, (gpointer)descr, egeAct_compare_descriptions ); + action->private_data->descriptions.push_back(descr); + std::sort(action->private_data->descriptions.begin(),action->private_data->descriptions.end()); } } } @@ -609,8 +615,8 @@ static void process_menu_action( GtkWidget* obj, gpointer data ) default: if ( what >= BUMP_CUSTOM ) { guint index = what - BUMP_CUSTOM; - if ( index < g_list_length( act->private_data->descriptions ) ) { - EgeAdjustmentDescr* descr = (EgeAdjustmentDescr*)g_list_nth_data( act->private_data->descriptions, index ); + if ( index < act->private_data->descriptions.size() ) { + EgeAdjustmentDescr* descr = act->private_data->descriptions[index]; if ( descr ) { gtk_adjustment_set_value( act->private_data->adj, descr->value ); } @@ -620,14 +626,13 @@ static void process_menu_action( GtkWidget* obj, gpointer data ) } } -static void create_single_menu_item( GCallback toggleCb, int val, GtkWidget* menu, EgeAdjustmentAction* act, GtkWidget** dst, GSList** group, gdouble num, gboolean active ) +static void create_single_menu_item( GCallback toggleCb, int val, GtkWidget* menu, EgeAdjustmentAction* act, GtkWidget** dst, Gtk::RadioMenuItem::Group *group, gdouble num, gboolean active ) { char* str = 0; EgeAdjustmentDescr* marker = 0; - GList* cur = act->private_data->descriptions; + std::vector<EgeAdjustmentDescr*> cur = act->private_data->descriptions; - while ( cur ) { - EgeAdjustmentDescr* descr = (EgeAdjustmentDescr*)cur->data; + for (auto descr:cur) { gdouble delta = num - descr->value; if ( delta < 0.0 ) { delta = -delta; @@ -636,17 +641,14 @@ static void create_single_menu_item( GCallback toggleCb, int val, GtkWidget* men marker = descr; break; } - cur = g_list_next( cur ); } str = g_strdup_printf( act->private_data->format, num, ((marker && marker->descr) ? ": " : ""), ((marker && marker->descr) ? marker->descr : "")); - *dst = gtk_radio_menu_item_new_with_label( *group, str ); - if ( !*group) { - *group = gtk_radio_menu_item_get_group( GTK_RADIO_MENU_ITEM(*dst) ); - } + auto rmi = new Gtk::RadioMenuItem(*group,Glib::ustring(str)); + *dst = GTK_WIDGET(rmi->gobj()); if ( active ) { gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(*dst), TRUE ); } @@ -658,44 +660,41 @@ static void create_single_menu_item( GCallback toggleCb, int val, GtkWidget* men g_free(str); } -static GList* flush_explicit_items( GList* descriptions, +static int flush_explicit_items( std::vector<EgeAdjustmentDescr*> descriptions, + int pos, GCallback toggleCb, int val, GtkWidget* menu, EgeAdjustmentAction* act, GtkWidget** dst, - GSList** group, + Gtk::RadioMenuItem::Group *group, gdouble num ) { - GList* cur = descriptions; - - if ( cur ) { - gdouble valUpper = num + act->private_data->epsilon; - gdouble valLower = num - act->private_data->epsilon; - - EgeAdjustmentDescr* descr = (EgeAdjustmentDescr*)cur->data; + if(pos >= descriptions.size() || pos < 0) return pos; + EgeAdjustmentDescr* descr = descriptions[pos]; - while ( cur && descr && (descr->value >= valLower) ) { - if ( descr->value > valUpper ) { - create_single_menu_item( toggleCb, val + g_list_position(act->private_data->descriptions, cur), menu, act, dst, group, descr->value, FALSE ); - } + gdouble valUpper = num + act->private_data->epsilon; + gdouble valLower = num - act->private_data->epsilon; - cur = g_list_previous( cur ); - descr = cur ? (EgeAdjustmentDescr*)cur->data : 0; + while ( pos>=0 && pos<descriptions.size() && descr && (descr->value >= valLower) ) { + if ( descr->value > valUpper ) { + create_single_menu_item( toggleCb, val + ( std::find(act->private_data->descriptions.begin(),act->private_data->descriptions.end(),descr) - act->private_data->descriptions.begin() ) , menu, act, dst, group, descr->value, FALSE ); } + pos--; + descr = (pos<0) ? descriptions[pos] : NULL; } - return cur; + return pos; } static GtkWidget* create_popup_number_menu( EgeAdjustmentAction* act ) { GtkWidget* menu = gtk_menu_new(); - GSList* group = 0; + Gtk::RadioMenuItem::Group group; GtkWidget* single = 0; - - GList* addOns = g_list_last( act->private_data->descriptions ); + std::vector<EgeAdjustmentDescr*> list = act->private_data->descriptions; + int addOns = list.size() - 1; gdouble base = gtk_adjustment_get_value( act->private_data->adj ); gdouble lower = 0.0; @@ -711,37 +710,37 @@ static GtkWidget* create_popup_number_menu( EgeAdjustmentAction* act ) if ( base < upper ) { - addOns = flush_explicit_items( addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, upper ); + addOns = flush_explicit_items( list, addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, upper ); create_single_menu_item( G_CALLBACK(process_menu_action), BUMP_TOP, menu, act, &single, &group, upper, FALSE ); if ( (base + page) < upper ) { - addOns = flush_explicit_items( addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base + page ); + addOns = flush_explicit_items( list, addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base + page ); create_single_menu_item( G_CALLBACK(process_menu_action), BUMP_PAGE_UP, menu, act, &single, &group, base + page, FALSE ); } if ( (base + step) < upper ) { - addOns = flush_explicit_items( addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base + step ); + addOns = flush_explicit_items( list, addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base + step ); create_single_menu_item( G_CALLBACK(process_menu_action), BUMP_UP, menu, act, &single, &group, base + step, FALSE ); } } - addOns = flush_explicit_items( addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base ); + addOns = flush_explicit_items( list, addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base ); create_single_menu_item( G_CALLBACK(process_menu_action), BUMP_NONE, menu, act, &single, &group, base, TRUE ); if ( base > lower ) { if ( (base - step) > lower ) { - addOns = flush_explicit_items( addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base - step ); + addOns = flush_explicit_items( list, addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base - step ); create_single_menu_item( G_CALLBACK(process_menu_action), BUMP_DOWN, menu, act, &single, &group, base - step, FALSE ); } if ( (base - page) > lower ) { - addOns = flush_explicit_items( addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base - page ); + addOns = flush_explicit_items( list, addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, base - page ); create_single_menu_item( G_CALLBACK(process_menu_action), BUMP_PAGE_DOWN, menu, act, &single, &group, base - page, FALSE ); } - addOns = flush_explicit_items( addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, lower ); + addOns = flush_explicit_items( list, addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, lower ); create_single_menu_item( G_CALLBACK(process_menu_action), BUMP_BOTTOM, menu, act, &single, &group, lower, FALSE ); } - if ( act->private_data->descriptions ) { - gdouble value = ((EgeAdjustmentDescr*)act->private_data->descriptions->data)->value; - flush_explicit_items( addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, value ); + if ( !act->private_data->descriptions.empty() ) { + gdouble value = ((EgeAdjustmentDescr*)act->private_data->descriptions[0])->value; + flush_explicit_items( list, addOns, G_CALLBACK(process_menu_action), BUMP_CUSTOM, menu, act, &single, &group, value ); } return menu; @@ -965,36 +964,37 @@ static gboolean process_tab( GtkWidget* widget, int direction ) GtkWidget* ggp = gp ? gtk_widget_get_parent(gp) : 0; if ( ggp && GTK_IS_TOOLBAR(ggp) ) { - GList* kids = gtk_container_get_children( GTK_CONTAINER(ggp) ); - if ( kids ) { + std::vector<Gtk::Widget*> kids = Glib::wrap(GTK_CONTAINER(ggp))->get_children(); + if ( !kids.empty() ) { GtkWidget* curr = widget; while ( curr && (gtk_widget_get_parent(curr) != ggp) ) { curr = gtk_widget_get_parent( curr ); } if ( curr ) { - GList* mid = g_list_find( kids, curr ); - while ( mid ) { - mid = ( direction < 0 ) ? g_list_previous(mid) : g_list_next(mid); - if ( mid && GTK_IS_TOOL_ITEM(mid->data) ) { + std::vector<Gtk::Widget*>::iterator mid=kids.end(); + for(auto i = kids.begin(); i!= kids.end(); ++i){ + if(curr == (*i)->gobj()) + mid = i; + } + while ( mid != kids.end() && !(mid==kids.begin() && direction<0 ) ) { + mid = ( direction < 0 ) ? std::prev(mid) : ++mid; + if ( mid!=kids.end() && GTK_IS_TOOL_ITEM((*mid)->gobj()) ) { /* potential target */ - GtkWidget* child = gtk_bin_get_child( GTK_BIN(mid->data) ); + GtkWidget* child = gtk_bin_get_child( GTK_BIN((*mid)->gobj()) ); if ( child && GTK_IS_BOX(child) ) { /* could be ours */ - GList* subChildren = gtk_container_get_children( GTK_CONTAINER(child) ); - if ( subChildren ) { - GList* last = g_list_last(subChildren); - if ( last && GTK_IS_SPIN_BUTTON(last->data) && gtk_widget_is_sensitive( GTK_WIDGET(last->data) ) ) { - gtk_widget_grab_focus( GTK_WIDGET(last->data) ); + std::vector<Gtk::Widget*> subChildren = Glib::wrap(GTK_CONTAINER(child))->get_children(); + if ( ! subChildren.empty() ) { + Gtk::Widget *last = subChildren[subChildren.size()-1]; + if ( GTK_IS_SPIN_BUTTON(last->gobj()) && gtk_widget_is_sensitive( GTK_WIDGET(last->gobj()) ) ) { + gtk_widget_grab_focus( GTK_WIDGET(last->gobj()) ); handled = TRUE; - mid = 0; /* to stop loop */ + mid = kids.end(); /* to stop loop */ } - - g_list_free(subChildren); } } } } } - g_list_free( kids ); } } diff --git a/src/widgets/ege-output-action.cpp b/src/widgets/ege-output-action.cpp index da29524a5..e7d74a25f 100644 --- a/src/widgets/ege-output-action.cpp +++ b/src/widgets/ege-output-action.cpp @@ -42,6 +42,8 @@ #include <string.h> #include <gtk/gtk.h> +#include <gtkmm/container.h> +#include <gtkmm/label.h> #include "widgets/ege-output-action.h" @@ -211,22 +213,23 @@ void fixup_labels( GObject *gobject, GParamSpec *arg1, gpointer user_data ) GSList* proxies = gtk_action_get_proxies( GTK_ACTION(gobject) ); gchar* str = 0; g_object_get( gobject, "label", &str, NULL ); + Glib::ustring str2(str); (void)user_data; while ( proxies ) { if ( GTK_IS_TOOL_ITEM(proxies->data) ) { /* Search for the things we built up in create_tool_item() */ - GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) ); - if ( children && children->data ) { - if ( GTK_IS_BOX(children->data) ) { - children = gtk_container_get_children( GTK_CONTAINER(children->data) ); - if ( children && g_list_next(children) ) { - GtkWidget* child = GTK_WIDGET( g_list_next(children)->data ); - if ( GTK_IS_LABEL(child) ) { - GtkLabel* lbl = GTK_LABEL(child); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(proxies->data))->get_children(); + if ( !children.empty() ) { + if ( GTK_IS_BOX(children[0]->gobj()) ) { + children = dynamic_cast<Gtk::Container *>(children[0])->get_children(); + if ( children.size()>1 ) { + Gtk::Widget *child = children[1]; + if ( GTK_IS_LABEL(child->gobj()) ) { + Gtk::Label* lbl = dynamic_cast<Gtk::Label *>(child); if ( EGE_OUTPUT_ACTION(gobject)->private_data->useMarkup ) { - gtk_label_set_markup( lbl, str ); + lbl->set_markup(str2); } else { - gtk_label_set_text( lbl, str ); + lbl->set_text(str2); } } } diff --git a/src/widgets/ege-select-one-action.cpp b/src/widgets/ege-select-one-action.cpp index 5555663e4..f51e48a8c 100644 --- a/src/widgets/ege-select-one-action.cpp +++ b/src/widgets/ege-select-one-action.cpp @@ -40,6 +40,8 @@ /* Note: this file should be kept compilable as both .cpp and .c */ #include <string.h> +#include <vector> +#include <gtkmm/checkmenuitem.h> #include <gtk/gtk.h> @@ -843,9 +845,9 @@ void resync_active( EgeSelectOneAction* act, gint active, gboolean override ) while ( proxies ) { if ( GTK_IS_TOOL_ITEM(proxies->data) ) { /* Search for the things we built up in create_tool_item() */ - GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) ); - if ( children && children->data ) { - gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" ); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(proxies->data))->get_children(); + if ( !children.empty() ) { + gpointer combodata = g_object_get_data( G_OBJECT(children[0]->gobj()), "ege-combo-box" ); if ( GTK_IS_COMBO_BOX(combodata) ) { GtkComboBox* combo = GTK_COMBO_BOX(combodata); @@ -854,8 +856,8 @@ void resync_active( EgeSelectOneAction* act, gint active, gboolean override ) } else if ( gtk_combo_box_get_active(combo) != active ) { gtk_combo_box_set_active( combo, active ); } - } else if ( GTK_IS_BOX(children->data) ) { - gpointer data = g_object_get_data( G_OBJECT(children->data), "ege-proxy_action-group" ); + } else if ( GTK_IS_BOX(children[0]->gobj()) ) { + gpointer data = g_object_get_data( G_OBJECT(children[0]->gobj()), "ege-proxy_action-group" ); if ( data ) { GSList* group = (GSList*)data; GtkRadioAction* oneAction = GTK_RADIO_ACTION(group->data); @@ -880,10 +882,9 @@ void resync_active( EgeSelectOneAction* act, gint active, gboolean override ) } } else if ( GTK_IS_MENU_ITEM(proxies->data) ) { GtkWidget* subMenu = gtk_menu_item_get_submenu( GTK_MENU_ITEM(proxies->data) ); - GList* children = gtk_container_get_children( GTK_CONTAINER(subMenu) ); - if ( children && (g_list_length(children) > (guint)active) ) { - gpointer data = g_list_nth_data( children, active ); - gtk_check_menu_item_set_active( GTK_CHECK_MENU_ITEM(data), TRUE ); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(subMenu))->get_children(); + if ( children.size() > (guint)active ) { + dynamic_cast<Gtk::CheckMenuItem*>(children[active])->set_active(true); } } @@ -900,14 +901,14 @@ void resync_sensitive( EgeSelectOneAction* act ) while ( proxies ) { if ( GTK_IS_TOOL_ITEM(proxies->data) ) { /* Search for the things we built up in create_tool_item() */ - GList* children = gtk_container_get_children( GTK_CONTAINER(proxies->data) ); - if ( children && children->data ) { - gpointer combodata = g_object_get_data( G_OBJECT(children->data), "ege-combo-box" ); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(proxies->data))->get_children(); + if ( !children.empty() ) { + gpointer combodata = g_object_get_data( G_OBJECT(children[0]->gobj()), "ege-combo-box" ); if ( GTK_IS_COMBO_BOX(combodata) ) { /* Not implemented */ - } else if ( GTK_IS_BOX(children->data) ) { - gpointer data = g_object_get_data( G_OBJECT(children->data), "ege-proxy_action-group" ); + } else if ( GTK_IS_BOX(children[0]->gobj()) ) { + gpointer data = g_object_get_data( G_OBJECT(children[0]->gobj()), "ege-proxy_action-group" ); if ( data ) { GSList* group = (GSList*)data; // List is backwards in group as compared to GtkTreeModel, we better do matching. diff --git a/src/widgets/gimp/ruler.cpp b/src/widgets/gimp/ruler.cpp index 6a1f7f903..8d73ada3b 100644 --- a/src/widgets/gimp/ruler.cpp +++ b/src/widgets/gimp/ruler.cpp @@ -32,6 +32,7 @@ #include <cstring> #include <cmath> #include <cstdio> +#include <set> #include "ruler.h" #include <glibmm/i18n.h> @@ -61,8 +62,9 @@ enum { /* All distances below are in 1/72nd's of an inch. (According to * Adobe, that's a point, but points are really 1/72.27 in.) */ -typedef struct +class SPRulerPrivate { +public: GtkOrientation orientation; Inkscape::Util::Unit const *unit; gdouble lower; @@ -78,8 +80,8 @@ typedef struct PangoLayout *layout; gdouble font_scale; - GList *track_widgets; -} SPRulerPrivate; + std::set<GtkWidget*> *track_widgets; +}; #define SP_RULER_GET_PRIVATE(ruler) \ G_TYPE_INSTANCE_GET_PRIVATE (ruler, SP_TYPE_RULER, SPRulerPrivate) @@ -178,6 +180,7 @@ sp_ruler_class_init (SPRulerClass *klass) g_type_class_add_private (object_class, sizeof (SPRulerPrivate)); + g_object_class_install_property (object_class, PROP_ORIENTATION, g_param_spec_enum ("orientation", @@ -269,6 +272,7 @@ sp_ruler_init (SPRuler *ruler) priv->pos_redraw_idle_id = 0; priv->font_scale = DEFAULT_RULER_FONT_SCALE; + priv->track_widgets = new std::set<GtkWidget*>; } static void @@ -277,14 +281,15 @@ sp_ruler_dispose (GObject *object) SPRuler *ruler = SP_RULER (object); SPRulerPrivate *priv = SP_RULER_GET_PRIVATE (ruler); - while (priv->track_widgets) - sp_ruler_remove_track_widget (ruler, GTK_WIDGET(priv->track_widgets->data)); + for (auto i:*(priv->track_widgets)) + sp_ruler_remove_track_widget (ruler, i); if (priv->pos_redraw_idle_id) { g_source_remove (priv->pos_redraw_idle_id); priv->pos_redraw_idle_id = 0; } + delete priv->track_widgets; G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -889,9 +894,10 @@ sp_ruler_add_track_widget (SPRuler *ruler, priv = SP_RULER_GET_PRIVATE (ruler); - g_return_if_fail (g_list_find (priv->track_widgets, widget) == NULL); + g_return_if_fail (priv->track_widgets->find(widget)==priv->track_widgets->end()); + - priv->track_widgets = g_list_prepend (priv->track_widgets, widget); + priv->track_widgets->insert(widget); g_signal_connect (widget, "motion-notify-event", G_CALLBACK (sp_ruler_track_widget_motion_notify), @@ -920,9 +926,9 @@ sp_ruler_remove_track_widget (SPRuler *ruler, priv = SP_RULER_GET_PRIVATE (ruler); - g_return_if_fail (g_list_find (priv->track_widgets, widget) != NULL); + g_return_if_fail (priv->track_widgets->find(widget)!=priv->track_widgets->end()); - priv->track_widgets = g_list_remove (priv->track_widgets, widget); + priv->track_widgets->erase(widget); g_signal_handlers_disconnect_by_func (widget, (gpointer) G_CALLBACK (sp_ruler_track_widget_motion_notify), diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 0c5f3cf47..fdba2b56d 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -268,17 +268,16 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) gvs->store->clear(); /* Pick up all gradients with vectors */ - GSList *gl = NULL; + std::vector<SPGradient *> gl; if (gvs->gr) { std::vector<SPObject *> gradients = gvs->gr->document->getResourceList("gradient"); for (std::vector<SPObject *>::const_iterator it = gradients.begin(); it != gradients.end(); ++it) { SPGradient* grad = SP_GRADIENT(*it); if ( grad->hasStops() && (grad->isSwatch() == gvs->swatched) ) { - gl = g_slist_prepend(gl, *it); + gl.push_back(SP_GRADIENT(*it)); } } } - gl = g_slist_reverse(gl); /* Get usage count of all the gradients */ std::map<SPGradient *, gint> usageCount; @@ -288,7 +287,7 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) Gtk::TreeModel::Row row = *(gvs->store->append()); row[gvs->columns->name] = _("No document selected"); - } else if (!gl) { + } else if (gl.empty()) { Gtk::TreeModel::Row row = *(gvs->store->append()); row[gvs->columns->name] = _("No gradients in document"); @@ -297,11 +296,7 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) row[gvs->columns->name] = _("No gradient selected"); } else { - while (gl) { - SPGradient *gr; - gr = SP_GRADIENT(gl->data); - gl = g_slist_remove(gl, gr); - + for (auto gr:gl) { unsigned long hhssll = sp_gradient_to_hhssll(gr); GdkPixbuf *pixb = sp_gradient_to_pixbuf (gr, 64, 18); Glib::ustring label = gr_prepare_label(gr); @@ -312,7 +307,6 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) row[gvs->columns->refcount] = usageCount[gr]; row[gvs->columns->data] = gr; row[gvs->columns->pixbuf] = Glib::wrap(pixb); - } } @@ -333,19 +327,14 @@ unsigned long sp_gradient_to_hhssll(SPGradient *gr) return ((int)(hsl[0]*100 * 10000)) + ((int)(hsl[1]*100 * 100)) + ((int)(hsl[2]*100 * 1)); } -static GSList *get_all_doc_items(GSList *list, SPObject *from, bool onlyvisible, bool onlysensitive, bool ingroups, GSList const *exclude) +static void get_all_doc_items(std::vector<SPItem*> &list, SPObject *from) { for (auto& child: from->children) { if (SP_IS_ITEM(&child)) { - list = g_slist_prepend(list, SP_ITEM(&child)); - } - - if (ingroups || SP_IS_ITEM(&child)) { - list = get_all_doc_items(list, &child, onlyvisible, onlysensitive, ingroups, exclude); + list.push_back(SP_ITEM(&child)); } + get_all_doc_items(list, &child); } - - return list; } /* @@ -377,15 +366,10 @@ void gr_get_usage_counts(SPDocument *doc, std::map<SPGradient *, gint> *mapUsage if (!doc) return; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); - bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); - bool ingroups = TRUE; - - GSList *all_list = get_all_doc_items(NULL, doc->getRoot(), onlyvisible, onlysensitive, ingroups, NULL); + std::vector<SPItem *> all_list; + get_all_doc_items(all_list, doc->getRoot()); - for (GSList *i = all_list; i != NULL; i = i->next) { - SPItem *item = SP_ITEM(i->data); + for (auto item:all_list) { if (!item->getId()) continue; SPGradient *gr = NULL; @@ -565,34 +549,29 @@ static void update_stop_list( GtkWidget *vb, SPGradient *gradient, SPStop *new_s GtkTreeIter iter; /* Populate the combobox store */ - GSList *sl = NULL; + std::vector<SPStop *> sl; if ( gradient->hasStops() ) { for (auto& ochild: gradient->children) { if (SP_IS_STOP(&ochild)) { - sl = g_slist_append(sl, &ochild); + sl.push_back(SP_STOP(&ochild)); } } } - if (!sl) { + if (sl.empty()) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, NULL, 1, _("No stops in gradient"), 2, NULL, -1); gtk_widget_set_sensitive (combo_box, FALSE); } else { - for (; sl != NULL; sl = sl->next){ - if (SP_IS_STOP(sl->data)){ - SPStop *stop = SP_STOP(sl->data); - Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(sl->data)->getRepr(); - Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32())); - GdkPixbuf *pb = cpv->toPixbuf(64, 16); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, 0, pb, 1, repr->attribute("id"), 2, stop, -1); - gtk_widget_set_sensitive (combo_box, FALSE); - } + for (auto stop:sl) { + Inkscape::XML::Node *repr = stop->getRepr(); + Inkscape::UI::Widget::ColorPreview *cpv = Gtk::manage(new Inkscape::UI::Widget::ColorPreview(stop->get_rgba32())); + GdkPixbuf *pb = cpv->toPixbuf(64, 16); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, pb, 1, repr->attribute("id"), 2, stop, -1); + gtk_widget_set_sensitive (combo_box, FALSE); } - gtk_widget_set_sensitive(combo_box, TRUE); } diff --git a/src/widgets/ink-action.h b/src/widgets/ink-action.h index 99786c878..396e4838b 100644 --- a/src/widgets/ink-action.h +++ b/src/widgets/ink-action.h @@ -2,7 +2,6 @@ #define SEEN_INK_ACTION #include <gtk/gtk.h> -#include "icon-size.h" #include "attributes.h" /* Equivalent to GTK Actions of the same type, but can support Inkscape SVG icons */ diff --git a/src/widgets/ink-toggle-action.cpp b/src/widgets/ink-toggle-action.cpp index c091a2e0d..200d0d558 100644 --- a/src/widgets/ink-toggle-action.cpp +++ b/src/widgets/ink-toggle-action.cpp @@ -51,9 +51,9 @@ static void ink_toggle_action_class_init( InkToggleActionClass* klass ) g_param_spec_int( "iconSize", "Icon Size", "The size the icon", - (int)Inkscape::ICON_SIZE_MENU, + GTK_ICON_SIZE_MENU, (int)99, - (int)Inkscape::ICON_SIZE_SMALL_TOOLBAR, + GTK_ICON_SIZE_SMALL_TOOLBAR, (GParamFlags)(G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT) ) ); g_type_class_add_private( klass, sizeof(InkToggleActionClass) ); diff --git a/src/widgets/ink-toggle-action.h b/src/widgets/ink-toggle-action.h index 9130b9f9f..f329f57a6 100644 --- a/src/widgets/ink-toggle-action.h +++ b/src/widgets/ink-toggle-action.h @@ -4,7 +4,6 @@ #include <gtk/gtk.h> #include "attributes.h" -#include "icon-size.h" G_BEGIN_DECLS #define INK_TOGGLE_ACTION_TYPE ( ink_toggle_action_get_type() ) diff --git a/src/widgets/makefile.in b/src/widgets/makefile.in deleted file mode 100644 index 5b756ebf3..000000000 --- a/src/widgets/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) widgets/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) widgets/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index 27fe4b63a..4457b712d 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -23,6 +23,7 @@ #include <cstring> #include <string> +#include <vector> #include "widgets/swatch-selector.h" #include "sp-pattern.h" @@ -789,25 +790,23 @@ static void sp_psel_mesh_change(GtkWidget * /*widget*/, SPPaintSelector *psel) /** - * Returns a list of meshes in the defs of the given source document as a GSList object - * Returns NULL if there are no meshes in the document. + * Returns a list of meshes in the defs of the given source document as a vector */ -static GSList * +static std::vector<SPMeshGradient *> ink_mesh_list_get (SPDocument *source) { + std::vector<SPMeshGradient *> pl; if (source == NULL) - return NULL; + return pl; + - GSList *pl = NULL; std::vector<SPObject *> meshes = source->getResourceList("gradient"); for (std::vector<SPObject *>::const_iterator it = meshes.begin(); it != meshes.end(); ++it) { if (SP_IS_MESHGRADIENT(*it) && SP_GRADIENT(*it) == SP_GRADIENT(*it)->getArray()) { // only if this is a root mesh - pl = g_slist_prepend(pl, *it); + pl.push_back(SP_MESHGRADIENT(*it)); } } - - pl = g_slist_reverse(pl); return pl; } @@ -815,14 +814,14 @@ ink_mesh_list_get (SPDocument *source) * Adds menu items for mesh list. */ static void -sp_mesh_menu_build (GtkWidget *combo, GSList *mesh_list, SPDocument */*source*/) +sp_mesh_menu_build (GtkWidget *combo, std::vector<SPMeshGradient *> &mesh_list, SPDocument */*source*/) { GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo))); GtkTreeIter iter; - for (; mesh_list != NULL; mesh_list = mesh_list->next) { + for (auto i:mesh_list) { - Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(mesh_list->data)->getRepr(); + Inkscape::XML::Node *repr = i->getRepr(); gchar const *meshid = repr->attribute("id"); gchar const *label = meshid; @@ -847,21 +846,8 @@ sp_mesh_menu_build (GtkWidget *combo, GSList *mesh_list, SPDocument */*source*/) */ static void sp_mesh_list_from_doc(GtkWidget *combo, SPDocument * /*current_doc*/, SPDocument *source, SPDocument * /*mesh_doc*/) { - GSList *pl = ink_mesh_list_get(source); - GSList *clean_pl = NULL; - - for (; pl != NULL; pl = pl->next) { - if (!SP_IS_MESHGRADIENT(pl->data)) { - continue; - } - // Add to the list of meshes we really do wish to show - clean_pl = g_slist_prepend (clean_pl, pl->data); - } - - sp_mesh_menu_build (combo, clean_pl, source); - - g_slist_free (pl); - g_slist_free (clean_pl); + std::vector<SPMeshGradient *> pl = ink_mesh_list_get(source); + sp_mesh_menu_build (combo, pl, source); } @@ -1138,24 +1124,22 @@ static void sp_psel_pattern_change(GtkWidget * /*widget*/, SPPaintSelector *psel /** - * Returns a list of patterns in the defs of the given source document as a GSList object - * Returns NULL if there are no patterns in the document. + * Returns a list of patterns in the defs of the given source document as a vector */ -static GSList * +static std::vector<SPPattern*> ink_pattern_list_get (SPDocument *source) { + std::vector<SPPattern *> pl; if (source == NULL) - return NULL; + return pl; - GSList *pl = NULL; std::vector<SPObject *> patterns = source->getResourceList("pattern"); for (std::vector<SPObject *>::const_iterator it = patterns.begin(); it != patterns.end(); ++it) { if (SP_PATTERN(*it) == SP_PATTERN(*it)->rootPattern()) { // only if this is a root pattern - pl = g_slist_prepend(pl, *it); + pl.push_back(SP_PATTERN(*it)); } } - pl = g_slist_reverse(pl); return pl; } @@ -1163,14 +1147,14 @@ ink_pattern_list_get (SPDocument *source) * Adds menu items for pattern list - derived from marker code, left hb etc in to make addition of previews easier at some point. */ static void -sp_pattern_menu_build (GtkWidget *combo, GSList *pattern_list, SPDocument */*source*/) +sp_pattern_menu_build (GtkWidget *combo, std::vector<SPPattern *> &pl, SPDocument */*source*/) { GtkListStore *store = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(combo))); GtkTreeIter iter; - for (; pattern_list != NULL; pattern_list = pattern_list->next) { + for (auto i=pl.rbegin(); i!=pl.rend(); ++i) { - Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(pattern_list->data)->getRepr(); + Inkscape::XML::Node *repr = (*i)->getRepr(); // label for combobox gchar const *label; @@ -1200,22 +1184,8 @@ sp_pattern_menu_build (GtkWidget *combo, GSList *pattern_list, SPDocument */*sou */ static void sp_pattern_list_from_doc(GtkWidget *combo, SPDocument * /*current_doc*/, SPDocument *source, SPDocument * /*pattern_doc*/) { - GSList *pl = ink_pattern_list_get(source); - GSList *clean_pl = NULL; - - for (; pl != NULL; pl = pl->next) { - if (!SP_IS_PATTERN(pl->data)) { - continue; - } - - // Add to the list of patterns we really do wish to show - clean_pl = g_slist_prepend (clean_pl, pl->data); - } - - sp_pattern_menu_build (combo, clean_pl, source); - - g_slist_free (pl); - g_slist_free (clean_pl); + std::vector<SPPattern *> pl = ink_pattern_list_get(source); + sp_pattern_menu_build (combo, pl, source); } diff --git a/src/widgets/pencil-toolbar.cpp b/src/widgets/pencil-toolbar.cpp index a9d27566d..ea7411285 100644 --- a/src/widgets/pencil-toolbar.cpp +++ b/src/widgets/pencil-toolbar.cpp @@ -205,41 +205,29 @@ static void freehand_simplify_lpe(InkToggleAction* itact, GObject *dataKludge) { } } -/** - * Generate the list of freehand advanced shape option entries. - */ -static GList * freehand_shape_dropdown_items_list() { - GList *glist = NULL; - - glist = g_list_append (glist, const_cast<gchar *>(C_("Freehand shape", "None"))); - glist = g_list_append (glist, _("Triangle in")); - glist = g_list_append (glist, _("Triangle out")); - glist = g_list_append (glist, _("Ellipse")); - glist = g_list_append (glist, _("From clipboard")); - glist = g_list_append (glist, _("Bend from clipboard")); - glist = g_list_append (glist, _("Last applied")); - - return glist; -} - static void freehand_add_advanced_shape_options(GtkActionGroup* mainActions, GObject* holder, bool tool_is_pencil) { /*advanced shape options */ { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT ); - - GList* items = 0; gint count = 0; - for ( items = freehand_shape_dropdown_items_list(); items ; items = g_list_next(items) ) + std::vector<gchar*> freehand_shape_dropdown_items_list = { + const_cast<gchar *>(C_("Freehand shape", "None")), + _("Triangle in"), + _("Triangle out"), + _("Ellipse"), + _("From clipboard"), + _("Bend from clipboard"), + _("Last applied") }; + + for (auto item:freehand_shape_dropdown_items_list) { GtkTreeIter iter; gtk_list_store_append( model, &iter ); - gtk_list_store_set( model, &iter, 0, reinterpret_cast<gchar*>(items->data), 1, count, -1 ); + gtk_list_store_set( model, &iter, 0, item, 1, count, -1 ); count++; } - g_list_free( items ); - items = 0; EgeSelectOneAction* act1 = ege_select_one_action_new( tool_is_pencil ? "SetPencilShapeAction" : "SetPenShapeAction", _("Shape:"), (_("Shape of new paths drawn by this tool")), NULL, GTK_TREE_MODEL(model)); diff --git a/src/widgets/spinbutton-events.cpp b/src/widgets/spinbutton-events.cpp index fdf88ec85..9666fc636 100644 --- a/src/widgets/spinbutton-events.cpp +++ b/src/widgets/spinbutton-events.cpp @@ -66,7 +66,7 @@ gboolean spinbutton_keypress(GtkWidget *w, GdkEventKey *event, gpointer /*data*/ { gboolean result = FALSE; // I didn't consume the event - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_latin_keyval(event)) { case GDK_KEY_Escape: // defocus spinbutton_undo(w); spinbutton_defocus(w); diff --git a/src/widgets/spw-utilities.cpp b/src/widgets/spw-utilities.cpp index 68fb78327..992f1f6b7 100644 --- a/src/widgets/spw-utilities.cpp +++ b/src/widgets/spw-utilities.cpp @@ -61,31 +61,6 @@ Gtk::Label * spw_label(Gtk::Grid *table, const gchar *label_text, int col, int r return label_widget; } -GtkWidget * -spw_label_old(GtkWidget *table, const gchar *label_text, int col, int row) -{ - GtkWidget *label_widget; - - label_widget = gtk_label_new (label_text); - g_assert(label_widget != NULL); - gtk_widget_set_halign(label_widget, GTK_ALIGN_END); - gtk_widget_show (label_widget); - -#if GTK_CHECK_VERSION(3,12,0) - gtk_widget_set_margin_start(label_widget, 4); - gtk_widget_set_margin_end(label_widget, 4); -#else - gtk_widget_set_margin_left(label_widget, 4); - gtk_widget_set_margin_right(label_widget, 4); -#endif - gtk_widget_set_hexpand(label_widget, TRUE); - gtk_widget_set_halign(label_widget, GTK_ALIGN_FILL); - gtk_widget_set_valign(label_widget, GTK_ALIGN_CENTER); - gtk_grid_attach(GTK_GRID(table), label_widget, col, row, 1, 1); - - return label_widget; -} - /** * Creates a horizontal layout manager with 4-pixel spacing between children * and space for 'width' columns. @@ -104,94 +79,6 @@ Gtk::HBox * spw_hbox(Gtk::Grid * table, int width, int col, int row) return hb; } -/** - * Creates a checkbutton widget and adds it to a vbox. - * This is a compound widget that includes a label. - */ -GtkWidget *spw_vbox_checkbutton(GtkWidget *dialog, GtkWidget *vbox, - const gchar *label, const gchar *tip, gchar *key, GCallback cb) -{ - g_assert (dialog != NULL); - g_assert (vbox != NULL); - - GtkWidget *b = gtk_check_button_new_with_label (label); - gtk_widget_set_tooltip_text(b, tip); - g_assert (b != NULL); - gtk_widget_show (b); - gtk_box_pack_start (GTK_BOX (vbox), b, FALSE, FALSE, 0); - g_object_set_data (G_OBJECT (b), "key", key); - g_object_set_data (G_OBJECT (dialog), key, b); - g_signal_connect (G_OBJECT (b), "toggled", cb, dialog); - return b; -} - - -/** - * Creates a checkbutton widget and adds it to a table. - * This is a compound widget that includes a label. - */ -GtkWidget * -spw_checkbutton(GtkWidget * dialog, GtkWidget * table, - const gchar * label, gchar * key, int /*col*/, int row, - int insensitive, GCallback cb) -{ - GtkWidget *b; - - g_assert(dialog != NULL); - g_assert(table != NULL); - - GtkWidget *l = gtk_label_new (label); - gtk_widget_set_halign(l, GTK_ALIGN_END); - gtk_widget_show (l); - - gtk_widget_set_halign(l, GTK_ALIGN_FILL); - gtk_widget_set_hexpand(l, TRUE); - gtk_widget_set_valign(l, GTK_ALIGN_CENTER); - gtk_grid_attach(GTK_GRID(table), l, 0, row, 1, 1); - - b = gtk_check_button_new (); - gtk_widget_show (b); - - gtk_widget_set_halign(b, GTK_ALIGN_FILL); - gtk_widget_set_hexpand(b, TRUE); - gtk_widget_set_valign(b, GTK_ALIGN_CENTER); - gtk_grid_attach(GTK_GRID(table), b, 1, row, 1, 1); - - g_object_set_data (G_OBJECT (b), "key", key); - g_object_set_data (G_OBJECT (dialog), key, b); - g_signal_connect (G_OBJECT (b), "toggled", cb, dialog); - if (insensitive == 1) { - gtk_widget_set_sensitive (b, FALSE); - } - return b; -} - -/** - * Creates a dropdown widget. This is a compound widget that includes - * a label as well as the dropdown. - */ -GtkWidget * -spw_dropdown(GtkWidget * dialog, GtkWidget * table, - const gchar * label_text, gchar * key, int row, - GtkWidget * selector - ) -{ - g_assert(dialog != NULL); - g_assert(table != NULL); - g_assert(selector != NULL); - - spw_label_old(table, label_text, 0, row); - - gtk_widget_show (selector); - gtk_widget_set_halign(selector, GTK_ALIGN_FILL); - gtk_widget_set_hexpand(selector, TRUE); - gtk_widget_set_valign(selector, GTK_ALIGN_CENTER); - gtk_grid_attach(GTK_GRID(table), selector, 1, row, 1, 1); - - g_object_set_data (G_OBJECT (dialog), key, selector); - return selector; -} - static void sp_set_font_size_recursive (GtkWidget *w, gpointer font) { @@ -249,9 +136,9 @@ gpointer sp_search_by_data_recursive(GtkWidget *w, gpointer key) if (r) return r; if (GTK_IS_CONTAINER(w)) { - GList *ch = gtk_container_get_children (GTK_CONTAINER(w)); - for (GList *i = ch; i != NULL; i = i->next) { - r = sp_search_by_data_recursive(GTK_WIDGET(i->data), key); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(w))->get_children(); + for (auto i:children) { + r = sp_search_by_data_recursive(GTK_WIDGET(i->gobj()), key); if (r) return r; } } @@ -272,9 +159,9 @@ GtkWidget *sp_search_by_value_recursive(GtkWidget *w, gchar *key, gchar *value) if (r && !strcmp (r, value)) return w; if (GTK_IS_CONTAINER(w)) { - GList *ch = gtk_container_get_children (GTK_CONTAINER(w)); - for (GList *i = ch; i != NULL; i = i->next) { - GtkWidget *child = sp_search_by_value_recursive(GTK_WIDGET(i->data), key, value); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(w))->get_children(); + for (auto i:children) { + GtkWidget *child = sp_search_by_value_recursive(GTK_WIDGET(i->gobj()), key, value); if (child) return child; } } diff --git a/src/widgets/spw-utilities.h b/src/widgets/spw-utilities.h index 71b451631..ea0d55279 100644 --- a/src/widgets/spw-utilities.h +++ b/src/widgets/spw-utilities.h @@ -27,22 +27,6 @@ namespace Gtk { Gtk::Label * spw_label(Gtk::Grid *table, gchar const *label_text, int col, int row, Gtk::Widget *target); Gtk::HBox * spw_hbox(Gtk::Grid *table, int width, int col, int row); -GtkWidget * spw_label_old(GtkWidget *table, gchar const *label_text, int col, int row); - -GtkWidget * -spw_vbox_checkbutton(GtkWidget *dialog, GtkWidget *table, - const gchar *label, const gchar *tip, gchar *key, GCallback cb); - -GtkWidget * -spw_checkbutton(GtkWidget *dialog, GtkWidget *table, - gchar const *label, gchar *key, int col, int row, - int sensitive, GCallback cb); - -GtkWidget * -spw_dropdown(GtkWidget *dialog, GtkWidget *table, - gchar const *label, gchar *key, int row, - GtkWidget *selector - ); void sp_set_font_size (GtkWidget *w, guint font); void sp_set_font_size_smaller (GtkWidget *w); diff --git a/src/widgets/stroke-marker-selector.cpp b/src/widgets/stroke-marker-selector.cpp index 96994741c..9ddcf993d 100644 --- a/src/widgets/stroke-marker-selector.cpp +++ b/src/widgets/stroke-marker-selector.cpp @@ -111,22 +111,20 @@ MarkerComboBox::refreshHistory() updating = true; - GSList *ml = get_marker_list(doc); + std::vector<SPMarker *> ml = get_marker_list(doc); /* * Seems to be no way to get notified of changes just to markers, * so listen to changes in all defs and check if the number of markers has changed here * to avoid unnecessary refreshes when things like gradients change */ - if (markerCount != g_slist_length(ml)) { + if (markerCount != ml.size()) { const char *active = get_active()->get_value(marker_columns.marker); sp_marker_list_from_doc(doc, true); set_selected(active); - markerCount = g_slist_length(ml); + markerCount = ml.size(); } - g_slist_free (ml); - updating = false; } @@ -295,45 +293,32 @@ void MarkerComboBox::set_selected(const gchar *name, gboolean retry/*=true*/) { */ void MarkerComboBox::sp_marker_list_from_doc(SPDocument *source, gboolean history) { - GSList *ml = get_marker_list(source); - GSList *clean_ml = NULL; - - for (; ml != NULL; ml = ml->next) { - if (!SP_IS_MARKER(ml->data)) - continue; - - // Add to the list of markers we really do wish to show - clean_ml = g_slist_prepend (clean_ml, ml->data); - } + std::vector<SPMarker *> ml = get_marker_list(source); remove_markers(history); // Seem to need to remove 2x remove_markers(history); - add_markers(clean_ml, source, history); - - g_slist_free (ml); - g_slist_free (clean_ml); - + add_markers(ml, source, history); } /** - * Returns a list of markers in the defs of the given source document as a GSList object + * Returns a list of markers in the defs of the given source document as a vector * Returns NULL if there are no markers in the document. */ -GSList *MarkerComboBox::get_marker_list (SPDocument *source) +std::vector<SPMarker *> MarkerComboBox::get_marker_list (SPDocument *source) { + std::vector<SPMarker *> ml; if (source == NULL) - return NULL; + return ml; - GSList *ml = NULL; SPDefs *defs = source->getDefs(); if (!defs) { - return NULL; + return ml; } for (auto& child: defs->children) { if (SP_IS_MARKER(&child)) { - ml = g_slist_prepend (ml, &child); + ml.push_back(SP_MARKER(&child)); } } return ml; @@ -361,7 +346,7 @@ void MarkerComboBox::remove_markers (gboolean history) /** * Adds markers in marker_list to the combo */ -void MarkerComboBox::add_markers (GSList *marker_list, SPDocument *source, gboolean history) +void MarkerComboBox::add_markers (std::vector<SPMarker *> const& marker_list, SPDocument *source, gboolean history) { // Do this here, outside of loop, to speed up preview generation: Inkscape::Drawing drawing; @@ -388,9 +373,9 @@ void MarkerComboBox::add_markers (GSList *marker_list, SPDocument *source, gbool row[marker_columns.separator] = false; } - for (; marker_list != NULL; marker_list = marker_list->next) { + for (auto i:marker_list) { - Inkscape::XML::Node *repr = reinterpret_cast<SPItem *>(marker_list->data)->getRepr(); + Inkscape::XML::Node *repr = i->getRepr(); gchar const *markid = repr->attribute("inkscape:stockid") ? repr->attribute("inkscape:stockid") : repr->attribute("id"); // generate preview diff --git a/src/widgets/stroke-marker-selector.h b/src/widgets/stroke-marker-selector.h index a7ee788b8..24389526c 100644 --- a/src/widgets/stroke-marker-selector.h +++ b/src/widgets/stroke-marker-selector.h @@ -9,7 +9,7 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - +#include <vector> #include <gtkmm/box.h> #include <gtkmm/combobox.h> #include <gtkmm/liststore.h> @@ -20,6 +20,7 @@ #include "document.h" #include "inkscape.h" #include "display/drawing.h" +#include "sp-marker.h" namespace Gtk { class Container; @@ -80,8 +81,8 @@ private: void init_combo(); void set_history(Gtk::TreeModel::Row match_row); void sp_marker_list_from_doc(SPDocument *source, gboolean history); - GSList *get_marker_list (SPDocument *source); - void add_markers (GSList *marker_list, SPDocument *source, gboolean history); + std::vector <SPMarker*> get_marker_list (SPDocument *source); + void add_markers (std::vector<SPMarker *> const& marker_list, SPDocument *source, gboolean history); void remove_markers (gboolean history); SPDocument *ink_markers_preview_doc (); Gtk::Image * create_marker_image(unsigned psize, gchar const *mname, diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 68e38e8ed..447af9c71 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -795,13 +795,10 @@ void ToolboxFactory::setToolboxDesktop(GtkWidget *toolbox, SPDesktop *desktop) SPDesktop *old_desktop = static_cast<SPDesktop*>(ptr); if (old_desktop) { - GList *children, *iter; - - children = gtk_container_get_children(GTK_CONTAINER(toolbox)); - for ( iter = children ; iter ; iter = iter->next ) { - gtk_container_remove( GTK_CONTAINER(toolbox), GTK_WIDGET(iter->data) ); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(toolbox))->get_children(); + for ( auto i:children ) { + gtk_container_remove( GTK_CONTAINER(toolbox), i->gobj() ); } - g_list_free(children); } g_object_set_data(G_OBJECT(toolbox), "desktop", (gpointer)desktop); @@ -894,20 +891,20 @@ void ToolboxFactory::setOrientation(GtkWidget* toolbox, GtkOrientation orientati g_message(" is a BOX"); #endif // DUMP_DETAILS - GList* children = gtk_container_get_children(GTK_CONTAINER(child)); - if (children) { - for (GList* curr = children; curr; curr = g_list_next(curr)) { - GtkWidget* child2 = GTK_WIDGET(curr->data); + std::vector<Gtk::Widget*> children = Glib::wrap(GTK_CONTAINER(child))->get_children(); + if (!children.empty()) { + for (auto curr:children) { + GtkWidget* child2 = curr->gobj(); #if DUMP_DETAILS GType type3 = G_OBJECT_TYPE(child2); g_message(" child2 [%s]", g_type_name(type3)); #endif // DUMP_DETAILS if (GTK_IS_CONTAINER(child2)) { - GList* children2 = gtk_container_get_children(GTK_CONTAINER(child2)); - if (children2) { - for (GList* curr2 = children2; curr2; curr2 = g_list_next(curr2)) { - GtkWidget* child3 = GTK_WIDGET(curr2->data); + std::vector<Gtk::Widget*> children2 = Glib::wrap(GTK_CONTAINER(child2))->get_children(); + if (!children2.empty()) { + for (auto curr2:children2) { + GtkWidget* child3 = curr2->gobj(); #if DUMP_DETAILS GType type4 = G_OBJECT_TYPE(child3); g_message(" child3 [%s]", g_type_name(type4)); @@ -917,7 +914,6 @@ void ToolboxFactory::setOrientation(GtkWidget* toolbox, GtkOrientation orientati gtk_orientable_set_orientation(GTK_ORIENTABLE(childBar), orientation); } } - g_list_free(children2); } } @@ -929,7 +925,6 @@ void ToolboxFactory::setOrientation(GtkWidget* toolbox, GtkOrientation orientati g_message("need to add dynamic switch"); } } - g_list_free(children); } else { // The call is being made before the toolbox proper has been setup. g_object_set_data(G_OBJECT(toolbox), HANDLE_POS_MARK, GINT_TO_POINTER(pos)); diff --git a/src/widgets/toolbox.h b/src/widgets/toolbox.h index 09178ec2f..afa382e5b 100644 --- a/src/widgets/toolbox.h +++ b/src/widgets/toolbox.h @@ -15,7 +15,6 @@ #include <glibmm/ustring.h> -#include "icon-size.h" #include "preferences.h" #define TOOLBAR_SLIDER_HINT "full" diff --git a/src/winmain.cpp b/src/winmain.cpp deleted file mode 100644 index 5120e44e0..000000000 --- a/src/winmain.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdlib.h> -#include <glib.h> - -#ifdef G_OS_WIN32 -#undef DATADIR - -#include <stdio.h> -#include <io.h> -#include <conio.h> - -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0501) -# undef _WIN32_WINNT -# define _WIN32_WINNT 0x0501 -#endif - -#include <windows.h> - -extern int main (int argc, char **argv); - -/* In case we build this as a windowed application */ - -#ifdef __GNUC__ -# ifndef _stdcall -# define _stdcall __attribute__((stdcall)) -# endif -#endif - -int _stdcall -WinMain (struct HINSTANCE__ */*hInstance*/, - struct HINSTANCE__ */*hPrevInstance*/, - char */*lpszCmdLine*/, - int /*nCmdShow*/) -{ - if (fileno (stdout) != -1 && - _get_osfhandle (fileno (stdout)) != -1) - { - /* stdout is fine, presumably redirected to a file or pipe */ - } - else - { - typedef BOOL (* WINAPI AttachConsole_t) (DWORD); - - AttachConsole_t p_AttachConsole = - (AttachConsole_t) GetProcAddress (GetModuleHandle ("kernel32.dll"), "AttachConsole"); - - if (p_AttachConsole != NULL && p_AttachConsole (ATTACH_PARENT_PROCESS)) - { - freopen ("CONOUT$", "w", stdout); - dup2 (fileno (stdout), 1); - freopen ("CONOUT$", "w", stderr); - dup2 (fileno (stderr), 2); - - } - } - - int ret; - ret = main (__argc, __argv); - return ret; -} - -#endif diff --git a/src/xml/attribute-record.h b/src/xml/attribute-record.h index 7caeab6b6..91118c8a0 100644 --- a/src/xml/attribute-record.h +++ b/src/xml/attribute-record.h @@ -22,13 +22,13 @@ namespace XML { * represented by this structure. */ struct AttributeRecord : public Inkscape::GC::Managed<> { - AttributeRecord(GQuark k, Inkscape::Util::ptr_shared<char> v) + AttributeRecord(GQuark k, Inkscape::Util::ptr_shared v) : key(k), value(v) {} /** @brief GQuark corresponding to the name of the attribute */ GQuark key; /** @brief Shared pointer to the value of the attribute */ - Inkscape::Util::ptr_shared<char> value; + Inkscape::Util::ptr_shared value; // accept default copy constructor and assignment operator }; diff --git a/src/xml/comment-node.h b/src/xml/comment-node.h index 56b8ad476..7c37a0d24 100644 --- a/src/xml/comment-node.h +++ b/src/xml/comment-node.h @@ -26,7 +26,7 @@ namespace XML { * @brief Comment node, e.g. <!-- Some comment --> */ struct CommentNode : public SimpleNode { - CommentNode(Util::ptr_shared<char> content, Document *doc) + CommentNode(Util::ptr_shared content, Document *doc) : SimpleNode(g_quark_from_static_string("comment"), doc) { setContent(content); diff --git a/src/xml/composite-node-observer.cpp b/src/xml/composite-node-observer.cpp index 7343ab1a8..581a4c226 100644 --- a/src/xml/composite-node-observer.cpp +++ b/src/xml/composite-node-observer.cpp @@ -69,7 +69,7 @@ void CompositeNodeObserver::notifyChildOrderChanged(Node &node, Node &child, void CompositeNodeObserver::notifyContentChanged( Node &node, - Util::ptr_shared<char> old_content, Util::ptr_shared<char> new_content + Util::ptr_shared old_content, Util::ptr_shared new_content ) { _startIteration(); for ( ObserverRecordList::iterator iter=_active.begin() ; @@ -84,7 +84,7 @@ void CompositeNodeObserver::notifyContentChanged( void CompositeNodeObserver::notifyAttributeChanged( Node &node, GQuark name, - Util::ptr_shared<char> old_value, Util::ptr_shared<char> new_value + Util::ptr_shared old_value, Util::ptr_shared new_value ) { _startIteration(); for ( ObserverRecordList::iterator iter=_active.begin() ; @@ -133,13 +133,13 @@ public: } } - void notifyContentChanged(Node &node, Util::ptr_shared<char> old_content, Util::ptr_shared<char> new_content) { + void notifyContentChanged(Node &node, Util::ptr_shared old_content, Util::ptr_shared new_content) { if (vector.content_changed) { vector.content_changed(&node, old_content, new_content, data); } } - void notifyAttributeChanged(Node &node, GQuark name, Util::ptr_shared<char> old_value, Util::ptr_shared<char> new_value) { + void notifyAttributeChanged(Node &node, GQuark name, Util::ptr_shared old_value, Util::ptr_shared new_value) { if (vector.attr_changed) { vector.attr_changed(&node, g_quark_to_string(name), old_value, new_value, false, data); } diff --git a/src/xml/composite-node-observer.h b/src/xml/composite-node-observer.h index 6e93a57da..1004617bf 100644 --- a/src/xml/composite-node-observer.h +++ b/src/xml/composite-node-observer.h @@ -75,12 +75,12 @@ public: Node *old_prev, Node *new_prev); void notifyContentChanged(Node &node, - Util::ptr_shared<char> old_content, - Util::ptr_shared<char> new_content); + Util::ptr_shared old_content, + Util::ptr_shared new_content); void notifyAttributeChanged(Node &node, GQuark name, - Util::ptr_shared<char> old_value, - Util::ptr_shared<char> new_value); + Util::ptr_shared old_value, + Util::ptr_shared new_value); private: unsigned _iterating; diff --git a/src/xml/event.cpp b/src/xml/event.cpp index 9a760ccc5..54f55d5c3 100644 --- a/src/xml/event.cpp +++ b/src/xml/event.cpp @@ -107,15 +107,15 @@ public: } void notifyAttributeChanged(Node &node, GQuark name, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> new_value) + Inkscape::Util::ptr_shared /*old_value*/, + Inkscape::Util::ptr_shared new_value) { node.setAttribute(g_quark_to_string(name), new_value); } void notifyContentChanged(Node &node, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> new_value) + Inkscape::Util::ptr_shared /*old_value*/, + Inkscape::Util::ptr_shared new_value) { node.setContent(new_value); } @@ -461,8 +461,8 @@ public: } void notifyAttributeChanged(Node &node, GQuark name, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> new_value) + Inkscape::Util::ptr_shared /*old_value*/, + Inkscape::Util::ptr_shared new_value) { if (new_value) { g_warning("Event: Set attribute %s to \"%s\" on %s", g_quark_to_string(name), new_value.pointer(), node_to_string(node).c_str()); @@ -472,8 +472,8 @@ public: } void notifyContentChanged(Node &node, - Inkscape::Util::ptr_shared<char> /*old_value*/, - Inkscape::Util::ptr_shared<char> new_value) + Inkscape::Util::ptr_shared /*old_value*/, + Inkscape::Util::ptr_shared new_value) { if (new_value) { g_warning("Event: Set content of %s to \"%s\"", node_to_string(node).c_str(), new_value.pointer()); diff --git a/src/xml/event.h b/src/xml/event.h index f6b734c29..ca79983ba 100644 --- a/src/xml/event.h +++ b/src/xml/event.h @@ -167,8 +167,8 @@ private: class EventChgAttr : public Event { public: EventChgAttr(Node *repr, GQuark k, - Inkscape::Util::ptr_shared<char> ov, - Inkscape::Util::ptr_shared<char> nv, + Inkscape::Util::ptr_shared ov, + Inkscape::Util::ptr_shared nv, Event *next) : Event(repr, next), key(k), oldval(ov), newval(nv) {} @@ -176,9 +176,9 @@ public: /// GQuark corresponding to the changed attribute's name GQuark key; /// Value of the attribute before the change - Inkscape::Util::ptr_shared<char> oldval; + Inkscape::Util::ptr_shared oldval; /// Value of the attribute after the change - Inkscape::Util::ptr_shared<char> newval; + Inkscape::Util::ptr_shared newval; private: Event *_optimizeOne(); @@ -192,15 +192,15 @@ private: class EventChgContent : public Event { public: EventChgContent(Node *repr, - Inkscape::Util::ptr_shared<char> ov, - Inkscape::Util::ptr_shared<char> nv, + Inkscape::Util::ptr_shared ov, + Inkscape::Util::ptr_shared nv, Event *next) : Event(repr, next), oldval(ov), newval(nv) {} /// Content of the node before the change - Inkscape::Util::ptr_shared<char> oldval; + Inkscape::Util::ptr_shared oldval; /// Content of the node after the change - Inkscape::Util::ptr_shared<char> newval; + Inkscape::Util::ptr_shared newval; private: Event *_optimizeOne(); diff --git a/src/xml/helper-observer.cpp b/src/xml/helper-observer.cpp index 957f3df0a..6f1094e53 100644 --- a/src/xml/helper-observer.cpp +++ b/src/xml/helper-observer.cpp @@ -44,10 +44,10 @@ void SignalObserver::notifyChildRemoved(XML::Node&, XML::Node&, XML::Node*) void SignalObserver::notifyChildOrderChanged(XML::Node&, XML::Node&, XML::Node*, XML::Node*) { signal_changed()(); } -void SignalObserver::notifyContentChanged(XML::Node&, Util::ptr_shared<char>, Util::ptr_shared<char>) +void SignalObserver::notifyContentChanged(XML::Node&, Util::ptr_shared, Util::ptr_shared) {} -void SignalObserver::notifyAttributeChanged(XML::Node&, GQuark, Util::ptr_shared<char>, Util::ptr_shared<char>) +void SignalObserver::notifyAttributeChanged(XML::Node&, GQuark, Util::ptr_shared, Util::ptr_shared) { signal_changed()(); } sigc::signal<void>& SignalObserver::signal_changed() diff --git a/src/xml/helper-observer.h b/src/xml/helper-observer.h index b4c0aba41..b06b61e9c 100644 --- a/src/xml/helper-observer.h +++ b/src/xml/helper-observer.h @@ -24,8 +24,8 @@ public: void notifyChildAdded(Node&, Node&, Node*); void notifyChildRemoved(Node&, Node&, Node*); void notifyChildOrderChanged(Node&, Node&, Node*, Node*); - void notifyContentChanged(Node&, Util::ptr_shared<char>, Util::ptr_shared<char>); - void notifyAttributeChanged(Node&, GQuark, Util::ptr_shared<char>, Util::ptr_shared<char>); + void notifyContentChanged(Node&, Util::ptr_shared, Util::ptr_shared); + void notifyAttributeChanged(Node&, GQuark, Util::ptr_shared, Util::ptr_shared); sigc::signal<void>& signal_changed(); private: sigc::signal<void> _signal_changed; diff --git a/src/xml/log-builder.cpp b/src/xml/log-builder.cpp index 2cbdcfacf..12577cf69 100644 --- a/src/xml/log-builder.cpp +++ b/src/xml/log-builder.cpp @@ -49,16 +49,16 @@ void LogBuilder::setChildOrder(Node &node, Node &child, } void LogBuilder::setContent(Node &node, - Util::ptr_shared<char> old_content, - Util::ptr_shared<char> new_content) + Util::ptr_shared old_content, + Util::ptr_shared new_content) { _log = new Inkscape::XML::EventChgContent(&node, old_content, new_content, _log); _log = _log->optimizeOne(); } void LogBuilder::setAttribute(Node &node, GQuark name, - Util::ptr_shared<char> old_value, - Util::ptr_shared<char> new_value) + Util::ptr_shared old_value, + Util::ptr_shared new_value) { _log = new Inkscape::XML::EventChgAttr(&node, name, old_value, new_value, _log); _log = _log->optimizeOne(); diff --git a/src/xml/log-builder.h b/src/xml/log-builder.h index e94dd1daa..8b0f6662d 100644 --- a/src/xml/log-builder.h +++ b/src/xml/log-builder.h @@ -58,12 +58,12 @@ public: Node *old_prev, Node *new_prev); void setContent(Node &node, - Util::ptr_shared<char> old_content, - Util::ptr_shared<char> new_content); + Util::ptr_shared old_content, + Util::ptr_shared new_content); void setAttribute(Node &node, GQuark name, - Util::ptr_shared<char> old_value, - Util::ptr_shared<char> new_value); + Util::ptr_shared old_value, + Util::ptr_shared new_value); /*@}*/ private: diff --git a/src/xml/makefile.in b/src/xml/makefile.in deleted file mode 100644 index 376b4c218..000000000 --- a/src/xml/makefile.in +++ /dev/null @@ -1,17 +0,0 @@ -# Convenience stub makefile to call the real Makefile. - -@SET_MAKE@ - -OBJEXT = @OBJEXT@ - -# Explicit so that it's the default rule. -all: - cd .. && $(MAKE) xml/all - -clean %.a %.$(OBJEXT): - cd .. && $(MAKE) xml/$@ - -.PHONY: all clean - -.SUFFIXES: -.SUFFIXES: .a .$(OBJEXT) diff --git a/src/xml/node-observer.h b/src/xml/node-observer.h index 9c7e096e5..28c492d66 100644 --- a/src/xml/node-observer.h +++ b/src/xml/node-observer.h @@ -123,8 +123,8 @@ public: * @param new_content New content of @c node */ virtual void notifyContentChanged(Node &node, - Util::ptr_shared<char> old_content, - Util::ptr_shared<char> new_content) { + Util::ptr_shared old_content, + Util::ptr_shared new_content) { INK_UNUSED(node); INK_UNUSED(old_content); INK_UNUSED(new_content); @@ -141,8 +141,8 @@ public: * @param new_value New value of the modified attribute */ virtual void notifyAttributeChanged(Node &node, GQuark name, - Util::ptr_shared<char> old_value, - Util::ptr_shared<char> new_value) { + Util::ptr_shared old_value, + Util::ptr_shared new_value) { INK_UNUSED(node); INK_UNUSED(name); INK_UNUSED(old_value); diff --git a/src/xml/pi-node.h b/src/xml/pi-node.h index 76a3dc741..eeed1632d 100644 --- a/src/xml/pi-node.h +++ b/src/xml/pi-node.h @@ -24,7 +24,7 @@ namespace XML { * @brief Processing instruction node, e.g. <?xml version="1.0" encoding="utf-8" standalone="no"?> */ struct PINode : public SimpleNode { - PINode(GQuark target, Util::ptr_shared<char> content, Document *doc) + PINode(GQuark target, Util::ptr_shared content, Document *doc) : SimpleNode(target, doc) { setContent(content); diff --git a/src/xml/rebase-hrefs.cpp b/src/xml/rebase-hrefs.cpp index a34df09a5..c023dc670 100644 --- a/src/xml/rebase-hrefs.cpp +++ b/src/xml/rebase-hrefs.cpp @@ -112,8 +112,8 @@ Inkscape::XML::rebase_href_attrs(gchar const *const old_abs_base, * * However, if we find that xlink:href doesn't need rebasing, then return immediately * with no change to attributes. */ - ptr_shared<char> old_href; - ptr_shared<char> sp_absref; + ptr_shared old_href; + ptr_shared sp_absref; List<AttributeRecord const> ret; { for (List<AttributeRecord const> ai(attributes); ai; ++ai) { diff --git a/src/xml/repr-io.cpp b/src/xml/repr-io.cpp index d8e0f5418..2ff9d4776 100644 --- a/src/xml/repr-io.cpp +++ b/src/xml/repr-io.cpp @@ -67,11 +67,6 @@ static void sp_repr_write_stream_element(Node *repr, Writer &out, gchar const *old_href_abs_base, gchar const *new_href_abs_base); -#ifdef HAVE_LIBWMF -static xmlDocPtr sp_wmf_convert (const char * file_name); -static char * sp_wmf_image_name (void * context); -#endif /* HAVE_LIBWMF */ - class XmlSource { @@ -323,19 +318,18 @@ int XmlSource::close() } /** - * Reads XML from a file, including WMF files, and returns the Document. + * Reads XML from a file, and returns the Document. * The default namespace can also be specified, if desired. */ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns) { - // g_warning( "Reading file: %s", filename ); xmlDocPtr doc = 0; Document * rdoc = 0; xmlSubstituteEntitiesDefault(1); - g_return_val_if_fail (filename != NULL, NULL); - if (!Inkscape::IO::file_test( filename, G_FILE_TEST_EXISTS )) { + g_return_val_if_fail(filename != NULL, NULL); + if (!Inkscape::IO::file_test(filename, G_FILE_TEST_EXISTS)) { g_warning("Can't open file: %s (doesn't exist)", filename); return NULL; } @@ -348,45 +342,32 @@ Document *sp_repr_read_file (const gchar * filename, const gchar *default_ns) gsize bytesWritten = 0; GError* error = NULL; // TODO: need to replace with our own fopen and reading - gchar* localFilename = g_filename_from_utf8 ( filename, - -1, &bytesRead, &bytesWritten, &error); - g_return_val_if_fail( localFilename != NULL, NULL ); - - Inkscape::IO::dump_fopen_call( filename, "N" ); + gchar* localFilename = g_filename_from_utf8(filename, -1, &bytesRead, &bytesWritten, &error); + g_return_val_if_fail(localFilename != NULL, NULL); -#ifdef HAVE_LIBWMF - if (strlen (localFilename) > 4) { - if ( (strcmp (localFilename + strlen (localFilename) - 4,".wmf") == 0) - || (strcmp (localFilename + strlen (localFilename) - 4,".WMF") == 0)) { - doc = sp_wmf_convert (localFilename); - } - } -#endif // !HAVE_LIBWMF + Inkscape::IO::dump_fopen_call(filename, "N"); - if ( !doc ) { - XmlSource src; + XmlSource src; - if ( (src.setFile(filename) == 0) ) { + if (src.setFile(filename) == 0) { + doc = src.readXml(); + rdoc = sp_repr_do_read(doc, default_ns); + // For some reason, failed ns loading results in this + // We try a system check version of load with NOENT for adobe + if (rdoc && strcmp(rdoc->root()->name(), "ns:svg") == 0) { + xmlFreeDoc(doc); + src.setFile(filename, true); doc = src.readXml(); - rdoc = sp_repr_do_read( doc, default_ns ); - // For some reason, failed ns loading results in this - // We try a system check version of load with NOENT for adobe - if(rdoc && strcmp(rdoc->root()->name(), "ns:svg") == 0) { - xmlFreeDoc( doc ); - src.setFile(filename, true); - doc = src.readXml(); - rdoc = sp_repr_do_read( doc, default_ns ); - } + rdoc = sp_repr_do_read(doc, default_ns); } } - - if ( doc ) { - xmlFreeDoc( doc ); + if (doc) { + xmlFreeDoc(doc); } - if ( localFilename ) { - g_free( localFilename ); + if (localFilename) { + g_free(localFilename); } return rdoc; @@ -580,7 +561,10 @@ static Node *sp_repr_svg_read_node (Document *xml_doc, xmlNodePtr node, const gc return NULL; // empty text node } - bool preserve = (xmlNodeGetSpacePreserve (node) == 1); + // Since libxml2 2.9.0, only element nodes are checked, thus check parent. + // Note: this only handles XML's rules for white space. SVG's specific rules + // are handled in sp-string.cpp. + bool preserve = (xmlNodeGetSpacePreserve (node->parent) == 1); xmlChar *p; for (p = node->content; *p && g_ascii_isspace (*p) && !preserve; p++) @@ -812,7 +796,7 @@ static void repr_write_comment( Writer &out, const gchar * val, bool addWhitespa namespace { typedef std::map<Glib::QueryQuark, gchar const *, Inkscape::compare_quark_ids> LocalNameMap; -typedef std::map<Glib::QueryQuark, Inkscape::Util::ptr_shared<char>, Inkscape::compare_quark_ids> NSMap; +typedef std::map<Glib::QueryQuark, Inkscape::Util::ptr_shared, Inkscape::compare_quark_ids> NSMap; gchar const *qname_local_name(Glib::QueryQuark qname) { static LocalNameMap local_name_map; @@ -846,7 +830,7 @@ void add_ns_map_entry(NSMap &ns_map, Glib::QueryQuark prefix) { g_warning("No namespace known for normalized prefix %s", g_quark_to_string(prefix)); } } else { - ns_map.insert(NSMap::value_type(prefix, ptr_shared<char>())); + ns_map.insert(NSMap::value_type(prefix, ptr_shared())); } } } @@ -905,7 +889,7 @@ static void sp_repr_write_stream_root_element(Node *repr, Writer &out, for ( NSMap::iterator iter=ns_map.begin() ; iter != ns_map.end() ; ++iter ) { Glib::QueryQuark prefix=(*iter).first; - ptr_shared<char> ns_uri=(*iter).second; + ptr_shared ns_uri=(*iter).second; if (prefix.id()) { if ( prefix != xml_prefix ) { diff --git a/src/xml/simple-document.cpp b/src/xml/simple-document.cpp index bae28e4b4..cf7851897 100644 --- a/src/xml/simple-document.cpp +++ b/src/xml/simple-document.cpp @@ -100,8 +100,8 @@ void SimpleDocument::notifyChildOrderChanged(Node &parent, } void SimpleDocument::notifyContentChanged(Node &node, - Util::ptr_shared<char> old_content, - Util::ptr_shared<char> new_content) + Util::ptr_shared old_content, + Util::ptr_shared new_content) { if (_in_transaction) { _log_builder.setContent(node, old_content, new_content); @@ -110,8 +110,8 @@ void SimpleDocument::notifyContentChanged(Node &node, void SimpleDocument::notifyAttributeChanged(Node &node, GQuark name, - Util::ptr_shared<char> old_value, - Util::ptr_shared<char> new_value) + Util::ptr_shared old_value, + Util::ptr_shared new_value) { if (_in_transaction) { _log_builder.setAttribute(node, name, old_value, new_value); diff --git a/src/xml/simple-document.h b/src/xml/simple-document.h index 7cbe50dda..01933076f 100644 --- a/src/xml/simple-document.h +++ b/src/xml/simple-document.h @@ -56,12 +56,12 @@ public: Node *old_prev, Node *new_prev); void notifyContentChanged(Node &node, - Util::ptr_shared<char> old_content, - Util::ptr_shared<char> new_content); + Util::ptr_shared old_content, + Util::ptr_shared new_content); void notifyAttributeChanged(Node &node, GQuark name, - Util::ptr_shared<char> old_value, - Util::ptr_shared<char> new_value); + Util::ptr_shared old_value, + Util::ptr_shared new_value); protected: SimpleDocument(SimpleDocument const &doc) diff --git a/src/xml/simple-node.cpp b/src/xml/simple-node.cpp index 6bd47fd22..78fc52a27 100644 --- a/src/xml/simple-node.cpp +++ b/src/xml/simple-node.cpp @@ -36,7 +36,7 @@ namespace XML { namespace { -Util::ptr_shared<char> stringify_node(Node const &node) { +Util::ptr_shared stringify_node(Node const &node) { gchar *string; switch (node.type()) { case ELEMENT_NODE: { @@ -59,7 +59,7 @@ Util::ptr_shared<char> stringify_node(Node const &node) { default: string = g_strdup_printf("unknown(%p)", &node); } - Util::ptr_shared<char> result=Util::share_string(string); + Util::ptr_shared result=Util::share_string(string); g_free(string); return result; } @@ -68,7 +68,7 @@ typedef Debug::SimpleEvent<Debug::Event::XML> DebugXML; class DebugXMLNode : public DebugXML { public: - DebugXMLNode(Node const &node, Util::ptr_shared<char> name) + DebugXMLNode(Node const &node, Util::ptr_shared name) : DebugXML(name) { _addProperty("node", stringify_node(node)); @@ -115,7 +115,7 @@ public: class DebugSetContent : public DebugXMLNode { public: DebugSetContent(Node const &node, - Util::ptr_shared<char> content) + Util::ptr_shared content) : DebugXMLNode(node, Util::share_static_string("set-content")) { _addProperty("content", content); @@ -133,7 +133,7 @@ class DebugSetAttribute : public DebugXMLNode { public: DebugSetAttribute(Node const &node, GQuark name, - Util::ptr_shared<char> value) + Util::ptr_shared value) : DebugXMLNode(node, Util::share_static_string("set-attribute")) { _addProperty("name", Util::share_static_string(g_quark_to_string(name))); @@ -290,8 +290,8 @@ void SimpleNode::_setParent(SimpleNode *parent) { } void SimpleNode::setContent(gchar const *content) { - ptr_shared<char> old_content=_content; - ptr_shared<char> new_content = ( content ? share_string(content) : ptr_shared<char>() ); + ptr_shared old_content=_content; + ptr_shared new_content = ( content ? share_string(content) : ptr_shared() ); Debug::EventTracker<> tracker; if (new_content) { @@ -365,9 +365,9 @@ SimpleNode::setAttribute(gchar const *name, gchar const *value, bool const /*is_ } Debug::EventTracker<> tracker; - ptr_shared<char> old_value=( existing ? existing->value : ptr_shared<char>() ); + ptr_shared old_value=( existing ? existing->value : ptr_shared() ); - ptr_shared<char> new_value=ptr_shared<char>(); + ptr_shared new_value=ptr_shared(); if (cleaned_value) { new_value = share_string(cleaned_value); tracker.set<DebugSetAttribute>(*this, key, new_value); diff --git a/src/xml/simple-node.h b/src/xml/simple-node.h index d09392249..f2cfa953c 100644 --- a/src/xml/simple-node.h +++ b/src/xml/simple-node.h @@ -144,7 +144,7 @@ private: Inkscape::Util::MutableList<AttributeRecord> _attributes; - Inkscape::Util::ptr_shared<char> _content; + Inkscape::Util::ptr_shared _content; unsigned _child_count; mutable bool _cached_positions_valid; diff --git a/src/xml/text-node.h b/src/xml/text-node.h index 53798b822..4d71203a5 100644 --- a/src/xml/text-node.h +++ b/src/xml/text-node.h @@ -26,13 +26,13 @@ namespace XML { * @brief Text node, e.g. "Some text" in <group>Some text</group> */ struct TextNode : public SimpleNode { - TextNode(Util::ptr_shared<char> content, Document *doc) + TextNode(Util::ptr_shared content, Document *doc) : SimpleNode(g_quark_from_static_string("string"), doc) { setContent(content); _is_CData = false; } - TextNode(Util::ptr_shared<char> content, Document *doc, bool is_CData) + TextNode(Util::ptr_shared content, Document *doc, bool is_CData) : SimpleNode(g_quark_from_static_string("string"), doc) { setContent(content); |
