diff options
| author | Jabiertxof <jtx@jtx> | 2016-12-16 22:53:43 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx> | 2016-12-16 22:53:43 +0000 |
| commit | 57175b32ef6539d7249a0d28d302c174ba453275 (patch) | |
| tree | f0ecbf4a9e6717e11a1a88e12f0ae9b82ef62df0 /src | |
| parent | Rollback 15315 (diff) | |
| download | inkscape-57175b32ef6539d7249a0d28d302c174ba453275.tar.gz inkscape-57175b32ef6539d7249a0d28d302c174ba453275.zip | |
remove rollback to 15315
(bzr r15295.1.26)
Diffstat (limited to 'src')
68 files changed, 816 insertions, 523 deletions
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index 65e511245..4c07c76ea 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -209,7 +209,7 @@ sp_desktop_set_style(Inkscape::ObjectSet *set, SPDesktop *desktop, SPCSSAttr *cs if (!change) return; -// 2. Emit signal +// 2. Emit signal... See desktop->connectSetStyle in text-tool, tweak-tool, and gradient-drag. bool intercepted = desktop->_set_style_signal.emit(css); /** \todo @@ -1045,6 +1045,7 @@ objects_query_fontnumbers (const std::vector<SPItem*> &objects, SPStyle *style_r bool lineheight_normal = false; bool lineheight_unit_proportional = false; bool lineheight_unit_absolute = false; + bool lineheight_set = false; // Set true if any object has lineheight set. double size_prev = 0; double letterspacing_prev = 0; @@ -1130,6 +1131,9 @@ objects_query_fontnumbers (const std::vector<SPItem*> &objects, SPStyle *style_r lineheight_normal = false; lineheight += lineheight_current * doc_scale; } + if (style->line_height.set) { + lineheight_set = true; + } if ((size_prev != 0 && style->font_size.computed != size_prev) || (letterspacing_prev != 0 && style->letter_spacing.computed != letterspacing_prev) || @@ -1205,6 +1209,9 @@ objects_query_fontnumbers (const std::vector<SPItem*> &objects, SPStyle *style_r } } + // Used by text toolbar unset 'line-height' + style_res->line_height.set = lineheight_set; + if (texts > 1) { if (different || different_lineheight) { return QUERY_STYLE_MULTIPLE_AVERAGED; @@ -1907,7 +1914,7 @@ sp_desktop_query_style_from_list (const std::vector<SPItem*> &list, SPStyle *sty int sp_desktop_query_style(SPDesktop *desktop, SPStyle *style, int property) { - // Used by text tool and in gradient dragging + // Used by text tool and in gradient dragging. See connectQueryStyle. int ret = desktop->_query_style_signal.emit(style, property); if (ret != QUERY_STYLE_NOTHING) diff --git a/src/file.cpp b/src/file.cpp index 55089209a..8f283e1f8 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -66,6 +66,10 @@ // For updating old Inkscape SVG files #include "display/canvas-grid.h" #include "sp-guide.h" +#include "selection-chemistry.h" +#include "persp3d.h" +#include "proj_pt.h" +#include "ui/shape-editor.h" #include <gtkmm.h> @@ -353,11 +357,13 @@ bool sp_file_open(const Glib::ustring &uri, bool need_fix_units = false; bool need_fix_guides = false; bool need_fix_grid_mm = false; - bool is_extension = false; + bool need_fix_box3d = false; + bool did_scaling = false; // Check if potentially need viewbox or unit fix switch (root->width.unit) { case SP_CSS_UNIT_PC: + case SP_CSS_UNIT_PT: case SP_CSS_UNIT_MM: case SP_CSS_UNIT_CM: case SP_CSS_UNIT_IN: @@ -366,13 +372,19 @@ bool sp_file_open(const Glib::ustring &uri, case SP_CSS_UNIT_NONE: case SP_CSS_UNIT_PX: need_fix_units = true; - default: break; + case SP_CSS_UNIT_EM: + case SP_CSS_UNIT_EX: + case SP_CSS_UNIT_PERCENT: // OK + break; + default: + std::cerr << "sp_file_open: Unhandled width unit!" << std::endl; } switch (root->height.unit) { case SP_CSS_UNIT_PC: + case SP_CSS_UNIT_PT: case SP_CSS_UNIT_MM: case SP_CSS_UNIT_CM: case SP_CSS_UNIT_IN: @@ -381,14 +393,21 @@ bool sp_file_open(const Glib::ustring &uri, case SP_CSS_UNIT_NONE: case SP_CSS_UNIT_PX: need_fix_units = true; - default: break; + case SP_CSS_UNIT_EM: + case SP_CSS_UNIT_EX: + case SP_CSS_UNIT_PERCENT: // OK + break; + default: + std::cerr << "sp_file_open: Unhandled height unit!" << std::endl; } // std::cout << "Absolute SVG units in root? " << (need_fix_viewbox?"true":"false") << std::endl; // std::cout << "User units in root? " << (need_fix_units ?"true":"false") << std::endl; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (!root->viewBox_set && need_fix_viewbox) { Glib::ustring msg = _( @@ -401,31 +420,37 @@ bool sp_file_open(const Glib::ustring &uri, Gtk::Label info; info.set_markup(msg.c_str()); info.show(); - scaleDialog.get_content_area()->pack_start(info, false, false, 20); + Gtk::CheckButton backupButton( _("Create backup file (in same directory).") ); - backupButton.set_active(); + bool backup = prefs->getBool("/options/dpifixbackup", true); + backupButton.set_active( backup ); backupButton.show(); - scaleDialog.get_content_area()->pack_start(backupButton, false, false, 20); - scaleDialog.add_button("Set 'viewBox'", 1); - scaleDialog.add_button("Scale elements", 2); - scaleDialog.add_button("Ignore", 3); + + scaleDialog.add_button(_("Set 'viewBox'"), 1); + scaleDialog.add_button(_("Scale elements"), 2); + scaleDialog.add_button(_("Ignore"), 3); + scaleDialog.add_button("Scale test - group", 4); + scaleDialog.add_button("Scale test - children", 5); gint response = scaleDialog.run(); - bool backup = backupButton.get_active(); + backup = backupButton.get_active(); + prefs->setBool("/options/dpifixbackup", backup); + + if ( backup && response != 3) { + sp_file_save_backup( uri ); + } + if (response == 1) { - if (backup) { - sp_file_save_backup( uri ); - } + doc->setViewBox(Geom::Rect::from_xywh( 0, 0, doc->getWidth().value("px") * ratio, doc->getHeight().value("px") * ratio)); + } else if (response == 2 ) { - if (backup) { - sp_file_save_backup( uri ); - } + std::list<Inkscape::Extension::Effect *> effects; Inkscape::Extension::db.get_effect_list(effects); std::list<Inkscape::Extension::Effect *>::iterator it = effects.begin(); @@ -442,12 +467,65 @@ bool sp_file_open(const Glib::ustring &uri, if (!did) { std::cerr << "sp_file_open: Failed to find dpi90to96 extension." << std::endl; } - is_extension = true; + did_scaling = true; + + } else if (response == 4) { + + // Save preferences + bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive",true); + bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); + + prefs->setBool("/options/kbselection/onlysensitive", false); + prefs->setBool("/options/kbselection/onlyvisible", false); + + Inkscape::Selection *selection = desktop->getSelection(); + Inkscape::SelectionHelper::selectAllInAll( desktop ); + selection->group(); + SPItem * group = selection->singleItem(); + if (group) { + group->setAttribute("transform","scale(1.06666667,1.06666667)"); + } else { + std::cerr << "sp_file_open: Failed to get group!" << std::endl; + } + selection->clear(); + selection->add( group ); + selection->ungroup(); + selection->clear(); + + prefs->setBool("/options/kbselection/onlysensitive", onlysensitive); + prefs->setBool("/options/kbselection/onlyvisible", onlyvisible ); + + did_scaling = true; + + } else if (response == 5) { + + // Save preferences + bool transform_stroke = prefs->getBool("/options/transform/stroke", true); + bool transform_rectcorners = prefs->getBool("/options/transform/rectcorners", true); + bool transform_pattern = prefs->getBool("/options/transform/pattern", true); + bool transform_gradient = prefs->getBool("/options/transform/gradient", true); + + prefs->setBool("/options/transform/stroke", true); + prefs->setBool("/options/transform/rectcorners", true); + prefs->setBool("/options/transform/pattern", true); + prefs->setBool("/options/transform/gradient", true); + + Inkscape::UI::ShapeEditor::blockSetItem(true); + doc->getRoot()->scaleChildItemsRec(Geom::Scale(1/ratio),Geom::Point(0, 0), false); + Inkscape::UI::ShapeEditor::blockSetItem(false); + + // Restore preferences + prefs->setBool("/options/transform/stroke", transform_stroke); + prefs->setBool("/options/transform/rectcorners", transform_rectcorners); + prefs->setBool("/options/transform/pattern", transform_pattern); + prefs->setBool("/options/transform/gradient", transform_gradient); } + + need_fix_box3d = true; need_fix_guides = true; // Always fix guides } - if (need_fix_units) { + else if (need_fix_units) { Glib::ustring msg = ( "Old Inkscape files use 1in == 90px. CSS requires 1in == 96px.\n" "Drawings meant to match a physical size (e.g. Letter or A4)\n" @@ -462,19 +540,27 @@ bool sp_file_open(const Glib::ustring &uri, scaleDialog.get_content_area()->pack_start(info, false, false, 20); Gtk::CheckButton backupButton( _("Create backup file (in same directory).") ); - scaleDialog.get_content_area()->pack_start(backupButton, false, false, 20); + bool backup = prefs->getBool("/options/dpifixbackup", true); + backupButton.set_active( backup ); backupButton.show(); + scaleDialog.get_content_area()->pack_start(backupButton, false, false, 20); - scaleDialog.add_button("Set 'viewBox'", 1); - scaleDialog.add_button("Scale elements", 2); - scaleDialog.add_button("Ignore", 3); + scaleDialog.add_button(_("Set 'viewBox'"), 1); + scaleDialog.add_button(_("Scale elements"), 2); + scaleDialog.add_button(_("Ignore"), 3); + scaleDialog.add_button("Scale test - group", 4); + scaleDialog.add_button("Scale test - children", 5); gint response = scaleDialog.run(); - bool backup = backupButton.get_active(); + backup = backupButton.get_active(); + prefs->setBool("/options/dpifixbackup", backup); + + if ( backup && response != 3) { + sp_file_save_backup( uri ); + } + if (response == 1) { - if (backup) { - sp_file_save_backup( uri ); - } + if (!root->viewBox_set) { doc->setViewBox(Geom::Rect::from_xywh( 0, 0, @@ -488,10 +574,10 @@ bool sp_file_open(const Glib::ustring &uri, doc->setWidthAndHeight( width, height, false ); need_fix_guides = true; // Only fix guides if drawing scaled + need_fix_box3d = true; + } else if (response == 2) { - if (backup) { - sp_file_save_backup( uri ); - } + std::list<Inkscape::Extension::Effect *> effects; Inkscape::Extension::db.get_effect_list(effects); std::list<Inkscape::Extension::Effect *>::iterator it = effects.begin(); @@ -509,14 +595,94 @@ bool sp_file_open(const Glib::ustring &uri, std::cerr << "sp_file_open: Failed to find dpi90to96 extension." << std::endl; } need_fix_guides = true; // Only fix guides if drawing scaled - is_extension = true; + did_scaling = true; + + } else if (response == 4) { + + Inkscape::Util::Quantity width = + Inkscape::Util::Quantity(doc->getWidth().value("px")/ratio, "px" ); + Inkscape::Util::Quantity height = + Inkscape::Util::Quantity(doc->getHeight().value("px")/ratio,"px" ); + doc->setWidthAndHeight( width, height, false ); + + if (!root->viewBox_set) { + + // Save preferences + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive",true); + bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); + + prefs->setBool("/options/kbselection/onlysensitive", false); + prefs->setBool("/options/kbselection/onlyvisible", false); + + Inkscape::Selection *selection = desktop->getSelection(); + Inkscape::SelectionHelper::selectAllInAll( desktop ); + selection->group(); + SPItem * group = selection->singleItem(); + if (group) { + group->setAttribute("transform","scale(1.06666667,1.06666667)"); + } else { + std::cerr << "sp_file_open: Failed to get group!" << std::endl; + } + selection->clear(); + selection->add( group ); + selection->ungroup(); + selection->clear(); + + prefs->setBool("/options/kbselection/onlysensitive", onlysensitive); + prefs->setBool("/options/kbselection/onlyvisible", onlyvisible ); + + did_scaling = true; + } + + need_fix_box3d = true; + need_fix_guides = true; // Only fix guides if drawing scaled + + } else if (response == 5) { + + Inkscape::Util::Quantity width = + Inkscape::Util::Quantity(doc->getWidth().value("px")/ratio, "px" ); + Inkscape::Util::Quantity height = + Inkscape::Util::Quantity(doc->getHeight().value("px")/ratio,"px" ); + doc->setWidthAndHeight( width, height, false ); + + if (!root->viewBox_set) { + + // Save preferences + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool transform_stroke = prefs->getBool("/options/transform/stroke", true); + bool transform_rectcorners = prefs->getBool("/options/transform/rectcorners", true); + bool transform_pattern = prefs->getBool("/options/transform/pattern", true); + bool transform_gradient = prefs->getBool("/options/transform/gradient", true); + + prefs->setBool("/options/transform/stroke", true); + prefs->setBool("/options/transform/rectcorners", true); + prefs->setBool("/options/transform/pattern", true); + prefs->setBool("/options/transform/gradient", true); + + Inkscape::UI::ShapeEditor::blockSetItem(true); + doc->getRoot()->scaleChildItemsRec(Geom::Scale(1/ratio),Geom::Point(0, 0), false); + Inkscape::UI::ShapeEditor::blockSetItem(false); + + // Restore preferences + prefs->setBool("/options/transform/stroke", transform_stroke); + prefs->setBool("/options/transform/rectcorners", transform_rectcorners); + prefs->setBool("/options/transform/pattern", transform_pattern); + prefs->setBool("/options/transform/gradient", transform_gradient); + + did_scaling = true; + } + + need_fix_box3d = true; + need_fix_guides = true; // Only fix guides if drawing scaled + } else { // Ignore need_fix_grid_mm = true; } } - // Fix guides and grids + // Fix guides and grids and perspective for (SPObject *child = root->firstChild() ; child; child = child->getNext() ) { SPNamedView *nv = dynamic_cast<SPNamedView *>(child); if (nv) { @@ -555,21 +721,53 @@ bool sp_file_open(const Glib::ustring &uri, } } else { if (need_fix_guides) { - // HACK: Scaling the document does not seem to cause - // grids defined in document units to be updated. - // This forces an update. - if(is_extension){ + if(did_scaling){ xy->Scale( Geom::Scale(ratio,ratio).inverse() ); } else { + // HACK: Scaling the document does not seem to cause + // grids defined in document units to be updated. + // This forces an update. xy->Scale( Geom::Scale(1,1) ); } } } } } + } // If SPNamedView + + SPDefs *defs = dynamic_cast<SPDefs *>(child); + if (defs && need_fix_box3d) { + for (SPObject *child = defs->firstChild() ; child; child = child->getNext() ) { + Persp3D* persp3d = dynamic_cast<Persp3D *>(child); + if (persp3d) { + std::vector<Glib::ustring> tokens; + + const gchar* vp_x = persp3d->getAttribute("inkscape:vp_x"); + const gchar* vp_y = persp3d->getAttribute("inkscape:vp_y"); + const gchar* vp_z = persp3d->getAttribute("inkscape:vp_z"); + const gchar* vp_o = persp3d->getAttribute("inkscape:persp3d-origin"); + // std::cout << "Found Persp3d: " + // << " vp_x: " << vp_x + // << " vp_y: " << vp_y + // << " vp_z: " << vp_z << std::endl; + Proj::Pt2 pt_x (vp_x); + Proj::Pt2 pt_y (vp_y); + Proj::Pt2 pt_z (vp_z); + Proj::Pt2 pt_o (vp_o); + pt_x = pt_x * (1.0/ratio); + pt_y = pt_y * (1.0/ratio); + pt_z = pt_z * (1.0/ratio); + pt_o = pt_o * (1.0/ratio); + persp3d->setAttribute("inkscape:vp_x",pt_x.coord_string()); + persp3d->setAttribute("inkscape:vp_y",pt_y.coord_string()); + persp3d->setAttribute("inkscape:vp_z",pt_z.coord_string()); + persp3d->setAttribute("inkscape:persp3d-origin",pt_o.coord_string()); + } + } } - } // Look for SPNamedView loop + } // Look for SPNamedView and SPDefs loop + // desktop->getDocument()->ensureUpToDate(); // Does not update box3d! DocumentUndo::done(desktop->getDocument(), SP_VERB_NONE, _("Update Document")); } // If old Inkscape version diff --git a/src/live_effects/lpe-angle_bisector.cpp b/src/live_effects/lpe-angle_bisector.cpp index 9bfbf4ca8..56d33eb4b 100644 --- a/src/live_effects/lpe-angle_bisector.cpp +++ b/src/live_effects/lpe-angle_bisector.cpp @@ -8,15 +8,13 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-angle_bisector.h" - -#include <2geom/sbasis-to-bezier.h> - +#include "2geom/sbasis-to-bezier.h" #include "sp-lpe-item.h" #include "knot-holder-entity.h" #include "knotholder.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-attach-path.cpp b/src/live_effects/lpe-attach-path.cpp index d2b44dd4e..302165719 100644 --- a/src/live_effects/lpe-attach-path.cpp +++ b/src/live_effects/lpe-attach-path.cpp @@ -4,15 +4,14 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> #include <math.h> - #include "live_effects/lpe-attach-path.h" - #include "display/curve.h" #include "sp-shape.h" #include "sp-text.h" #include "2geom/path-sink.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-bendpath.cpp b/src/live_effects/lpe-bendpath.cpp index c24d38d7b..b1e133292 100644 --- a/src/live_effects/lpe-bendpath.cpp +++ b/src/live_effects/lpe-bendpath.cpp @@ -7,9 +7,10 @@ #include "live_effects/lpe-bendpath.h" #include "sp-item-group.h" - #include "knot-holder-entity.h" #include "knotholder.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> using std::vector; diff --git a/src/live_effects/lpe-bounding-box.cpp b/src/live_effects/lpe-bounding-box.cpp index 2de768c3a..11fb34e04 100644 --- a/src/live_effects/lpe-bounding-box.cpp +++ b/src/live_effects/lpe-bounding-box.cpp @@ -3,14 +3,14 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - -#include <glibmm/i18n.h> - #include "live_effects/lpe-bounding-box.h" #include "display/curve.h" #include "sp-shape.h" #include "sp-text.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-bspline.h b/src/live_effects/lpe-bspline.h index 7823f00f0..90cf82c19 100644 --- a/src/live_effects/lpe-bspline.h +++ b/src/live_effects/lpe-bspline.h @@ -6,8 +6,8 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "live_effects/effect.h" +#include "live_effects/effect.h" #include <vector> namespace Inkscape { diff --git a/src/live_effects/lpe-circle_3pts.cpp b/src/live_effects/lpe-circle_3pts.cpp index 18252f6a0..3410b13f2 100644 --- a/src/live_effects/lpe-circle_3pts.cpp +++ b/src/live_effects/lpe-circle_3pts.cpp @@ -17,6 +17,8 @@ // You might need to include other 2geom files. You can add them here: #include <2geom/circle.h> #include <2geom/path-sink.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-circle_with_radius.cpp b/src/live_effects/lpe-circle_with_radius.cpp index 6e03cb1ce..fcefc4ec6 100644 --- a/src/live_effects/lpe-circle_with_radius.cpp +++ b/src/live_effects/lpe-circle_with_radius.cpp @@ -17,6 +17,8 @@ // You might need to include other 2geom files. You can add them here: #include <2geom/circle.h> #include <2geom/path-sink.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> using namespace Geom; diff --git a/src/live_effects/lpe-clone-original.cpp b/src/live_effects/lpe-clone-original.cpp index 7541c0be2..10418a02d 100644 --- a/src/live_effects/lpe-clone-original.cpp +++ b/src/live_effects/lpe-clone-original.cpp @@ -4,11 +4,10 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-clone-original.h" - #include "display/curve.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-constructgrid.cpp b/src/live_effects/lpe-constructgrid.cpp index 4af8891e8..8d24f9f47 100644 --- a/src/live_effects/lpe-constructgrid.cpp +++ b/src/live_effects/lpe-constructgrid.cpp @@ -10,9 +10,9 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-constructgrid.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index 1133e083a..5b94e9083 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -11,36 +11,17 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <gtkmm.h> #include <gdk/gdk.h> #include <2geom/path-intersection.h> #include <2geom/sbasis-to-bezier.h> #include "live_effects/lpe-copy_rotate.h" - -#include "knotholder.h" // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { -namespace CR { - -class KnotHolderEntityStartingAngle : public LPEKnotHolderEntity { -public: - KnotHolderEntityStartingAngle(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; - -class KnotHolderEntityRotationAngle : public LPEKnotHolderEntity { -public: - KnotHolderEntityRotationAngle(LPECopyRotate *effect) : LPEKnotHolderEntity(effect) {}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; - -} // namespace CR - bool pointInTriangle(Geom::Point const &p, Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3) { @@ -59,6 +40,7 @@ pointInTriangle(Geom::Point const &p, Geom::Point const &p1, Geom::Point const & LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : Effect(lpeobject), origin(_("Origin"), _("Origin of the rotation"), "origin", &wr, this), + starting_point("hidden", "hidden", "starting_point", &wr, this), starting_angle(_("Starting:"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0), rotation_angle(_("Rotation angle:"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 60.0), num_copies(_("Number of copies:"), _("Number of copies of the original path"), "num_copies", &wr, this, 6), @@ -74,6 +56,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : registerParameter(&copies_to_360); registerParameter(&fuse_paths); registerParameter(&starting_angle); + registerParameter(&starting_point); registerParameter(&rotation_angle); registerParameter(&num_copies); registerParameter(&origin); @@ -87,6 +70,41 @@ LPECopyRotate::~LPECopyRotate() } +Gtk::Widget * LPECopyRotate::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(); + 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 != "starting_point") { + 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; + } + return dynamic_cast<Gtk::Widget *>(vbox); +} + + void LPECopyRotate::doOnApply(SPLPEItem const* lpeitem) { @@ -104,11 +122,6 @@ LPECopyRotate::doOnApply(SPLPEItem const* lpeitem) void LPECopyRotate::transform_multiply(Geom::Affine const& postmul, bool set) { - if(fuse_paths) { - Geom::Coord angle = Geom::deg_from_rad(atan(-postmul[1]/postmul[0])); - angle += starting_angle; - starting_angle.param_set_value(angle); - } // cycle through all parameters. Most parameters will not need transformation, but path and point params do. for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); ++it) { @@ -146,11 +159,25 @@ LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem) dir = unit_vector(B - A); // I first suspected the minus sign to be a bug in 2geom but it is // likely due to SVG's choice of coordinate system orientation (max) + bool near = Geom::are_near(previous_start_point, (Geom::Point)starting_point, 0.01); + if (!near) { + starting_angle.param_set_value(deg_from_rad(-angle_between(dir, starting_point - origin))); + if (GDK_SHIFT_MASK) { + dist_angle_handle = L2(B - A); + } else { + dist_angle_handle = L2(starting_point - origin); + } + } start_pos = origin + dir * Rotate(-rad_from_deg(starting_angle)) * dist_angle_handle; rot_pos = origin + dir * Rotate(-rad_from_deg(rotation_angle+starting_angle)) * dist_angle_handle; + if (near) { + starting_point.param_setValue(start_pos); + } + previous_start_point = (Geom::Point)starting_point; if ( fuse_paths || copies_to_360 ) { rot_pos = origin; } + SPLPEItem * item = const_cast<SPLPEItem*>(lpeitem); item->apply_to_clippath(item); item->apply_to_mask(item); @@ -418,85 +445,6 @@ LPECopyRotate::resetDefaults(SPItem const* item) original_bbox(SP_LPE_ITEM(item)); } -void -LPECopyRotate::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) -{ - { - KnotHolderEntity *e = new CR::KnotHolderEntityStartingAngle(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the starting angle")); - knotholder->add(e); - } - { - KnotHolderEntity *e = new CR::KnotHolderEntityRotationAngle(this); - e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the rotation angle")); - knotholder->add(e); - } -}; - -namespace CR { - -using namespace Geom; - -void -KnotHolderEntityStartingAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) -{ - LPECopyRotate* lpe = dynamic_cast<LPECopyRotate *>(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - // I first suspected the minus sign to be a bug in 2geom but it is - // likely due to SVG's choice of coordinate system orientation (max) - lpe->starting_angle.param_set_value(deg_from_rad(-angle_between(lpe->dir, s - lpe->origin))); - if (state & GDK_SHIFT_MASK) { - lpe->dist_angle_handle = L2(lpe->B - lpe->A); - } else { - lpe->dist_angle_handle = L2(p - lpe->origin); - } - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); -} - -void -KnotHolderEntityRotationAngle::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) -{ - LPECopyRotate* lpe = dynamic_cast<LPECopyRotate *>(_effect); - - Geom::Point const s = snap_knot_position(p, state); - - // I first suspected the minus sign to be a bug in 2geom but it is - // likely due to SVG's choice of coordinate system orientation (max) - lpe->rotation_angle.param_set_value(deg_from_rad(-angle_between(lpe->dir, s - lpe->origin)) - lpe->starting_angle); - if (state & GDK_SHIFT_MASK) { - lpe->dist_angle_handle = L2(lpe->B - lpe->A); - } else { - lpe->dist_angle_handle = L2(p - lpe->origin); - } - - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); -} - -Geom::Point -KnotHolderEntityStartingAngle::knot_get() const -{ - LPECopyRotate const *lpe = dynamic_cast<LPECopyRotate const*>(_effect); - return lpe->start_pos; -} - -Geom::Point -KnotHolderEntityRotationAngle::knot_get() const -{ - LPECopyRotate const *lpe = dynamic_cast<LPECopyRotate const*>(_effect); - return lpe->rot_pos; -} - -} // namespace CR - -/* ######################## */ - } //namespace LivePathEffect } /* namespace Inkscape */ diff --git a/src/live_effects/lpe-copy_rotate.h b/src/live_effects/lpe-copy_rotate.h index 87af867df..8f9fc12ac 100644 --- a/src/live_effects/lpe-copy_rotate.h +++ b/src/live_effects/lpe-copy_rotate.h @@ -21,12 +21,6 @@ namespace Inkscape { namespace LivePathEffect { -namespace CR { -// we need a separate namespace to avoid clashes with LPEPerpBisector -class KnotHolderEntityStartingAngle; -class KnotHolderEntityRotationAngle; -} - class LPECopyRotate : public Effect, GroupBBoxEffect { public: LPECopyRotate(LivePathEffectObject *lpeobject); @@ -38,16 +32,13 @@ public: virtual void split(Geom::PathVector &path_in, Geom::Path const ÷r); virtual void resetDefaults(SPItem const* item); virtual void transform_multiply(Geom::Affine const& postmul, bool set); - /* the knotholder entity classes must be declared friends */ - friend class CR::KnotHolderEntityStartingAngle; - friend class CR::KnotHolderEntityRotationAngle; - void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); - + virtual Gtk::Widget * newWidget(); protected: virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); private: PointParam origin; + PointParam starting_point; ScalarParam starting_angle; ScalarParam rotation_angle; ScalarParam num_copies; @@ -58,6 +49,7 @@ private: Geom::Point dir; Geom::Point start_pos; Geom::Point rot_pos; + Geom::Point previous_start_point; double dist_angle_handle; LPECopyRotate(const LPECopyRotate&); LPECopyRotate& operator=(const LPECopyRotate&); diff --git a/src/live_effects/lpe-curvestitch.cpp b/src/live_effects/lpe-curvestitch.cpp index 3beedaf57..38cbeaac0 100644 --- a/src/live_effects/lpe-curvestitch.cpp +++ b/src/live_effects/lpe-curvestitch.cpp @@ -13,8 +13,6 @@ */ #include "ui/widget/scalar.h" -#include <glibmm/i18n.h> - #include "live_effects/lpe-curvestitch.h" #include "sp-path.h" @@ -22,6 +20,9 @@ #include "xml/repr.h" #include <2geom/bezier-to-sbasis.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-dynastroke.cpp b/src/live_effects/lpe-dynastroke.cpp index 7e22f6e51..50bbe6451 100644 --- a/src/live_effects/lpe-dynastroke.cpp +++ b/src/live_effects/lpe-dynastroke.cpp @@ -16,6 +16,8 @@ #include <2geom/bezier-to-sbasis.h> #include <2geom/sbasis-math.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-ellipse_5pts.cpp b/src/live_effects/lpe-ellipse_5pts.cpp index 0371fc313..28e7058d7 100644 --- a/src/live_effects/lpe-ellipse_5pts.cpp +++ b/src/live_effects/lpe-ellipse_5pts.cpp @@ -12,15 +12,14 @@ */ #include "live_effects/lpe-ellipse_5pts.h" - -// You might need to include other 2geom files. You can add them here: -#include <glibmm/i18n.h> #include <2geom/circle.h> #include <2geom/ellipse.h> #include <2geom/path-sink.h> #include "inkscape.h" #include "desktop.h" #include "message-stack.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-envelope.cpp b/src/live_effects/lpe-envelope.cpp index c3b0a7c10..61a696435 100644 --- a/src/live_effects/lpe-envelope.cpp +++ b/src/live_effects/lpe-envelope.cpp @@ -6,6 +6,8 @@ #include "live_effects/lpe-envelope.h" #include "display/curve.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> using std::vector; diff --git a/src/live_effects/lpe-extrude.cpp b/src/live_effects/lpe-extrude.cpp index d22007f76..daa30d45a 100644 --- a/src/live_effects/lpe-extrude.cpp +++ b/src/live_effects/lpe-extrude.cpp @@ -12,10 +12,10 @@ */ #include "live_effects/lpe-extrude.h" - +#include "sp-item.h" +// TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> -#include "sp-item.h" namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-fill-between-many.cpp b/src/live_effects/lpe-fill-between-many.cpp index 2087925fa..1e2eadfdb 100644 --- a/src/live_effects/lpe-fill-between-many.cpp +++ b/src/live_effects/lpe-fill-between-many.cpp @@ -11,7 +11,7 @@ #include "display/curve.h" #include "sp-shape.h" #include "sp-text.h" - +// TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> namespace Inkscape { diff --git a/src/live_effects/lpe-fill-between-strokes.cpp b/src/live_effects/lpe-fill-between-strokes.cpp index b1e328d18..0dbebdf26 100644 --- a/src/live_effects/lpe-fill-between-strokes.cpp +++ b/src/live_effects/lpe-fill-between-strokes.cpp @@ -3,14 +3,13 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - -#include <glibmm/i18n.h> - #include "live_effects/lpe-fill-between-strokes.h" #include "display/curve.h" #include "sp-shape.h" #include "sp-text.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index 24ee2ccc3..1e2df7dc8 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -25,8 +25,8 @@ // for programmatically updating knots #include "ui/tools-switch.h" - // TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> using namespace Geom; namespace Inkscape { diff --git a/src/live_effects/lpe-gears.cpp b/src/live_effects/lpe-gears.cpp index 1d5398aa5..17579c64e 100644 --- a/src/live_effects/lpe-gears.cpp +++ b/src/live_effects/lpe-gears.cpp @@ -7,10 +7,9 @@ */ #include "live_effects/lpe-gears.h" - -#include <glibmm/i18n.h> - #include <2geom/bezier-to-sbasis.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> using std::vector; using namespace Geom; diff --git a/src/live_effects/lpe-interpolate.cpp b/src/live_effects/lpe-interpolate.cpp index 43da4d105..e95dc5f38 100644 --- a/src/live_effects/lpe-interpolate.cpp +++ b/src/live_effects/lpe-interpolate.cpp @@ -9,15 +9,15 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - -#include <glibmm/i18n.h> - #include "live_effects/lpe-interpolate.h" #include <2geom/sbasis-to-bezier.h> #include "sp-path.h" #include "display/curve.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-interpolate_points.cpp b/src/live_effects/lpe-interpolate_points.cpp index ab0576174..0a0bcea14 100644 --- a/src/live_effects/lpe-interpolate_points.cpp +++ b/src/live_effects/lpe-interpolate_points.cpp @@ -12,8 +12,9 @@ */ #include "live_effects/lpe-interpolate_points.h" - #include "live_effects/lpe-powerstroke-interpolators.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-jointype.cpp b/src/live_effects/lpe-jointype.cpp index 3bfbd6288..dacb87dd9 100644 --- a/src/live_effects/lpe-jointype.cpp +++ b/src/live_effects/lpe-jointype.cpp @@ -19,6 +19,8 @@ #include <2geom/elliptical-arc.h> #include "lpe-jointype.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp index 474523aa3..c35da0601 100644 --- a/src/live_effects/lpe-knot.cpp +++ b/src/live_effects/lpe-knot.cpp @@ -33,6 +33,9 @@ #include "document.h" #include "document-undo.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-lattice.cpp b/src/live_effects/lpe-lattice.cpp index 091b6ddca..acffed000 100644 --- a/src/live_effects/lpe-lattice.cpp +++ b/src/live_effects/lpe-lattice.cpp @@ -20,7 +20,8 @@ #include <2geom/sbasis-2d.h> #include <2geom/bezier-to-sbasis.h> - +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> using namespace Geom; namespace Inkscape { diff --git a/src/live_effects/lpe-lattice2.cpp b/src/live_effects/lpe-lattice2.cpp index 9e9fc153a..e827491c0 100644 --- a/src/live_effects/lpe-lattice2.cpp +++ b/src/live_effects/lpe-lattice2.cpp @@ -16,12 +16,15 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <gtkmm.h> #include "live_effects/lpe-lattice2.h" #include "display/curve.h" #include "helper/geom.h" #include <2geom/sbasis-2d.h> #include <2geom/bezier-to-sbasis.h> + // TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> using namespace Geom; diff --git a/src/live_effects/lpe-lattice2.h b/src/live_effects/lpe-lattice2.h index 4a025d182..59a0350d3 100644 --- a/src/live_effects/lpe-lattice2.h +++ b/src/live_effects/lpe-lattice2.h @@ -18,7 +18,7 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <gtkmm.h> + #include "live_effects/effect.h" #include "live_effects/parameter/enum.h" #include "live_effects/parameter/point.h" diff --git a/src/live_effects/lpe-line_segment.cpp b/src/live_effects/lpe-line_segment.cpp index 4c9edabd4..cc024fb92 100644 --- a/src/live_effects/lpe-line_segment.cpp +++ b/src/live_effects/lpe-line_segment.cpp @@ -13,6 +13,8 @@ #include "live_effects/lpe-line_segment.h" #include "ui/tools/lpe-tool.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp index 11620b23f..f34421df2 100644 --- a/src/live_effects/lpe-mirror_symmetry.cpp +++ b/src/live_effects/lpe-mirror_symmetry.cpp @@ -13,6 +13,10 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ + +#include <gtkmm.h> +#include "live_effects/lpeobject.h" +#include "live_effects/lpeobject-reference.h" #include "live_effects/lpe-mirror_symmetry.h" #include "display/curve.h" #include "svg/path-string.h" @@ -27,6 +31,7 @@ #include "knotholder.h" #include "style.h" #include "xml/sp-css-attr.h" + // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> @@ -43,17 +48,6 @@ static const Util::EnumData<ModeType> ModeTypeData[MT_END] = { static const Util::EnumDataConverter<ModeType> MTConverter(ModeTypeData, MT_END); -namespace MS { - -class KnotHolderEntityCenterMirrorSymmetry : public LPEKnotHolderEntity { -public: - KnotHolderEntityCenterMirrorSymmetry(LPEMirrorSymmetry *effect) : LPEKnotHolderEntity(effect){}; - virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state); - virtual Geom::Point knot_get() const; -}; - -} // namespace MS - LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : Effect(lpeobject), mode(_("Mode"), _("Symmetry move mode"), "mode", MTConverter, &wr, this, MT_FREE), @@ -61,27 +55,26 @@ LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : discard_orig_path(_("Discard original path?"), _("Check this to only keep the mirrored part of the path"), "discard_orig_path", &wr, this, false), fuse_paths(_("Fuse paths"), _("Fuse original and the reflection into a single path"), "fuse_paths", &wr, this, false), oposite_fuse(_("Opposite fuse"), _("Picks the other side of the mirror as the original"), "oposite_fuse", &wr, this, false), - split_elements(_("Split elements"), _("Split elements, this allow gradients and other paints"), "split_elements", &wr, this, false), - start_point(_("Start mirror line"), _("Start mirror line"), "start_point", &wr, this, "Adjust the start of mirroring"), - end_point(_("End mirror line"), _("End mirror line"), "end_point", &wr, this, "Adjust end of mirroring"), - id_origin("id_origin", "id_origin", "id_origin", &wr, this,"") + split_elements(_("Split elements"), _("Split elements, this allow gradients and other paints. Group result to apply nested"), "split_elements", &wr, this, false), + start_point(_("Start mirror line"), _("Start mirror line"), "start_point", &wr, this, _("Adjust the start of mirroring")), + end_point(_("End mirror line"), _("End mirror line"), "end_point", &wr, this, _("Adjust end of mirroring")), + center_point(_("Center mirror line"), _("Center mirror line"), "center_point", &wr, this, _("Adjust center of mirroring")) { show_orig_path = true; registerParameter(&mode); - registerParameter( &split_gap); - registerParameter( &discard_orig_path); - registerParameter( &fuse_paths); - registerParameter( &oposite_fuse); - registerParameter( &split_elements); - registerParameter( &start_point); - registerParameter( &end_point); - registerParameter( &id_origin); - id_origin.param_hide_canvas_text(); + registerParameter(&split_gap); + registerParameter(&discard_orig_path); + registerParameter(&fuse_paths); + registerParameter(&oposite_fuse); + registerParameter(&split_elements); + registerParameter(&start_point); + registerParameter(&end_point); + registerParameter(¢er_point); split_gap.param_set_range(-999999.0, 999999.0); split_gap.param_set_increments(0.1, 0.1); split_gap.param_set_digits(2); apply_to_clippath_and_mask = true; - actual = true; + previous_center = Geom::Point(0,0); } LPEMirrorSymmetry::~LPEMirrorSymmetry() @@ -94,11 +87,10 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem); if (SPDesktop *desktop = SP_ACTIVE_DESKTOP) { Inkscape::Selection *sel = desktop->getSelection(); - if ( sel && !sel->isEmpty() && actual) { + if ( sel && !sel->isEmpty()) { SPItem *item = sel->singleItem(); if (item) { if(std::strcmp(splpeitem->getId(),item->getId()) != 0) { - actual = false; return; } } @@ -117,11 +109,14 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) point_a = Geom::Point(center_point[X],boundingbox_Y.min()); point_b = Geom::Point(center_point[X],boundingbox_Y.max()); } + if (Geom::are_near((Geom::Point)start_point, (Geom::Point)end_point, 0.01)) { + start_point.param_setValue(point_a); + end_point.param_setValue(point_b); + } line_separation.setPoints(point_a, point_b); if ( mode == MT_X || mode == MT_Y ) { start_point.param_setValue(point_a); end_point.param_setValue(point_b); - center_point = Geom::middle_point(point_a, point_b); } else if ( mode == MT_FREE) { if(!are_near(previous_center,center_point, 0.01)) { Geom::Point trans = center_point - previous_center; @@ -129,7 +124,6 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) end_point.param_setValue(end_point * trans); line_separation.setPoints(start_point, end_point); } else { - center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); line_separation.setPoints(start_point, end_point); } } else if ( mode == MT_V){ @@ -142,7 +136,6 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) Geom::Point ep = Geom::Point(view_box_rect.width()/2.0, view_box_rect.height()); ep *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); end_point.param_setValue(ep); - center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); line_separation.setPoints(start_point, end_point); } } else { //horizontal page @@ -155,53 +148,56 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) Geom::Point ep = Geom::Point(view_box_rect.width(), view_box_rect.height()/2.0); ep *= i2anc_affine(SP_OBJECT(lpeitem), SP_OBJECT(SP_ACTIVE_DESKTOP->currentLayer()->parent)) .inverse(); end_point.param_setValue(ep); - center_point = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); line_separation.setPoints(start_point, end_point); } } - previous_center = center_point; - if (split_elements) { - ms_container = dynamic_cast<SPObject *>(splpeitem->parent); + + previous_center = Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); + if (!are_near(previous_center, center_point,0.01)) { + center_point.param_setValue(previous_center); + } + if (split_elements && allow_split()) { + container = dynamic_cast<SPObject *>(splpeitem->parent); SPDocument * doc = SP_ACTIVE_DOCUMENT; Inkscape::XML::Node *root = splpeitem->document->getReprRoot(); Inkscape::XML::Node *root_origin = doc->getReprRoot(); if (root_origin != root) { return; } - Geom::Point point_a(line_separation.initialPoint()); - Geom::Point point_b(line_separation.finalPoint()); - Geom::Point gap(split_gap,0); - Geom::Translate m1(point_a[0], point_a[1]); - double hyp = Geom::distance(point_a, point_b); - double cos = 0; - double sin = 0; - if (hyp > 0) { - cos = (point_b[0] - point_a[0]) / hyp; - sin = (point_b[1] - point_a[1]) / hyp; - } - Geom::Affine m2(cos, -sin, sin, cos, 0.0, 0.0); - Geom::Point dir = unit_vector(point_b - point_a); - Geom::Point offset = (point_a + point_b)/2 + dir.ccw() * split_gap; - line_separation *= Geom::Translate(offset); - Geom::Scale sca(1.0, -1.0); - const char * id_original = id_origin.param_getSVGValue(); - const char * id = g_strdup(Glib::ustring("mirror-").append(id_original).append("-").append(this->getRepr()->attribute("id")).c_str()); - m = m1.inverse() * m2; - m = m * sca; - m = m * m2.inverse(); - m = m * m1; - m = m * lpeitem->transform; - if (std::strcmp(splpeitem->getId(), id) == 0) { - createMirror(splpeitem, m, id_original); - } else { - createMirror(splpeitem, m, id); - } - elements.clear(); - elements.push_back(id); - elements.push_back(id_original); + const char * mirror = g_strdup(Glib::ustring("mirror-b-").append(this->getRepr()->attribute("id")).c_str()); +// if (std::strcmp(splpeitem->getId(), mirror_b) == 0) { +// syncMirror(splpeitem, mirror_a); +// } else { + Geom::Point point_a(line_separation.initialPoint()); + Geom::Point point_b(line_separation.finalPoint()); + Geom::Point gap(split_gap,0); + Geom::Translate m1(point_a[0], point_a[1]); + double hyp = Geom::distance(point_a, point_b); + double cos = 0; + double sin = 0; + if (hyp > 0) { + cos = (point_b[0] - point_a[0]) / hyp; + sin = (point_b[1] - point_a[1]) / hyp; + } + Geom::Affine m2(cos, -sin, sin, cos, 0.0, 0.0); + Geom::Point dir = unit_vector(point_b - point_a); + Geom::Point offset = (point_a + point_b)/2 + dir.ccw() * split_gap; + line_separation *= Geom::Translate(offset); + Geom::Scale sca(1.0, -1.0); + m = m1.inverse() * m2; + m = m * sca; + m = m * m2.inverse(); + m = m * m1; + m = m * splpeitem->transform; + createMirror(splpeitem, m); + //} } else { - elements.clear(); + if (!allow_split()) { + std::cout << "Only one operation of split allowed. Group results to nested effects.\n"; + split_elements.param_setValue(false); + } processObjects(LPE_ERASE); + elements.clear(); } } @@ -255,7 +251,7 @@ LPEMirrorSymmetry::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, c if (c) { dest->getRepr()->setAttribute(att,sp_svg_write_path(c->get_pathvector())); c->reset(); - g_free(c); + g_free(c); } else { dest->getRepr()->setAttribute(att,NULL); } @@ -268,9 +264,19 @@ LPEMirrorSymmetry::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, c } void -LPEMirrorSymmetry::createMirror(SPLPEItem *origin, Geom::Affine transform, const char * id) +LPEMirrorSymmetry::createMirror(SPLPEItem *origin, Geom::Affine transform) { if (SPDesktop *desktop = SP_ACTIVE_DESKTOP) { + const char * id; + Glib::ustring idbase = Glib::ustring(sp_lpe_item->getId()); + size_t pos = idbase.find("-mirror"); + if (pos <= idbase.size()) { + id = g_strdup(idbase.substr(pos).c_str()); + } else { + id = g_strdup(idbase.append("-mirror").c_str()); + elements.clear(); + elements.push_back(id); + } Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::URI SVGElem_uri(Glib::ustring("#").append(id).c_str()); Inkscape::URIReference* SVGElemRef = new Inkscape::URIReference(desktop->doc()); @@ -282,24 +288,95 @@ LPEMirrorSymmetry::createMirror(SPLPEItem *origin, Geom::Affine transform, const } else { phantom = origin->getRepr()->duplicate(xml_doc); } - phantom->setAttribute("id", id); if (!elemref) { - elemref = ms_container->appendChildRepr(phantom); + elemref = container->appendChildRepr(phantom); Inkscape::GC::release(phantom); } - cloneAttrbutes(SP_OBJECT(origin), elemref, true, "inkscape:original-d", NULL); //NULL required + cloneAttrbutes(SP_OBJECT(origin), elemref, true, "inkscape:original-d", "inkscape:path-effect", NULL); //NULL required elemref->getRepr()->setAttribute("transform" , sp_svg_transform_write(transform)); - if (elemref->parent != ms_container) { + if (elemref->parent != container) { Inkscape::XML::Node *copy = phantom->duplicate(xml_doc); copy->setAttribute("id", id); - ms_container->appendChildRepr(copy); + container->appendChildRepr(copy); Inkscape::GC::release(copy); elemref->deleteObject(); } } } +//void +//LPEMirrorSymmetry::syncMirror(SPLPEItem *origin, const char * id) +//{ +// if (SPDesktop *desktop = SP_ACTIVE_DESKTOP) { +// Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); +// Inkscape::URI SVGElem_uri(Glib::ustring("#").append(id).c_str()); +// Inkscape::URIReference* SVGElemRef = new Inkscape::URIReference(desktop->doc()); +// SVGElemRef->attach(SVGElem_uri); +// SPObject *elemref= NULL; +// Inkscape::XML::Node *phantom = NULL; +// if (elemref = SVGElemRef->getObject()) { +// cloneAttrbutes(SP_OBJECT(origin), elemref, true, "inkscape:original-d", "inkscape:path-effect", NULL); //NULL required +// } +// } +//} + +bool +LPEMirrorSymmetry::allow_split(){ + if (sp_lpe_item->path_effect_list->empty()) { + return false; + } + size_t count = 0; + for (PathEffectList::const_iterator it = sp_lpe_item->path_effect_list->begin(); it != sp_lpe_item->path_effect_list->end(); ++it) + { + LivePathEffectObject *lpeobj = (*it)->lpeobject; + if (lpeobj) { + Inkscape::LivePathEffect::LPEMirrorSymmetry * ms = dynamic_cast<Inkscape::LivePathEffect::LPEMirrorSymmetry *>(lpeobj->get_lpe()); + if (ms && ms->split_elements) { + count++; + } + } + } + return count <= 1; +} + +//Gtk::Widget * +//LPEMirrorSymmetry::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); +// 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()); +// if (widg) { +// if (param->param_key == "split_elements") { +// Gtk::CheckButton *widg_registered = Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg)); +// if (!allow_split()) { +// widg_registered->set_sensitive("false"); +// } +// widg = dynamic_cast<Gtk::Widget *>(widg_registered); +// } +// Glib::ustring *tip = param->param_getTooltip(); +// 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; +// } +// return dynamic_cast<Gtk::Widget *>(vbox); +//} + //TODO: Migrate the tree next function to effect.cpp/h to avoid duplication void LPEMirrorSymmetry::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) @@ -349,15 +426,15 @@ LPEMirrorSymmetry::processObjects(LpeAction lpe_action) break; case LPE_ERASE: - if (std::strcmp(elemref->getId(),id_origin.param_getSVGValue()) != 0) { + //if (std::strcmp(elemref->getId(),sp_lpe_item->getId()) != 0) { elemref->deleteObject(); - } + //} break; case LPE_VISIBILITY: css = sp_repr_css_attr_new(); sp_repr_css_attr_add_from_string(css, elemref->getRepr()->attribute("style")); - if (!this->isVisible() && std::strcmp(elemref->getId(),id_origin.param_getSVGValue()) != 0) { + if (!this->isVisible()/* && std::strcmp(elemref->getId(),sp_lpe_item->getId()) != 0*/) { css->setAttribute("display", "none"); } else { css->setAttribute("display", NULL); @@ -382,8 +459,6 @@ void LPEMirrorSymmetry::transform_multiply(Geom::Affine const& postmul, bool set) { if( !split_elements) { - center_point *= postmul; - previous_center = center_point; // cycle through all parameters. Most parameters will not need transformation, but path and point params do. for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); ++it) { Parameter * param = *it; @@ -406,10 +481,15 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem) start_point.param_update_default(point_a); end_point.param_setValue(point_b); end_point.param_update_default(point_b); - center_point = point_c; + center_point.param_setValue(point_c); previous_center = center_point; - id_origin.param_setValue(Glib::ustring(lpeitem->getId())); - id_origin.write_to_SVG(); +// SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem); +// if (!lpeitem->hasPathEffectOfType(this->effectType(), false) ){ //first applied not ready yet +// const char * mirror_a = g_strdup(Glib::ustring("mirror-a-").append(this->getRepr()->attribute("id")).c_str()); +// splpeitem->setAttribute("id", mirror_a); +// first_lpe.param_setValue(this->getRepr()->attribute("id")); +// first_lpe.write_to_SVG(); +// } } @@ -560,41 +640,6 @@ LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in) return path_out; } - -Gtk::Widget *LPEMirrorSymmetry::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(); - 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 != "id_origin") { - 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; - } - return dynamic_cast<Gtk::Widget *>(vbox); -} - void LPEMirrorSymmetry::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) { @@ -610,43 +655,6 @@ LPEMirrorSymmetry::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector hp_vec.push_back(helper); } -void -LPEMirrorSymmetry::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item) -{ - SPKnotShapeType knot_shape = SP_KNOT_SHAPE_CIRCLE; - SPKnotModeType knot_mode = SP_KNOT_MODE_XOR; - guint32 knot_color = 0x0000ff00; - { - KnotHolderEntity *c = new MS::KnotHolderEntityCenterMirrorSymmetry(this); - c->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, - _("Adjust the center"), knot_shape, knot_mode, knot_color ); - knotholder->add(c); - } -}; - -namespace MS { - -using namespace Geom; - -void -KnotHolderEntityCenterMirrorSymmetry::knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) -{ - LPEMirrorSymmetry* lpe = dynamic_cast<LPEMirrorSymmetry *>(_effect); - Geom::Point const s = snap_knot_position(p, state); - lpe->center_point = s; - // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. - sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); -} - -Geom::Point -KnotHolderEntityCenterMirrorSymmetry::knot_get() const -{ - LPEMirrorSymmetry const *lpe = dynamic_cast<LPEMirrorSymmetry const*>(_effect); - return lpe->center_point; -} - -} // namespace CR - } //namespace LivePathEffect } /* namespace Inkscape */ diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h index 7b090ed82..12ceebaf8 100644 --- a/src/live_effects/lpe-mirror_symmetry.h +++ b/src/live_effects/lpe-mirror_symmetry.h @@ -15,10 +15,10 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <gtkmm.h> + #include "live_effects/effect.h" -#include "live_effects/parameter/text.h" #include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/text.h" #include "live_effects/parameter/point.h" #include "live_effects/parameter/path.h" #include "live_effects/parameter/enum.h" @@ -27,11 +27,6 @@ namespace Inkscape { namespace LivePathEffect { -namespace MS { -// we need a separate namespace to avoid clashes with LPEPerpBisector -class KnotHolderEntityCenterMirrorSymmetry; -} - enum ModeType { MT_V, MT_H, @@ -51,14 +46,13 @@ public: virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in); virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); - virtual Gtk::Widget *newWidget(); +// virtual Gtk::Widget * newWidget(); void processObjects(LpeAction lpe_action); - /* the knotholder entity classes must be declared friends */ - friend class MS::KnotHolderEntityCenterMirrorSymmetry; - void createMirror(SPLPEItem *origin, Geom::Affine transform, const char * id); + void createMirror(SPLPEItem *origin, Geom::Affine transform); // void cloneAttrbutes(Inkscape::XML::Node * origin, Inkscape::XML::Node * dest, const char * first_attribute, ...); +// void syncMirror(SPLPEItem *origin, const char * id); void cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * first_attribute, ...); - void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item); + bool allow_split(); protected: virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); @@ -72,13 +66,11 @@ private: BoolParam split_elements; PointParam start_point; PointParam end_point; - TextParam id_origin; + PointParam center_point; Geom::Line line_separation; Geom::Point previous_center; - Geom::Point center_point; - bool actual; std::vector<const char *> elements; - SPObject * ms_container; + SPObject * container; LPEMirrorSymmetry(const LPEMirrorSymmetry&); LPEMirrorSymmetry& operator=(const LPEMirrorSymmetry&); }; diff --git a/src/live_effects/lpe-offset.cpp b/src/live_effects/lpe-offset.cpp index a0fa46c3f..057f404e0 100644 --- a/src/live_effects/lpe-offset.cpp +++ b/src/live_effects/lpe-offset.cpp @@ -11,13 +11,12 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-offset.h" #include "sp-shape.h" #include "display/curve.h" - #include <2geom/elliptical-arc.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-parallel.cpp b/src/live_effects/lpe-parallel.cpp index 9cd8ecf46..276749c43 100644 --- a/src/live_effects/lpe-parallel.cpp +++ b/src/live_effects/lpe-parallel.cpp @@ -11,14 +11,15 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-parallel.h" #include "sp-shape.h" #include "display/curve.h" #include "knotholder.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-path_length.cpp b/src/live_effects/lpe-path_length.cpp index 6ec1e0ede..a06dbde98 100644 --- a/src/live_effects/lpe-path_length.cpp +++ b/src/live_effects/lpe-path_length.cpp @@ -11,10 +11,10 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-path_length.h" #include "util/units.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-patternalongpath.cpp b/src/live_effects/lpe-patternalongpath.cpp index 15c2817c4..9cfeffee7 100644 --- a/src/live_effects/lpe-patternalongpath.cpp +++ b/src/live_effects/lpe-patternalongpath.cpp @@ -12,6 +12,8 @@ #include "knotholder.h" #include <algorithm> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> using std::vector; diff --git a/src/live_effects/lpe-perp_bisector.cpp b/src/live_effects/lpe-perp_bisector.cpp index f69dae6a1..bce22250a 100644 --- a/src/live_effects/lpe-perp_bisector.cpp +++ b/src/live_effects/lpe-perp_bisector.cpp @@ -11,9 +11,6 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - -#include <glibmm/i18n.h> - #include "live_effects/lpe-perp_bisector.h" #include "display/curve.h" #include "sp-path.h" @@ -21,6 +18,9 @@ #include "knotholder.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { namespace PB { diff --git a/src/live_effects/lpe-perspective-envelope.cpp b/src/live_effects/lpe-perspective-envelope.cpp index 6a6b59519..e834c0e86 100644 --- a/src/live_effects/lpe-perspective-envelope.cpp +++ b/src/live_effects/lpe-perspective-envelope.cpp @@ -20,6 +20,9 @@ #include "display/curve.h" #include <gsl/gsl_linalg.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + using namespace Geom; namespace Inkscape { diff --git a/src/live_effects/lpe-perspective_path.cpp b/src/live_effects/lpe-perspective_path.cpp index cb4e43d87..2c6d66cee 100644 --- a/src/live_effects/lpe-perspective_path.cpp +++ b/src/live_effects/lpe-perspective_path.cpp @@ -11,8 +11,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ #include <gtkmm.h> -#include <glibmm/i18n.h> - #include "persp3d.h" //#include "transf_mat_3x4.h" #include "document-private.h" @@ -23,6 +21,9 @@ #include "desktop.h" #include <util/units.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 329a00756..e9f3975c7 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -25,6 +25,9 @@ #include <2geom/circle.h> #include "helper/geom.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Geom { // should all be moved to 2geom at some point diff --git a/src/live_effects/lpe-recursiveskeleton.cpp b/src/live_effects/lpe-recursiveskeleton.cpp index ed0c915ce..aa0db920b 100644 --- a/src/live_effects/lpe-recursiveskeleton.cpp +++ b/src/live_effects/lpe-recursiveskeleton.cpp @@ -10,12 +10,13 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-recursiveskeleton.h" #include <2geom/bezier-to-sbasis.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-rough-hatches.cpp b/src/live_effects/lpe-rough-hatches.cpp index 2fb65b349..3cc8658ea 100644 --- a/src/live_effects/lpe-rough-hatches.cpp +++ b/src/live_effects/lpe-rough-hatches.cpp @@ -13,7 +13,6 @@ */ #include "ui/widget/scalar.h" -#include <glibmm/i18n.h> #include "live_effects/lpe-rough-hatches.h" #include "sp-item.h" @@ -23,6 +22,8 @@ #include <2geom/sbasis-math.h> #include <2geom/bezier-to-sbasis.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp index 3a486ff10..c6edffd9b 100644 --- a/src/live_effects/lpe-roughen.cpp +++ b/src/live_effects/lpe-roughen.cpp @@ -13,11 +13,14 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <gtkmm.h> #include "live_effects/lpe-roughen.h" #include "display/curve.h" #include <boost/functional/hash.hpp> #include "helper/geom.h" + // TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h index dbdb91e62..bab06022f 100644 --- a/src/live_effects/lpe-roughen.h +++ b/src/live_effects/lpe-roughen.h @@ -12,7 +12,6 @@ #ifndef INKSCAPE_LPE_ROUGHEN_H #define INKSCAPE_LPE_ROUGHEN_H -#include <gtkmm.h> #include "live_effects/effect.h" #include "live_effects/parameter/enum.h" #include "live_effects/parameter/parameter.h" diff --git a/src/live_effects/lpe-ruler.cpp b/src/live_effects/lpe-ruler.cpp index 3a2d78b2c..60c2a3e1c 100644 --- a/src/live_effects/lpe-ruler.cpp +++ b/src/live_effects/lpe-ruler.cpp @@ -12,7 +12,8 @@ */ #include "live_effects/lpe-ruler.h" - +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-show_handles.cpp b/src/live_effects/lpe-show_handles.cpp index 170b6dccb..7c298d0e7 100644 --- a/src/live_effects/lpe-show_handles.cpp +++ b/src/live_effects/lpe-show_handles.cpp @@ -6,6 +6,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <gtkmm.h> #include "live_effects/lpe-show_handles.h" #include <2geom/sbasis-to-bezier.h> #include <2geom/svg-path-parser.h> @@ -13,6 +14,7 @@ #include "desktop-style.h" #include "style.h" #include "svg/svg.h" + // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> diff --git a/src/live_effects/lpe-show_handles.h b/src/live_effects/lpe-show_handles.h index 3eda04649..c46abd2c2 100644 --- a/src/live_effects/lpe-show_handles.h +++ b/src/live_effects/lpe-show_handles.h @@ -8,7 +8,6 @@ * Copyright (C) Jabier Arraiza Cenoz 2014 <jabier.arraiza@marker.es> * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <gtkmm.h> #include "helper/geom-nodetype.h" #include "live_effects/effect.h" #include "live_effects/lpegroupbbox.h" diff --git a/src/live_effects/lpe-simplify.cpp b/src/live_effects/lpe-simplify.cpp index ec21e10d2..8bdb19b4f 100644 --- a/src/live_effects/lpe-simplify.cpp +++ b/src/live_effects/lpe-simplify.cpp @@ -2,6 +2,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include <gtkmm.h> #include "live_effects/lpe-simplify.h" #include "display/curve.h" #include "helper/geom.h" @@ -9,6 +10,7 @@ #include "svg/svg.h" #include "ui/tools/node-tool.h" #include "ui/icon-names.h" + // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> diff --git a/src/live_effects/lpe-simplify.h b/src/live_effects/lpe-simplify.h index 8135561af..6c407f572 100644 --- a/src/live_effects/lpe-simplify.h +++ b/src/live_effects/lpe-simplify.h @@ -6,7 +6,6 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <gtkmm.h> #include "live_effects/effect.h" #include "live_effects/parameter/togglebutton.h" #include "live_effects/lpegroupbbox.h" diff --git a/src/live_effects/lpe-skeleton.cpp b/src/live_effects/lpe-skeleton.cpp index 7d34db699..adc4a3493 100644 --- a/src/live_effects/lpe-skeleton.cpp +++ b/src/live_effects/lpe-skeleton.cpp @@ -20,8 +20,7 @@ #include "live_effects/lpe-skeleton.h" -// You might need to include other 2geom files. You can add them here: - +// TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> namespace Inkscape { diff --git a/src/live_effects/lpe-sketch.cpp b/src/live_effects/lpe-sketch.cpp index 95e2f6f0d..e01516f2e 100644 --- a/src/live_effects/lpe-sketch.cpp +++ b/src/live_effects/lpe-sketch.cpp @@ -13,13 +13,14 @@ #include "live_effects/lpe-sketch.h" -#include <glibmm/i18n.h> - // You might need to include other 2geom files. You can add them here: #include <2geom/sbasis-math.h> #include <2geom/bezier-to-sbasis.h> #include <2geom/path-intersection.h> +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-tangent_to_curve.cpp b/src/live_effects/lpe-tangent_to_curve.cpp index b308ef8d7..76d4ea71b 100644 --- a/src/live_effects/lpe-tangent_to_curve.cpp +++ b/src/live_effects/lpe-tangent_to_curve.cpp @@ -13,13 +13,13 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-tangent_to_curve.h" #include "sp-path.h" #include "display/curve.h" #include "knotholder.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp index f6f6b33dc..4ffc41691 100644 --- a/src/live_effects/lpe-taperstroke.cpp +++ b/src/live_effects/lpe-taperstroke.cpp @@ -26,6 +26,8 @@ #include "svg/svg.h" #include "knotholder.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> template<typename T> inline bool withinRange(T value, T low, T high) { diff --git a/src/live_effects/lpe-test-doEffect-stack.cpp b/src/live_effects/lpe-test-doEffect-stack.cpp index c7ecf6481..324893706 100644 --- a/src/live_effects/lpe-test-doEffect-stack.cpp +++ b/src/live_effects/lpe-test-doEffect-stack.cpp @@ -4,10 +4,11 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-test-doEffect-stack.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + using std::memcpy; namespace Inkscape { diff --git a/src/live_effects/lpe-text_label.cpp b/src/live_effects/lpe-text_label.cpp index 602a6897c..709d05e18 100644 --- a/src/live_effects/lpe-text_label.cpp +++ b/src/live_effects/lpe-text_label.cpp @@ -11,10 +11,11 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <glibmm/i18n.h> - #include "live_effects/lpe-text_label.h" +// TODO due to internal breakage in glibmm headers, this must be last: +#include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-transform_2pts.cpp b/src/live_effects/lpe-transform_2pts.cpp index 78db622f2..e1f36eee7 100644 --- a/src/live_effects/lpe-transform_2pts.cpp +++ b/src/live_effects/lpe-transform_2pts.cpp @@ -20,6 +20,7 @@ // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> + namespace Inkscape { namespace LivePathEffect { diff --git a/src/live_effects/lpe-vonkoch.cpp b/src/live_effects/lpe-vonkoch.cpp index 2486f3366..47e2a1cec 100644 --- a/src/live_effects/lpe-vonkoch.cpp +++ b/src/live_effects/lpe-vonkoch.cpp @@ -5,7 +5,7 @@ */ #include "live_effects/lpe-vonkoch.h" - +// TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> //using std::vector; diff --git a/src/live_effects/parameter/fontbutton.cpp b/src/live_effects/parameter/fontbutton.cpp index ff8ab76a0..64c203093 100644 --- a/src/live_effects/parameter/fontbutton.cpp +++ b/src/live_effects/parameter/fontbutton.cpp @@ -4,7 +4,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ - +#include <gtkmm.h> #include "ui/widget/registered-widget.h" #include "live_effects/parameter/fontbutton.h" #include "live_effects/effect.h" diff --git a/src/live_effects/parameter/fontbutton.h b/src/live_effects/parameter/fontbutton.h index 387ad130b..df47251a2 100644 --- a/src/live_effects/parameter/fontbutton.h +++ b/src/live_effects/parameter/fontbutton.h @@ -8,7 +8,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ #include <glib.h> -#include <gtkmm.h> #include "live_effects/parameter/parameter.h" namespace Inkscape { diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index ff43c2ca3..ed00092b2 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -74,8 +74,7 @@ static char const preferences_skeleton[] = " </group>\n" "\n" " <group id=\"tools\"\n" -" bounding_box=\"0\"\n" -" style=\"fill:none;stroke:black;stroke-opacity:1;stroke-width:1px;stroke-linejoin:miter;stroke-linecap:butt;\">\n" +" bounding_box=\"0\">\n" " <group id=\"shapes\" style=\"fill-rule:evenodd;\" selcue=\"1\" gradientdrag=\"1\">\n" " <eventcontext id=\"rect\" style=\"fill:blue;\" usecurrent=\"1\"/>\n" " <eventcontext id=\"3dbox\" style=\"stroke:none;stroke-linejoin:round;\" usecurrent=\"1\">\n" @@ -88,7 +87,7 @@ static char const preferences_skeleton[] = " </eventcontext>\n" " <eventcontext id=\"arc\" style=\"fill:red;\" end=\"0\" start=\"0\" usecurrent=\"1\"/>\n" " <eventcontext id=\"star\" magnitude=\"5\" style=\"fill:yellow;\" usecurrent=\"1\"/>\n" -" <eventcontext id=\"spiral\" style=\"fill:none;\" usecurrent=\"0\"/>\n" +" <eventcontext id=\"spiral\" style=\"fill:none;stroke:black\" expansion=\"1\" usecurrent=\"0\"/>\n" " </group>\n" " <group id=\"freehand\"\n" " style=\"fill:none;stroke:black;stroke-opacity:1;stroke-linejoin:miter;stroke-linecap:butt;\">\n" diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 96dcdbe30..7b2507b5e 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -584,12 +584,13 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d SPText * text = dynamic_cast<SPText *>(citem); if (text) { //this causes a change in text-on-path appearance when there is a non-conformal transform, see bug #1594565 - double scale = (ctrans.expansionX() + ctrans.expansionY()) / 2.0; SPTextPath * text_path = dynamic_cast<SPTextPath *>(text->firstChild()); if (!text_path) { nrepr->setAttribute("transform", affinestr); } else { - sp_recursive_scale_text_size(nrepr, scale); + // The following breaks roundtripping group -> ungroup + // double scale = (ctrans.expansionX() + ctrans.expansionY()) / 2.0; + // sp_recursive_scale_text_size(nrepr, scale); Geom::Affine ttrans = ctrans.inverse() * SP_ITEM(text)->transform * ctrans; gchar *affinestr = sp_svg_transform_write(ttrans); nrepr->setAttribute("transform", affinestr); diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index 9cf9dadc1..98428512f 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -607,7 +607,7 @@ bool SPLPEItem::hasPathEffect() const return true; } -bool SPLPEItem::hasPathEffectOfType(int const type) const +bool SPLPEItem::hasPathEffectOfType(int const type, bool is_ready) const { if (path_effect_list->empty()) { return false; @@ -619,7 +619,9 @@ bool SPLPEItem::hasPathEffectOfType(int const type) const if (lpeobj) { Inkscape::LivePathEffect::Effect const* lpe = lpeobj->get_lpe(); if (lpe && (lpe->effectType() == type)) { - return true; + if (is_ready || lpe->isReady()) { + return true; + } } } } diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h index 9e5cb3329..db4a0c7a3 100644 --- a/src/sp-lpe-item.h +++ b/src/sp-lpe-item.h @@ -73,7 +73,7 @@ public: bool pathEffectsEnabled() const; bool hasPathEffect() const; - bool hasPathEffectOfType(int const type) const; + bool hasPathEffectOfType(int const type, bool is_ready = true) const; bool hasPathEffectRecursive() const; Inkscape::LivePathEffect::Effect* getPathEffectOfType(int type); Inkscape::LivePathEffect::Effect const* getPathEffectOfType(int type) const; diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp index f2604976e..f192d0e44 100644 --- a/src/sp-mesh-array.cpp +++ b/src/sp-mesh-array.cpp @@ -1198,7 +1198,7 @@ void SPMeshNodeArray::create( SPMeshGradient *mg, SPItem *item, Geom::OptRect bb ry = arc->ry.computed; start = arc->start; end = arc->end; - if( end == start ) { + if( end <= start ) { end += 2.0 * M_PI; } } @@ -2026,7 +2026,7 @@ guint SPMeshNodeArray::side_arc( std::vector<guint> corners ) { { case 'L': case 'l': - std::cout << "SPMeshNodeArray::arc_sides: Can't convert straight lines to arcs."; + std::cerr << "SPMeshNodeArray::side_arc: Can't convert straight lines to arcs." << std::endl; break; case 'C': @@ -2052,15 +2052,15 @@ guint SPMeshNodeArray::side_arc( std::vector<guint> corners ) { ++arced; } else { - std::cout << "SPMeshNodeArray::arc_sides: No crossing, can't turn into arc." << std::endl; + std::cerr << "SPMeshNodeArray::side_arc: No crossing, can't turn into arc." << std::endl; } } else { - std::cout << "SPMeshNodeArray::arc_sides: Handles parallel, can't turn into arc." << std::endl; + std::cerr << "SPMeshNodeArray::side_arc: Handles parallel, can't turn into arc." << std::endl; } break; } default: - std::cout << "SPMeshNodeArray::arc_sides: Invalid path type: " << n[1]->path_type << std::endl; + std::cerr << "SPMeshNodeArray::side_arc: Invalid path type: " << n[1]->path_type << std::endl; } } } diff --git a/src/ui/tools/tweak-tool.cpp b/src/ui/tools/tweak-tool.cpp index 56939cc30..ff5d623c2 100644 --- a/src/ui/tools/tweak-tool.cpp +++ b/src/ui/tools/tweak-tool.cpp @@ -1084,7 +1084,8 @@ sp_tweak_dilate (TweakTool *tc, Geom::Point event_p, Geom::Point p, Geom::Point double move_force = get_move_force(tc); double color_force = MIN(sqrt(path_force)/20.0, 1); - auto items= selection->items(); +// auto items= selection->items(); + std::vector<SPItem*> items(selection->items().begin(), selection->items().end()); for(auto i=items.begin();i!=items.end(); ++i){ SPItem *item = *i; diff --git a/src/widgets/mesh-toolbar.cpp b/src/widgets/mesh-toolbar.cpp index f7b7a6ec9..ea0faf1df 100644 --- a/src/widgets/mesh-toolbar.cpp +++ b/src/widgets/mesh-toolbar.cpp @@ -67,76 +67,79 @@ static bool blocked = false; //## Mesh ## //######################## -/* - * Get the current selection and dragger status from the desktop - */ -void ms_read_selection( Inkscape::Selection *selection, - SPMeshGradient *&ms_selected, - bool &ms_selected_multi, - SPMeshType &ms_type, - bool &ms_type_multi ) + +// Get a list of selected meshes taking into account fill/stroke toggles +std::vector<SPMeshGradient *> ms_get_dt_selected_gradients(Inkscape::Selection *selection) { + std::vector<SPMeshGradient *> ms_selected; + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool edit_fill = prefs->getBool("/tools/mesh/edit_fill", true); + bool edit_stroke = prefs->getBool("/tools/mesh/edit_stroke", true); - // Read desktop selection - bool first = true; - ms_type = SP_MESH_TYPE_COONS; - auto itemlist= selection->items(); for(auto i=itemlist.begin();i!=itemlist.end();++i){ - SPItem *item = *i; + SPItem *item = *i;// get the items gradient, not the getVector() version SPStyle *style = item->style; - if (style && (style->fill.isPaintserver())) { - SPPaintServer *server = item->style->getFillPaintServer(); - if ( SP_IS_MESHGRADIENT(server) ) { - - SPMeshGradient *gradient = SP_MESHGRADIENT(server); // ->getVector(); - SPMeshType type = gradient->type; + if (style) { - if (gradient != ms_selected) { - if (ms_selected) { - ms_selected_multi = true; - } else { - ms_selected = gradient; - } + + if (edit_fill && style->fill.isPaintserver()) { + SPPaintServer *server = item->style->getFillPaintServer(); + SPMeshGradient *mesh = dynamic_cast<SPMeshGradient *>(server); + if (mesh) { + ms_selected.push_back(mesh); } - if( type != ms_type ) { - if (ms_type != SP_MESH_TYPE_COONS && !first) { - ms_type_multi = true; - } else { - ms_type = type; - } + } + + if (edit_stroke && style->stroke.isPaintserver()) { + SPPaintServer *server = item->style->getStrokePaintServer(); + SPMeshGradient *mesh = dynamic_cast<SPMeshGradient *>(server); + if (mesh) { + ms_selected.push_back(mesh); } - first = false; } } - if (style && (style->stroke.isPaintserver())) { - SPPaintServer *server = item->style->getStrokePaintServer(); - if ( SP_IS_MESHGRADIENT(server) ) { + } + return ms_selected; +} - SPMeshGradient *gradient = SP_MESHGRADIENT(server); // ->getVector(); - SPMeshType type = gradient->type; - if (gradient != ms_selected) { - if (ms_selected) { - ms_selected_multi = true; - } else { - ms_selected = gradient; - } - } - if( type != ms_type ) { - if (ms_type != SP_MESH_TYPE_COONS && !first) { - ms_type_multi = true; - } else { - ms_type = type; - } - } - first = false; +/* + * Get the current selection status from the desktop + */ +void ms_read_selection( Inkscape::Selection *selection, + SPMeshGradient *&ms_selected, + bool &ms_selected_multi, + SPMeshType &ms_type, + bool &ms_type_multi ) +{ + ms_selected = NULL; + ms_selected_multi = false; + ms_type = SP_MESH_TYPE_COONS; + ms_type_multi = false; + + bool first = true; + + // Read desktop selection, taking into account fill/stroke toggles + std::vector<SPMeshGradient *> meshes = ms_get_dt_selected_gradients( selection ); + for (auto i = meshes.begin(); i != meshes.end(); ++i) { + if (first) { + ms_selected = (*i); + ms_type = (*i)->type; + first = false; + } else { + if (ms_selected != (*i)) { + ms_selected_multi = true; + } + if (ms_type != (*i)->type) { + ms_type_multi = true; } } } - } +} /* * Core function, setup all the widgets whenever something changes on the desktop @@ -173,7 +176,7 @@ static void ms_tb_selection_changed(Inkscape::Selection * /*selection*/, gpointe // std::cout << " type: " << ms_type << std::endl; EgeSelectOneAction* type = (EgeSelectOneAction *) g_object_get_data(G_OBJECT(widget), "mesh_select_type_action"); - gtk_action_set_sensitive( GTK_ACTION(type), (ms_selected && !ms_selected_multi) ); + gtk_action_set_sensitive( GTK_ACTION(type), (ms_selected && !ms_type_multi) ); if (ms_selected) { blocked = TRUE; ege_select_one_action_set_active( type, ms_type ); @@ -204,34 +207,6 @@ static void ms_defs_modified(SPObject * /*defs*/, guint /*flags*/, GObject *widg ms_tb_selection_changed(NULL, widget); } -void ms_get_dt_selected_gradient(Inkscape::Selection *selection, SPMeshGradient *&ms_selected) -{ - SPMeshGradient *gradient = 0; - - auto itemlist= selection->items(); - for(auto i=itemlist.begin();i!=itemlist.end();++i){ - SPItem *item = *i;// get the items gradient, not the getVector() version - SPStyle *style = item->style; - SPPaintServer *server = 0; - - if (style && (style->fill.isPaintserver())) { - server = item->style->getFillPaintServer(); - } - if (style && (style->stroke.isPaintserver())) { - server = item->style->getStrokePaintServer(); - } - - if ( SP_IS_MESHGRADIENT(server) ) { - gradient = SP_MESHGRADIENT(server); - } - } - - if (gradient) { - ms_selected = gradient; - } -} - - /* * Callback functions for user actions */ @@ -296,18 +271,17 @@ static void ms_type_changed(EgeSelectOneAction *act, GtkWidget *widget) SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data(G_OBJECT(widget), "desktop")); Inkscape::Selection *selection = desktop->getSelection(); - SPMeshGradient *gradient = 0; - ms_get_dt_selected_gradient(selection, gradient); + std::vector<SPMeshGradient *> meshes = ms_get_dt_selected_gradients(selection); - if (gradient) { - SPMeshType type = (SPMeshType) ege_select_one_action_get_active(act); + SPMeshType type = (SPMeshType) ege_select_one_action_get_active(act); + for (auto i = meshes.begin(); i != meshes.end(); ++i) { // std::cout << " type: " << type << std::endl; - gradient->type = type; - gradient->type_set = true; - gradient->updateRepr(); - - DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, - _("Set mesh type")); + (*i)->type = type; + (*i)->type_set = true; + (*i)->updateRepr(); + } + if (!meshes.empty() ) { + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH,_("Set mesh type")); } } @@ -366,7 +340,7 @@ static void ms_toggle_handles(void) } } -static void ms_toggle_fill_stroke(void) +static void ms_toggle_fill_stroke(InkToggleAction * /*act*/, gpointer data) { MeshTool *mt = get_mesh_tool(); if (mt) { @@ -374,6 +348,7 @@ static void ms_toggle_fill_stroke(void) drag->updateDraggers(); drag->updateLines(); drag->updateLevels(); + ms_tb_selection_changed(NULL, data); // Need to update Type widget } } @@ -507,7 +482,7 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/mesh/edit_fill"); g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); - g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(ms_toggle_fill_stroke), 0); + g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(ms_toggle_fill_stroke), holder); } /* Edit stroke mesh */ @@ -520,7 +495,7 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/mesh/edit_stroke"); g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher); - g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(ms_toggle_fill_stroke), 0); + g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(ms_toggle_fill_stroke), holder); } /* Show/hide side and tensor handles */ diff --git a/src/widgets/text-toolbar.cpp b/src/widgets/text-toolbar.cpp index 114d946bb..784c467f1 100644 --- a/src/widgets/text-toolbar.cpp +++ b/src/widgets/text-toolbar.cpp @@ -117,6 +117,8 @@ static void sp_print_fontstyle( SPStyle *query ) { } #endif +static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/, GObject *tbl, bool subselection = false); + // Font family static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GObject *tbl ) { @@ -225,8 +227,35 @@ static void sp_text_fontsize_value_changed( Ink_ComboBoxEntry_Action *act, GObje sp_repr_css_set_property (css, "font-size", osfs.str().c_str()); // Apply font size to selected objects. + // Calling sp_desktop_set_style will result in a call to TextTool::_styleSet() which + // will set the style on selected text inside the <text> element. If we want to set + // the style on the outer <text> objects we need to bypass this call. + bool outer = prefs->getInt("/tools/text/outer_style", false); SPDesktop *desktop = SP_ACTIVE_DESKTOP; - sp_desktop_set_style (desktop, css, true, true); + if (outer) { + Inkscape::Selection *selection = desktop->getSelection(); + auto itemlist= selection->items(); + for(auto i=itemlist.begin();i!=itemlist.end(); ++i){ + if (dynamic_cast<SPText *>(*i) || dynamic_cast<SPFlowtext *>(*i)) { + SPItem *item = *i; + + // Scale by inverse of accumulated parent transform + SPCSSAttr *css_set = sp_repr_css_attr_new(); + sp_repr_css_merge(css_set, css); + Geom::Affine const local(item->i2doc_affine()); + double const ex(local.descrim()); + if ( (ex != 0.0) && (ex != 1.0) ) { + sp_css_attr_scale(css_set, 1/ex); + } + + item->changeCSS(css_set,"style"); + + sp_repr_css_attr_unref(css_set); + } + } + } else { + sp_desktop_set_style (desktop, css, true, true); + } // If no selected objects, set default. SPStyle query(SP_ACTIVE_DOCUMENT); @@ -281,6 +310,40 @@ static void sp_text_fontstyle_value_changed( Ink_ComboBoxEntry_Action *act, GObj g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } +// Changes selection to only text outer elements. +static void sp_text_outer_style_changed( InkToggleAction*act, GObject *tbl ) +{ + bool outer = gtk_toggle_action_get_active( GTK_TOGGLE_ACTION(act) ); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/tools/text/outer_style", outer); + + // Update widgets to reflect new state of Text Outer Style button. + sp_text_toolbox_selection_changed( NULL, tbl ); +} + +// Unset line height on selection's inner text objects (tspan, etc.). +static void sp_text_lineheight_unset_changed( InkToggleAction*act, GObject *tbl ) +{ + // quit if run by the _changed callbacks + if (g_object_get_data(G_OBJECT(tbl), "freeze")) { + return; + } + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); + + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_unset_property(css, "line-height"); + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + sp_desktop_set_style (desktop, css); + + sp_repr_css_attr_unref(css); + + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_TEXT, + _("Text: Unset line height.")); + + g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); +} + // Handles both Superscripts and Subscripts static void sp_text_script_changed( InkToggleAction* act, GObject *tbl ) { @@ -549,9 +612,34 @@ static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl ) sp_repr_css_set_property (css, "line-height", osfs.str().c_str()); - // Apply line-height to selected objects. + // Apply line-height to selected objects. See comment in font size function. + bool outer = prefs->getInt("/tools/text/outer_style", false); SPDesktop *desktop = SP_ACTIVE_DESKTOP; - sp_desktop_set_style (desktop, css, true, false); + if (outer) { + Inkscape::Selection *selection = desktop->getSelection(); + auto itemlist= selection->items(); + for(auto i=itemlist.begin();i!=itemlist.end(); ++i){ + if (dynamic_cast<SPText *>(*i) || dynamic_cast<SPFlowtext *>(*i)) { + SPItem *item = *i; + + // Scale by inverse of accumulated parent transform + SPCSSAttr *css_set = sp_repr_css_attr_new(); + sp_repr_css_merge(css_set, css); + Geom::Affine const local(item->i2doc_affine()); + double const ex(local.descrim()); + if ( (ex != 0.0) && (ex != 1.0) ) { + sp_css_attr_scale(css_set, 1/ex); + } + + item->changeCSS(css_set,"style"); + + sp_repr_css_attr_unref(css_set); + } + } + } else { + sp_desktop_set_style (desktop, css, true, true); + } + // Only need to save for undo if a text item has been changed. @@ -652,7 +740,7 @@ static void sp_text_lineheight_unit_changed( gpointer /* */, GObject *tbl ) double font_size = 0; int count = 0; for(auto i=itemlist.begin();i!=itemlist.end(); ++i){ - if (SP_IS_TEXT (*i)) { + if (SP_IS_TEXT (*i) || SP_IS_FLOWTEXT(*i)) { double doc_scale = Geom::Affine((*i)->i2dt_affine()).descrim(); font_size += (*i)->style->font_size.computed * doc_scale; ++count; @@ -681,7 +769,7 @@ static void sp_text_lineheight_unit_changed( gpointer /* */, GObject *tbl ) double font_size = 0; int count = 0; for(auto i=itemlist.begin();i!=itemlist.end(); ++i){ - if (SP_IS_TEXT (*i)) { + if (SP_IS_TEXT (*i) || SP_IS_FLOWTEXT (*i)) { double doc_scale = Geom::Affine((*i)->i2dt_affine()).descrim(); font_size += (*i)->style->font_size.computed * doc_scale; ++count; @@ -1073,7 +1161,7 @@ static void sp_text_set_sizes(GtkListStore* model_size, int unit) * It is called whenever a text selection is changed, including stepping cursor * through text, or setting focus to text. */ -static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/, GObject *tbl, bool subselection = false) // don't bother to update font list if subsel changed +static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/, GObject *tbl, bool subselection) // don't bother to update font list if subsel changed { #ifdef DEBUG_TEXT static int count = 0; @@ -1082,12 +1170,11 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ std::cout << "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&" << std::endl; std::cout << "sp_text_toolbox_selection_changed: start " << count << std::endl; - std::cout << " Selected items:" << std::endl; - for (GSList const *items = SP_ACTIVE_DESKTOP->getSelection()->itemList(); - items != NULL; - items = items->next) - { - const gchar* id = reinterpret_cast<SPItem *>(items->data)->getId(); + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + Inkscape::Selection *selection = desktop->getSelection(); + auto itemlist0= selection->items(); + for(auto i=itemlist0.begin();i!=itemlist0.end(); ++i) { + const gchar* id = (*i)->getId(); std::cout << " " << id << std::endl; } Glib::ustring selected_text = sp_text_get_selected_text((SP_ACTIVE_DESKTOP)->event_context); @@ -1129,8 +1216,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ gboolean isFlow = false; auto itemlist= SP_ACTIVE_DESKTOP->getSelection()->items(); for(auto i=itemlist.begin();i!=itemlist.end(); ++i){ - // const gchar* id = reinterpret_cast<SPItem *>(items->data)->getId(); - // std::cout << " " << id << std::endl; + // std::cout << " " << ((*i)->getId()?(*i)->getId():"null") << std::endl; if( SP_IS_FLOWTEXT(*i)) { isFlow = true; // std::cout << " Found flowed text" << std::endl; @@ -1148,10 +1234,26 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ SPStyle query(SP_ACTIVE_DOCUMENT); int result_family = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_FONTFAMILY); int result_style = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_FONTSTYLE); - int result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_FONTNUMBERS); int result_baseline = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_BASELINES); int result_wmode = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_WRITINGMODES); + // Calling sp_desktop_query_style will result in a call to TextTool::_styleQueried(). + // This returns the style of the selected text inside the <text> element... which + // is often the style of one or more <tspan>s. If we want the style of the outer + // <text> objects then we need to bypass the call to TextTool::_styleQueried(). + // The desktop selection never includes the elements inside the <text> element. + int result_numbers = 0; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + bool outer = prefs->getInt("/tools/text/outer_style", false); + if (outer) { + Inkscape::Selection *selection = desktop->getSelection(); + std::vector<SPItem *> vec(selection->items().begin(), selection->items().end()); + result_numbers = sp_desktop_query_style_from_list (vec, &query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + } else { + result_numbers = sp_desktop_query_style (SP_ACTIVE_DESKTOP, &query, QUERY_STYLE_PROPERTY_FONTNUMBERS); + } + /* * If no text in selection (querying returned nothing), read the style from * the /tools/text preferencess (default style for new texts). Return if @@ -1326,7 +1428,13 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ } // Save unit so we can do convertions between new/old units. g_object_set_data( tbl, "lineheight_unit", GINT_TO_POINTER(line_height_unit)); - + + // Enable and turn on only if selection includes an object with line height set. + InkToggleAction* lineHeightUnset = + INK_TOGGLE_ACTION( g_object_get_data( tbl, "TextLineHeightUnsetAction")); + gtk_action_set_sensitive(GTK_ACTION(lineHeightUnset), query.line_height.set ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(lineHeightUnset), query.line_height.set ); + // Word spacing double wordSpacing; if (query.word_spacing.normal) wordSpacing = 0.0; @@ -2021,6 +2129,32 @@ void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObje g_object_set( G_OBJECT(eact), "iconId", "text_rotation", NULL ); } + /* Text line height unset */ + { + InkToggleAction* act = ink_toggle_action_new( "TextLineHeightUnsetAction", // Name + _("Unset line height"), // Label + _("If enabled, line height is set on part of selection. Click to unset."), + INKSCAPE_ICON("paint-unknown"), + secondarySize ); // Icon size + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_lineheight_unset_changed), holder ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/line_height_unset", false) ); + g_object_set_data( holder, "TextLineHeightUnsetAction", act ); + } + + /* Text outer style */ + { + InkToggleAction* act = ink_toggle_action_new( "TextOuterStyleAction", // Name + _("Show outer style"), // Label + _("Show style of outermost text element. The 'font-size' and 'line-height' values of the outermost text element determine the minimum line spacing in the block."), + INKSCAPE_ICON("text_outer_style"), + secondarySize ); // Icon size + gtk_action_group_add_action( mainActions, GTK_ACTION( act ) ); + g_signal_connect_after( G_OBJECT(act), "toggled", G_CALLBACK(sp_text_outer_style_changed), holder ); + gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs->getBool("/tools/text/outer_style", false) ); + g_object_set_data( holder, "TextOuterStyleAction", act ); + } + // Is this necessary to call? Shouldn't hurt. sp_text_toolbox_selection_changed(desktop->getSelection(), holder); diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 53de2d342..a3db3c33d 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -508,18 +508,19 @@ static gchar const * ui_descr = " <toolbar name='TextToolbar'>" " <toolitem action='TextFontFamilyAction' />" - " <toolitem action='TextFontSizeAction' />" " <toolitem action='TextFontStyleAction' />" -// " <toolitem action='TextBoldAction' />" -// " <toolitem action='TextItalicAction' />" + " <separator />" + " <toolitem action='TextOuterStyleAction' />" + " <toolitem action='TextFontSizeAction' />" + " <toolitem action='TextLineHeightAction' />" + " <toolitem action='TextLineHeightUnitsAction' />" + " <toolitem action='TextLineHeightUnsetAction' />" " <separator />" " <toolitem action='TextAlignAction' />" " <separator />" " <toolitem action='TextSuperscriptAction' />" " <toolitem action='TextSubscriptAction' />" " <separator />" - " <toolitem action='TextLineHeightAction' />" - " <toolitem action='TextLineHeightUnitsAction' />" " <toolitem action='TextLetterSpacingAction' />" " <toolitem action='TextWordSpacingAction' />" " <toolitem action='TextDxAction' />" |
