From 6ec542b8becf1a402c3109f44d2b028a8c87a26c Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 8 Oct 2015 12:15:34 +0200 Subject: Correct transform when picking colors under mesh. (bzr r14401) --- src/sp-mesh-array.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/sp-mesh-array.cpp b/src/sp-mesh-array.cpp index 445c9a8f6..d76b884ae 100644 --- a/src/sp-mesh-array.cpp +++ b/src/sp-mesh-array.cpp @@ -313,7 +313,7 @@ bool SPMeshPatchI::tensorIsSet( unsigned int i ) { /** Return tensor control point for "corner" i. - If not sest, returns calculated (Coons) point. + If not set, returns calculated (Coons) point. */ Geom::Point SPMeshPatchI::getTensorPoint( guint k ) { @@ -1058,11 +1058,11 @@ void SPMeshNodeArray::create( SPMesh *mg, SPItem *item, Geom::OptRect bbox ) { Geom::Point center = bbox->midpoint(); // Must keep repr and array in sync. We have two choices: - // Build the repr first and the "read" it. - // Construct the array and the "write" it. + // Build the repr first and then "read" it. + // Construct the array and then "write" it. // We'll do the second. - // Remove any existing mesh. We could chose to simply scale an existing mesh... + // Remove any existing mesh. We could choose to simply scale an existing mesh... //clear(); // We get called twice when a new mesh is created...WHY? @@ -2265,10 +2265,12 @@ guint SPMeshNodeArray::color_pick( std::vector icorners, SPItem* item ) { // Region to average over Geom::Point p = n->p; - // std::cout << " p: " << p << std::endl; + // std::cout << " before transform: p: " << p << std::endl; p *= gr->gradientTransform; - // std::cout << " p: " << p << std::endl; - + // std::cout << " after transform: p: " << p << std::endl; + p *= item->i2doc_affine(); + // std::cout << " after transform: p: " << p << std::endl; + // If on edge, move inward guint cols = patch_columns()+1; guint rows = patch_rows()+1; @@ -2277,7 +2279,7 @@ guint SPMeshNodeArray::color_pick( std::vector icorners, SPItem* item ) { guint ncol = col * 3; guint nrow = row * 3; - double size = 3.0; + const double size = 3.0; // Top edge if( row == 0 ) { -- cgit v1.2.3 From 92d48dff17928ec1f964e5671383a9ebb32f3a6b Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 8 Oct 2015 12:25:06 +0200 Subject: Add buttons for some side/corner mesh opeartions. (bzr r14402) --- src/ui/tools/mesh-tool.cpp | 2 +- src/ui/tools/mesh-tool.h | 2 ++ src/widgets/mesh-toolbar.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++- src/widgets/toolbox.cpp | 5 ++- 4 files changed, 84 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index 813d6ae5b..303757493 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -316,7 +316,7 @@ static void sp_mesh_context_split_near_point(MeshTool *rc, SPItem *item, Geom:: /** Wrapper for various mesh operations that require a list of selected corner nodes. */ -static void +void sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation ) { diff --git a/src/ui/tools/mesh-tool.h b/src/ui/tools/mesh-tool.h index d952c9010..91b35b3af 100644 --- a/src/ui/tools/mesh-tool.h +++ b/src/ui/tools/mesh-tool.h @@ -20,6 +20,7 @@ #include #include #include "ui/tools/tool-base.h" +#include "sp-mesh-array.h" #define SP_MESH_CONTEXT(obj) (dynamic_cast((Inkscape::UI::Tools::ToolBase*)obj)) #define SP_IS_MESH_CONTEXT(obj) (dynamic_cast((const Inkscape::UI::Tools::ToolBase*)obj) != NULL) @@ -57,6 +58,7 @@ private: void sp_mesh_context_select_next(ToolBase *event_context); void sp_mesh_context_select_prev(ToolBase *event_context); +void sp_mesh_context_corner_operation(MeshTool *event_context, MeshCornerOperation operation ); } } diff --git a/src/widgets/mesh-toolbar.cpp b/src/widgets/mesh-toolbar.cpp index 1af55d9cd..bef9129b9 100644 --- a/src/widgets/mesh-toolbar.cpp +++ b/src/widgets/mesh-toolbar.cpp @@ -34,6 +34,7 @@ #include "widgets/gradient-image.h" #include "style.h" +#include "inkscape.h" #include "preferences.h" #include "document-private.h" #include "document-undo.h" @@ -66,6 +67,7 @@ using Inkscape::DocumentUndo; using Inkscape::UI::ToolboxFactory; using Inkscape::UI::PrefPusher; +using Inkscape::UI::Tools::MeshTool; static bool blocked = false; @@ -314,10 +316,49 @@ static void ms_type_changed(EgeSelectOneAction *act, GtkWidget *widget) } } +/** Temporary hack: Returns the mesh tool in the active desktop. + * Will go away during tool refactoring. */ +static MeshTool *get_mesh_tool() +{ + MeshTool *tool = 0; + if (SP_ACTIVE_DESKTOP ) { + Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + if (SP_IS_MESH_CONTEXT(ec)) { + tool = static_cast(ec); + } + } + return tool; +} + +static void ms_toggle_sides(void) +{ + MeshTool *mt = get_mesh_tool(); + if (mt) { + sp_mesh_context_corner_operation( mt, MG_CORNER_SIDE_TOGGLE ); + } +} + +static void ms_make_elliptical(void) +{ + MeshTool *mt = get_mesh_tool(); + if (mt) { + sp_mesh_context_corner_operation( mt, MG_CORNER_SIDE_ARC ); + } +} + +static void ms_pick_colors(void) +{ + MeshTool *mt = get_mesh_tool(); + if (mt) { + sp_mesh_context_corner_operation( mt, MG_CORNER_COLOR_PICK ); + } +} + static void mesh_toolbox_watch_ec(SPDesktop* dt, Inkscape::UI::Tools::ToolBase* ec, GObject* holder); /** * Mesh auxiliary toolbar construction and setup. + * Don't forget to add to XML in widgets/toolbox.cpp! * */ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObject* holder) @@ -466,7 +507,7 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); } - /* Typeing method */ + /* Type */ { GtkListStore* model = gtk_list_store_new( 2, G_TYPE_STRING, G_TYPE_INT ); @@ -487,6 +528,41 @@ void sp_mesh_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObj gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); g_object_set_data( holder, "mesh_select_type_action", act ); } + + { + InkAction* act = ink_action_new( "MeshToggleSidesAction", + _("Toggle Sides"), + _("Toggle selected sides between Beziers and lines."), + INKSCAPE_ICON("node-segment-line"), + secondarySize ); + g_object_set( act, "short_label", _("Toggle side:"), NULL ); + g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(ms_toggle_sides), 0 ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + } + + { + InkAction* act = ink_action_new( "MeshMakeEllipticalAction", + _("Make elliptical"), + _("Make selected sides elliptical by changing length of handles. Works best if handles already approximate ellipse."), + INKSCAPE_ICON("node-segment-curve"), + secondarySize ); + g_object_set( act, "short_label", _("Make elliptical:"), NULL ); + g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(ms_make_elliptical), 0 ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + } + + { + InkAction* act = ink_action_new( "MeshPickColorsAction", + _("Pick colors:"), + _("Pick colors for selected corner nodes from underneath mesh."), + INKSCAPE_ICON("color-picker"), + secondarySize ); + g_object_set( act, "short_label", _("Pick Color"), NULL ); + g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(ms_pick_colors), 0 ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + } + + } static void mesh_toolbox_watch_ec(SPDesktop* desktop, Inkscape::UI::Tools::ToolBase* ec, GObject* holder) diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index cdf39e9ef..a1c32352c 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -519,9 +519,12 @@ static gchar const * ui_descr = // " " // " " // " " + " " + " " + " " + " " " " " " - " " " " " " -- cgit v1.2.3 From 17f2a27dfcfbf68d218193a830faa9580ce8a363 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sat, 10 Oct 2015 21:17:34 +0200 Subject: Added new button to get global measure as a dimension (bzr r14393.1.15) --- src/ui/tools/measure-tool.cpp | 169 ++++++++++++++++++++++++++++------------ src/ui/tools/measure-tool.h | 1 + src/widgets/measure-toolbar.cpp | 35 ++++++++- src/widgets/toolbox.cpp | 2 + 4 files changed, 155 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 32f164a96..585128135 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -25,6 +25,7 @@ #include "desktop.h" #include "svg/svg.h" #include "document.h" +#include "document-undo.h" #include #include "pixmaps/cursor-measure.xpm" #include "preferences.h" @@ -50,11 +51,14 @@ #include "enums.h" #include "ui/control-manager.h" #include "knot-enums.h" +#include "desktop-style.h" +#include "verbs.h" #include using Inkscape::ControlManager; using Inkscape::CTLINE_SECONDARY; using Inkscape::Util::unit_table; +using Inkscape::DocumentUndo; #define MT_KNOT_COLOR_NORMAL 0xffffff00 #define MT_KNOT_COLOR_MOUSEOVER 0xff000000 @@ -74,7 +78,7 @@ const std::string MeasureTool::prefsPath = "/tools/measure"; namespace { -gint const DIMENSION_OFFSET = 35; +gint dimension_offset = 35; /** * Simple class to use for removing label overlap. @@ -236,8 +240,10 @@ void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom } // namespace -static Geom::Point start_p = Geom::Point(); -static Geom::Point end_p = Geom::Point(); +Geom::Point const MAGIC_POINT = Geom::Point(-0.0003432532004303,-0.006745034004304); +static Geom::Point start_p = MAGIC_POINT; +static Geom::Point end_p = MAGIC_POINT; + MeasureTool::MeasureTool() : ToolBase(cursor_measure_xpm, 4, 4) , grabbed(NULL) @@ -256,10 +262,10 @@ MeasureTool::MeasureTool() this->knot_end->setStroke(0x0000007f, 0x0000007f, 0x0000007f); this->knot_end->setShape(SP_KNOT_SHAPE_CIRCLE); this->knot_end->updateCtrl(); - if(end_p != Geom::Point()){ - this->knot_start->setPosition(start_p, SP_KNOT_STATE_NORMAL); + if(end_p != MAGIC_POINT){ + this->knot_start->moveto(start_p); this->knot_start->show(); - this->knot_end->setPosition(end_p, SP_KNOT_STATE_NORMAL); + this->knot_end->moveto(end_p); this->knot_end->show(); this->showCanvasItems(); } @@ -288,9 +294,9 @@ MeasureTool::~MeasureTool() { void MeasureTool::reverseKnots(){ Geom::Point start = start_p; Geom::Point end = end_p; - this->knot_start->setPosition(end, SP_KNOT_STATE_NORMAL); + this->knot_start->moveto(end); this->knot_start->show(); - this->knot_end->setPosition(start, SP_KNOT_STATE_NORMAL); + this->knot_end->moveto(start); this->knot_end->show(); this->showCanvasItems(end, start); } @@ -304,7 +310,7 @@ void MeasureTool::knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppo Inkscape::SnappedPoint sp = m.freeSnap(scp); if(start_p != sp.getPoint()){ start_p = sp.getPoint(); - this->knot_start->setPosition(start_p, SP_KNOT_STATE_MOUSEOVER); + this->knot_start->moveto(start_p); } m.unSetup(); } @@ -320,7 +326,7 @@ void MeasureTool::knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppoin Inkscape::SnappedPoint sp = m.freeSnap(scp); if(end_p != sp.getPoint()){ end_p = sp.getPoint(); - this->knot_end->setPosition(end_p, SP_KNOT_STATE_MOUSEOVER); + this->knot_end->moveto(end_p); } m.unSetup(); } @@ -328,7 +334,7 @@ void MeasureTool::knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppoin } void MeasureTool::knotUngrabbedHandler(SPKnot */*knot*/, unsigned int state){ - showCanvasItems(this->knot_start->position(), end_p); + showCanvasItems(this->knot_start->position(), this->knot_end->position()); } @@ -432,18 +438,20 @@ bool MeasureTool::root_handler(GdkEvent* event) { break; } case GDK_MOTION_NOTIFY: { - if (!(event->motion.state & GDK_BUTTON1_MASK) && !(event->motion.state & GDK_SHIFT_MASK)) { - Geom::Point const motion_w(event->motion.x, event->motion.y); - Geom::Point const motion_dt(desktop->w2d(motion_w)); + if (!(event->motion.state & GDK_BUTTON1_MASK)){ + if(!(event->motion.state & GDK_SHIFT_MASK)) { + Geom::Point const motion_w(event->motion.x, event->motion.y); + Geom::Point const motion_dt(desktop->w2d(motion_w)); - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); - Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE); - scp.addOrigin(start_point); + Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE); + scp.addOrigin(start_point); - m.preSnap(scp); - m.unSetup(); + m.preSnap(scp); + m.unSetup(); + } } else { ret = TRUE; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -482,12 +490,13 @@ bool MeasureTool::root_handler(GdkEvent* event) { break; } case GDK_BUTTON_RELEASE: { - this->knot_start->setPosition(start_point, SP_KNOT_STATE_NORMAL); + this->knot_start->moveto(start_point); this->knot_start->show(); + Geom::Point end_point = end_p; if(last_end){ - Geom::Point end_point = desktop->w2d(*last_end); + end_point = desktop->w2d(*last_end); if (event->button.state & GDK_CONTROL_MASK) { - spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state); + spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state); } else if (!(event->button.state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); @@ -497,14 +506,14 @@ bool MeasureTool::root_handler(GdkEvent* event) { end_point = sp.getPoint(); m.unSetup(); } - this->knot_end->setPosition(end_point, SP_KNOT_STATE_NORMAL); - this->knot_end->show(); } + this->knot_end->moveto(end_point); + this->knot_end->show(); + showCanvasItems(start_point, end_point); if (this->grabbed) { sp_canvas_item_ungrab(this->grabbed, event->button.time); this->grabbed = NULL; } - sp_event_context_discard_delayed_snap_event(this); break; } default: @@ -562,7 +571,7 @@ void MeasureTool::setMarker(bool isStart){ } else { repr2->setAttribute("id", "Arrow2SendPath"); } - repr2->setAttribute("style", "fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round;stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"); + repr2->setAttribute("style", "stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"); if(isStart){ repr2->setAttribute("transform", "scale(0.3) translate(-2.3,0)"); } else { @@ -574,17 +583,18 @@ void MeasureTool::setMarker(bool isStart){ } void MeasureTool::toMarkDimension(){ - Geom::Point windowNormal = Geom::unit_vector(Geom::rot90(desktop->d2w(end_p - start_p))); - Geom::Point normal = desktop->w2d(windowNormal); setMarkers(); Geom::PathVector c; Geom::Path p; - p.start(desktop->doc2dt(start_p) + normal * 60); - p.appendNew(desktop->doc2dt(end_p) + normal * 60); + Geom::Ray ray(start_p,end_p); + Geom::Point start = start_p + Geom::Point::polar(ray.angle(), 5); + start = desktop->doc2dt(start + Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0))); + Geom::Point end = end_p + Geom::Point::polar(ray.angle(), -5); + end = desktop->doc2dt(end+ Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0))); + p.start(start); + p.appendNew(end); c.push_back(p); - c *= desktop->doc2dt(); c *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - c *= Geom::Scale(95.0); SPDesktop *desktop = this->desktop; SPDocument *doc = desktop->getDocument(); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); @@ -592,21 +602,79 @@ void MeasureTool::toMarkDimension(){ Inkscape::XML::Node *repr; repr = xml_doc->createElement("svg:path"); gchar const *str = sp_svg_write_path(c); - gchar const *style_str = "fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"; + Geom::Point stroke_width = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + std::stringstream style_str; + style_str.imbue(std::locale::classic()); + style_str << "fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:" << stroke_width[Geom::X] << ";stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"; g_assert( str != NULL ); repr->setAttribute("d", str); - repr->setAttribute("style", style_str); - // Attach repr + repr->setAttribute("style", style_str.str().c_str()); SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); Inkscape::GC::release(repr); item->updateRepr(); } + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring unit_name = prefs->getString("/tools/measure/unit"); + if (!unit_name.compare("")) { + unit_name = "px"; + } + double fontsize = prefs->getInt("/tools/measure/fontsize") * (96/72); + Geom::Point middle = Geom::middle_point(start, end); + double totallengthval = (end_p - start_p).length(); + totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name); + gchar *totallength_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); + setLabelText(totallength_str, middle, fontsize, Geom::deg_to_rad(180) - ray.angle()); // Flush pending updates doc->ensureUpToDate(); + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE, + _("Add global meassure line")); //reset(); } +void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle) +{ + /* Create */ + Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + Inkscape::XML::Node *rtext = xml_doc->createElement("svg:text"); + rtext->setAttribute("xml:space", "preserve"); + + + /* Set style */ + sp_desktop_apply_style_tool(desktop, rtext, "/tools/text", true); + + sp_repr_set_svg_double(rtext, "x", 0); + sp_repr_set_svg_double(rtext, "y", 0); + + /* Create */ + Inkscape::XML::Node *rtspan = xml_doc->createElement("svg:tspan"); + rtspan->setAttribute("sodipodi:role", "line"); // otherwise, why bother creating the tspan? + std::stringstream text_style; + text_style.imbue(std::locale::classic()); + text_style << "font-style:normal;font-weight:normal;font-size:" << fontsize << "px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"; + rtspan->setAttribute("style", text_style.str().c_str()); + rtext->addChild(rtspan, NULL); + Inkscape::GC::release(rtspan); + /* Create TEXT */ + Inkscape::XML::Node *rstring = xml_doc->createTextNode(value); + rtspan->addChild(rstring, NULL); + Inkscape::GC::release(rstring); + SPItem *text_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(rtext)); + Inkscape::GC::release(rtext); + text_item->updateRepr(); + Geom::OptRect bbox = text_item->geometricBounds(); + if (bbox) { + Geom::Coord posX = Geom::middle_point(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->right(), bbox->top()))[Geom::X]; + Geom::Coord posY = Geom::middle_point(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->left(), bbox->bottom()))[Geom::Y]; + text_item->transform *= Geom::Translate(Geom::Point(posX, posY)).inverse(); + pos = pos + Geom::Point::polar(angle + Geom::deg_to_rad(90), -Geom::distance(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->left(), bbox->bottom()))); + } + text_item->transform *= Geom::Rotate(angle); + text_item->transform *= Geom::Translate(pos); + text_item->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true); +} + void MeasureTool::reset(){ this->knot_start->hide(); this->knot_end->hide(); @@ -622,6 +690,9 @@ void MeasureTool::showCanvasItems(){ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point){ SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if(!desktop || !start_point.isFinite() || !end_point.isFinite() || end_point == MAGIC_POINT){ + return; + } start_p = start_point; end_p = end_point; //clear previous temporary canvas items, we'll draw new ones @@ -632,6 +703,7 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool show_in_between = prefs->getBool("/tools/measure/show_in_between"); bool all_layers = prefs->getBool("/tools/measure/all_layers"); + dimension_offset = prefs->getDouble("/tools/measure/offset"); Geom::PathVector lineseg; Geom::Path p; p.start(desktop->dt2doc(start_point)); @@ -660,13 +732,13 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); r->setMode(RUBBERBAND_MODE_TOUCHPATH); if(!show_in_between){ - r->start(desktop,start_point); - r->move(end_point); + r->start(desktop,start_p); + r->move(end_p); items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2); r->stop(); r->setMode(RUBBERBAND_MODE_TOUCHPATH); - r->start(desktop,end_point); - r->move(start_point); + r->start(desktop,end_p); + r->move(start_p); std::vector items_reverse = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2); r->stop(); if(items_reverse.size() == 2 && items_reverse[1] != items[0] && items_reverse[1] != items[1]){ @@ -722,8 +794,7 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point unit_name = "px"; } - double fontsize = prefs->getInt("/tools/measure/fontsize"); - + double fontsize = prefs->getInt("/tools/measure/fontsize") * (96/72); // Normal will be used for lines and text Geom::Point windowNormal = Geom::unit_vector(Geom::rot90(desktop->d2w(end_point - start_point))); Geom::Point normal = desktop->w2d(windowNormal); @@ -748,7 +819,7 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point LabelPlacement placement; placement.lengthVal = (intersections[idx] - intersections[idx - 1]).length(); placement.lengthVal = Inkscape::Util::Quantity::convert(placement.lengthVal, "px", unit_name); - placement.offset = DIMENSION_OFFSET; + placement.offset = dimension_offset; placement.start = desktop->doc2dt( (intersections[idx - 1] + intersections[idx]) / 2 ); placement.end = placement.start - (normal * placement.offset); @@ -830,7 +901,7 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point gchar *total_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), desktop, - desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * 60, + desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2), total_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; @@ -893,18 +964,18 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point ControlManager &mgr = ControlManager::getManager(); SPCtrlLine *control_line = 0; control_line = mgr.createControlLine(desktop->getTempGroup(), - desktop->doc2dt(intersections[0]) + normal * 60, - desktop->doc2dt(intersections[intersections.size() - 1]) + normal * 60); + desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2), + desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); control_line = mgr.createControlLine(desktop->getTempGroup(), desktop->doc2dt(intersections[0]), - desktop->doc2dt(intersections[0]) + normal * 60); + desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); control_line = mgr.createControlLine(desktop->getTempGroup(), desktop->doc2dt(intersections[intersections.size() - 1]), - desktop->doc2dt(intersections[intersections.size() - 1]) + normal * 60); + desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); } @@ -928,7 +999,7 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point ControlManager &mgr = ControlManager::getManager(); SPCtrlLine *control_line = mgr.createControlLine(desktop->getTempGroup(), desktop->doc2dt(measure_text_pos), - desktop->doc2dt(measure_text_pos) - (normal * DIMENSION_OFFSET), + desktop->doc2dt(measure_text_pos) - (normal * dimension_offset), CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); } diff --git a/src/ui/tools/measure-tool.h b/src/ui/tools/measure-tool.h index 44153a144..0670fb9f7 100644 --- a/src/ui/tools/measure-tool.h +++ b/src/ui/tools/measure-tool.h @@ -43,6 +43,7 @@ public: virtual void setMarkers(); virtual void setMarker(bool isStart); virtual const std::string& getPrefsPath(); + void setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle); void knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state); void knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state); void knotUngrabbedHandler(SPKnot */*knot*/, unsigned int /*state*/); diff --git a/src/widgets/measure-toolbar.cpp b/src/widgets/measure-toolbar.cpp index a619418db..9c782b4b6 100644 --- a/src/widgets/measure-toolbar.cpp +++ b/src/widgets/measure-toolbar.cpp @@ -86,6 +86,22 @@ sp_measure_fontsize_value_changed(GtkAdjustment *adj, GObject *tbl) } } +static void +sp_measure_offset_value_changed(GtkAdjustment *adj, GObject *tbl) +{ + SPDesktop *desktop = static_cast(g_object_get_data( tbl, "desktop" )); + + if (DocumentUndo::getUndoSensitive(desktop->getDocument())) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt(Glib::ustring("/tools/measure/offset"), + gtk_adjustment_get_value(adj)); + MeasureTool *mt = get_measure_tool(); + if (mt) { + mt->showCanvasItems(); + } + } +} + static void measure_unit_changed(GtkAction* /*act*/, GObject* tbl) { UnitTracker* tracker = reinterpret_cast(g_object_get_data(tbl, "tracker")); @@ -180,13 +196,12 @@ void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, G _("The font size to be used in the measurement labels"), "/tools/measure/fontsize", 0.0, GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, - 10, 36, 1.0, 4.0, + 1, 36, 1.0, 4.0, 0, 0, 0, sp_measure_fontsize_value_changed); gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); } - // units label { EgeOutputAction* act = ege_output_action_new( "measure_units_label", _("Units:"), _("The units to be used for the measurements"), 0 ); @@ -201,6 +216,20 @@ void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, G g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(measure_unit_changed), holder ); gtk_action_group_add_action( mainActions, act ); } + + /* Offset */ + { + eact = create_adjustment_action( "MeasureOffsetAction", + _("Offset"), _("Offset:"), + _("The offset size"), + "/tools/measure/offset", 30.0, + GTK_WIDGET(desktop->canvas), holder, FALSE, NULL, + 0.0, 90000.0, 1.0, 4.0, + 0, 0, 0, + sp_measure_offset_value_changed); + gtk_action_group_add_action( mainActions, GTK_ACTION(eact) ); + } + // ignore_1st_and_last { InkToggleAction* act = ink_toggle_action_new( "MeasureIgnore1stAndLast", @@ -249,7 +278,7 @@ void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, G InkAction* act = ink_action_new( "MeasureMarkDimension", _("Mark Dimension"), _("Mark Dimension"), - INKSCAPE_ICON("draw-geometry-mirror"), + INKSCAPE_ICON("tool-pointer"), secondarySize ); g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_to_mark_dimension), 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 765e91629..65a0cd9cb 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -339,6 +339,8 @@ static gchar const * ui_descr = " " " " " " + " " + " " " " " " " " -- cgit v1.2.3 From b76d7592902d9e27cb442e203ebffed4a915b8e6 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 12 Oct 2015 12:05:07 +0200 Subject: Fix from Johan to prevent referencing null C++ pointer. Found via Clang scan build. (bzr r14404) --- src/ui/clipboard.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index 816daf2e5..0792fb9c5 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -565,7 +565,7 @@ bool ClipboardManagerImpl::pastePathEffect(SPDesktop *desktop) } Inkscape::Selection *selection = desktop->getSelection(); - if (selection && selection->isEmpty()) { + if (!selection || selection->isEmpty()) { _userWarn(desktop, _("Select object(s) to paste live path effect to.")); return false; } -- cgit v1.2.3 From 2653fd7c3a138f91181f7bb64e1fd342c943ee7b Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Mon, 12 Oct 2015 12:37:15 +0200 Subject: Convert Measure to Item done (bzr r14393.1.17) --- src/ui/tools/measure-tool.cpp | 905 ++++++++++++++++++++++++++-------------- src/ui/tools/measure-tool.h | 21 +- src/widgets/measure-toolbar.cpp | 17 + src/widgets/toolbox.cpp | 1 + 4 files changed, 638 insertions(+), 306 deletions(-) (limited to 'src') diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 585128135..76b8e931e 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -4,6 +4,7 @@ * Authors: * Felipe Correa da Silva Sanches * Jon A. Cruz + * Jabiertxo Arraiza * * Copyright (C) 2011 Authors * @@ -14,42 +15,44 @@ #include #include #include "util/units.h" -#include "macros.h" -#include "rubberband.h" +#include "display/canvas-text.h" #include "display/curve.h" -#include "text-editing.h" -#include "display/sp-ctrlline.h" #include "display/sodipodi-ctrl.h" +#include "display/sp-ctrlline.h" +#include "display/sp-canvas.h" #include "display/sp-canvas-item.h" #include "display/sp-canvas-util.h" -#include "desktop.h" #include "svg/svg.h" -#include "document.h" -#include "document-undo.h" -#include -#include "pixmaps/cursor-measure.xpm" -#include "preferences.h" -#include "inkscape.h" -#include "knot.h" +#include "svg/svg-color.h" #include "ui/tools/measure-tool.h" #include "ui/tools/freehand-base.h" -#include "display/canvas-text.h" -#include "path-chemistry.h" -#include "2geom/line.h" +#include "ui/control-manager.h" +#include <2geom/line.h> #include <2geom/path-intersection.h> #include <2geom/pathvector.h> #include <2geom/crossing.h> #include <2geom/angle.h> #include <2geom/transforms.h> -#include "snap.h" #include "sp-namedview.h" #include "sp-shape.h" #include "sp-text.h" #include "sp-flowtext.h" #include "sp-defs.h" #include "sp-item.h" +#include "macros.h" +#include "rubberband.h" +#include "path-chemistry.h" +#include "desktop.h" +#include "document.h" +#include "document-undo.h" +#include "viewbox.h" +#include "snap.h" +#include "text-editing.h" +#include "pixmaps/cursor-measure.xpm" +#include "preferences.h" +#include "inkscape.h" +#include "knot.h" #include "enums.h" -#include "ui/control-manager.h" #include "knot-enums.h" #include "desktop-style.h" #include "verbs.h" @@ -63,20 +66,21 @@ using Inkscape::DocumentUndo; #define MT_KNOT_COLOR_NORMAL 0xffffff00 #define MT_KNOT_COLOR_MOUSEOVER 0xff000000 + namespace Inkscape { namespace UI { namespace Tools { std::vector measure_tmp_items; -const std::string& MeasureTool::getPrefsPath() { +const std::string& MeasureTool::getPrefsPath() +{ return MeasureTool::prefsPath; } const std::string MeasureTool::prefsPath = "/tools/measure"; -namespace -{ +namespace { gint dimension_offset = 35; @@ -196,8 +200,9 @@ Geom::Point calcAngleDisplayAnchor(SPDesktop *desktop, double angle, double base * @param end the point that ends at the edge of the arc segment. * @param anchor the anchor point for displaying the text label. * @param angle the angle of the arc segment to draw. + * @param measure_rpr the container of the curve if converted to items. */ -void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom::Point const &end, Geom::Point const &anchor, double angle) +void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom::Point const &end, Geom::Point const &anchor, double angle, Inkscape::XML::Node *measure_repr = NULL) { // Given that we have a point on the arc's edge and the angle of the arc, we need to get the two endpoints. @@ -205,7 +210,7 @@ void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom double sideLen = std::abs((end - center).length()); if (sideLen > 0.0) { double factor = std::min(1.0, textLen / sideLen); - + // arc start Geom::Point p1 = end * (Geom::Affine(Geom::Translate(-center)) * Geom::Affine(Geom::Scale(factor)) @@ -235,9 +240,47 @@ void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const ¢er, Geom SPCtrlCurve *curve = ControlManager::getManager().createControlCurve(desktop->getTempGroup(), p1, p2, p3, p4, CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(SP_CANVAS_ITEM(curve), 0, true)); + if(measure_repr) { + Geom::PathVector c; + Geom::Path p; + p.start(desktop->doc2dt(p1)); + p.appendNew(desktop->doc2dt(p2),desktop->doc2dt(p3),desktop->doc2dt(p4)); + c.push_back(p); + c *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + SPDocument *doc = desktop->getDocument(); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + if (c.size() == 1) { + Inkscape::XML::Node *repr; + repr = xml_doc->createElement("svg:path"); + gchar const *str = sp_svg_write_path(c); + Geom::Point strokewidth = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + SPCSSAttr *css = sp_repr_css_attr_new(); + std::stringstream stroke_width; + stroke_width.imbue(std::locale::classic()); + stroke_width << strokewidth[Geom::X] / desktop->current_zoom(); + sp_repr_css_set_property (css, "stroke-width", stroke_width.str().c_str()); + sp_repr_css_set_property (css, "fill", "none"); + guint32 line_color_secondary = 0xff00007f; + gchar c[64]; + sp_svg_write_color (c, sizeof(c), line_color_secondary); + sp_repr_css_set_property (css, "stroke", c); + sp_repr_css_set_property (css, "stroke-linecap", "butt"); + sp_repr_css_set_property (css, "stroke-linejoin", "miter"); + sp_repr_css_set_property (css, "stroke-miterlimit", "4"); + sp_repr_css_set_property (css, "stroke-dasharray", "none"); + sp_repr_css_set_property (css, "stroke-opacity", "0.5"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); + g_assert( str != NULL ); + repr->setAttribute("d", str); + measure_repr->addChild(repr, NULL); + Inkscape::GC::release(repr); + } + } } } - } // namespace Geom::Point const MAGIC_POINT = Geom::Point(-0.0003432532004303,-0.006745034004304); @@ -249,7 +292,7 @@ MeasureTool::MeasureTool() , grabbed(NULL) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - // create the knot + // create the knots this->knot_start = new SPKnot(desktop, N_("Measure start")); this->knot_start->setMode(SP_KNOT_MODE_XOR); this->knot_start->setFill(MT_KNOT_COLOR_NORMAL, MT_KNOT_COLOR_MOUSEOVER, MT_KNOT_COLOR_MOUSEOVER); @@ -262,12 +305,13 @@ MeasureTool::MeasureTool() this->knot_end->setStroke(0x0000007f, 0x0000007f, 0x0000007f); this->knot_end->setShape(SP_KNOT_SHAPE_CIRCLE); this->knot_end->updateCtrl(); - if(end_p != MAGIC_POINT){ + Geom::Rect display_area = desktop->get_display_area () ; + if(display_area.interiorContains(start_p) && display_area.interiorContains(end_p) && end_p != MAGIC_POINT) { this->knot_start->moveto(start_p); this->knot_start->show(); this->knot_end->moveto(end_p); this->knot_end->show(); - this->showCanvasItems(); + showCanvasItems(); } this->_knot_start_moved_connection = this->knot_start->moved_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotStartMovedHandler)); this->_knot_start_ungrabbed_connection = this->knot_start->ungrabbed_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotUngrabbedHandler)); @@ -276,7 +320,8 @@ MeasureTool::MeasureTool() } -MeasureTool::~MeasureTool() { +MeasureTool::~MeasureTool() +{ this->_knot_start_moved_connection.disconnect(); this->_knot_start_ungrabbed_connection.disconnect(); this->_knot_end_moved_connection.disconnect(); @@ -291,7 +336,8 @@ MeasureTool::~MeasureTool() { measure_tmp_items.clear(); } -void MeasureTool::reverseKnots(){ +void MeasureTool::reverseKnots() +{ Geom::Point start = start_p; Geom::Point end = end_p; this->knot_start->moveto(end); @@ -301,45 +347,59 @@ void MeasureTool::reverseKnots(){ this->showCanvasItems(end, start); } -void MeasureTool::knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state){ - if (!(state & GDK_SHIFT_MASK)) { +void MeasureTool::knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state) +{ + Geom::Point point = this->knot_start->position(); + if (state & GDK_CONTROL_MASK) { + spdc_endpoint_snap_rotation(this, point, end_p, state); + } else if (!(state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); - Inkscape::SnapCandidatePoint scp(this->knot_start->position(), Inkscape::SNAPSOURCE_OTHER_HANDLE); + Inkscape::SnapCandidatePoint scp(point, Inkscape::SNAPSOURCE_OTHER_HANDLE); scp.addOrigin(this->knot_end->position()); Inkscape::SnappedPoint sp = m.freeSnap(scp); - if(start_p != sp.getPoint()){ - start_p = sp.getPoint(); - this->knot_start->moveto(start_p); - } + point = sp.getPoint(); m.unSetup(); } - showCanvasItems(start_p, this->knot_end->position()); + if(start_p != point) { + start_p = point; + this->knot_start->moveto(start_p); + } + showCanvasItems(start_p, end_p); } -void MeasureTool::knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state){ - if (!(state & GDK_SHIFT_MASK)) { +void MeasureTool::knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state) +{ + Geom::Point point = this->knot_end->position(); + if (state & GDK_CONTROL_MASK) { + spdc_endpoint_snap_rotation(this, point, start_p, state); + } else if (!(state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); - Inkscape::SnapCandidatePoint scp(this->knot_end->position(), Inkscape::SNAPSOURCE_OTHER_HANDLE); + Inkscape::SnapCandidatePoint scp(point, Inkscape::SNAPSOURCE_OTHER_HANDLE); scp.addOrigin(this->knot_start->position()); Inkscape::SnappedPoint sp = m.freeSnap(scp); - if(end_p != sp.getPoint()){ - end_p = sp.getPoint(); - this->knot_end->moveto(end_p); - } + point = sp.getPoint(); m.unSetup(); } - showCanvasItems(this->knot_start->position(), end_p); + if(end_p != point) { + end_p = point; + this->knot_end->moveto(end_p); + } + showCanvasItems(start_p, end_p); } -void MeasureTool::knotUngrabbedHandler(SPKnot */*knot*/, unsigned int state){ - showCanvasItems(this->knot_start->position(), this->knot_end->position()); +void MeasureTool::knotUngrabbedHandler(SPKnot */*knot*/, unsigned int state) +{ + this->knot_start->moveto(start_p); + this->knot_end->moveto(end_p); + showCanvasItems(start_p, end_p); } -void MeasureTool::finish() { +void MeasureTool::finish() +{ this->enableGrDrag(false); if (this->grabbed) { @@ -386,9 +446,9 @@ static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom: double eps = 0.0001; SPDocument* doc = desktop->getDocument(); if (((*m).ta > eps && - item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta - eps), false, NULL)) || - ((*m).ta + eps < 1 && - item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta + eps), false, NULL)) ) { + item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta - eps), false, NULL)) || + ((*m).ta + eps < 1 && + item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta + eps), false, NULL)) ) { intersections.push_back((*m).ta); } #else @@ -398,106 +458,83 @@ static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom: } } -bool MeasureTool::root_handler(GdkEvent* event) { +bool MeasureTool::root_handler(GdkEvent* event) +{ gint ret = FALSE; switch (event->type) { - case GDK_BUTTON_PRESS: { - this->knot_start->hide(); - this->knot_end->hide(); - Geom::Point const button_w(event->button.x, event->button.y); - explicitBase = boost::none; - last_end = boost::none; - start_point = desktop->w2d(button_w); - - if (event->button.button == 1 && !this->space_panning) { - // save drag origin - start_point = desktop->w2d(Geom::Point(event->button.x, event->button.y)); - within_tolerance = true; - - ret = TRUE; - } + case GDK_BUTTON_PRESS: { + this->knot_start->hide(); + this->knot_end->hide(); + Geom::Point const button_w(event->button.x, event->button.y); + explicitBase = boost::none; + last_end = boost::none; + start_point = desktop->w2d(button_w); + + if (event->button.button == 1 && !this->space_panning) { + // save drag origin + start_point = desktop->w2d(Geom::Point(event->button.x, event->button.y)); + within_tolerance = true; + + ret = TRUE; + } - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - m.freeSnapReturnByRef(start_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); - m.unSetup(); + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + m.freeSnapReturnByRef(start_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); + m.unSetup(); - sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), - GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, - NULL, event->button.time); - this->grabbed = SP_CANVAS_ITEM(desktop->acetate); - break; - } - case GDK_KEY_PRESS: { - if ((event->key.keyval == GDK_KEY_Shift_L) || (event->key.keyval == GDK_KEY_Shift_R)) { - if (last_end) { - explicitBase = last_end; - } + sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), + GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK, + NULL, event->button.time); + this->grabbed = SP_CANVAS_ITEM(desktop->acetate); + break; + } + case GDK_KEY_PRESS: { + if ((event->key.keyval == GDK_KEY_Shift_L) || (event->key.keyval == GDK_KEY_Shift_R)) { + if (last_end) { + explicitBase = last_end; } - break; } - case GDK_MOTION_NOTIFY: { - if (!(event->motion.state & GDK_BUTTON1_MASK)){ - if(!(event->motion.state & GDK_SHIFT_MASK)) { - Geom::Point const motion_w(event->motion.x, event->motion.y); - Geom::Point const motion_dt(desktop->w2d(motion_w)); + break; + } + case GDK_MOTION_NOTIFY: { + if (!(event->motion.state & GDK_BUTTON1_MASK)) { + if(!(event->motion.state & GDK_SHIFT_MASK)) { + Geom::Point const motion_w(event->motion.x, event->motion.y); + Geom::Point const motion_dt(desktop->w2d(motion_w)); - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); - Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE); - scp.addOrigin(start_point); + Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE); + scp.addOrigin(start_point); - m.preSnap(scp); - m.unSetup(); - } - } else { - ret = TRUE; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); - Geom::Point const motion_w(event->motion.x, event->motion.y); - if ( within_tolerance){ - if ( Geom::LInfty( motion_w - start_point ) < tolerance) { - return FALSE; // Do not drag if we're within tolerance from origin. - } - } - // Once the user has moved farther than tolerance from the original location - // (indicating they intend to move the object, not click), then always process the - // motion notify coordinates as given (no snapping back to origin) - within_tolerance = false; - if(event->motion.time == 0 || !last_end || Geom::LInfty( motion_w - *last_end ) > (tolerance/2)){ - Geom::Point const motion_w(event->motion.x, event->motion.y); - Geom::Point const motion_dt(desktop->w2d(motion_w)); - Geom::Point end_point = motion_dt; - - if (event->motion.state & GDK_CONTROL_MASK) { - spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state); - } else if (!(event->motion.state & GDK_SHIFT_MASK)) { - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - Inkscape::SnapCandidatePoint scp(end_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); - scp.addOrigin(start_point); - Inkscape::SnappedPoint sp = m.freeSnap(scp); - end_point = sp.getPoint(); - m.unSetup(); - } - showCanvasItems(start_point, end_point); - last_end = motion_w ; + m.preSnap(scp); + m.unSetup(); + } + } else { + ret = TRUE; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); + Geom::Point const motion_w(event->motion.x, event->motion.y); + if ( within_tolerance) { + if ( Geom::LInfty( motion_w - start_point ) < tolerance) { + return FALSE; // Do not drag if we're within tolerance from origin. } - gobble_motion_events(GDK_BUTTON1_MASK); } - break; - } - case GDK_BUTTON_RELEASE: { - this->knot_start->moveto(start_point); - this->knot_start->show(); - Geom::Point end_point = end_p; - if(last_end){ - end_point = desktop->w2d(*last_end); - if (event->button.state & GDK_CONTROL_MASK) { + // Once the user has moved farther than tolerance from the original location + // (indicating they intend to move the object, not click), then always process the + // motion notify coordinates as given (no snapping back to origin) + within_tolerance = false; + if(event->motion.time == 0 || !last_end || Geom::LInfty( motion_w - *last_end ) > (tolerance/4.0)) { + Geom::Point const motion_w(event->motion.x, event->motion.y); + Geom::Point const motion_dt(desktop->w2d(motion_w)); + Geom::Point end_point = motion_dt; + + if (event->motion.state & GDK_CONTROL_MASK) { spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state); - } else if (!(event->button.state & GDK_SHIFT_MASK)) { + } else if (!(event->motion.state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); Inkscape::SnapCandidatePoint scp(end_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); @@ -506,153 +543,317 @@ bool MeasureTool::root_handler(GdkEvent* event) { end_point = sp.getPoint(); m.unSetup(); } + showCanvasItems(start_point, end_point); + last_end = motion_w ; } - this->knot_end->moveto(end_point); - this->knot_end->show(); - showCanvasItems(start_point, end_point); - if (this->grabbed) { - sp_canvas_item_ungrab(this->grabbed, event->button.time); - this->grabbed = NULL; + gobble_motion_events(GDK_BUTTON1_MASK); + } + break; + } + case GDK_BUTTON_RELEASE: { + this->knot_start->moveto(start_point); + this->knot_start->show(); + Geom::Point end_point = end_p; + if(last_end) { + end_point = desktop->w2d(*last_end); + if (event->button.state & GDK_CONTROL_MASK) { + spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state); + } else if (!(event->button.state & GDK_SHIFT_MASK)) { + SnapManager &m = desktop->namedview->snap_manager; + m.setup(desktop); + Inkscape::SnapCandidatePoint scp(end_point, Inkscape::SNAPSOURCE_OTHER_HANDLE); + scp.addOrigin(start_point); + Inkscape::SnappedPoint sp = m.freeSnap(scp); + end_point = sp.getPoint(); + m.unSetup(); } - break; } - default: - break; + this->knot_end->moveto(end_point); + this->knot_end->show(); + showCanvasItems(start_point, end_point); + if (this->grabbed) { + sp_canvas_item_ungrab(this->grabbed, event->button.time); + this->grabbed = NULL; + } + break; + } + default: + break; } if (!ret) { ret = ToolBase::root_handler(event); } - + return ret; } -void MeasureTool::setMarkers(){ - SPDesktop *desktop = this->desktop; +void MeasureTool::setMarkers() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; SPDocument *doc = desktop->getDocument(); SPObject *arrowStart = doc->getObjectById("Arrow2Sstart"); SPObject *arrowEnd = doc->getObjectById("Arrow2Send"); if (!arrowStart) { setMarker(true); } - if(!arrowEnd){ + if(!arrowEnd) { setMarker(false); } } -void MeasureTool::setMarker(bool isStart){ - SPDesktop *desktop = this->desktop; +void MeasureTool::setMarker(bool isStart) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; SPDocument *doc = desktop->getDocument(); SPDefs *defs = doc->getDefs(); - Inkscape::XML::Node *repr; + Inkscape::XML::Node *rmarker; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - repr = xml_doc->createElement("svg:marker"); - if(isStart){ - repr->setAttribute("id", "Arrow2Sstart"); + rmarker = xml_doc->createElement("svg:marker"); + if(isStart) { + rmarker->setAttribute("id", "Arrow2Sstart"); } else { - repr->setAttribute("id", "Arrow2Send"); + rmarker->setAttribute("id", "Arrow2Send"); } - repr->setAttribute("inkscape:isstock", "true"); - if(isStart){ - repr->setAttribute("inkscape:stockid", "Arrow2Sstart"); + rmarker->setAttribute("inkscape:isstock", "true"); + if(isStart) { + rmarker->setAttribute("inkscape:stockid", "Arrow2Sstart"); } else { - repr->setAttribute("inkscape:stockid", "Arrow2Send"); + rmarker->setAttribute("inkscape:stockid", "Arrow2Send"); } - repr->setAttribute("orient", "auto"); - repr->setAttribute("refX", "0.0"); - repr->setAttribute("refY", "0.0"); - repr->setAttribute("style", "overflow:visible;"); - SPItem *item = SP_ITEM(defs->appendChildRepr(repr)); - Inkscape::GC::release(repr); - item->updateRepr(); - Inkscape::XML::Node *repr2; - repr2 = xml_doc->createElement("svg:path"); - repr2->setAttribute("d", "M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"); - if(isStart){ - repr2->setAttribute("id", "Arrow2SstartPath"); + rmarker->setAttribute("orient", "auto"); + rmarker->setAttribute("refX", "0.0"); + rmarker->setAttribute("refY", "0.0"); + rmarker->setAttribute("style", "overflow:visible;"); + SPItem *marker = SP_ITEM(defs->appendChildRepr(rmarker)); + Inkscape::GC::release(rmarker); + marker->updateRepr(); + Inkscape::XML::Node *rpath; + rpath = xml_doc->createElement("svg:path"); + rpath->setAttribute("d", "M 8.72,4.03 L -2.21,0.02 L 8.72,-4.00 C 6.97,-1.63 6.98,1.62 8.72,4.03 z"); + if(isStart) { + rpath->setAttribute("id", "Arrow2SstartPath"); } else { - repr2->setAttribute("id", "Arrow2SendPath"); + rpath->setAttribute("id", "Arrow2SendPath"); } - repr2->setAttribute("style", "stroke:#000000;stroke-opacity:1;fill:#000000;fill-opacity:1"); - if(isStart){ - repr2->setAttribute("transform", "scale(0.3) translate(-2.3,0)"); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property (css, "stroke", "none"); + sp_repr_css_set_property (css, "fill", "#000000"); + sp_repr_css_set_property (css, "fill-opacity", "1"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + rpath->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); + if(isStart) { + rpath->setAttribute("transform", "scale(0.3) translate(-2.3,0)"); } else { - repr2->setAttribute("transform", "scale(0.3) rotate(180) translate(-2.3,0)"); + rpath->setAttribute("transform", "scale(0.3) rotate(180) translate(-2.3,0)"); } - SPItem *item2 = SP_ITEM(item->appendChildRepr(repr2)); - Inkscape::GC::release(repr2); - item2->updateRepr(); + SPItem *path = SP_ITEM(marker->appendChildRepr(rpath)); + Inkscape::GC::release(rpath); + path->updateRepr(); +} + +void MeasureTool::toItem() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDocument *doc = desktop->getDocument(); + Geom::Ray ray(start_p,end_p); + guint32 line_color_primary = 0x0000ff7f; + Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + Inkscape::XML::Node *rgroup = xml_doc->createElement("svg:g"); + showCanvasItems(start_p, end_p, true, rgroup); + setLine(start_p,end_p, false, &line_color_primary, rgroup); + SPItem *measure_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(rgroup)); + Inkscape::GC::release(rgroup); + measure_item->updateRepr(); + doc->ensureUpToDate(); + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Convert measure to items")); + reset(); } -void MeasureTool::toMarkDimension(){ +void MeasureTool::toMarkDimension() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDocument *doc = desktop->getDocument(); setMarkers(); - Geom::PathVector c; - Geom::Path p; Geom::Ray ray(start_p,end_p); Geom::Point start = start_p + Geom::Point::polar(ray.angle(), 5); - start = desktop->doc2dt(start + Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0))); + start = start + Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0)); Geom::Point end = end_p + Geom::Point::polar(ray.angle(), -5); - end = desktop->doc2dt(end+ Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0))); - p.start(start); - p.appendNew(end); + end = end+ Geom::Point::polar(ray.angle() + Geom::deg_to_rad(90), -(dimension_offset / 4.0)); + guint32 color = 0x000000ff; + setLine(start, end, true, &color); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring unit_name = prefs->getString("/tools/measure/unit"); + if (!unit_name.compare("")) { + unit_name = "px"; + } + double fontsize = prefs->getInt("/tools/measure/fontsize") * (96/72); + Geom::Point middle = Geom::middle_point(start, end); + double totallengthval = (end_p - start_p).length(); + totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name); + gchar *totallength_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); + setLabelText(totallength_str, middle, fontsize, Geom::deg_to_rad(180) - ray.angle()); + doc->ensureUpToDate(); + DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add global meassure line")); +} + +void MeasureTool::setLine(Geom::Point start_point,Geom::Point end_point, bool markers, guint32 *color, Inkscape::XML::Node *measure_repr) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if(!desktop || !start_point.isFinite() || !end_point.isFinite()) { + return; + } + Geom::PathVector c; + Geom::Path p; + p.start(desktop->doc2dt(start_point)); + p.appendNew(desktop->doc2dt(end_point)); c.push_back(p); c *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - SPDesktop *desktop = this->desktop; SPDocument *doc = desktop->getDocument(); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); if (c.size() == 1) { Inkscape::XML::Node *repr; repr = xml_doc->createElement("svg:path"); gchar const *str = sp_svg_write_path(c); - Geom::Point stroke_width = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - std::stringstream style_str; - style_str.imbue(std::locale::classic()); - style_str << "fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:" << stroke_width[Geom::X] << ";stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow2Sstart);marker-end:url(#Arrow2Send)"; + Geom::Point strokewidth = Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + SPCSSAttr *css = sp_repr_css_attr_new(); + std::stringstream stroke_width; + stroke_width.imbue(std::locale::classic()); + if(measure_repr) { + stroke_width << strokewidth[Geom::X] / desktop->current_zoom(); + } else { + stroke_width << strokewidth[Geom::X]; + } + sp_repr_css_set_property (css, "stroke-width", stroke_width.str().c_str()); + sp_repr_css_set_property (css, "fill", "none"); + if(color) { + gchar c[64]; + sp_svg_write_color (c, sizeof(c), *color); + sp_repr_css_set_property (css, "stroke", c); + } else { + sp_repr_css_set_property (css, "stroke", "#000000"); + } + sp_repr_css_set_property (css, "stroke-linecap", "butt"); + sp_repr_css_set_property (css, "stroke-linejoin", "miter"); + sp_repr_css_set_property (css, "stroke-miterlimit", "4"); + sp_repr_css_set_property (css, "stroke-dasharray", "none"); + if(measure_repr) { + sp_repr_css_set_property (css, "stroke-opacity", "0.5"); + } else { + sp_repr_css_set_property (css, "stroke-opacity", "1"); + } + if(markers) { + sp_repr_css_set_property (css, "marker-start", "url(#Arrow2Sstart)"); + sp_repr_css_set_property (css, "marker-end", "url(#Arrow2Send)"); + } + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); g_assert( str != NULL ); repr->setAttribute("d", str); - repr->setAttribute("style", style_str.str().c_str()); - SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); - Inkscape::GC::release(repr); - item->updateRepr(); + if(measure_repr) { + measure_repr->addChild(repr, NULL); + Inkscape::GC::release(repr); + } else { + SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); + Inkscape::GC::release(repr); + item->updateRepr(); + } } +} - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring unit_name = prefs->getString("/tools/measure/unit"); - if (!unit_name.compare("")) { - unit_name = "px"; +void MeasureTool::setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if(!desktop || !origin.isFinite()) { + return; + } + char const * svgd; + svgd = "m -3.55,-3.55 7.11,7.11 m 0,-7.11 -7.11,7.11"; + Geom::PathVector c = sp_svg_read_pathv(svgd); + Geom::Scale scale = Geom::Scale(desktop->current_zoom()).inverse(); + c *= scale; + Geom::Point strokewidth = (Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse())/ desktop->current_zoom(); + c *= Geom::Translate(Geom::Point(strokewidth/2.0) - (scale.vector() * 0.5)); + c *= Geom::Translate(desktop->doc2dt(origin)); + c *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + SPDocument *doc = desktop->getDocument(); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + if (c.size() == 2) { + Inkscape::XML::Node *repr; + repr = xml_doc->createElement("svg:path"); + gchar const *str = sp_svg_write_path(c); + SPCSSAttr *css = sp_repr_css_attr_new(); + std::stringstream stroke_width; + stroke_width.imbue(std::locale::classic()); + stroke_width << strokewidth[Geom::X]; + sp_repr_css_set_property (css, "stroke-width", stroke_width.str().c_str()); + sp_repr_css_set_property (css, "fill", "none"); + guint32 line_color_secondary = 0xff0000ff; + gchar c[64]; + sp_svg_write_color (c, sizeof(c), line_color_secondary); + sp_repr_css_set_property (css, "stroke", c); + sp_repr_css_set_property (css, "stroke-linecap", "butt"); + sp_repr_css_set_property (css, "stroke-linejoin", "miter"); + sp_repr_css_set_property (css, "stroke-miterlimit", "4"); + sp_repr_css_set_property (css, "stroke-dasharray", "none"); + sp_repr_css_set_property (css, "stroke-opacity", "0.5"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + repr->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); + g_assert( str != NULL ); + repr->setAttribute("d", str); + measure_repr->addChild(repr, NULL); + Inkscape::GC::release(repr); } - double fontsize = prefs->getInt("/tools/measure/fontsize") * (96/72); - Geom::Point middle = Geom::middle_point(start, end); - double totallengthval = (end_p - start_p).length(); - totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name); - gchar *totallength_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); - setLabelText(totallength_str, middle, fontsize, Geom::deg_to_rad(180) - ray.angle()); - // Flush pending updates - doc->ensureUpToDate(); - DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE, - _("Add global meassure line")); - //reset(); } -void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle) +void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle, guint32 *background, Inkscape::XML::Node *measure_repr, CanvasTextAnchorPositionEnum text_anchor) { - /* Create */ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + /* Create */ + pos = desktop->doc2dt(pos); Inkscape::XML::Node *rtext = xml_doc->createElement("svg:text"); rtext->setAttribute("xml:space", "preserve"); /* Set style */ sp_desktop_apply_style_tool(desktop, rtext, "/tools/text", true); - - sp_repr_set_svg_double(rtext, "x", 0); - sp_repr_set_svg_double(rtext, "y", 0); + if(measure_repr) { + sp_repr_set_svg_double(rtext, "x", 2); + sp_repr_set_svg_double(rtext, "y", 2); + } else { + sp_repr_set_svg_double(rtext, "x", 0); + sp_repr_set_svg_double(rtext, "y", 0); + } /* Create */ Inkscape::XML::Node *rtspan = xml_doc->createElement("svg:tspan"); rtspan->setAttribute("sodipodi:role", "line"); // otherwise, why bother creating the tspan? - std::stringstream text_style; - text_style.imbue(std::locale::classic()); - text_style << "font-style:normal;font-weight:normal;font-size:" << fontsize << "px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"; - rtspan->setAttribute("style", text_style.str().c_str()); + SPCSSAttr *css = sp_repr_css_attr_new(); + std::stringstream font_size; + font_size.imbue(std::locale::classic()); + font_size << fontsize ; + sp_repr_css_set_property (css, "font-size", font_size.str().c_str()); + sp_repr_css_set_property (css, "font-style", "normal"); + sp_repr_css_set_property (css, "font-weight", "normal"); + sp_repr_css_set_property (css, "line-height", "125%"); + sp_repr_css_set_property (css, "letter-spacing", "0px"); + sp_repr_css_set_property (css, "word-spacing", "0px"); + if(measure_repr) { + sp_repr_css_set_property (css, "fill", "#FFFFFF"); + } else { + sp_repr_css_set_property (css, "fill", "#000000"); + } + sp_repr_css_set_property (css, "fill-opacity", "1"); + sp_repr_css_set_property (css, "stroke", "none"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + rtspan->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); rtext->addChild(rtspan, NULL); Inkscape::GC::release(rtspan); /* Create TEXT */ @@ -663,19 +864,63 @@ void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsi Inkscape::GC::release(rtext); text_item->updateRepr(); Geom::OptRect bbox = text_item->geometricBounds(); - if (bbox) { - Geom::Coord posX = Geom::middle_point(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->right(), bbox->top()))[Geom::X]; - Geom::Coord posY = Geom::middle_point(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->left(), bbox->bottom()))[Geom::Y]; - text_item->transform *= Geom::Translate(Geom::Point(posX, posY)).inverse(); - pos = pos + Geom::Point::polar(angle + Geom::deg_to_rad(90), -Geom::distance(Geom::Point(bbox->left(), bbox->top()), Geom::Point(bbox->left(), bbox->bottom()))); + if (!measure_repr && bbox) { + Geom::Point center = bbox->midpoint(); + text_item->transform *= Geom::Translate(center).inverse(); + pos = pos + Geom::Point::polar(angle+ Geom::deg_to_rad(90), -bbox->height()); + } + if(measure_repr) { + /* Create */ + Inkscape::XML::Node *rgroup = xml_doc->createElement("svg:g"); + /* Create */ + Inkscape::XML::Node *rrect = xml_doc->createElement("svg:rect"); + SPCSSAttr *css = sp_repr_css_attr_new (); + gchar c[64]; + sp_svg_write_color (c, sizeof(c), *background); + sp_repr_css_set_property (css, "fill", c); + sp_repr_css_set_property (css, "fill-opacity", "0.5"); + sp_repr_css_set_property (css, "stroke-width", "0"); + Glib::ustring css_str; + sp_repr_css_write_string(css,css_str); + rrect->setAttribute("style", css_str.c_str()); + sp_repr_css_attr_unref (css); + sp_repr_set_svg_double(rgroup, "x", 0); + sp_repr_set_svg_double(rgroup, "y", 0); + sp_repr_set_svg_double(rrect, "x", 0); + sp_repr_set_svg_double(rrect, "y", -bbox->height()); + sp_repr_set_svg_double(rrect, "width", (bbox->width()) + 6); + sp_repr_set_svg_double(rrect, "height", (bbox->height()) + 6); + Inkscape::XML::Node *rtextitem = text_item->getRepr(); + text_item->deleteObject(); + rgroup->addChild(rtextitem, NULL); + Inkscape::GC::release(rtextitem); + rgroup->addChild(rrect, NULL); + Inkscape::GC::release(rrect); + SPItem *text_item_box = SP_ITEM(desktop->currentLayer()->appendChildRepr(rgroup)); + Geom::Scale scale = Geom::Scale(desktop->current_zoom()).inverse(); + if(bbox && text_anchor == TEXT_ANCHOR_CENTER) { + text_item_box->transform *= Geom::Translate(bbox->midpoint() - Geom::Point(1.0,1.0)).inverse(); + } + text_item_box->transform *= scale; + text_item_box->transform *= Geom::Translate(Geom::Point() - (scale.vector() * 0.5)); + text_item_box->transform *= Geom::Translate(pos); + text_item_box->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + text_item_box->updateRepr(); + text_item_box->doWriteTransform(text_item_box->getRepr(), text_item_box->transform, NULL, true); + Inkscape::XML::Node *rlabel = text_item_box->getRepr(); + text_item_box->deleteObject(); + measure_repr->addChild(rlabel, NULL); + Inkscape::GC::release(rlabel); + } else { + text_item->transform *= Geom::Rotate(angle); + text_item->transform *= Geom::Translate(pos); + text_item->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true); } - text_item->transform *= Geom::Rotate(angle); - text_item->transform *= Geom::Translate(pos); - text_item->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true); } -void MeasureTool::reset(){ +void MeasureTool::reset() +{ this->knot_start->hide(); this->knot_end->hide(); for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) { @@ -684,15 +929,19 @@ void MeasureTool::reset(){ measure_tmp_items.clear(); } -void MeasureTool::showCanvasItems(){ +void MeasureTool::showCanvasItems() +{ showCanvasItems(start_p, end_p); } -void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point){ +void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point, bool to_item, Inkscape::XML::Node *measure_repr) +{ SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if(!desktop || !start_point.isFinite() || !end_point.isFinite() || end_point == MAGIC_POINT){ + if(!desktop || !start_point.isFinite() || !end_point.isFinite() || end_point == MAGIC_POINT) { return; } + guint32 line_color_primary = 0x0000ff7f; + guint32 line_color_secondary = 0xff00007f; start_p = start_point; end_p = end_point; //clear previous temporary canvas items, we'll draw new ones @@ -731,7 +980,7 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point std::vector items; Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop); r->setMode(RUBBERBAND_MODE_TOUCHPATH); - if(!show_in_between){ + if(!show_in_between) { r->start(desktop,start_p); r->move(end_p); items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2); @@ -741,10 +990,10 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point r->move(start_p); std::vector items_reverse = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints(), all_layers, 2); r->stop(); - if(items_reverse.size() == 2 && items_reverse[1] != items[0] && items_reverse[1] != items[1]){ + if(items_reverse.size() == 2 && items_reverse[1] != items[0] && items_reverse[1] != items[1]) { items.push_back(items_reverse[1]); } - if(items_reverse.size() >= 1 && items_reverse[0] != items[1]){ + if(items_reverse.size() >= 1 && items_reverse[0] != items[1]) { items.push_back(items_reverse[0]); } } else { @@ -754,10 +1003,10 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point r->stop(); } std::vector intersection_times; - for (std::vector::const_iterator i=items.begin();i!=items.end();i++) { + for (std::vector::const_iterator i=items.begin(); i!=items.end(); i++) { SPItem *item = *i; if (SP_IS_SHAPE(item)) { - calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times); + calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times); } else { if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin(); @@ -802,11 +1051,11 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point std::vector intersections; std::sort(intersection_times.begin(), intersection_times.end()); for (std::vector::iterator iter_t = intersection_times.begin(); iter_t != intersection_times.end(); iter_t++) { - if(show_in_between){ + if(show_in_between) { intersections.push_back(lineseg[0].pointAt(*iter_t)); } } - if(!show_in_between && intersection_times.size() > 1){ + if(!show_in_between && intersection_times.size() > 1) { intersections.push_back(lineseg[0].pointAt(intersection_times[0])); intersections.push_back(lineseg[0].pointAt(intersection_times[intersection_times.size()-1])); } @@ -828,47 +1077,52 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point // Adjust positions repositionOverlappingLabels(placements, desktop, windowNormal, fontsize); - for (std::vector::iterator it = placements.begin(); it != placements.end(); ++it) - { + for (std::vector::iterator it = placements.begin(); it != placements.end(); ++it) { LabelPlacement &place = *it; // TODO cleanup memory, Glib::ustring, etc.: gchar *measure_str = g_strdup_printf("%.2f %s", place.lengthVal, unit_name.c_str()); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), - desktop, - place.end, - measure_str); + desktop, + place.end, + measure_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; canvas_tooltip->rgba_background = 0x0000007f; canvas_tooltip->outline = false; canvas_tooltip->background = true; canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER; - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0)); + if(to_item) { + guint32 background = canvas_tooltip->rgba_background; + setLabelText(measure_str, place.end, fontsize, 0, &background, measure_repr); + } g_free(measure_str); } Geom::Point angleDisplayPt = calcAngleDisplayAnchor(desktop, angle, baseAngle, - start_point, end_point, - fontsize); + start_point, end_point, + fontsize); { // TODO cleanup memory, Glib::ustring, etc.: gchar *angle_str = g_strdup_printf("%.2f °", angle * 180/M_PI); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), - desktop, - angleDisplayPt, - angle_str); + desktop, + angleDisplayPt, + angle_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; canvas_tooltip->rgba_background = 0x337f337f; canvas_tooltip->outline = false; canvas_tooltip->background = true; canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER; - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0)); + if(to_item) { + guint32 background = canvas_tooltip->rgba_background; + setLabelText(angle_str, angleDisplayPt, fontsize, 0, &background, measure_repr); + } g_free(angle_str); } @@ -879,17 +1133,20 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point // TODO cleanup memory, Glib::ustring, etc.: gchar *totallength_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), - desktop, - end_point + desktop->w2d(Geom::Point(3*fontsize, -fontsize)), - totallength_str); + desktop, + end_point + desktop->w2d(Geom::Point(3*fontsize, -fontsize)), + totallength_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; canvas_tooltip->rgba_background = 0x3333337f; canvas_tooltip->outline = false; canvas_tooltip->background = true; canvas_tooltip->anchor_position = TEXT_ANCHOR_LEFT; - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0)); + if(to_item) { + guint32 background = canvas_tooltip->rgba_background; + setLabelText(totallength_str, end_point + desktop->w2d(Geom::Point(3*fontsize, -fontsize)), fontsize, 0, &background, measure_repr, TEXT_ANCHOR_LEFT); + } g_free(totallength_str); } @@ -900,44 +1157,68 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point // TODO cleanup memory, Glib::ustring, etc.: gchar *total_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str()); SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(), - desktop, - desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2), - total_str); + desktop, + desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2), + total_str); sp_canvastext_set_fontsize(canvas_tooltip, fontsize); canvas_tooltip->rgba = 0xffffffff; canvas_tooltip->rgba_background = 0x33337f7f; canvas_tooltip->outline = false; canvas_tooltip->background = true; canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER; - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0)); + if(to_item) { + guint32 background = canvas_tooltip->rgba_background; + setLabelText(total_str, desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * (dimension_offset * 2), fontsize, 0, &background, measure_repr); + } g_free(total_str); } + // Initial point + { + SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(), + SP_TYPE_CTRL, + "anchor", SP_ANCHOR_CENTER, + "size", 8.0, + "stroked", TRUE, + "stroke_color", 0xff0000ff, + "mode", SP_KNOT_MODE_XOR, + "shape", SP_KNOT_SHAPE_CROSS, + NULL ); + + SP_CTRL(canvasitem)->moveto(start_point); + measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0)); + if(to_item) { + setPoint(start_point, measure_repr); + } + } + // Now that text has been added, we can add lines and controls so that they go underneath for (size_t idx = 0; idx < intersections.size(); ++idx) { // Display the intersection indicator (i.e. the cross) SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(), - SP_TYPE_CTRL, - "anchor", SP_ANCHOR_CENTER, - "size", 8.0, - "stroked", TRUE, - "stroke_color", 0xff0000ff, - "mode", SP_KNOT_MODE_XOR, - "shape", SP_KNOT_SHAPE_CROSS, - NULL ); + SP_TYPE_CTRL, + "anchor", SP_ANCHOR_CENTER, + "size", 8.0, + "stroked", TRUE, + "stroke_color", 0xff0000ff, + "mode", SP_KNOT_MODE_XOR, + "shape", SP_KNOT_SHAPE_CROSS, + NULL ); SP_CTRL(canvasitem)->moveto(desktop->doc2dt(intersections[idx])); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0)); + if(to_item) { + setPoint(desktop->doc2dt(intersections[idx]), measure_repr); + } } - // Since adding goes to the bottom, do all lines last. // draw main control line { SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(), - start_point, - end_point); + start_point, + end_point); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); if ((end_point[Geom::X] != start_point[Geom::X]) && (end_point[Geom::Y] != start_point[Geom::Y])) { @@ -951,12 +1232,18 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point } SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(), - start_point, - anchorEnd, - CTLINE_SECONDARY); + start_point, + anchorEnd, + CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); - - createAngleDisplayCurve(desktop, start_point, end_point, angleDisplayPt, angle); + if(to_item) { + setLine(start_point, + anchorEnd, + false, + &line_color_secondary, + measure_repr); + } + createAngleDisplayCurve(desktop, start_point, end_point, angleDisplayPt, angle, measure_repr); } } @@ -967,29 +1254,50 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2), desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); - + if(to_item) { + setLine(desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2), + desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2), + false, + &line_color_primary, + measure_repr); + } control_line = mgr.createControlLine(desktop->getTempGroup(), desktop->doc2dt(intersections[0]), desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); - + if(to_item) { + setLine(desktop->doc2dt(intersections[0]), + desktop->doc2dt(intersections[0]) + normal * (dimension_offset * 2), + false, + &line_color_primary, + measure_repr); + } control_line = mgr.createControlLine(desktop->getTempGroup(), desktop->doc2dt(intersections[intersections.size() - 1]), desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2)); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); + if(to_item) { + setLine(desktop->doc2dt(intersections[intersections.size() - 1]), + desktop->doc2dt(intersections[intersections.size() - 1]) + normal * (dimension_offset * 2), + false, + &line_color_primary, + measure_repr); + } } // call-out lines - for (std::vector::iterator it = placements.begin(); it != placements.end(); ++it) - { + for (std::vector::iterator it = placements.begin(); it != placements.end(); ++it) { LabelPlacement &place = *it; ControlManager &mgr = ControlManager::getManager(); SPCtrlLine *control_line = mgr.createControlLine(desktop->getTempGroup(), - place.start, - place.end, - CTLINE_SECONDARY); + place.start, + place.end, + CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); + if(to_item) { + setLine(place.start,place.end, false, &line_color_secondary, measure_repr); + } } { @@ -998,28 +1306,19 @@ void MeasureTool::showCanvasItems(Geom::Point start_point, Geom::Point end_point ControlManager &mgr = ControlManager::getManager(); SPCtrlLine *control_line = mgr.createControlLine(desktop->getTempGroup(), - desktop->doc2dt(measure_text_pos), - desktop->doc2dt(measure_text_pos) - (normal * dimension_offset), - CTLINE_SECONDARY); + desktop->doc2dt(measure_text_pos), + desktop->doc2dt(measure_text_pos) - (normal * dimension_offset), + CTLINE_SECONDARY); measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0)); + if(to_item) { + setLine(desktop->doc2dt(measure_text_pos), + desktop->doc2dt(measure_text_pos) - (normal * dimension_offset), + false, + &line_color_secondary, + measure_repr); + } } } - - // Initial point - { - SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(), - SP_TYPE_CTRL, - "anchor", SP_ANCHOR_CENTER, - "size", 8.0, - "stroked", TRUE, - "stroke_color", 0xff0000ff, - "mode", SP_KNOT_MODE_XOR, - "shape", SP_KNOT_SHAPE_CROSS, - NULL ); - - SP_CTRL(canvasitem)->moveto(start_point); - measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0)); - } } } } diff --git a/src/ui/tools/measure-tool.h b/src/ui/tools/measure-tool.h index 0670fb9f7..ee45c18e5 100644 --- a/src/ui/tools/measure-tool.h +++ b/src/ui/tools/measure-tool.h @@ -6,7 +6,7 @@ * * Authors: * Felipe Correa da Silva Sanches - * + * Jabiertxo Arraiza * Copyright (C) 2011 Authors * * Released under GNU GPL, read the file 'COPYING' for more information @@ -15,6 +15,7 @@ #include #include "ui/tools/tool-base.h" #include <2geom/point.h> +#include "display/canvas-text.h" #include #define SP_MEASURE_CONTEXT(obj) (dynamic_cast((Inkscape::UI::Tools::ToolBase*)obj)) @@ -36,14 +37,17 @@ public: virtual void finish(); virtual bool root_handler(GdkEvent* event); virtual void showCanvasItems(); - virtual void showCanvasItems(Geom::Point start_point, Geom::Point end_point); + virtual void showCanvasItems(Geom::Point start_point, Geom::Point end_point, bool to_item = false, Inkscape::XML::Node *measure_repr = NULL); virtual void reverseKnots(); virtual void toMarkDimension(); + virtual void toItem(); virtual void reset(); virtual void setMarkers(); virtual void setMarker(bool isStart); virtual const std::string& getPrefsPath(); - void setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle); + void setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr); + void setLine(Geom::Point start_point,Geom::Point end_point, bool markers = false, guint32 *color = NULL, Inkscape::XML::Node *measure_repr = NULL); + void setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle, guint32 *background = NULL, Inkscape::XML::Node *measure_repr = NULL, CanvasTextAnchorPositionEnum text_anchor = TEXT_ANCHOR_CENTER ); void knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state); void knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state); void knotUngrabbedHandler(SPKnot */*knot*/, unsigned int /*state*/); @@ -66,3 +70,14 @@ private: } #endif // SEEN_SP_MEASURING_CONTEXT_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/widgets/measure-toolbar.cpp b/src/widgets/measure-toolbar.cpp index 9c782b4b6..48c781fb3 100644 --- a/src/widgets/measure-toolbar.cpp +++ b/src/widgets/measure-toolbar.cpp @@ -178,6 +178,13 @@ static void sp_to_mark_dimension(void){ } } +static void sp_to_item(void){ + MeasureTool *mt = get_measure_tool(); + if (mt) { + mt->toItem(); + } +} + void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, GObject* holder) { UnitTracker* tracker = new UnitTracker(Inkscape::Util::UNIT_TYPE_LINEAR); @@ -283,6 +290,16 @@ void sp_measure_toolbox_prep(SPDesktop * desktop, GtkActionGroup* mainActions, G g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_to_mark_dimension), 0 ); gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); } + //to item + { + InkAction* act = ink_action_new( "MeasureToItem", + _("Convert to item"), + _("Convert to item"), + INKSCAPE_ICON("path-reverse"), + secondarySize ); + g_signal_connect_after( G_OBJECT(act), "activate", G_CALLBACK(sp_to_item), 0 ); + gtk_action_group_add_action( mainActions, GTK_ACTION(act) ); + } } // end of sp_measure_toolbox_prep() diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 3daa3c467..665502745 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -348,6 +348,7 @@ static gchar const * ui_descr = " " " " " " + " " " " " " -- cgit v1.2.3 From f586b5aeb837df4cd4e3aac55c0e0fcba4ae54fa Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 12 Oct 2015 13:48:06 +0200 Subject: Fix position of text when 'direction' is 'rtl' (right-to-left). (bzr r14405) --- src/libnrtype/Layout-TNG-Compute.cpp | 28 ++++++++++++++++++++++------ src/libnrtype/Layout-TNG-Input.cpp | 6 +++--- 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/libnrtype/Layout-TNG-Compute.cpp b/src/libnrtype/Layout-TNG-Compute.cpp index d81e1b6b4..c4b0a5bee 100644 --- a/src/libnrtype/Layout-TNG-Compute.cpp +++ b/src/libnrtype/Layout-TNG-Compute.cpp @@ -24,15 +24,31 @@ namespace Text { #define TRACE(_args) IFTRACE(g_print _args) // ******* enum conversion tables + +// These enums are probably from the SVG 1.0 era where one could interpret 'writing-mode' as setting direction. +// SVG 1.1 makes it clear that 'direction' should be used. 'direction' has only two values 'ltr' and 'rtl'. +// The first two values for the 'writing-mode' enum just happen to match the first two value of 'direction' so the +// existing code worked when 'writing-mode' was changed to 'direction'. +// static Layout::EnumConversionItem const enum_convert_spstyle_direction_to_pango_direction[] = { +// {SP_CSS_WRITING_MODE_LR_TB, PANGO_DIRECTION_LTR}, +// {SP_CSS_WRITING_MODE_RL_TB, PANGO_DIRECTION_RTL}, +// {SP_CSS_WRITING_MODE_TB_LR, PANGO_DIRECTION_LTR}}; // this is correct + +// static Layout::EnumConversionItem const enum_convert_spstyle_direction_to_my_direction[] = { +// {SP_CSS_WRITING_MODE_LR_TB, Layout::LEFT_TO_RIGHT}, +// {SP_CSS_WRITING_MODE_RL_TB, Layout::RIGHT_TO_LEFT}, +// {SP_CSS_WRITING_MODE_TB_LR, Layout::LEFT_TO_RIGHT}}; // this is correct + +// Proper 'direction' enums static Layout::EnumConversionItem const enum_convert_spstyle_direction_to_pango_direction[] = { - {SP_CSS_WRITING_MODE_LR_TB, PANGO_DIRECTION_LTR}, - {SP_CSS_WRITING_MODE_RL_TB, PANGO_DIRECTION_RTL}, - {SP_CSS_WRITING_MODE_TB_LR, PANGO_DIRECTION_LTR}}; // this is correct + {SP_CSS_DIRECTION_LTR, PANGO_DIRECTION_LTR}, + {SP_CSS_DIRECTION_RTL, PANGO_DIRECTION_RTL}}; static Layout::EnumConversionItem const enum_convert_spstyle_direction_to_my_direction[] = { - {SP_CSS_WRITING_MODE_LR_TB, Layout::LEFT_TO_RIGHT}, - {SP_CSS_WRITING_MODE_RL_TB, Layout::RIGHT_TO_LEFT}, - {SP_CSS_WRITING_MODE_TB_LR, Layout::LEFT_TO_RIGHT}}; // this is correct + {SP_CSS_DIRECTION_LTR, Layout::LEFT_TO_RIGHT}, + {SP_CSS_DIRECTION_RTL, Layout::RIGHT_TO_LEFT}}; + + /** \brief private to Layout. Does the real work of text flowing. diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp index 84f3f260e..c9cfe81cc 100644 --- a/src/libnrtype/Layout-TNG-Input.cpp +++ b/src/libnrtype/Layout-TNG-Input.cpp @@ -202,13 +202,13 @@ Layout::Direction Layout::InputStreamTextSource::styleGetBlockProgression() cons } -static Layout::Alignment text_anchor_to_alignment(unsigned anchor, Layout::Direction /*para_direction*/) +static Layout::Alignment text_anchor_to_alignment(unsigned anchor, Layout::Direction para_direction) { switch (anchor) { default: - case SP_CSS_TEXT_ANCHOR_START: return Layout::LEFT; + case SP_CSS_TEXT_ANCHOR_START: return para_direction == Layout::LEFT_TO_RIGHT ? Layout::LEFT : Layout::RIGHT; case SP_CSS_TEXT_ANCHOR_MIDDLE: return Layout::CENTER; - case SP_CSS_TEXT_ANCHOR_END: return Layout::RIGHT; + case SP_CSS_TEXT_ANCHOR_END: return para_direction == Layout::LEFT_TO_RIGHT ? Layout::RIGHT : Layout::LEFT; } } -- cgit v1.2.3 From 328132ad756f7b094341c52175d184449155fe0f Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Mon, 12 Oct 2015 18:08:22 +0200 Subject: Fix positions of genetated intersection items (bzr r14393.1.19) --- src/ui/tools/measure-tool.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index 76b8e931e..00d66b4c9 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -733,7 +733,7 @@ void MeasureTool::setLine(Geom::Point start_point,Geom::Point end_point, bool ma } else { sp_repr_css_set_property (css, "stroke", "#000000"); } - sp_repr_css_set_property (css, "stroke-linecap", "butt"); + sp_repr_css_set_property (css, "stroke-linecap", "square"); sp_repr_css_set_property (css, "stroke-linejoin", "miter"); sp_repr_css_set_property (css, "stroke-miterlimit", "4"); sp_repr_css_set_property (css, "stroke-dasharray", "none"); @@ -770,12 +770,12 @@ void MeasureTool::setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr return; } char const * svgd; - svgd = "m -3.55,-3.55 7.11,7.11 m 0,-7.11 -7.11,7.11"; + svgd = "m 0.707,0.707 6.586,6.586 m 0,-6.586 -6.586,6.586"; Geom::PathVector c = sp_svg_read_pathv(svgd); Geom::Scale scale = Geom::Scale(desktop->current_zoom()).inverse(); + c *= Geom::Translate(Geom::Point(-3.5,-3.5)); c *= scale; - Geom::Point strokewidth = (Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse())/ desktop->current_zoom(); - c *= Geom::Translate(Geom::Point(strokewidth/2.0) - (scale.vector() * 0.5)); + c *= Geom::Translate(Geom::Point() - (scale.vector() * 0.5)); c *= Geom::Translate(desktop->doc2dt(origin)); c *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); SPDocument *doc = desktop->getDocument(); @@ -785,6 +785,7 @@ void MeasureTool::setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr repr = xml_doc->createElement("svg:path"); gchar const *str = sp_svg_write_path(c); SPCSSAttr *css = sp_repr_css_attr_new(); + Geom::Point strokewidth = (Geom::Point(1,1) * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse())/ desktop->current_zoom(); std::stringstream stroke_width; stroke_width.imbue(std::locale::classic()); stroke_width << strokewidth[Geom::X]; @@ -794,7 +795,7 @@ void MeasureTool::setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr gchar c[64]; sp_svg_write_color (c, sizeof(c), line_color_secondary); sp_repr_css_set_property (css, "stroke", c); - sp_repr_css_set_property (css, "stroke-linecap", "butt"); + sp_repr_css_set_property (css, "stroke-linecap", "square"); sp_repr_css_set_property (css, "stroke-linejoin", "miter"); sp_repr_css_set_property (css, "stroke-miterlimit", "4"); sp_repr_css_set_property (css, "stroke-dasharray", "none"); -- cgit v1.2.3 From af1bbe5ddd52aef9e74a778006b01b3a0e249e5d Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Tue, 13 Oct 2015 12:11:48 +0200 Subject: Fix position node splited Added parameter to Symm move nodes, Todo:Get better english strings (bzr r14407) --- src/live_effects/lpe-roughen.cpp | 125 +++++++++++++++++++++++++++++++++------ src/live_effects/lpe-roughen.h | 7 ++- 2 files changed, 111 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp index 33ffd96d6..108b34a26 100644 --- a/src/live_effects/lpe-roughen.cpp +++ b/src/live_effects/lpe-roughen.cpp @@ -49,8 +49,10 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) "global_randomize", &wr, this, 1.), shift_nodes(_("Shift nodes"), _("Shift nodes"), "shift_nodes", &wr, this, true), - shift_node_handles(_("Shift node handles"), _("Shift node handles"), - "shift_node_handles", &wr, this, true) + shift_handles(_("Shift node handles"), _("Shift node handles"), + "shift_handles", &wr, this, true), + shift_handles_sym(_("Sym shift node handles"), _("Sym shift node handles"), + "shift_handles_sym", &wr, this, false) { registerParameter(&method); registerParameter(&max_segment_size); @@ -59,7 +61,8 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) registerParameter(&displace_y); registerParameter(&global_randomize); registerParameter(&shift_nodes); - registerParameter(&shift_node_handles); + registerParameter(&shift_handles); + registerParameter(&shift_handles_sym); displace_x.param_set_range(0., Geom::infinity()); displace_y.param_set_range(0., Geom::infinity()); global_randomize.param_set_range(0., Geom::infinity()); @@ -170,6 +173,7 @@ void LPERoughen::doEffect(SPCurve *curve) Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); Geom::Path::const_iterator curve_endit = path_it->end_default(); SPCurve *nCurve = new SPCurve(); + Geom::Point prev(0, 0); if (path_it->closed()) { const Geom::Curve &closingline = path_it->back_closed(); @@ -212,18 +216,26 @@ void LPERoughen::doEffect(SPCurve *curve) } else { splits = ceil(length / max_segment_size); } - for (unsigned int t = splits; t >= 1; t--) { - if (t == 1 && splits != 1) { + Geom::Curve const * original = nCurve->last_segment()->duplicate() ; + for (unsigned int t = 1; t <= splits; t++) { + if(t == splits && splits != 1){ continue; } - const SPCurve *tmp; + SPCurve const * tmp; if (splits == 1) { tmp = jitter(nCurve->last_segment()); } else { - tmp = addNodesAndJitter(nCurve->last_segment(), 1. / t); + bool last = false; + if(t == splits-1){ + last = true; + } + double time = Geom::nearest_time(original->pointAt((1. / (double)splits) * t), *nCurve->last_segment()); + tmp = addNodesAndJitter(nCurve->last_segment(), prev, time, last); } if (nCurve->get_segment_count() > 1) { - nCurve->backspace(); + if(t!= splits){ + nCurve->backspace(); + } nCurve->append_continuous(tmp, 0.001); } else { nCurve = tmp->copy(); @@ -237,6 +249,27 @@ void LPERoughen::doEffect(SPCurve *curve) first = false; } if (path_it->closed()) { + if(shift_handles_sym && curve_it2 == curve_endit){ + SPCurve *out = new SPCurve(); + nCurve = nCurve->create_reverse(); + Geom::CubicBezier const *cubic_start = dynamic_cast(nCurve->first_segment()); + Geom::CubicBezier const *cubic = dynamic_cast(nCurve->last_segment()); + Geom::Point oposite = nCurve->first_segment()->initialPoint(); + if(cubic_start){ + Geom::Ray ray((*cubic_start)[1], (*cubic_start)[0]); + double dist = Geom::distance((*cubic_start)[1], (*cubic_start)[0]); + oposite = Geom::Point::polar(ray.angle(),dist) + (*cubic_start)[0]; + } + if(cubic){ + out->moveto((*cubic)[0]); + out->curveto((*cubic)[1], oposite, (*cubic)[3]); + } else { + out->moveto(nCurve->last_segment()->initialPoint()); + out->curveto(nCurve->last_segment()->initialPoint(), oposite, nCurve->last_segment()->finalPoint()); + } + nCurve->backspace(); + nCurve->append_continuous(out, 0.001); + } nCurve->closepath_current(); } curve->append(nCurve, false); @@ -245,7 +278,7 @@ void LPERoughen::doEffect(SPCurve *curve) } } -SPCurve *LPERoughen::addNodesAndJitter(const Geom::Curve *A, double t) +SPCurve const * LPERoughen::addNodesAndJitter(Geom::Curve const * A, Geom::Point &prev, double t, bool last) { SPCurve *out = new SPCurve(); Geom::CubicBezier const *cubic = dynamic_cast(&*A); @@ -259,38 +292,94 @@ SPCurve *LPERoughen::addNodesAndJitter(const Geom::Curve *A, double t) point3 = randomize(); point_b3 = randomize(); } - if (shift_node_handles) { + if (shift_handles && !shift_handles_sym) { point1 = randomize(); point2 = randomize(); point_b1 = randomize(); point_b2 = randomize(); - } else { + } else if(shift_handles_sym) { + Geom::Ray ray(prev,A->initialPoint()); + double dist = Geom::distance(prev, A->initialPoint()); + point1 = Geom::Point::polar(ray.angle(),dist) + A->initialPoint(); + if(prev==Geom::Point(0,0)){ + point1 = A->pointAt(t / 3) + randomize(); + } + point2 = A->pointAt((t / 3) * 2) + randomize(); + Geom::Ray ray2(point2, point3); + double dist2 = Geom::distance(point2, point3); + point_b1 = Geom::Point::polar(ray2.angle(),dist2) + point3; + point1 = point1 - A->pointAt(t / 3); + point2 = point2 - A->pointAt((t / 3) * 2); + point_b1 = randomize(); + point_b2 = randomize(); + }else { point2 = point3; point_b1 = point3; point_b2 = point_b3; } - if (cubic) { + if(shift_handles_sym && cubic) { + std::pair div = cubic->subdivide(t); + std::vector seg1 = div.first.controlPoints(), + seg2 = div.second.controlPoints(); + out->moveto(seg1[0]); + Geom::Ray ray(prev,A->initialPoint()); + double dist = Geom::distance(seg1[1], A->initialPoint()); + point1 = Geom::Point::polar(ray.angle(),dist) + A->initialPoint(); + point2 = seg1[2] + point2; + point3 = seg1[3] + point3; + if(prev==Geom::Point(0,0)){ + point1 = seg1[1] + randomize(); + } + out->curveto(point1, point2, point3); + + Geom::Ray ray2(point2, point3); + double dist2 = Geom::distance(seg2[1], point3); + point_b1 = Geom::Point::polar(ray2.angle(),dist2) + point3; + point_b2 = seg2[2]; + out->curveto(point_b1, point_b2, seg2[3]); + } else if(shift_handles_sym && !cubic) { + out->moveto(A->initialPoint()); + Geom::Ray ray(prev,A->initialPoint()); + double dist = Geom::distance(A->pointAt(t / 3) + randomize(), A->initialPoint()); + point1 = Geom::Point::polar(ray.angle(),dist) + A->initialPoint(); + point2 = A->pointAt((t / 3) * 2) + point2; + point3 = A->pointAt(t) + point3; + if(prev==Geom::Point(0,0)){ + point1 = A->pointAt(t / 3) + randomize(); + } + out->curveto(point1, point2, point3); + Geom::Ray ray2(point2, point3); + double dist2 = Geom::distance(A->pointAt(t + ((t / 3) * 2)) + point_b2, point3); + point_b1 = Geom::Point::polar(ray2.angle(),dist2) + point3; + point_b2 = A->pointAt(t + ((t / 3) * 2)) + point_b2; + out->curveto(point_b1, point_b2, A->finalPoint()); + } else if (cubic) { std::pair div = cubic->subdivide(t); std::vector seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints(); out->moveto(seg1[0]); out->curveto(seg1[1] + point1, seg1[2] + point2, seg1[3] + point3); out->curveto(seg2[1] + point_b1, seg2[2], seg2[3]); - } else if (shift_node_handles) { + } else if (shift_handles) { out->moveto(A->initialPoint()); out->curveto(A->pointAt(t / 3) + point1, A->pointAt((t / 3) * 2) + point2, A->pointAt(t) + point3); - out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t + ((t / 3) * 2)), - A->finalPoint()); + out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t + ((t / 3) * 2)) + point_b2, + A->finalPoint()); } else { out->moveto(A->initialPoint()); out->lineto(A->pointAt(t) + point3); out->lineto(A->finalPoint()); } + if(last){ + prev = point_b2; + } else { + prev = point2; + } return out; } -SPCurve *LPERoughen::jitter(const Geom::Curve *A) +SPCurve *LPERoughen::jitter(Geom::Curve const * A) { SPCurve *out = new SPCurve(); Geom::CubicBezier const *cubic = dynamic_cast(&*A); @@ -300,7 +389,7 @@ SPCurve *LPERoughen::jitter(const Geom::Curve *A) if (shift_nodes) { point3 = randomize(); } - if (shift_node_handles) { + if (shift_handles) { point1 = randomize(); point2 = randomize(); } else { @@ -309,7 +398,7 @@ SPCurve *LPERoughen::jitter(const Geom::Curve *A) if (cubic) { out->moveto((*cubic)[0]); out->curveto((*cubic)[1] + point1, (*cubic)[2] + point2, (*cubic)[3] + point3); - } else if (shift_node_handles) { + } else if (shift_handles) { out->moveto(A->initialPoint()); out->curveto(A->pointAt(0.3333) + point1, A->pointAt(0.6666) + point2, A->finalPoint() + point3); diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h index 2b285cd40..8241cedca 100644 --- a/src/live_effects/lpe-roughen.h +++ b/src/live_effects/lpe-roughen.h @@ -38,8 +38,8 @@ public: virtual double sign(double randNumber); virtual Geom::Point randomize(); virtual void doBeforeEffect(SPLPEItem const * lpeitem); - virtual SPCurve *addNodesAndJitter(const Geom::Curve *A, double t); - virtual SPCurve *jitter(const Geom::Curve *A); + virtual SPCurve const * addNodesAndJitter(Geom::Curve const * A, Geom::Point &prev, double t, bool last); + virtual SPCurve *jitter(Geom::Curve const * A); virtual Geom::Point tPoint(Geom::Point A, Geom::Point B, double t = 0.5); virtual Gtk::Widget *newWidget(); @@ -51,7 +51,8 @@ private: RandomParam displace_y; RandomParam global_randomize; BoolParam shift_nodes; - BoolParam shift_node_handles; + BoolParam shift_handles; + BoolParam shift_handles_sym; LPERoughen(const LPERoughen &); LPERoughen &operator=(const LPERoughen &); -- cgit v1.2.3 From f886fd682e7e4ea2622fbb523dc3a14ba75569a3 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Tue, 13 Oct 2015 22:09:54 +0200 Subject: Added a parameter to roughen LPE to allow fixed displacement of points (bzr r14408) --- src/live_effects/lpe-roughen.cpp | 235 +++++++++++++++++++++------------------ src/live_effects/lpe-roughen.h | 5 +- 2 files changed, 127 insertions(+), 113 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp index 108b34a26..6f24c288d 100644 --- a/src/live_effects/lpe-roughen.cpp +++ b/src/live_effects/lpe-roughen.cpp @@ -52,7 +52,9 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) shift_handles(_("Shift node handles"), _("Shift node handles"), "shift_handles", &wr, this, true), shift_handles_sym(_("Sym shift node handles"), _("Sym shift node handles"), - "shift_handles_sym", &wr, this, false) + "shift_handles_sym", &wr, this, false), + fixed_displacement(_("Fixed displacement"), _("Fixed displacement, 1/3 of segment lenght"), + "fixed_displacement", &wr, this, false) { registerParameter(&method); registerParameter(&max_segment_size); @@ -63,6 +65,7 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) registerParameter(&shift_nodes); registerParameter(&shift_handles); registerParameter(&shift_handles_sym); + registerParameter(&fixed_displacement); displace_x.param_set_range(0., Geom::infinity()); displace_y.param_set_range(0., Geom::infinity()); global_randomize.param_set_range(0., Geom::infinity()); @@ -150,12 +153,15 @@ double LPERoughen::sign(double random_number) return random_number; } -Geom::Point LPERoughen::randomize() +Geom::Point LPERoughen::randomize(double max_lenght) { double displace_x_parsed = displace_x * global_randomize; double displace_y_parsed = displace_y * global_randomize; - Geom::Point output = Geom::Point(sign(displace_x_parsed), sign(displace_y_parsed)); + if( fixed_displacement ){ + Geom::Ray ray(Geom::Point(0,0),output); + output = Geom::Point::polar(ray.angle(), max_lenght); + } return output; } @@ -181,33 +187,24 @@ void LPERoughen::doEffect(SPCurve *curve) curve_endit = path_it->end_open(); } } - Geom::Point initialMove(0, 0); - if (shift_nodes) { - initialMove = randomize(); - } - Geom::Point initialPoint = curve_it1->initialPoint() + initialMove; - nCurve->moveto(initialPoint); + nCurve->moveto(curve_it1->initialPoint()); Geom::Point point0(0, 0); - Geom::Point point1(0, 0); - Geom::Point point2(0, 0); - Geom::Point point3(0, 0); - bool first = true; + Geom::Point point_a1(0, 0); + Geom::Point point_a2(0, 0); + Geom::Point point_a3(0, 0); while (curve_it1 != curve_endit) { Geom::CubicBezier const *cubic = NULL; point0 = curve_it1->initialPoint(); - point1 = curve_it1->initialPoint(); - point2 = curve_it1->finalPoint(); - point3 = curve_it1->finalPoint(); + point_a1 = curve_it1->initialPoint(); + point_a2 = curve_it1->finalPoint(); + point_a3 = curve_it1->finalPoint(); cubic = dynamic_cast(&*curve_it1); if (cubic) { - point1 = (*cubic)[1]; - if (shift_nodes && first) { - point1 = (*cubic)[1] + initialMove; - } - point2 = (*cubic)[2]; - nCurve->curveto(point1, point2, point3); + point_a1 = (*cubic)[1]; + point_a2 = (*cubic)[2]; + nCurve->curveto(point_a1, point_a2, point_a3); } else { - nCurve->lineto(point3); + nCurve->lineto(point_a3); } double length = curve_it1->length(0.001); std::size_t splits = 0; @@ -223,7 +220,7 @@ void LPERoughen::doEffect(SPCurve *curve) } SPCurve const * tmp; if (splits == 1) { - tmp = jitter(nCurve->last_segment()); + tmp = jitter(nCurve->last_segment(), prev); } else { bool last = false; if(t == splits-1){ @@ -233,9 +230,7 @@ void LPERoughen::doEffect(SPCurve *curve) tmp = addNodesAndJitter(nCurve->last_segment(), prev, time, last); } if (nCurve->get_segment_count() > 1) { - if(t!= splits){ - nCurve->backspace(); - } + nCurve->backspace(); nCurve->append_continuous(tmp, 0.001); } else { nCurve = tmp->copy(); @@ -246,7 +241,6 @@ void LPERoughen::doEffect(SPCurve *curve) if(curve_it2 != curve_endit) { ++curve_it2; } - first = false; } if (path_it->closed()) { if(shift_handles_sym && curve_it2 == curve_endit){ @@ -254,7 +248,7 @@ void LPERoughen::doEffect(SPCurve *curve) nCurve = nCurve->create_reverse(); Geom::CubicBezier const *cubic_start = dynamic_cast(nCurve->first_segment()); Geom::CubicBezier const *cubic = dynamic_cast(nCurve->last_segment()); - Geom::Point oposite = nCurve->first_segment()->initialPoint(); + Geom::Point oposite = nCurve->first_segment()->pointAt(1.0/3.0); if(cubic_start){ Geom::Ray ray((*cubic_start)[1], (*cubic_start)[0]); double dist = Geom::distance((*cubic_start)[1], (*cubic_start)[0]); @@ -269,7 +263,9 @@ void LPERoughen::doEffect(SPCurve *curve) } nCurve->backspace(); nCurve->append_continuous(out, 0.001); + nCurve = nCurve->create_reverse(); } + nCurve->move_endpoints(nCurve->last_segment()->finalPoint(), nCurve->last_segment()->finalPoint()); nCurve->closepath_current(); } curve->append(nCurve, false); @@ -282,129 +278,146 @@ SPCurve const * LPERoughen::addNodesAndJitter(Geom::Curve const * A, Geom::Point { SPCurve *out = new SPCurve(); Geom::CubicBezier const *cubic = dynamic_cast(&*A); - Geom::Point point1(0, 0); - Geom::Point point2(0, 0); - Geom::Point point3(0, 0); + double max_lenght = Geom::distance(A->initialPoint(),A->pointAt(t)) / 3.0; + Geom::Point point_a1(0, 0); + Geom::Point point_a2(0, 0); + Geom::Point point_a3(0, 0); Geom::Point point_b1(0, 0); Geom::Point point_b2(0, 0); Geom::Point point_b3(0, 0); if (shift_nodes) { - point3 = randomize(); - point_b3 = randomize(); + point_a3 = randomize(max_lenght); + if(last){ + point_b3 = randomize(max_lenght); + } } - if (shift_handles && !shift_handles_sym) { - point1 = randomize(); - point2 = randomize(); - point_b1 = randomize(); - point_b2 = randomize(); - } else if(shift_handles_sym) { - Geom::Ray ray(prev,A->initialPoint()); - double dist = Geom::distance(prev, A->initialPoint()); - point1 = Geom::Point::polar(ray.angle(),dist) + A->initialPoint(); - if(prev==Geom::Point(0,0)){ - point1 = A->pointAt(t / 3) + randomize(); + if (shift_handles || shift_handles_sym) { + point_a1 = randomize(max_lenght); + point_a2 = randomize(max_lenght); + point_b1 = randomize(max_lenght); + if(last){ + point_b2 = randomize(max_lenght); + } + } else { + point_a2 = point_a3; + point_b1 = point_a3; + if(last){ + point_b2 = point_b3; } - point2 = A->pointAt((t / 3) * 2) + randomize(); - Geom::Ray ray2(point2, point3); - double dist2 = Geom::distance(point2, point3); - point_b1 = Geom::Point::polar(ray2.angle(),dist2) + point3; - point1 = point1 - A->pointAt(t / 3); - point2 = point2 - A->pointAt((t / 3) * 2); - point_b1 = randomize(); - point_b2 = randomize(); - }else { - point2 = point3; - point_b1 = point3; - point_b2 = point_b3; } if(shift_handles_sym && cubic) { std::pair div = cubic->subdivide(t); std::vector seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints(); - out->moveto(seg1[0]); Geom::Ray ray(prev,A->initialPoint()); - double dist = Geom::distance(seg1[1], A->initialPoint()); - point1 = Geom::Point::polar(ray.angle(),dist) + A->initialPoint(); - point2 = seg1[2] + point2; - point3 = seg1[3] + point3; - if(prev==Geom::Point(0,0)){ - point1 = seg1[1] + randomize(); + point_a1 = Geom::Point::polar(ray.angle(), max_lenght); + if(prev == Geom::Point(0,0)){ + point_a1 = randomize(max_lenght); + } + if(last){ + prev = A->pointAt(1 - (t / 3)) + point_b2; + } else { + point_b3 = Geom::Point(0,0); + point_b2 = Geom::Point(0,0); + } + Geom::Ray ray2(seg2[1] + point_b1, seg1[3] + point_a3); + point_a2 = Geom::Point::polar(ray2.angle(), max_lenght); + if(!last){ + prev = seg1[3] + point_a3 + point_a2; + } + out->moveto(seg1[0]); + out->curveto(seg1[0] + point_a1, seg1[3] + point_a3 + point_a2, seg1[3] + point_a3); + if(last){ + out->curveto(seg2[1] + point_b1, A->pointAt(1 - (t / 3)) + point_b2, seg2[3] + point_b3); + } else { + out->curveto(seg2[1] + point_b1, seg2[2] + point_b2, seg2[3] + point_b3); } - out->curveto(point1, point2, point3); - - Geom::Ray ray2(point2, point3); - double dist2 = Geom::distance(seg2[1], point3); - point_b1 = Geom::Point::polar(ray2.angle(),dist2) + point3; - point_b2 = seg2[2]; - out->curveto(point_b1, point_b2, seg2[3]); } else if(shift_handles_sym && !cubic) { - out->moveto(A->initialPoint()); Geom::Ray ray(prev,A->initialPoint()); - double dist = Geom::distance(A->pointAt(t / 3) + randomize(), A->initialPoint()); - point1 = Geom::Point::polar(ray.angle(),dist) + A->initialPoint(); - point2 = A->pointAt((t / 3) * 2) + point2; - point3 = A->pointAt(t) + point3; + point_a1 = Geom::Point::polar(ray.angle(), max_lenght); if(prev==Geom::Point(0,0)){ - point1 = A->pointAt(t / 3) + randomize(); + point_a1 = randomize(max_lenght); + } + if(last){ + prev = A->pointAt(1 - (t / 3)) + point_b2; + } else { + point_b3 = Geom::Point(0,0); + point_b2 = Geom::Point(0,0); + } + Geom::Ray ray2(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t) + point_a3); + point_a2 = Geom::Point::polar(ray2.angle(), max_lenght); + if(!last){ + prev = A->pointAt((t / 3) * 2) + point_a2; + } + out->moveto(A->initialPoint()); + out->curveto(A->initialPoint() + point_a1, A->pointAt(t) + point_a3 + point_a2, A->pointAt(t) + point_a3); + if(last){ + out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(1 - (t / 3)) + point_b2, A->finalPoint() + point_b3); + } else { + out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t +((t / 3) * 2)) + point_b2, A->finalPoint() + point_b3); } - out->curveto(point1, point2, point3); - Geom::Ray ray2(point2, point3); - double dist2 = Geom::distance(A->pointAt(t + ((t / 3) * 2)) + point_b2, point3); - point_b1 = Geom::Point::polar(ray2.angle(),dist2) + point3; - point_b2 = A->pointAt(t + ((t / 3) * 2)) + point_b2; - out->curveto(point_b1, point_b2, A->finalPoint()); } else if (cubic) { std::pair div = cubic->subdivide(t); std::vector seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints(); out->moveto(seg1[0]); - out->curveto(seg1[1] + point1, seg1[2] + point2, seg1[3] + point3); - out->curveto(seg2[1] + point_b1, seg2[2], seg2[3]); + out->curveto(seg1[1] + point_a1, seg1[2] + point_a2, seg1[3] + point_a3); + out->curveto(seg2[1] + point_b1, seg2[2] + point_b2, seg2[3] + point_b3); } else if (shift_handles) { out->moveto(A->initialPoint()); - out->curveto(A->pointAt(t / 3) + point1, A->pointAt((t / 3) * 2) + point2, - A->pointAt(t) + point3); - out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t + ((t / 3) * 2)) + point_b2, - A->finalPoint()); + out->curveto(A->pointAt(t / 3) + point_a1, A->pointAt((t / 3) * 2) + point_a2, A->pointAt(t) + point_a3); + out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t +((t / 3) * 2)) + point_b2, A->finalPoint() + point_b3); } else { out->moveto(A->initialPoint()); - out->lineto(A->pointAt(t) + point3); - out->lineto(A->finalPoint()); - } - if(last){ - prev = point_b2; - } else { - prev = point2; + out->lineto(A->pointAt(t) + point_a3); + out->lineto(A->finalPoint() + point_b3); } return out; } -SPCurve *LPERoughen::jitter(Geom::Curve const * A) +SPCurve *LPERoughen::jitter(Geom::Curve const * A, Geom::Point &prev) { SPCurve *out = new SPCurve(); Geom::CubicBezier const *cubic = dynamic_cast(&*A); - Geom::Point point1(0, 0); - Geom::Point point2(0, 0); - Geom::Point point3(0, 0); + double max_lenght = Geom::distance(A->initialPoint(),A->finalPoint()) / 3.0; + Geom::Point point_a1(0, 0); + Geom::Point point_a2(0, 0); + Geom::Point point_a3(0, 0); if (shift_nodes) { - point3 = randomize(); + point_a3 = randomize(max_lenght); } - if (shift_handles) { - point1 = randomize(); - point2 = randomize(); - } else { - point2 = point3; + if (shift_handles || shift_handles_sym) { + point_a1 = randomize(max_lenght); + point_a2 = randomize(max_lenght); } - if (cubic) { + if(shift_handles_sym && cubic) { + Geom::Ray ray(prev,A->initialPoint()); + point_a1 = Geom::Point::polar(ray.angle(), max_lenght); + if(prev == Geom::Point(0,0)){ + point_a1 = A->pointAt(1.0/3.0) + randomize(max_lenght); + } + prev = (*cubic)[2] + point_a2; + out->moveto((*cubic)[0]); + out->curveto((*cubic)[0] + point_a1, (*cubic)[2] + point_a2, (*cubic)[3] + point_a3); + } else if(shift_handles_sym && !cubic) { + Geom::Ray ray(prev,A->initialPoint()); + point_a1 = Geom::Point::polar(ray.angle(), max_lenght); + if(prev==Geom::Point(0,0)){ + point_a1 = A->pointAt(1.0/3.0) + randomize(max_lenght); + } + prev = A->pointAt((1.0/3.0) * 2) + point_a2; + out->moveto(A->initialPoint()); + out->curveto(A->initialPoint() + point_a1, A->pointAt((1.0/3.0) * 2) + point_a2, A->finalPoint() + point_a3); + } else if (cubic) { out->moveto((*cubic)[0]); - out->curveto((*cubic)[1] + point1, (*cubic)[2] + point2, (*cubic)[3] + point3); + out->curveto((*cubic)[1] + point_a1, (*cubic)[2] + point_a2, (*cubic)[3] + point_a3); } else if (shift_handles) { out->moveto(A->initialPoint()); - out->curveto(A->pointAt(0.3333) + point1, A->pointAt(0.6666) + point2, - A->finalPoint() + point3); + out->curveto(A->pointAt(0.3333) + point_a1, A->pointAt(0.6666) + point_a2, + A->finalPoint() + point_a3); } else { out->moveto(A->initialPoint()); - out->lineto(A->finalPoint() + point3); + out->lineto(A->finalPoint() + point_a3); } return out; } diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h index 8241cedca..e221e95fb 100644 --- a/src/live_effects/lpe-roughen.h +++ b/src/live_effects/lpe-roughen.h @@ -36,10 +36,10 @@ public: virtual void doEffect(SPCurve *curve); virtual double sign(double randNumber); - virtual Geom::Point randomize(); + virtual Geom::Point randomize(double max_lenght); virtual void doBeforeEffect(SPLPEItem const * lpeitem); virtual SPCurve const * addNodesAndJitter(Geom::Curve const * A, Geom::Point &prev, double t, bool last); - virtual SPCurve *jitter(Geom::Curve const * A); + virtual SPCurve *jitter(Geom::Curve const * A, Geom::Point &prev); virtual Geom::Point tPoint(Geom::Point A, Geom::Point B, double t = 0.5); virtual Gtk::Widget *newWidget(); @@ -53,6 +53,7 @@ private: BoolParam shift_nodes; BoolParam shift_handles; BoolParam shift_handles_sym; + BoolParam fixed_displacement; LPERoughen(const LPERoughen &); LPERoughen &operator=(const LPERoughen &); -- cgit v1.2.3 From bdf7f8acb13e3c1920307674e3fea3cbca8ba12e Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 14 Oct 2015 13:20:09 +0200 Subject: Fix from Johan to prevent referencing null C++ pointer. Found via Clang scan build. (bzr r14409) --- src/widgets/gradient-vector.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 259d4c9af..8e92f589a 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -842,7 +842,8 @@ static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *s GtkWidget *vb, *w, *f; - g_return_val_if_fail(!gradient || SP_IS_GRADIENT(gradient), NULL); + g_return_val_if_fail(gradient != NULL, NULL); + g_return_val_if_fail(SP_IS_GRADIENT(gradient), NULL); #if GTK_CHECK_VERSION(3,0,0) vb = gtk_box_new(GTK_ORIENTATION_VERTICAL, PAD); -- cgit v1.2.3 From d6926d4ffcd9fdf0c1e69fb3bf9397eac0f54f81 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Wed, 14 Oct 2015 20:42:56 +0200 Subject: improved results of roughen LPE (bzr r14410) --- src/live_effects/lpe-roughen.cpp | 44 ++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp index 6f24c288d..dec3f955f 100644 --- a/src/live_effects/lpe-roughen.cpp +++ b/src/live_effects/lpe-roughen.cpp @@ -314,23 +314,19 @@ SPCurve const * LPERoughen::addNodesAndJitter(Geom::Curve const * A, Geom::Point if(prev == Geom::Point(0,0)){ point_a1 = randomize(max_lenght); } - if(last){ - prev = A->pointAt(1 - (t / 3)) + point_b2; - } else { - point_b3 = Geom::Point(0,0); - point_b2 = Geom::Point(0,0); - } - Geom::Ray ray2(seg2[1] + point_b1, seg1[3] + point_a3); - point_a2 = Geom::Point::polar(ray2.angle(), max_lenght); + ray.setPoints(seg2[1] + point_a3 + point_b1, seg1[3] + point_a3); + point_a2 = Geom::Point::polar(ray.angle(), max_lenght); if(!last){ prev = seg1[3] + point_a3 + point_a2; + } else { + prev = A->pointAt(1 - (t / 3)) + point_b2 + point_b3; } out->moveto(seg1[0]); - out->curveto(seg1[0] + point_a1, seg1[3] + point_a3 + point_a2, seg1[3] + point_a3); + out->curveto(seg1[0] + point_a1, seg1[2] + point_a3 + point_a2, seg1[3] + point_a3); if(last){ - out->curveto(seg2[1] + point_b1, A->pointAt(1 - (t / 3)) + point_b2, seg2[3] + point_b3); + out->curveto(seg2[1] + point_a3 + point_b1, A->pointAt(1 - (t / 3)) + point_b2 + point_b3, seg2[3] + point_b3); } else { - out->curveto(seg2[1] + point_b1, seg2[2] + point_b2, seg2[3] + point_b3); + out->curveto(seg2[1] + point_a3 + point_b1, seg2[2] + point_b2 + point_b3, seg2[3] + point_b3); } } else if(shift_handles_sym && !cubic) { Geom::Ray ray(prev,A->initialPoint()); @@ -338,35 +334,31 @@ SPCurve const * LPERoughen::addNodesAndJitter(Geom::Curve const * A, Geom::Point if(prev==Geom::Point(0,0)){ point_a1 = randomize(max_lenght); } - if(last){ - prev = A->pointAt(1 - (t / 3)) + point_b2; - } else { - point_b3 = Geom::Point(0,0); - point_b2 = Geom::Point(0,0); - } - Geom::Ray ray2(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t) + point_a3); - point_a2 = Geom::Point::polar(ray2.angle(), max_lenght); + ray.setPoints(A->pointAt(t + (t / 3)) + point_a3 + point_b1, A->pointAt(t) + point_a3); + point_a2 = Geom::Point::polar(ray.angle(), max_lenght); if(!last){ prev = A->pointAt((t / 3) * 2) + point_a2; + } else { + prev = A->pointAt(1 - (t / 3)) + point_b2 + point_b3; } out->moveto(A->initialPoint()); - out->curveto(A->initialPoint() + point_a1, A->pointAt(t) + point_a3 + point_a2, A->pointAt(t) + point_a3); + out->curveto(A->initialPoint() + point_a1, A->pointAt((t / 3) * 2) + point_a3 + point_a2, A->pointAt(t) + point_a3); if(last){ - out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(1 - (t / 3)) + point_b2, A->finalPoint() + point_b3); + out->curveto(A->pointAt(t + (t / 3)) + point_a3 + point_b1, A->pointAt(1 - (t / 3)) + point_b2 + point_b3, A->finalPoint() + point_b3); } else { - out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t +((t / 3) * 2)) + point_b2, A->finalPoint() + point_b3); + out->curveto(A->pointAt(t + (t / 3)) + point_a3 + point_b1, A->pointAt(t +((t / 3) * 2)) + point_b2 + point_b3, A->finalPoint() + point_b3); } } else if (cubic) { std::pair div = cubic->subdivide(t); std::vector seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints(); out->moveto(seg1[0]); - out->curveto(seg1[1] + point_a1, seg1[2] + point_a2, seg1[3] + point_a3); - out->curveto(seg2[1] + point_b1, seg2[2] + point_b2, seg2[3] + point_b3); + out->curveto(seg1[1] + point_a1, seg1[2] + point_a2 + point_a3, seg1[3] + point_a3); + out->curveto(seg2[1] + point_a3 + point_b1, seg2[2] + point_b2 + point_b3, seg2[3] + point_b3); } else if (shift_handles) { out->moveto(A->initialPoint()); - out->curveto(A->pointAt(t / 3) + point_a1, A->pointAt((t / 3) * 2) + point_a2, A->pointAt(t) + point_a3); - out->curveto(A->pointAt(t + (t / 3)) + point_b1, A->pointAt(t +((t / 3) * 2)) + point_b2, A->finalPoint() + point_b3); + out->curveto(A->pointAt(t / 3) + point_a1, A->pointAt((t / 3) * 2) + point_a2 + point_a3, A->pointAt(t) + point_a3); + out->curveto(A->pointAt(t + (t / 3)) + point_a3 + point_b1, A->pointAt(t +((t / 3) * 2)) + point_b2 + point_b3, A->finalPoint() + point_b3); } else { out->moveto(A->initialPoint()); out->lineto(A->pointAt(t) + point_a3); -- cgit v1.2.3 From e49ce373b61fba07422c156090b0ee7553cde18f Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Wed, 14 Oct 2015 21:47:34 +0200 Subject: Fix snapping while rotating a selection Fixed bugs: - https://launchpad.net/bugs/1479167 (bzr r14411) --- src/2geom/path-sink.cpp | 4 ++-- src/object-snapper.cpp | 43 ++++++------------------------------------- src/pure-transform.cpp | 2 +- 3 files changed, 9 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/2geom/path-sink.cpp b/src/2geom/path-sink.cpp index 3b8d407f8..77301b716 100644 --- a/src/2geom/path-sink.cpp +++ b/src/2geom/path-sink.cpp @@ -73,8 +73,8 @@ void PathSink::feed(Rect const &r) { void PathSink::feed(Circle const &e) { Coord r = e.radius(); Point c = e.center(); - Point a = c + Point(0, c[Y] + r); - Point b = c + Point(0, c[Y] - r); + Point a = c + Point(0, +r); + Point b = c + Point(0, -r); moveTo(a); arcTo(r, r, 0, false, false, b); diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 634d56aa6..7302f9de6 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -637,7 +637,6 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(IntermSnapResults &isr, constraint_line.appendNew(p_max_on_cl); constraint_path.push_back(constraint_line); } - // Length of constraint_path will always be one bool strict_snapping = _snapmanager->snapprefs.getStrictSnapping(); @@ -646,45 +645,15 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(IntermSnapResults &isr, for (std::vector::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); ++k) { if (k->path_vector && _allowSourceToSnapToTarget(p.getSourceType(), (*k).target_type, strict_snapping)) { // Do the intersection math - Geom::CrossingSet cs = Geom::crossings(constraint_path, *(k->path_vector)); - // Store the results as intersection points - unsigned int index = 0; - for (Geom::CrossingSet::const_iterator i = cs.begin(); i != cs.end(); ++i) { - if (index >= constraint_path.size()) { - break; - } - // Reconstruct and store the points of intersection - for (Geom::Crossings::const_iterator m = (*i).begin(); m != (*i).end(); ++m) { - intersections.push_back(constraint_path[index].pointAt((*m).ta)); - } - index++; - } - - //Geom::crossings will not consider the closing segment apparently, so we'll handle that separately here - //TODO: This should have been fixed in rev. #9859, which makes this workaround obsolete - for(Geom::PathVector::iterator it_pv = k->path_vector->begin(); it_pv != k->path_vector->end(); ++it_pv) { - if (it_pv->closed()) { - // Get the closing linesegment and convert it to a path - Geom::Path cls; - cls.close(false); - cls.append(it_pv->back_closed()); - // Intersect that closing path with the constrained path - Geom::Crossings cs = Geom::crossings(constraint_path.front(), cls); - // Reconstruct and store the points of intersection - index = 0; // assuming the constraint path vector has only one path - for (Geom::Crossings::const_iterator m = cs.begin(); m != cs.end(); ++m) { - intersections.push_back(constraint_path[index].pointAt((*m).ta)); - } - } - } + std::vector inters = constraint_path.intersect(*(k->path_vector)); - // Convert the collected points of intersection to snapped points - for (std::vector::iterator p_inters = intersections.begin(); p_inters != intersections.end(); ++p_inters) { + // Convert the collected intersections to snapped points + for (std::vector::const_iterator i = inters.begin(); i != inters.end(); ++i) { // Convert to desktop coordinates - (*p_inters) = dt->doc2dt(*p_inters); + Geom::Point p_inters = dt->doc2dt(i->point()); // Construct a snapped point - Geom::Coord dist = Geom::L2(p.getPoint() - *p_inters); - SnappedPoint s = SnappedPoint(*p_inters, p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, false, k->target_bbox); + Geom::Coord dist = Geom::L2(p.getPoint() - p_inters); + SnappedPoint s = SnappedPoint(p_inters, p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true, false, k->target_bbox); // Store the snapped point if (dist <= tolerance) { // If the intersection is within snapping range, then we might snap to it isr.points.push_back(s); diff --git a/src/pure-transform.cpp b/src/pure-transform.cpp index aa89c8a8e..9c7054b9f 100644 --- a/src/pure-transform.cpp +++ b/src/pure-transform.cpp @@ -63,7 +63,7 @@ void PureTransform::snap(::SnapManager *sm, std::vector todo(owner->hrefList); todo.push_front(owner->parent); while(!todo.empty()){ -- cgit v1.2.3 From b39fc82af6e1320d3c2b301a1639965b04f05fd9 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Thu, 15 Oct 2015 01:13:10 +0200 Subject: clang-format (bzr r14413) --- src/uri-references.cpp | 159 +++++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/uri-references.cpp b/src/uri-references.cpp index 0aae9b39d..b6ccdbf5f 100644 --- a/src/uri-references.cpp +++ b/src/uri-references.cpp @@ -26,74 +26,91 @@ namespace Inkscape { URIReference::URIReference(SPObject *owner) - : _owner(owner), _owner_document(NULL), _obj(NULL), _uri(NULL) + : _owner(owner) + , _owner_document(NULL) + , _obj(NULL) + , _uri(NULL) { g_assert(_owner != NULL); /* FIXME !!! attach to owner's destroy signal to clean up in case */ } URIReference::URIReference(SPDocument *owner_document) - : _owner(NULL), _owner_document(owner_document), _obj(NULL), _uri(NULL) + : _owner(NULL) + , _owner_document(owner_document) + , _obj(NULL) + , _uri(NULL) { g_assert(_owner_document != NULL); } -URIReference::~URIReference() -{ - detach(); -} +URIReference::~URIReference() { detach(); } /* * The main ideas here are: * (1) "If we are inside a clone, then we can accept if and only if our "original thing" can accept the reference" - * (this caused problems when there are clones because a change in ids triggers signals for the object hrefing this id, but also its cloned reprs - * (descendants of referencing an ancestor of the href'ing object)). The way it is done here is *atrocious*, but i could not find a better way. + * (this caused problems when there are clones because a change in ids triggers signals for the object hrefing this id, + *but also its cloned reprs + * (descendants of referencing an ancestor of the href'ing object)). The way it is done here is *atrocious*, but i + *could not find a better way. * FIXME: find a better and safer way to find the "original object" of anyone with the flag ->cloned * - * (2) Once we have an (potential owner) object, it can accept a href to obj, iff the graph of objects where directed edges are + * (2) Once we have an (potential owner) object, it can accept a href to obj, iff the graph of objects where directed + *edges are * either parent->child relations , *** or href'ing to href'ed *** relations, stays acyclic. - * We can go either from owner and up in the tree, or from obj and down, in either case this will be in the worst case linear in the number of objects. - * There are no easy objects allowing to do the second proposition, while "hrefList" is a "list of objects href'ing us", so we'll take this. + * We can go either from owner and up in the tree, or from obj and down, in either case this will be in the worst case + *linear in the number of objects. + * There are no easy objects allowing to do the second proposition, while "hrefList" is a "list of objects href'ing us", + *so we'll take this. * Then we keep a set of already visited elements, and do a DFS on this graph. if we find obj, then BOOM. */ -bool URIReference::_acceptObject(SPObject *obj) const { - //we go back following hrefList and parent to find if the object already references ourselves indirectly - std::set done; - SPObject * owner = getOwner(); - if(!owner)return true; - while(owner->cloned){ - std::vector positions; - while(owner->cloned){ - int position=0; - SPObject* c = owner->parent->firstChild(); - while(c != owner && dynamic_cast(c) ){position++;c=c->next;} - positions.push_back(position); - owner=owner->parent; - } - owner = ((SPUse*)owner)->get_original(); - for(int i=positions.size()-2;i>=0;i--)owner=owner->childList(false)[positions[i]]; - } - //once we have the "original" object (hopefully) we look at who is referencing it - if(obj == owner)return false; - std::list todo(owner->hrefList); - todo.push_front(owner->parent); - while(!todo.empty()){ - SPObject* e = todo.front(); - todo.pop_front(); - if(!dynamic_cast(e))continue; - if(done.insert(e).second){ - if(e==obj){return false;} - todo.push_front(e->parent); - todo.insert(todo.begin(),e->hrefList.begin(),e->hrefList.end()); - } - } +bool URIReference::_acceptObject(SPObject *obj) const +{ + // we go back following hrefList and parent to find if the object already references ourselves indirectly + std::set done; + SPObject *owner = getOwner(); + if (!owner) + return true; + while (owner->cloned) { + std::vector positions; + while (owner->cloned) { + int position = 0; + SPObject *c = owner->parent->firstChild(); + while (c != owner && dynamic_cast(c)) { + position++; + c = c->next; + } + positions.push_back(position); + owner = owner->parent; + } + owner = ((SPUse *)owner)->get_original(); + for (int i = positions.size() - 2; i >= 0; i--) + owner = owner->childList(false)[positions[i]]; + } + // once we have the "original" object (hopefully) we look at who is referencing it + if (obj == owner) + return false; + std::list todo(owner->hrefList); + todo.push_front(owner->parent); + while (!todo.empty()) { + SPObject *e = todo.front(); + todo.pop_front(); + if (!dynamic_cast(e)) + continue; + if (done.insert(e).second) { + if (e == obj) { + return false; + } + todo.push_front(e->parent); + todo.insert(todo.begin(), e->hrefList.begin(), e->hrefList.end()); + } + } return true; } - void URIReference::attach(const URI &uri) throw(BadURIException) { SPDocument *document = NULL; @@ -109,32 +126,30 @@ void URIReference::attach(const URI &uri) throw(BadURIException) // PNG and JPG files are allowed (in the case of feImage). gchar *filename = uri.toString(); bool skip = false; - if( g_str_has_suffix( filename, ".jpg" ) || - g_str_has_suffix( filename, ".JPG" ) || - g_str_has_suffix( filename, ".png" ) || - g_str_has_suffix( filename, ".PNG" ) ) { + if (g_str_has_suffix(filename, ".jpg") || g_str_has_suffix(filename, ".JPG") || + g_str_has_suffix(filename, ".png") || g_str_has_suffix(filename, ".PNG")) { skip = true; } - + // The path contains references to separate document files to load. - if(document && uri.getPath() && !skip ) { + if (document && uri.getPath() && !skip) { std::string base = document->getBase() ? document->getBase() : ""; std::string path = uri.getFullPath(base); - if(!path.empty()) { + if (!path.empty()) { document = document->createChildDoc(path); } else { document = NULL; } } - if(!document) { + if (!document) { g_warning("Can't get document for referenced URI: %s", filename); - g_free( filename ); + g_free(filename); return; } - g_free( filename ); + g_free(filename); gchar const *fragment = uri.getFragment(); - if ( !uri.isRelative() || uri.getQuery() || !fragment ) { + if (!uri.isRelative() || uri.getQuery() || !fragment) { throw UnsupportedURIException(); } @@ -149,9 +164,9 @@ void URIReference::attach(const URI &uri) throw(BadURIException) the strlen calculation and validity testing to before strdup, and copying just the id without the "))". -- pjrm */ if (!strncmp(fragment, "xpointer(id(", 12)) { - id = g_strdup(fragment+12); + id = g_strdup(fragment + 12); size_t const len = strlen(id); - if ( len < 3 || strcmp(id+len-2, "))") ) { + if (len < 3 || strcmp(id + len - 2, "))")) { g_free(id); throw MalformedURIException(); } @@ -184,13 +199,14 @@ void URIReference::detach() void URIReference::_setObject(SPObject *obj) { - if ( obj && !_acceptObject(obj) ) { + if (obj && !_acceptObject(obj)) { obj = NULL; } - if ( obj == _obj ) return; + if (obj == _obj) + return; - SPObject *old_obj=_obj; + SPObject *old_obj = _obj; _obj = obj; _release_connection.disconnect(); @@ -211,7 +227,7 @@ void URIReference::_setObject(SPObject *obj) */ void URIReference::_release(SPObject *obj) { - g_assert( _obj == obj ); + g_assert(_obj == obj); _setObject(NULL); } @@ -219,28 +235,27 @@ void URIReference::_release(SPObject *obj) -SPObject* sp_css_uri_reference_resolve( SPDocument *document, const gchar *uri ) +SPObject *sp_css_uri_reference_resolve(SPDocument *document, const gchar *uri) { - SPObject* ref = NULL; + SPObject *ref = NULL; - if ( document && uri && ( strncmp(uri, "url(", 4) == 0 ) ) { - gchar *trimmed = extract_uri( uri ); - if ( trimmed ) { - ref = sp_uri_reference_resolve( document, trimmed ); - g_free( trimmed ); + if (document && uri && (strncmp(uri, "url(", 4) == 0)) { + gchar *trimmed = extract_uri(uri); + if (trimmed) { + ref = sp_uri_reference_resolve(document, trimmed); + g_free(trimmed); } } return ref; } -SPObject * -sp_uri_reference_resolve (SPDocument *document, const gchar *uri) +SPObject *sp_uri_reference_resolve(SPDocument *document, const gchar *uri) { - SPObject* ref = NULL; + SPObject *ref = NULL; - if ( uri && (*uri == '#') ) { - ref = document->getObjectById( uri + 1 ); + if (uri && (*uri == '#')) { + ref = document->getObjectById(uri + 1); } return ref; -- cgit v1.2.3 From b80f68e9585593a78bad9ae34385cbebe780299a Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 15 Oct 2015 13:52:47 +0200 Subject: Add new 'writing-mode' values, remove 'block-progression', fix a few typos. (bzr r14416) --- src/attributes-test.h | 3 ++- src/attributes.cpp | 2 +- src/attributes.h | 2 +- src/libnrtype/Layout-TNG-Input.cpp | 7 ------- src/style-enums.h | 39 +++++++++++++++++++++++++------------- src/style.cpp | 27 ++++++++++++++------------ src/style.h | 8 ++++---- 7 files changed, 49 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/attributes-test.h b/src/attributes-test.h index 411304ec3..e197deedf 100644 --- a/src/attributes-test.h +++ b/src/attributes-test.h @@ -43,6 +43,7 @@ public: SVG 2: text-decoration-fill, text-decoration-stroke SVG 2: solid-color, solid-opacity SVG 2: Hatches and Meshes + CSS 3: text-orientation CSS 3: font-variant-xxx, font-feature-settings */ struct {char const *attr; bool supported;} const all_attrs[] = { @@ -69,7 +70,6 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"baseProfile", false}, {"bbox", true}, {"bias", true}, - {"block-progression", true}, {"by", true}, {"calcMode", true}, {"cap-height", true}, @@ -334,6 +334,7 @@ struct {char const *attr; bool supported;} const all_attrs[] = { {"widths", true}, {"word-spacing", true}, {"writing-mode", true}, + {"text-orientation", true}, {"x", true}, {"x-height", true}, {"x1", true}, diff --git a/src/attributes.cpp b/src/attributes.cpp index 991834cb2..a237f8861 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -440,8 +440,8 @@ static SPStyleProp const props[] = { /* Text (css3) */ {SP_PROP_DIRECTION, "direction"}, - {SP_PROP_BLOCK_PROGRESSION, "block-progression"}, {SP_PROP_WRITING_MODE, "writing-mode"}, + {SP_PROP_TEXT_ORIENTATION, "text-orientation"}, {SP_PROP_UNICODE_BIDI, "unicode-bidi"}, {SP_PROP_ALIGNMENT_BASELINE, "alignment-baseline"}, {SP_PROP_BASELINE_SHIFT, "baseline-shift"}, diff --git a/src/attributes.h b/src/attributes.h index 47f1388b0..42ec99d8f 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -444,8 +444,8 @@ enum SPAttributeEnum { SP_PROP_TEXT_TRANSFORM, SP_PROP_DIRECTION, - SP_PROP_BLOCK_PROGRESSION, SP_PROP_WRITING_MODE, + SP_PROP_TEXT_ORIENTATION, SP_PROP_UNICODE_BIDI, SP_PROP_ALIGNMENT_BASELINE, SP_PROP_BASELINE_SHIFT, diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp index c9cfe81cc..9c2fc5c11 100644 --- a/src/libnrtype/Layout-TNG-Input.cpp +++ b/src/libnrtype/Layout-TNG-Input.cpp @@ -172,11 +172,6 @@ float Layout::InputStreamTextSource::styleComputeFontSize() const return medium_font_size * inherit_multiplier; } -static const Layout::EnumConversionItem enum_convert_spstyle_block_progression_to_direction[] = { - {SP_CSS_BLOCK_PROGRESSION_TB, Layout::TOP_TO_BOTTOM}, - {SP_CSS_BLOCK_PROGRESSION_LR, Layout::LEFT_TO_RIGHT}, - {SP_CSS_BLOCK_PROGRESSION_RL, Layout::RIGHT_TO_LEFT}}; - static const Layout::EnumConversionItem enum_convert_spstyle_writing_mode_to_direction[] = { {SP_CSS_WRITING_MODE_LR_TB, Layout::TOP_TO_BOTTOM}, {SP_CSS_WRITING_MODE_RL_TB, Layout::TOP_TO_BOTTOM}, @@ -190,8 +185,6 @@ Layout::Direction Layout::InputStreamTextSource::styleGetBlockProgression() cons SPStyle const *this_style = style; for ( ; ; ) { - if (this_style->block_progression.set) - return (Layout::Direction)_enum_converter(this_style->block_progression.computed, enum_convert_spstyle_block_progression_to_direction, sizeof(enum_convert_spstyle_block_progression_to_direction)/sizeof(enum_convert_spstyle_block_progression_to_direction[0])); if (this_style->writing_mode.set) return (Layout::Direction)_enum_converter(this_style->writing_mode.computed, enum_convert_spstyle_writing_mode_to_direction, sizeof(enum_convert_spstyle_writing_mode_to_direction)/sizeof(enum_convert_spstyle_writing_mode_to_direction[0])); if (this_style->object == NULL || this_style->object->parent == NULL) break; diff --git a/src/style-enums.h b/src/style-enums.h index dfc99282c..03255b3b1 100644 --- a/src/style-enums.h +++ b/src/style-enums.h @@ -163,12 +163,6 @@ enum SPCSSDirection { SP_CSS_DIRECTION_RTL }; -enum SPCSSBlockProgression { - SP_CSS_BLOCK_PROGRESSION_TB, - SP_CSS_BLOCK_PROGRESSION_RL, - SP_CSS_BLOCK_PROGRESSION_LR -}; - enum SPCSSWritingMode { SP_CSS_WRITING_MODE_LR_TB, SP_CSS_WRITING_MODE_RL_TB, @@ -176,6 +170,16 @@ enum SPCSSWritingMode { SP_CSS_WRITING_MODE_TB_LR }; +// CSS WRITING MODES 3 +enum SPCSSTextOrientation { + SP_CSS_TEXT_ORIENTATION_MIXED, + SP_CSS_TEXT_ORIENTATION_UPRIGHT, + SP_CSS_TEXT_ORIENTATION_SIDEWAYS_RIGHT, + SP_CSS_TEXT_ORIENTATION_SIDEWAYS_LEFT, + SP_CSS_TEXT_ORIENTATION_SIDEWAYS, + SP_CSS_TEXT_ORIENTATION_USE_GLYPH_ORIENTATION +}; + enum SPTextAnchor { SP_CSS_TEXT_ANCHOR_START, SP_CSS_TEXT_ANCHOR_MIDDLE, @@ -489,13 +493,6 @@ static SPStyleEnum const enum_direction[] = { {NULL, -1} }; -static SPStyleEnum const enum_block_progression[] = { - {"tb", SP_CSS_BLOCK_PROGRESSION_TB}, - {"rl", SP_CSS_BLOCK_PROGRESSION_RL}, - {"lr", SP_CSS_BLOCK_PROGRESSION_LR}, - {NULL, -1} -}; - static SPStyleEnum const enum_writing_mode[] = { /* Note that using the same enumerator for lr as lr-tb means we write as lr-tb even if the * input file said lr. We prefer writing lr-tb on the grounds that the spec says the initial @@ -504,12 +501,28 @@ static SPStyleEnum const enum_writing_mode[] = { * ECMA scripts may be surprised to find tb-rl in DOM if they set the attribute to rl, so * sharing enumerators for different strings may be a bug (once we support ecma script). */ + // SVG 1.1 Deprecated but still must be supported in SVG 2. {"lr-tb", SP_CSS_WRITING_MODE_LR_TB}, {"rl-tb", SP_CSS_WRITING_MODE_RL_TB}, {"tb-rl", SP_CSS_WRITING_MODE_TB_RL}, {"lr", SP_CSS_WRITING_MODE_LR_TB}, {"rl", SP_CSS_WRITING_MODE_RL_TB}, {"tb", SP_CSS_WRITING_MODE_TB_RL}, + // SVG 2 & CSS 3 Writing Modes + {"horizontal-tb", SP_CSS_WRITING_MODE_LR_TB}, // This is correct, 'direction' distinguishes between 'lr' and 'rl'. + {"vertical-rl", SP_CSS_WRITING_MODE_TB_RL}, + {"vertical-lr", SP_CSS_WRITING_MODE_TB_LR}, + {NULL, -1} +}; + +// CSS WRITING MODES 3 +static SPStyleEnum const enum_text_orientation[] = { + {"mixed", SP_CSS_TEXT_ORIENTATION_MIXED}, // Default + {"upright", SP_CSS_TEXT_ORIENTATION_UPRIGHT}, + {"sideways-right", SP_CSS_TEXT_ORIENTATION_SIDEWAYS_RIGHT}, + {"sideways-left", SP_CSS_TEXT_ORIENTATION_SIDEWAYS_LEFT}, + {"sideways", SP_CSS_TEXT_ORIENTATION_SIDEWAYS}, + {"use-glyph-orientation", SP_CSS_TEXT_ORIENTATION_USE_GLYPH_ORIENTATION}, {NULL, -1} }; diff --git a/src/style.cpp b/src/style.cpp index 0cb5db0a7..369127792 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -136,8 +136,8 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) : text_transform( "text-transform", enum_text_transform, SP_CSS_TEXT_TRANSFORM_NONE ), direction( "direction", enum_direction, SP_CSS_DIRECTION_LTR ), - block_progression("block-progression", enum_block_progression, SP_CSS_BLOCK_PROGRESSION_TB), writing_mode( "writing-mode", enum_writing_mode, SP_CSS_WRITING_MODE_LR_TB ), + text_orientation( "text-orientation",enum_text_orientation,SP_CSS_TEXT_ORIENTATION_MIXED ), baseline_shift(), text_anchor( "text-anchor", enum_text_anchor, SP_CSS_TEXT_ANCHOR_START ), white_space( "white-space", enum_white_space, SP_CSS_WHITE_SPACE_NORMAL ), @@ -318,9 +318,9 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) : _properties.push_back( &word_spacing ); _properties.push_back( &text_transform ); - _properties.push_back( &direction ); - _properties.push_back( &block_progression ); _properties.push_back( &writing_mode ); + _properties.push_back( &direction ); + _properties.push_back( &text_orientation ); _properties.push_back( &baseline_shift ); _properties.push_back( &text_anchor ); _properties.push_back( &white_space ); @@ -413,8 +413,8 @@ SPStyle::SPStyle(SPDocument *document_in, SPObject *object_in) : // _propmap.insert( std::make_pair( text_transform.name, reinterpret_cast(&SPStyle::text_transform ) ) ); // _propmap.insert( std::make_pair( direction.name, reinterpret_cast(&SPStyle::direction ) ) ); - // _propmap.insert( std::make_pair( block_progression.name, reinterpret_cast(&SPStyle::block_progression ) ) ); // _propmap.insert( std::make_pair( writing_mode.name, reinterpret_cast(&SPStyle::writing_mode ) ) ); + // _propmap.insert( std::make_pair( text_orientation.name, reinterpret_cast(&SPStyle::text_orientation ) ) ); // _propmap.insert( std::make_pair( baseline_shift.name, reinterpret_cast(&SPStyle::baseline_shift ) ) ); // _propmap.insert( std::make_pair( text_anchor.name, reinterpret_cast(&SPStyle::text_anchor ) ) ); // _propmap.insert( std::make_pair( white_space.name, reinterpret_cast(&SPStyle::white_space ) ) ); @@ -778,12 +778,12 @@ SPStyle::readIfUnset( gint id, gchar const *val ) { case SP_PROP_DIRECTION: direction.readIfUnset( val ); break; - case SP_PROP_BLOCK_PROGRESSION: - block_progression.readIfUnset( val ); - break; case SP_PROP_WRITING_MODE: writing_mode.readIfUnset( val ); break; + case SP_PROP_TEXT_ORIENTATION: + text_orientation.readIfUnset( val ); + break; case SP_PROP_TEXT_ANCHOR: text_anchor.readIfUnset( val ); break; @@ -1689,16 +1689,19 @@ sp_style_unset_property_attrs(SPObject *o) repr->setAttribute("text-anchor", NULL); } if (style->white_space.set) { - repr->setAttribute("white_space", NULL); + repr->setAttribute("white-space", NULL); } if (style->shape_inside.set) { - repr->setAttribute("shape_inside", NULL); + repr->setAttribute("shape-inside", NULL); } if (style->shape_padding.set) { - repr->setAttribute("shape_padding", NULL); + repr->setAttribute("shape-padding", NULL); } if (style->writing_mode.set) { - repr->setAttribute("writing_mode", NULL); + repr->setAttribute("writing-mode", NULL); + } + if (style->text_orientation.set) { + repr->setAttribute("text-orientation", NULL); } if (style->filter.set) { repr->setAttribute("filter", NULL); @@ -1781,8 +1784,8 @@ sp_css_attr_unset_text(SPCSSAttr *css) sp_repr_css_set_property(css, "word-spacing", NULL); sp_repr_css_set_property(css, "text-transform", NULL); sp_repr_css_set_property(css, "direction", NULL); - sp_repr_css_set_property(css, "block-progression", NULL); sp_repr_css_set_property(css, "writing-mode", NULL); + sp_repr_css_set_property(css, "text-orientation", NULL); sp_repr_css_set_property(css, "text-anchor", NULL); sp_repr_css_set_property(css, "white-space", NULL); sp_repr_css_set_property(css, "shape-inside", NULL); diff --git a/src/style.h b/src/style.h index 02432d3e7..3948b876c 100644 --- a/src/style.h +++ b/src/style.h @@ -142,12 +142,12 @@ public: SPIEnum text_transform; /* CSS3 Text */ - /** text direction (css3 text 3.2) */ + /** text direction (svg1.1) */ SPIEnum direction; - /** block progression (css3 text 3.2) */ - SPIEnum block_progression; - /** Writing mode (css3 text 3.2 and svg1.1 10.7.2) */ + /** Writing mode (svg1.1 10.7.2, CSS Writing Modes 3) */ SPIEnum writing_mode; + /** Text orientation (CSS Writing Modes 3) */ + SPIEnum text_orientation; /** Baseline shift (svg1.1 10.9.2) */ SPIBaselineShift baseline_shift; -- cgit v1.2.3 From d929999b79640a8b1425a999483d782883035d3b Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 15 Oct 2015 14:14:01 +0200 Subject: Simplify code after removal of 'block-progression'. (bzr r14417) --- src/libnrtype/Layout-TNG-Input.cpp | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/libnrtype/Layout-TNG-Input.cpp b/src/libnrtype/Layout-TNG-Input.cpp index 9c2fc5c11..77480cebe 100644 --- a/src/libnrtype/Layout-TNG-Input.cpp +++ b/src/libnrtype/Layout-TNG-Input.cpp @@ -172,27 +172,24 @@ float Layout::InputStreamTextSource::styleComputeFontSize() const return medium_font_size * inherit_multiplier; } -static const Layout::EnumConversionItem enum_convert_spstyle_writing_mode_to_direction[] = { - {SP_CSS_WRITING_MODE_LR_TB, Layout::TOP_TO_BOTTOM}, - {SP_CSS_WRITING_MODE_RL_TB, Layout::TOP_TO_BOTTOM}, - {SP_CSS_WRITING_MODE_TB_RL, Layout::RIGHT_TO_LEFT}, - {SP_CSS_WRITING_MODE_TB_LR, Layout::LEFT_TO_RIGHT}}; - Layout::Direction Layout::InputStreamTextSource::styleGetBlockProgression() const { - // this function shouldn't be necessary, but since style.cpp doesn't support - // shorthand properties yet, it is. - SPStyle const *this_style = style; + switch( style->writing_mode.computed ) { - for ( ; ; ) { - if (this_style->writing_mode.set) - return (Layout::Direction)_enum_converter(this_style->writing_mode.computed, enum_convert_spstyle_writing_mode_to_direction, sizeof(enum_convert_spstyle_writing_mode_to_direction)/sizeof(enum_convert_spstyle_writing_mode_to_direction[0])); - if (this_style->object == NULL || this_style->object->parent == NULL) break; - this_style = this_style->object->parent->style; - if (this_style == NULL) break; - } + case SP_CSS_WRITING_MODE_LR_TB: + case SP_CSS_WRITING_MODE_RL_TB: return TOP_TO_BOTTOM; + + case SP_CSS_WRITING_MODE_TB_RL: + return RIGHT_TO_LEFT; + + case SP_CSS_WRITING_MODE_TB_LR: + return LEFT_TO_RIGHT; + default: + std::cerr << "Layout::InputTextStream::styleGetBlockProgression: invalid writing mode." << std::endl; + } + return TOP_TO_BOTTOM; } static Layout::Alignment text_anchor_to_alignment(unsigned anchor, Layout::Direction para_direction) -- cgit v1.2.3 From f8a67994cf1d608c6f14e7c41497b62f4a402392 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Thu, 15 Oct 2015 17:15:00 +0200 Subject: Bug fixes in roughen and added uption to retract handles (bzr r14418) --- src/live_effects/lpe-roughen.cpp | 82 ++++++++++++++++++---------------------- src/live_effects/lpe-roughen.h | 1 + 2 files changed, 38 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp index dec3f955f..ed1ddcaf8 100644 --- a/src/live_effects/lpe-roughen.cpp +++ b/src/live_effects/lpe-roughen.cpp @@ -51,6 +51,8 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) true), shift_handles(_("Shift node handles"), _("Shift node handles"), "shift_handles", &wr, this, true), + retract_handles(_("Retract node handles"), _("Retract node handles"), + "retract_handles", &wr, this, false), shift_handles_sym(_("Sym shift node handles"), _("Sym shift node handles"), "shift_handles_sym", &wr, this, false), fixed_displacement(_("Fixed displacement"), _("Fixed displacement, 1/3 of segment lenght"), @@ -64,6 +66,7 @@ LPERoughen::LPERoughen(LivePathEffectObject *lpeobject) registerParameter(&global_randomize); registerParameter(&shift_nodes); registerParameter(&shift_handles); + registerParameter(&retract_handles); registerParameter(&shift_handles_sym); registerParameter(&fixed_displacement); displace_x.param_set_range(0., Geom::infinity()); @@ -167,8 +170,7 @@ Geom::Point LPERoughen::randomize(double max_lenght) void LPERoughen::doEffect(SPCurve *curve) { - Geom::PathVector const original_pathv = - pathv_to_linear_and_cubic_beziers(curve->get_pathvector()); + Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector()); curve->reset(); for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) { @@ -180,31 +182,14 @@ void LPERoughen::doEffect(SPCurve *curve) Geom::Path::const_iterator curve_endit = path_it->end_default(); SPCurve *nCurve = new SPCurve(); Geom::Point prev(0, 0); - if (path_it->closed()) { - const Geom::Curve &closingline = - path_it->back_closed(); - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { - curve_endit = path_it->end_open(); - } - } nCurve->moveto(curve_it1->initialPoint()); - Geom::Point point0(0, 0); - Geom::Point point_a1(0, 0); - Geom::Point point_a2(0, 0); - Geom::Point point_a3(0, 0); while (curve_it1 != curve_endit) { Geom::CubicBezier const *cubic = NULL; - point0 = curve_it1->initialPoint(); - point_a1 = curve_it1->initialPoint(); - point_a2 = curve_it1->finalPoint(); - point_a3 = curve_it1->finalPoint(); cubic = dynamic_cast(&*curve_it1); if (cubic) { - point_a1 = (*cubic)[1]; - point_a2 = (*cubic)[2]; - nCurve->curveto(point_a1, point_a2, point_a3); + nCurve->curveto((*cubic)[1], (*cubic)[2], curve_it1->finalPoint()); } else { - nCurve->lineto(point_a3); + nCurve->lineto(curve_it1->finalPoint()); } double length = curve_it1->length(0.001); std::size_t splits = 0; @@ -238,12 +223,10 @@ void LPERoughen::doEffect(SPCurve *curve) delete tmp; } ++curve_it1; - if(curve_it2 != curve_endit) { - ++curve_it2; - } + ++curve_it2; } if (path_it->closed()) { - if(shift_handles_sym && curve_it2 == curve_endit){ + if(shift_handles_sym && curve_it1 == curve_endit && !retract_handles){ SPCurve *out = new SPCurve(); nCurve = nCurve->create_reverse(); Geom::CubicBezier const *cubic_start = dynamic_cast(nCurve->first_segment()); @@ -305,7 +288,17 @@ SPCurve const * LPERoughen::addNodesAndJitter(Geom::Curve const * A, Geom::Point point_b2 = point_b3; } } - if(shift_handles_sym && cubic) { + if(retract_handles){ + out->moveto(A->initialPoint()); + out->lineto(A->pointAt(t) + point_a3); + if(cubic && !last){ + std::pair div = cubic->subdivide(t); + std::vector seg2 = div.second.controlPoints(); + out->curveto(seg2[1], seg2[2], seg2[3]); + } else { + out->lineto(A->finalPoint() + point_b3); + } + } else if(shift_handles_sym && cubic) { std::pair div = cubic->subdivide(t); std::vector seg1 = div.first.controlPoints(), seg2 = div.second.controlPoints(); @@ -314,15 +307,15 @@ SPCurve const * LPERoughen::addNodesAndJitter(Geom::Curve const * A, Geom::Point if(prev == Geom::Point(0,0)){ point_a1 = randomize(max_lenght); } - ray.setPoints(seg2[1] + point_a3 + point_b1, seg1[3] + point_a3); + ray.setPoints(seg2[1] + point_a3 + point_b1, seg2[0] + point_a3); point_a2 = Geom::Point::polar(ray.angle(), max_lenght); - if(!last){ - prev = seg1[3] + point_a3 + point_a2; - } else { + if(last){ prev = A->pointAt(1 - (t / 3)) + point_b2 + point_b3; + } else { + prev = seg1[3] + point_a2 + point_a3; } out->moveto(seg1[0]); - out->curveto(seg1[0] + point_a1, seg1[2] + point_a3 + point_a2, seg1[3] + point_a3); + out->curveto(seg1[0] + point_a1, seg1[3] + point_a2 + point_a3, seg1[3] + point_a3); if(last){ out->curveto(seg2[1] + point_a3 + point_b1, A->pointAt(1 - (t / 3)) + point_b2 + point_b3, seg2[3] + point_b3); } else { @@ -336,18 +329,14 @@ SPCurve const * LPERoughen::addNodesAndJitter(Geom::Curve const * A, Geom::Point } ray.setPoints(A->pointAt(t + (t / 3)) + point_a3 + point_b1, A->pointAt(t) + point_a3); point_a2 = Geom::Point::polar(ray.angle(), max_lenght); - if(!last){ - prev = A->pointAt((t / 3) * 2) + point_a2; - } else { - prev = A->pointAt(1 - (t / 3)) + point_b2 + point_b3; - } - out->moveto(A->initialPoint()); - out->curveto(A->initialPoint() + point_a1, A->pointAt((t / 3) * 2) + point_a3 + point_a2, A->pointAt(t) + point_a3); if(last){ - out->curveto(A->pointAt(t + (t / 3)) + point_a3 + point_b1, A->pointAt(1 - (t / 3)) + point_b2 + point_b3, A->finalPoint() + point_b3); + prev = A->pointAt(t +((t / 3) * 2)) + point_b2 + point_b3; } else { - out->curveto(A->pointAt(t + (t / 3)) + point_a3 + point_b1, A->pointAt(t +((t / 3) * 2)) + point_b2 + point_b3, A->finalPoint() + point_b3); + prev = A->pointAt(t) + point_a3 + point_a2; } + out->moveto(A->initialPoint()); + out->curveto(A->initialPoint() + point_a1, A->pointAt(t) + point_a3 + point_a2, A->pointAt(t) + point_a3); + out->curveto(A->pointAt(t + (t / 3)) + point_a3 + point_b1, A->pointAt(t +((t / 3) * 2)) + point_b2 + point_b3, A->finalPoint() + point_b3); } else if (cubic) { std::pair div = cubic->subdivide(t); std::vector seg1 = div.first.controlPoints(), @@ -382,7 +371,10 @@ SPCurve *LPERoughen::jitter(Geom::Curve const * A, Geom::Point &prev) point_a1 = randomize(max_lenght); point_a2 = randomize(max_lenght); } - if(shift_handles_sym && cubic) { + if(retract_handles){ + out->moveto(A->initialPoint()); + out->lineto(A->finalPoint() + point_a3); + } else if(shift_handles_sym && cubic) { Geom::Ray ray(prev,A->initialPoint()); point_a1 = Geom::Point::polar(ray.angle(), max_lenght); if(prev == Geom::Point(0,0)){ @@ -390,7 +382,7 @@ SPCurve *LPERoughen::jitter(Geom::Curve const * A, Geom::Point &prev) } prev = (*cubic)[2] + point_a2; out->moveto((*cubic)[0]); - out->curveto((*cubic)[0] + point_a1, (*cubic)[2] + point_a2, (*cubic)[3] + point_a3); + out->curveto((*cubic)[0] + point_a1, (*cubic)[2] + point_a2 + point_a3, (*cubic)[3] + point_a3); } else if(shift_handles_sym && !cubic) { Geom::Ray ray(prev,A->initialPoint()); point_a1 = Geom::Point::polar(ray.angle(), max_lenght); @@ -399,13 +391,13 @@ SPCurve *LPERoughen::jitter(Geom::Curve const * A, Geom::Point &prev) } prev = A->pointAt((1.0/3.0) * 2) + point_a2; out->moveto(A->initialPoint()); - out->curveto(A->initialPoint() + point_a1, A->pointAt((1.0/3.0) * 2) + point_a2, A->finalPoint() + point_a3); + out->curveto(A->initialPoint() + point_a1, A->pointAt((1.0/3.0) * 2) + point_a2 + point_a3, A->finalPoint() + point_a3); } else if (cubic) { out->moveto((*cubic)[0]); - out->curveto((*cubic)[1] + point_a1, (*cubic)[2] + point_a2, (*cubic)[3] + point_a3); + out->curveto((*cubic)[1] + point_a1, (*cubic)[2] + point_a2 + point_a3, (*cubic)[3] + point_a3); } else if (shift_handles) { out->moveto(A->initialPoint()); - out->curveto(A->pointAt(0.3333) + point_a1, A->pointAt(0.6666) + point_a2, + out->curveto(A->pointAt(0.3333) + point_a1, A->pointAt(0.6666) + point_a2 + point_a3, A->finalPoint() + point_a3); } else { out->moveto(A->initialPoint()); diff --git a/src/live_effects/lpe-roughen.h b/src/live_effects/lpe-roughen.h index e221e95fb..57a516310 100644 --- a/src/live_effects/lpe-roughen.h +++ b/src/live_effects/lpe-roughen.h @@ -52,6 +52,7 @@ private: RandomParam global_randomize; BoolParam shift_nodes; BoolParam shift_handles; + BoolParam retract_handles; BoolParam shift_handles_sym; BoolParam fixed_displacement; -- cgit v1.2.3