From: dvlierop2 Date: Fri, 20 Feb 2009 21:49:07 +0000 (+0000) Subject: The snap indicator's tooltip now displays "A to B", whereas before it only displayed... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=771d00baf3d15209a77dce026f7ef45a78365e62;p=inkscape.git The snap indicator's tooltip now displays "A to B", whereas before it only displayed "B". --- diff --git a/src/arc-context.cpp b/src/arc-context.cpp index da236ae87..115b5534c 100644 --- a/src/arc-context.cpp +++ b/src/arc-context.cpp @@ -228,7 +228,7 @@ static gint sp_arc_context_root_handler(SPEventContext *event_context, GdkEvent SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); Geom::Point pt2g = to_2geom(ac->center); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE); ac->center = from_2geom(pt2g); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp index 2b76233f5..e8cee44b0 100644 --- a/src/box3d-context.cpp +++ b/src/box3d-context.cpp @@ -294,7 +294,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven /* Snap center */ SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true, bc->item); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, button_dt); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, button_dt, Inkscape::SNAPSOURCE_HANDLE); bc->center = from_2geom(button_dt); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), @@ -326,7 +326,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true, bc->item); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, motion_dt); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, motion_dt, Inkscape::SNAPSOURCE_HANDLE); bc->ctrl_dragged = event->motion.state & GDK_CONTROL_MASK; @@ -360,7 +360,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven bc->drag_ptC_proj = cur_persp->tmat.preimage (from_2geom(motion_dt), bc->drag_ptB_proj[Proj::X], Proj::X); } Geom::Point pt2g = to_2geom(bc->drag_ptC); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE); bc->drag_ptC = from_2geom(pt2g); } diff --git a/src/connector-context.cpp b/src/connector-context.cpp index 6fa709b18..a3bb19de6 100644 --- a/src/connector-context.cpp +++ b/src/connector-context.cpp @@ -537,7 +537,7 @@ connector_handle_button_press(SPConnectorContext *const cc, GdkEventButton const // as there's no other points to go off. SnapManager &m = cc->desktop->namedview->snap_manager; m.setup(cc->desktop); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE); } spcc_connector_set_initial_point(cc, from_2geom(pt2g)); diff --git a/src/context-fns.cpp b/src/context-fns.cpp index 54b07a02a..30062504c 100644 --- a/src/context-fns.cpp +++ b/src/context-fns.cpp @@ -132,11 +132,11 @@ Geom::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item Inkscape::SnappedPoint s[2]; /* Try to snap p[0] (the opposite corner) along the constraint vector */ - s[0] = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[0]), + s[0] = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[0]), Inkscape::SNAPSOURCE_HANDLE, Inkscape::Snapper::ConstraintLine(p[0] - p[1])); /* Try to snap p[1] (the dragged corner) along the constraint vector */ - s[1] = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[1]), + s[1] = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[1]), Inkscape::SNAPSOURCE_HANDLE, Inkscape::Snapper::ConstraintLine(p[1] - p[0])); /* Choose the best snap and update points accordingly */ @@ -157,7 +157,7 @@ Geom::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item /* Our origin is the opposite corner. Snap the drag point along the constraint vector */ p[0] = center; - snappoint = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[1]), + snappoint = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[1]), Inkscape::SNAPSOURCE_HANDLE, Inkscape::Snapper::ConstraintLine(p[1] - p[0])); if (snappoint.getSnapped()) { p[1] = snappoint.getPoint(); @@ -175,8 +175,8 @@ Geom::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item Inkscape::SnappedPoint s[2]; - s[0] = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[0])); - s[1] = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[1])); + s[0] = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[0]), Inkscape::SNAPSOURCE_HANDLE); + s[1] = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[1]), Inkscape::SNAPSOURCE_HANDLE); if (s[0].getSnapDistance() < s[1].getSnapDistance()) { if (s[0].getSnapped()) { @@ -197,7 +197,7 @@ Geom::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item /* There's no constraint on the corner point, so just snap it to anything */ p[0] = center; p[1] = pt; - snappoint = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(pt)); + snappoint = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(pt), Inkscape::SNAPSOURCE_HANDLE); if (snappoint.getSnapped()) { p[1] = snappoint.getPoint(); } @@ -209,7 +209,7 @@ Geom::Rect Inkscape::snap_rectangular_box(SPDesktop const *desktop, SPItem *item p[0] = sp_desktop_dt2doc_xy_point(desktop, p[0]); p[1] = sp_desktop_dt2doc_xy_point(desktop, p[1]); - + return Geom::Rect(Geom::Point(MIN(p[0][Geom::X], p[1][Geom::X]), MIN(p[0][Geom::Y], p[1][Geom::Y])), Geom::Point(MAX(p[0][Geom::X], p[1][Geom::X]), MAX(p[0][Geom::Y], p[1][Geom::Y]))); } diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 076dcdd33..ea5393d39 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -757,9 +757,9 @@ CanvasAxonomGridSnapper::_getSnapLines(Geom::Point const &p) const return s; } -void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, Geom::Point const normal_to_line, Geom::Point const point_on_line) const +void CanvasAxonomGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, target, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); sc.grid_lines.push_back(dummy); } diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h index 4849f08ad..ecbd846a1 100644 --- a/src/display/canvas-axonomgrid.h +++ b/src/display/canvas-axonomgrid.h @@ -78,7 +78,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; - void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; + void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; CanvasAxonomGrid *grid; }; diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 49a1211eb..3e7295b90 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -1003,9 +1003,9 @@ CanvasXYGridSnapper::_getSnapLines(Geom::Point const &p) const return s; } -void CanvasXYGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, Geom::Point const normal_to_line, Geom::Point const point_on_line) const +void CanvasXYGridSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, target, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); sc.grid_lines.push_back(dummy); } diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index 85e890fef..37e30fab0 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -166,7 +166,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; - void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; + void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Point const normal_to_line, const Geom::Point point_on_line) const; CanvasXYGrid *grid; }; diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index 1785da7b9..e55c8faac 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -75,8 +75,11 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const p) case SNAPTARGET_GRID_GUIDE_INTERSECTION: target_name = _("grid-guide intersection"); break; - case SNAPTARGET_NODE: - target_name = _("node"); + case SNAPTARGET_NODE_CUSP: + target_name = _("cusp node"); + break; + case SNAPTARGET_NODE_SMOOTH: + target_name = _("smooth node"); break; case SNAPTARGET_PATH: target_name = _("path"); @@ -96,15 +99,91 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const p) case SNAPTARGET_PAGE_BORDER: target_name = _("page border"); break; + case SNAPTARGET_LINE_MIDPOINT: + target_name = _("line midpoint"); + break; + case SNAPTARGET_OBJECT_MIDPOINT: + target_name = _("object midpoint"); + break; + case SNAPTARGET_ROTATION_CENTER: + target_name = _("object rotation center"); + break; + case SNAPTARGET_HANDLE: + target_name = _("handle"); + break; + case SNAPTARGET_BBOX_EDGE_MIDPOINT: + target_name = _("bounding box side midpoint"); + break; + case SNAPTARGET_BBOX_MIDPOINT: + target_name = _("bounding box midpoint"); + break; + case SNAPTARGET_PAGE_CORNER: + target_name = _("page corner"); + break; + case SNAPTARGET_CONVEX_HULL_CORNER: + target_name = _("convex hull corner"); + break; + case SNAPTARGET_ELLIPSE_QUADRANT_POINT: + target_name = _("quadrant point"); + break; default: g_warning("Snap target has not yet been defined!"); break; } - // std::cout << "Snapped to: " << target_name << std::endl; + + gchar *source_name = _("UNDEFINED"); + switch (p.getSource()) { + case SNAPSOURCE_UNDEFINED: + source_name = _("UNDEFINED"); + break; + case SNAPSOURCE_BBOX_CORNER: + source_name = _("Bounding box corner"); + break; + case SNAPSOURCE_BBOX_MIDPOINT: + source_name = _("Bounding box midpoint"); + break; + case SNAPSOURCE_BBOX_EDGE_MIDPOINT: + source_name = _("Bounding box side midpoint"); + break; + case SNAPSOURCE_NODE_SMOOTH: + source_name = _("Smooth node"); + break; + case SNAPSOURCE_NODE_CUSP: + source_name = _("Cusp node"); + break; + case SNAPSOURCE_LINE_MIDPOINT: + source_name = _("Line midpoint"); + break; + case SNAPSOURCE_OBJECT_MIDPOINT: + source_name = _("Object midpoint"); + break; + case SNAPSOURCE_ROTATION_CENTER: + source_name = _("Object rotation center"); + break; + case SNAPSOURCE_HANDLE: + source_name = _("Handle"); + break; + case SNAPSOURCE_PATH_INTERSECTION: + source_name = _("Path intersection"); + break; + case SNAPSOURCE_GUIDE: + source_name = _("Guide"); + break; + case SNAPSOURCE_CONVEX_HULL_CORNER: + source_name = _("Convex hull corner"); + break; + case SNAPSOURCE_ELLIPSE_QUADRANT_POINT: + source_name = _("Quadrant point"); + break; + default: + g_warning("Snap source has not yet been defined!"); + break; + } + //std::cout << "Snapped " << source_name << " to " << target_name << std::endl; // Display the snap indicator (i.e. the cross) SPCanvasItem * canvasitem = NULL; - if (p.getTarget() == SNAPTARGET_NODE) { + if (p.getTarget() == SNAPTARGET_NODE_SMOOTH || p.getTarget() == SNAPTARGET_NODE_CUSP) { canvasitem = sp_canvas_item_new(sp_desktop_tempgroup (_desktop), SP_TYPE_CTRL, "anchor", GTK_ANCHOR_CENTER, @@ -136,7 +215,8 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const p) GtkSettings *settings = gtk_widget_get_settings (&(_desktop->canvas->widget)); // If we set the timeout too short, then the tooltip might not show at all (most noticeable when a long snap delay is active) g_object_set(settings, "gtk-tooltip-timeout", 200, NULL); // tooltip will be shown after x msec. - gtk_widget_set_tooltip_text(&(_desktop->canvas->widget), target_name); + gchar *tooltip_text = g_strconcat(source_name, _(" to "), target_name, NULL); + gtk_widget_set_tooltip_text(&(_desktop->canvas->widget), tooltip_text); // has_tooltip will be true by now because gtk_widget_set_has_tooltip() has been called implicitly update_tooltip(); // The snap indicator will be removed automatically because it's a temporary canvas item; the tooltip @@ -157,7 +237,7 @@ SnapIndicator::remove_snaptarget() } void -SnapIndicator::set_new_snapsource(Geom::Point const p) +SnapIndicator::set_new_snapsource(std::pair const p) { remove_snapsource(); @@ -177,7 +257,7 @@ SnapIndicator::set_new_snapsource(Geom::Point const p) "shape", SP_KNOT_SHAPE_CIRCLE, NULL ); - SP_CTRL(canvasitem)->moveto(p); + SP_CTRL(canvasitem)->moveto(p.first); _snapsource = _desktop->add_temporary_canvasitem(canvasitem, 1000); } } diff --git a/src/display/snap-indicator.h b/src/display/snap-indicator.h index 672d2e78c..ae0963b4f 100644 --- a/src/display/snap-indicator.h +++ b/src/display/snap-indicator.h @@ -29,7 +29,7 @@ public: void set_new_snaptarget(Inkscape::SnappedPoint const p); void remove_snaptarget(); - void set_new_snapsource(Geom::Point const p); + void set_new_snapsource(std::pair const p); void remove_snapsource(); protected: diff --git a/src/draw-context.cpp b/src/draw-context.cpp index a8d6187f6..b860c457d 100644 --- a/src/draw-context.cpp +++ b/src/draw-context.cpp @@ -513,7 +513,7 @@ void spdc_endpoint_snap_rotation(SPEventContext const *const ec, Geom::Point &p, SnapManager &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager; m.setup(SP_EVENT_CONTEXT_DESKTOP(ec)); Geom::Point pt2g = to_2geom(p); - m.constrainedSnapReturnByRef( Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::Snapper::ConstraintLine(best)); + m.constrainedSnapReturnByRef( Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE, Inkscape::Snapper::ConstraintLine(best)); p = from_2geom(pt2g); } } @@ -525,7 +525,7 @@ void spdc_endpoint_snap_free(SPEventContext const * const ec, Geom::Point& p, gu SnapManager &m = SP_EVENT_CONTEXT_DESKTOP(ec)->namedview->snap_manager; m.setup(SP_EVENT_CONTEXT_DESKTOP(ec)); Geom::Point pt2g = to_2geom(p); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE); p = from_2geom(pt2g); } diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp index e9b46a2c2..16df41f7a 100644 --- a/src/gradient-context.cpp +++ b/src/gradient-context.cpp @@ -560,7 +560,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event) /* Snap center to nearest magnetic point */ SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, button_dt); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, button_dt, Inkscape::SNAPSOURCE_HANDLE); rc->origin = from_2geom(button_dt); } diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index a24f45c84..76bed32cf 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -598,7 +598,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp SPDesktop *desktop = dragger->parent->desktop; SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); - Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p)); + Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p), Inkscape::SNAPSOURCE_HANDLE); if (s.getSnapped()) { p = s.getPoint(); sp_knot_moveto (knot, p); @@ -610,7 +610,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp dist = fabs(p[Geom::Y] - dragger->parent->hor_levels[i]); if (dist < snap_dist) { p[Geom::Y] = dragger->parent->hor_levels[i]; - s = Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_GRADIENT, dist, snap_dist, false, false); + s = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_HANDLE, Inkscape::SNAPTARGET_GRADIENT, dist, snap_dist, false, false); was_snapped = true; sp_knot_moveto (knot, p); } @@ -619,7 +619,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp dist = fabs(p[Geom::X] - dragger->parent->vert_levels[i]); if (dist < snap_dist) { p[Geom::X] = dragger->parent->vert_levels[i]; - s = Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_GRADIENT, dist, snap_dist, false, false); + s = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_HANDLE, Inkscape::SNAPTARGET_GRADIENT, dist, snap_dist, false, false); was_snapped = true; sp_knot_moveto (knot, p); } diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp index f344d891f..6df066cbb 100644 --- a/src/guide-snapper.cpp +++ b/src/guide-snapper.cpp @@ -66,9 +66,9 @@ bool Inkscape::GuideSnapper::ThisSnapperMightSnap() const return (_snap_enabled && _snapmanager->snapprefs.getSnapToGuides() && _snapmanager->snapprefs.getSnapModeBBoxOrNodes() && _snapmanager->getNamedView()->showguides); } -void Inkscape::GuideSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, Geom::Point const normal_to_line, Geom::Point const point_on_line) const +void Inkscape::GuideSnapper::_addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Point const normal_to_line, Geom::Point const point_on_line) const { - SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); + SnappedLine dummy = SnappedLine(snapped_point, snapped_distance, source, target, getSnapperTolerance(), getSnapperAlwaysSnap(), normal_to_line, point_on_line); sc.guide_lines.push_back(dummy); } diff --git a/src/guide-snapper.h b/src/guide-snapper.h index dd5581654..8b59194e8 100644 --- a/src/guide-snapper.h +++ b/src/guide-snapper.h @@ -36,7 +36,7 @@ public: private: LineList _getSnapLines(Geom::Point const &p) const; - void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, Geom::Point const normal_to_line, Geom::Point const point_on_line) const; + void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Point const normal_to_line, Geom::Point const point_on_line) const; }; } diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp index 36a072c44..df58d356a 100644 --- a/src/knot-holder-entity.cpp +++ b/src/knot-holder-entity.cpp @@ -1,8 +1,8 @@ #define __KNOT_HOLDER_ENTITY_C__ -/** \file - * KnotHolderEntity definition. - * +/** \file + * KnotHolderEntity definition. + * * Authors: * Mitsuru Oka * Maximilian Albert @@ -82,7 +82,7 @@ KnotHolderEntity::update_knot() Geom::Point dp(knot_get() * i2d); _moved_connection.block(); - sp_knot_set_position(knot, dp, SP_KNOT_STATE_NORMAL); + sp_knot_set_position(knot, dp, SP_KNOT_STATE_NORMAL); _moved_connection.unblock(); } @@ -93,7 +93,7 @@ KnotHolderEntity::snap_knot_position(Geom::Point const &p) Geom::Point s = p * i2d; SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true, item); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, s); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, s, Inkscape::SNAPSOURCE_HANDLE); return s * i2d.inverse(); } diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index bc43d640b..d751993dd 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -26,10 +26,11 @@ Inkscape::LineSnapper::LineSnapper(SnapManager *sm, Geom::Coord const d) : Snapp void Inkscape::LineSnapper::freeSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &/*f*/, Geom::OptRect const &/*bbox_to_snap*/, std::vector const */*it*/, - std::vector */*unselected_nodes*/) const + std::vector > */*unselected_nodes*/) const { if (!(_snap_enabled && _snapmanager->snapprefs.getSnapFrom(t)) ) { return; @@ -50,7 +51,8 @@ void Inkscape::LineSnapper::freeSnap(SnappedConstraints &sc, Geom::Coord const dist = Geom::L2(p_proj - p); //Store any line that's within snapping range if (dist < getSnapperTolerance()) { - _addSnappedLine(sc, p_proj, dist, i->first, i->second); + _addSnappedLine(sc, p_proj, dist, source_type, Inkscape::SNAPTARGET_UNDEFINED, i->first, i->second); + // We don't know if we're snapping to grids or guides here; therefore the snap target type will be set in findBestSnap() // std::cout << " -> distance = " << dist; } // std::cout << std::endl; @@ -60,6 +62,7 @@ void Inkscape::LineSnapper::freeSnap(SnappedConstraints &sc, void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &/*f*/, Geom::OptRect const &/*bbox_to_snap*/, ConstraintLine const &c, @@ -97,9 +100,7 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, // This snappoint is therefore fully constrained, so there's no need // to look for additional intersections; just return the snapped point // and forget about the line - sc.points.push_back(SnappedPoint(t, Inkscape::SNAPTARGET_UNDEFINED, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true)); - // The type of the snap target is yet undefined, as we cannot tell whether - // we're snapping to grid or the guide lines; must be set by on a higher level + sc.points.push_back(SnappedPoint(t, source_type, Inkscape::SNAPTARGET_UNDEFINED, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true)); } } } diff --git a/src/line-snapper.h b/src/line-snapper.h index 91e8ca596..3a7ed6aae 100644 --- a/src/line-snapper.h +++ b/src/line-snapper.h @@ -27,14 +27,16 @@ public: void freeSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &first_point, Geom::OptRect const &bbox_to_snap, std::vector const *it, - std::vector *unselected_nodes) const; + std::vector > *unselected_nodes) const; void constrainedSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &first_point, Geom::OptRect const &bbox_to_snap, ConstraintLine const &c, @@ -52,7 +54,7 @@ private: */ virtual LineList _getSnapLines(Geom::Point const &p) const = 0; - virtual void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, Geom::Point const normal_to_line, Geom::Point const point_on_line) const = 0; + virtual void _addSnappedLine(SnappedConstraints &sc, Geom::Point const snapped_point, Geom::Coord const snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Point const normal_to_line, Geom::Point const point_on_line) const = 0; }; } diff --git a/src/nodepath.cpp b/src/nodepath.cpp index cc38acbe5..845d47b3b 100644 --- a/src/nodepath.cpp +++ b/src/nodepath.cpp @@ -1350,13 +1350,13 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath, * must provide that information. */ // Build a list of the unselected nodes to which the snapper should snap - std::vector unselected_nodes; + std::vector > unselected_nodes; for (GList *spl = nodepath->subpaths; spl != NULL; spl = spl->next) { Inkscape::NodePath::SubPath *subpath = (Inkscape::NodePath::SubPath *) spl->data; for (GList *nl = subpath->nodes; nl != NULL; nl = nl->next) { Inkscape::NodePath::Node *node = (Inkscape::NodePath::Node *) nl->data; if (!node->selected) { - unselected_nodes.push_back(to_2geom(node->pos)); + unselected_nodes.push_back(std::make_pair(to_2geom(node->pos), node->type == Inkscape::NodePath::NODE_SMOOTH ? Inkscape::SNAPTARGET_NODE_SMOOTH : Inkscape::SNAPTARGET_NODE_CUSP)); } } } @@ -1388,12 +1388,13 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath, Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data; if (!closest_only || n == closest_node) { //try to snap either all selected nodes or only the closest one Inkscape::SnappedPoint s; + Inkscape::SnapSourceType source_type = (n->type == Inkscape::NodePath::NODE_SMOOTH ? Inkscape::SNAPSOURCE_NODE_SMOOTH : Inkscape::SNAPSOURCE_NODE_CUSP); if (constrained) { Inkscape::Snapper::ConstraintLine dedicated_constraint = constraint; dedicated_constraint.setPoint(n->pos); - s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(n->pos + delta), dedicated_constraint); + s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(n->pos + delta), source_type, dedicated_constraint); } else { - s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(n->pos + delta)); + s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(n->pos + delta), source_type); } if (s.getSnapped()) { @@ -3945,6 +3946,7 @@ static gboolean node_handle_request(SPKnot *knot, Geom::Point &p, guint state, g } Inkscape::NodePath::Node *othernode = opposite->other; + Inkscape::SnapSourceType source_type = (n->type == Inkscape::NodePath::NODE_SMOOTH ? Inkscape::SNAPSOURCE_NODE_SMOOTH : Inkscape::SNAPSOURCE_NODE_CUSP); if (othernode) { if ((n->type != Inkscape::NodePath::NODE_CUSP) && sp_node_side_is_line(n, opposite)) { /* We are smooth node adjacent with line */ @@ -3958,16 +3960,16 @@ static gboolean node_handle_request(SPKnot *knot, Geom::Point &p, guint state, g p = n->pos + (scal / linelen) * ndelta; } if ((state & GDK_SHIFT_MASK) == 0) { - s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::Snapper::ConstraintLine(p, ndelta)); + s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, source_type, Inkscape::Snapper::ConstraintLine(p, ndelta)); } } else { if ((state & GDK_SHIFT_MASK) == 0) { - s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); + s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, source_type); } } } else { if ((state & GDK_SHIFT_MASK) == 0) { - s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); + s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, source_type); } } diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 515008964..e2ca05408 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -47,7 +47,7 @@ Inkscape::ObjectSnapper::ObjectSnapper(SnapManager *sm, Geom::Coord const d) : Snapper(sm, d) { _candidates = new std::vector; - _points_to_snap_to = new std::vector; + _points_to_snap_to = new std::vector >; _paths_to_snap_to = new std::vector >; } @@ -196,7 +196,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType SPItem::APPROXIMATE_BBOX : SPItem::GEOMETRIC_BBOX; } - // Consider the page border for snapping + // Consider the page border for snapping to if (_snapmanager->snapprefs.getSnapToPageBorder()) { _getBorderNodes(_points_to_snap_to); } @@ -235,7 +235,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType _snapmanager->snapprefs.setSnapIntersectionCS(false); } - sp_item_snappoints(root_item, SnapPointsIter(*_points_to_snap_to), &_snapmanager->snapprefs); + sp_item_snappoints(root_item, true, *_points_to_snap_to, &_snapmanager->snapprefs); if (_snapmanager->snapprefs.getSnapToItemPath()) { _snapmanager->snapprefs.setSnapIntersectionCS(old_pref); @@ -248,7 +248,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType // of the item AND the bbox of the clipping path at the same time if (!(*i).clip_or_mask) { Geom::OptRect b = sp_item_bbox_desktop(root_item, bbox_type); - getBBoxPoints(b, _points_to_snap_to, _snapmanager->snapprefs.getSnapToBBoxNode(), _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints(), _snapmanager->snapprefs.getSnapBBoxMidpoints()); + getBBoxPoints(b, _points_to_snap_to, true, _snapmanager->snapprefs.getSnapToBBoxNode(), _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints(), _snapmanager->snapprefs.getSnapBBoxMidpoints()); } } } @@ -258,8 +258,9 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType void Inkscape::ObjectSnapper::_snapNodes(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &first_point, - std::vector *unselected_nodes) const + std::vector > *unselected_nodes) const { // Iterate through all nodes, find out which one is the closest to p, and snap to it! @@ -272,10 +273,10 @@ void Inkscape::ObjectSnapper::_snapNodes(SnappedConstraints &sc, SnappedPoint s; bool success = false; - for (std::vector::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) { - Geom::Coord dist = Geom::L2(*k - p); + for (std::vector >::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) { + Geom::Coord dist = Geom::L2((*k).first - p); if (dist < getSnapperTolerance() && dist < s.getSnapDistance()) { - s = SnappedPoint(*k, SNAPTARGET_NODE, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + s = SnappedPoint((*k).first, source_type, static_cast((*k).second), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); success = true; } } @@ -298,13 +299,13 @@ void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &s Geom::Coord tol = getSnapperTolerance(); - for (std::vector::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) { + for (std::vector >::const_iterator k = _points_to_snap_to->begin(); k != _points_to_snap_to->end(); k++) { // Project each node (*k) on the guide line (running through point p) - Geom::Point p_proj = project_on_linesegment(*k, p, p + Geom::rot90(guide_normal)); - Geom::Coord dist = Geom::L2(*k - p_proj); // distance from node to the guide + Geom::Point p_proj = project_on_linesegment((*k).first, p, p + Geom::rot90(guide_normal)); + Geom::Coord dist = Geom::L2((*k).first - p_proj); // distance from node to the guide Geom::Coord dist2 = Geom::L2(p - p_proj); // distance from projection of node on the guide, to the mouse location if ((dist < tol && dist2 < tol) || (getSnapperAlwaysSnap() && dist < s.getSnapDistance())) { - s = SnappedPoint(*k, SNAPTARGET_NODE, dist, tol, getSnapperAlwaysSnap(), true); + s = SnappedPoint((*k).first, SNAPSOURCE_GUIDE, static_cast((*k).second), dist, tol, getSnapperAlwaysSnap(), true); success = true; } } @@ -344,7 +345,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType if (_snapmanager->snapprefs.getSnapToPageBorder()) { Geom::PathVector *border_path = _getBorderPathv(); if (border_path != NULL) { - _paths_to_snap_to->push_back(std::make_pair(border_path, SNAPTARGET_PAGE_BORDER)); + _paths_to_snap_to->push_back(std::make_pair(border_path, SNAPTARGET_PAGE_BORDER)); } } @@ -392,7 +393,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType if (curve) { // We will get our own copy of the path, which must be freed at some point Geom::PathVector *borderpathv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), (*i).additional_affine); - _paths_to_snap_to->push_back(std::make_pair(borderpathv, SNAPTARGET_PATH)); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it. + _paths_to_snap_to->push_back(std::make_pair(borderpathv, SNAPTARGET_PATH)); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it. curve->unref(); } } @@ -409,7 +410,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType sp_item_invoke_bbox(root_item, rect, i2doc, TRUE, bbox_type); if (rect) { Geom::PathVector *path = _getPathvFromRect(*rect); - _paths_to_snap_to->push_back(std::make_pair(path, SNAPTARGET_BBOX_EDGE)); + _paths_to_snap_to->push_back(std::make_pair(path, SNAPTARGET_BBOX_EDGE)); } } } @@ -421,8 +422,9 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &first_point, - std::vector *unselected_nodes, + std::vector > *unselected_nodes, SPPath const *selected_path) const { _collectPaths(t, first_point); @@ -446,7 +448,7 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc, SPCurve *curve = curve_for_item(SP_ITEM(selected_path)); if (curve) { Geom::PathVector *pathv = pathvector_for_curve(SP_ITEM(selected_path), curve, true, true, Geom::identity(), Geom::identity()); // We will get our own copy of the path, which must be freed at some point - _paths_to_snap_to->push_back(std::make_pair(pathv, SNAPTARGET_PATH)); + _paths_to_snap_to->push_back(std::make_pair(pathv, SNAPTARGET_PATH)); curve->unref(); } } @@ -496,7 +498,7 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc, if (!being_edited || (c1 && c2)) { Geom::Coord const dist = Geom::distance(sp_doc, p_doc); if (dist < getSnapperTolerance()) { - sc.curves.push_back(Inkscape::SnappedCurve(sp_dt, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, curve, it_p->second)); + sc.curves.push_back(Inkscape::SnappedCurve(sp_dt, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, curve, source_type, it_p->second)); } } } @@ -505,7 +507,7 @@ void Inkscape::ObjectSnapper::_snapPaths(SnappedConstraints &sc, } /* Returns true if point is coincident with one of the unselected nodes */ -bool Inkscape::ObjectSnapper::isUnselectedNode(Geom::Point const &point, std::vector const *unselected_nodes) const +bool Inkscape::ObjectSnapper::isUnselectedNode(Geom::Point const &point, std::vector > const *unselected_nodes) const { if (unselected_nodes == NULL) { return false; @@ -515,8 +517,8 @@ bool Inkscape::ObjectSnapper::isUnselectedNode(Geom::Point const &point, std::ve return false; } - for (std::vector::const_iterator i = unselected_nodes->begin(); i != unselected_nodes->end(); i++) { - if (Geom::L2(point - *i) < 1e-4) { + for (std::vector >::const_iterator i = unselected_nodes->begin(); i != unselected_nodes->end(); i++) { + if (Geom::L2(point - (*i).first) < 1e-4) { return true; } } @@ -527,6 +529,7 @@ bool Inkscape::ObjectSnapper::isUnselectedNode(Geom::Point const &point, std::ve void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const source_type, bool const &first_point, ConstraintLine const &c) const { @@ -572,7 +575,7 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, // When it's within snapping range, then return it // (within snapping range == between p_min_on_cl and p_max_on_cl == 0 < ta < 1) Geom::Coord dist = Geom::L2(_snapmanager->getDesktop()->dt2doc(p_proj_on_cl) - p_inters); - SnappedPoint s(_snapmanager->getDesktop()->doc2dt(p_inters), k->second, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint s(_snapmanager->getDesktop()->doc2dt(p_inters), source_type, k->second, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); sc.points.push_back(s); } } @@ -585,10 +588,11 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &first_point, Geom::OptRect const &bbox_to_snap, std::vector const *it, - std::vector *unselected_nodes) const + std::vector > *unselected_nodes) const { if (_snap_enabled == false || _snapmanager->snapprefs.getSnapFrom(t) == false ) { return; @@ -605,7 +609,7 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, || _snapmanager->snapprefs.getSnapLineMidpoints() || _snapmanager->snapprefs.getSnapObjectMidpoints() || _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints() || _snapmanager->snapprefs.getIncludeItemCenter()) { - _snapNodes(sc, t, p, first_point, unselected_nodes); + _snapNodes(sc, t, p, source_type, first_point, unselected_nodes); } if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { @@ -622,9 +626,9 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, g_assert(it->size() == 1); path = SP_PATH(*it->begin()); } - _snapPaths(sc, t, p, first_point, unselected_nodes, path); + _snapPaths(sc, t, p, source_type, first_point, unselected_nodes, path); } else { - _snapPaths(sc, t, p, first_point, NULL, NULL); + _snapPaths(sc, t, p, source_type, first_point, NULL, NULL); } } } @@ -632,6 +636,7 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &first_point, Geom::OptRect const &bbox_to_snap, ConstraintLine const &c, @@ -648,7 +653,7 @@ void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, } // A constrained snap, is a snap in only one degree of freedom (specified by the constraint line). - // This is usefull for example when scaling an object while maintaining a fixed aspect ratio. It's + // This is useful for example when scaling an object while maintaining a fixed aspect ratio. It's // nodes are only allowed to move in one direction (i.e. in one degree of freedom). // When snapping to objects, we either snap to their nodes or their paths. It is however very @@ -657,7 +662,7 @@ void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, // so we will more or less snap to them anyhow. if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { - _snapPathsConstrained(sc, t, p, first_point, c); + _snapPathsConstrained(sc, t, p, source_type, first_point, c); } } @@ -743,31 +748,31 @@ Geom::PathVector* Inkscape::ObjectSnapper::_getPathvFromRect(Geom::Rect const re } } -void Inkscape::ObjectSnapper::_getBorderNodes(std::vector *points) const +void Inkscape::ObjectSnapper::_getBorderNodes(std::vector > *points) const { Geom::Coord w = sp_document_width(_snapmanager->getDocument()); Geom::Coord h = sp_document_height(_snapmanager->getDocument()); - points->push_back(Geom::Point(0,0)); - points->push_back(Geom::Point(0,h)); - points->push_back(Geom::Point(w,h)); - points->push_back(Geom::Point(w,0)); + points->push_back(std::make_pair(Geom::Point(0,0), SNAPTARGET_PAGE_CORNER)); + points->push_back(std::make_pair(Geom::Point(0,h), SNAPTARGET_PAGE_CORNER)); + points->push_back(std::make_pair(Geom::Point(w,h), SNAPTARGET_PAGE_CORNER)); + points->push_back(std::make_pair(Geom::Point(w,0), SNAPTARGET_PAGE_CORNER)); } -void Inkscape::getBBoxPoints(Geom::OptRect const bbox, std::vector *points, bool const includeCorners, bool const includeLineMidpoints, bool const includeObjectMidpoints) +void Inkscape::getBBoxPoints(Geom::OptRect const bbox, std::vector > *points, bool const isTarget, bool const includeCorners, bool const includeLineMidpoints, bool const includeObjectMidpoints) { if (bbox) { // collect the corners of the bounding box for ( unsigned k = 0 ; k < 4 ; k++ ) { if (includeCorners) { - points->push_back(bbox->corner(k)); + points->push_back(std::make_pair((bbox->corner(k)), isTarget ? int(Inkscape::SNAPTARGET_BBOX_CORNER) : int(Inkscape::SNAPSOURCE_BBOX_CORNER))); } // optionally, collect the midpoints of the bounding box's edges too if (includeLineMidpoints) { - points->push_back((bbox->corner(k) + bbox->corner((k+1) % 4))/2); + points->push_back(std::make_pair((bbox->corner(k) + bbox->corner((k+1) % 4))/2, isTarget ? int(Inkscape::SNAPTARGET_BBOX_EDGE_MIDPOINT) : int(Inkscape::SNAPSOURCE_BBOX_EDGE_MIDPOINT))); } } if (includeObjectMidpoints) { - points->push_back(bbox->midpoint()); + points->push_back(std::make_pair(bbox->midpoint(), isTarget ? int(Inkscape::SNAPTARGET_BBOX_MIDPOINT) : int(Inkscape::SNAPSOURCE_BBOX_MIDPOINT))); } } } diff --git a/src/object-snapper.h b/src/object-snapper.h index 9a6978d47..f220106e3 100644 --- a/src/object-snapper.h +++ b/src/object-snapper.h @@ -69,14 +69,16 @@ public: void freeSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &first_point, Geom::OptRect const &bbox_to_snap, std::vector const *it, - std::vector *unselected_nodes) const; + std::vector > *unselected_nodes) const; void constrainedSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, + SnapSourceType const &source_type, bool const &first_point, Geom::OptRect const &bbox_to_snap, ConstraintLine const &c, @@ -85,7 +87,7 @@ public: private: //store some lists of candidates, points and paths, so we don't have to rebuild them for each point we want to snap std::vector *_candidates; - std::vector *_points_to_snap_to; + std::vector > *_points_to_snap_to; std::vector > *_paths_to_snap_to; void _findCandidates(SPObject* parent, @@ -99,8 +101,9 @@ private: void _snapNodes(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, // in desktop coordinates + SnapSourceType const &source_type, bool const &first_point, - std::vector *unselected_nodes) const; // in desktop coordinates + std::vector > *unselected_nodes) const; // in desktop coordinates void _snapTranslatingGuideToNodes(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, @@ -113,17 +116,19 @@ private: void _snapPaths(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, // in desktop coordinates + SnapSourceType const &source_type, bool const &first_point, - std::vector *unselected_nodes, // in desktop coordinates + std::vector > *unselected_nodes, // in desktop coordinates SPPath const *selected_path) const; void _snapPathsConstrained(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, Geom::Point const &p, // in desktop coordinates - bool const &first_point, + SnapSourceType const source_type, + bool const &first_point, ConstraintLine const &c) const; - bool isUnselectedNode(Geom::Point const &point, std::vector const *unselected_nodes) const; + bool isUnselectedNode(Geom::Point const &point, std::vector > const *unselected_nodes) const; void _collectPaths(Inkscape::SnapPreferences::PointType const &t, bool const &first_point) const; @@ -131,11 +136,11 @@ private: void _clear_paths() const; Geom::PathVector* _getBorderPathv() const; Geom::PathVector* _getPathvFromRect(Geom::Rect const rect) const; - void _getBorderNodes(std::vector *points) const; + void _getBorderNodes(std::vector > *points) const; }; // end of ObjectSnapper class -void getBBoxPoints(Geom::OptRect const bbox, std::vector *points, bool const includeCorners, bool const includeLineMidpoints, bool const includeObjectMidpoints); +void getBBoxPoints(Geom::OptRect const bbox, std::vector > *points, bool const isTarget, bool const includeCorners, bool const includeLineMidpoints, bool const includeObjectMidpoints); } // end of namespace Inkscape diff --git a/src/pen-context.cpp b/src/pen-context.cpp index 804c736be..7ff3de9e1 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -477,7 +477,7 @@ static gint pen_handle_button_press(SPPenContext *const pc, GdkEventButton const if (!(bevent.state & GDK_SHIFT_MASK)) { SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE); } spdc_create_single_dot(event_context, p, "/tools/freehand/pen", bevent.state); ret = TRUE; diff --git a/src/pencil-context.cpp b/src/pencil-context.cpp index de286ea5a..3e3a95c24 100644 --- a/src/pencil-context.cpp +++ b/src/pencil-context.cpp @@ -259,7 +259,7 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve if (bevent.state & GDK_CONTROL_MASK) { if (!(bevent.state & GDK_SHIFT_MASK)) { - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE); } spdc_create_single_dot(event_context, p, "/tools/freehand/pencil", bevent.state); sp_canvas_set_snap_delay_active(desktop->canvas, false); @@ -277,10 +277,10 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve // anchor, which is handled by the sibling branch above) selection->clear(); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new path")); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE); } else if (selection->singleItem() && SP_IS_PATH(selection->singleItem())) { desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Appending to selected path")); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE); } } pc->sa = anchor; diff --git a/src/rect-context.cpp b/src/rect-context.cpp index c63e1dc2a..3650e05b1 100644 --- a/src/rect-context.cpp +++ b/src/rect-context.cpp @@ -266,7 +266,7 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent /* Snap center */ SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, button_dt); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, button_dt, Inkscape::SNAPSOURCE_HANDLE); rc->center = from_2geom(button_dt); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), diff --git a/src/satisfied-guide-cns.cpp b/src/satisfied-guide-cns.cpp index 3ffebeb06..505e18675 100644 --- a/src/satisfied-guide-cns.cpp +++ b/src/satisfied-guide-cns.cpp @@ -6,14 +6,14 @@ #include void satisfied_guide_cns(SPDesktop const &desktop, - std::vector const &snappoints, + SnapPointsWithType const &snappoints, std::vector &cns) { SPNamedView const &nv = *sp_desktop_namedview(&desktop); for (GSList const *l = nv.guides; l != NULL; l = l->next) { SPGuide &g = *SP_GUIDE(l->data); for (unsigned int i = 0; i < snappoints.size(); ++i) { - if (approx_equal( sp_guide_distance_from_pt(&g, snappoints[i]), 0) ) { + if (approx_equal( sp_guide_distance_from_pt(&g, snappoints[i].first), 0) ) { cns.push_back(SPGuideConstraint(&g, i)); } } diff --git a/src/satisfied-guide-cns.h b/src/satisfied-guide-cns.h index 1952bef44..99229f64c 100644 --- a/src/satisfied-guide-cns.h +++ b/src/satisfied-guide-cns.h @@ -4,10 +4,12 @@ #include #include <2geom/forward.h> #include +#include + class SPGuideConstraint; void satisfied_guide_cns(SPDesktop const &desktop, - std::vector const &snappoints, + SnapPointsWithType const &snappoints, std::vector &cns); diff --git a/src/selection.cpp b/src/selection.cpp index ea1c0053f..4d92a18df 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -441,48 +441,48 @@ boost::optional Selection::center() const { /** * Compute the list of points in the selection that are to be considered for snapping. */ -std::vector Selection::getSnapPoints(SnapPreferences const *snapprefs) const { +std::vector > Selection::getSnapPoints(SnapPreferences const *snapprefs) const { GSList const *items = const_cast(this)->itemList(); - + SnapPreferences snapprefs_dummy = *snapprefs; // create a local copy of the snapping prefs snapprefs_dummy.setIncludeItemCenter(false); // locally disable snapping to the item center - - std::vector p; + + std::vector > p; for (GSList const *iter = items; iter != NULL; iter = iter->next) { SPItem *this_item = SP_ITEM(iter->data); - sp_item_snappoints(this_item, SnapPointsIter(p), &snapprefs_dummy); - + sp_item_snappoints(this_item, false, p, &snapprefs_dummy); + //Include the transformation origin for snapping //For a selection or group only the overall origin is considered if (snapprefs != NULL && snapprefs->getIncludeItemCenter()) { - p.push_back(this_item->getCenter()); - } + p.push_back(std::make_pair(this_item->getCenter(), SNAPSOURCE_ROTATION_CENTER)); + } } return p; } -std::vector Selection::getSnapPointsConvexHull(SnapPreferences const *snapprefs) const { +std::vector > Selection::getSnapPointsConvexHull(SnapPreferences const *snapprefs) const { GSList const *items = const_cast(this)->itemList(); - std::vector p; + std::vector > p; for (GSList const *iter = items; iter != NULL; iter = iter->next) { - sp_item_snappoints(SP_ITEM(iter->data), SnapPointsIter(p), snapprefs); + sp_item_snappoints(SP_ITEM(iter->data), false, p, snapprefs); } - std::vector pHull; + std::vector > pHull; if (!p.empty()) { - std::vector::iterator i; - Geom::RectHull cvh(p.front()); + std::vector >::iterator i; + Geom::RectHull cvh((p.front()).first); for (i = p.begin(); i != p.end(); i++) { // these are the points we get back - cvh.add(*i); + cvh.add((*i).first); } Geom::OptRect rHull = cvh.bounds(); if (rHull) { for ( unsigned i = 0 ; i < 4 ; ++i ) { - pHull.push_back(rHull->corner(i)); + pHull.push_back(std::make_pair(rHull->corner(i), SNAPSOURCE_CONVEX_HULL_CORNER)); } } } diff --git a/src/selection.h b/src/selection.h index f3ab8e1c1..ecb1ef45e 100644 --- a/src/selection.h +++ b/src/selection.h @@ -30,6 +30,7 @@ #include "gc-soft-ptr.h" #include "util/list.h" #include "sp-item.h" +#include "snapped-point.h" class SPItem; class SPBox3D; @@ -57,7 +58,7 @@ namespace Inkscape { * at the given desktop. Both SPItem and SPRepr lists can be retrieved * from the selection. Many actions operate on the selection, so it is * widely used throughout the code. - * It also implements its own asynchronous notification signals that + * It also implements its own asynchronous notification signals that * UI elements can listen to. */ class Selection : public Inkscape::GC::Managed<>, @@ -249,7 +250,7 @@ public: * @brief Returns the bounding rectangle of the selection * * \todo how is this different from bounds()? - */ + */ NRRect *boundsInDocument(NRRect *dest, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) const; /** @@ -268,13 +269,13 @@ public: * @brief Gets the selection's snap points. * @return Selection's snap points */ - std::vector getSnapPoints(SnapPreferences const *snapprefs) const; + std::vector > getSnapPoints(SnapPreferences const *snapprefs) const; /** * @brief Gets the snap points of a selection that form a convex hull. * @return Selection's convex hull points */ - std::vector getSnapPointsConvexHull(SnapPreferences const *snapprefs) const; + std::vector > getSnapPointsConvexHull(SnapPreferences const *snapprefs) const; /** * @brief Connects a slot to be notified of selection changes @@ -291,8 +292,8 @@ public: } /** - * @brief Connects a slot to be notified of selected - * object modifications + * @brief Connects a slot to be notified of selected + * object modifications * * This method connects the given slot such that it will * receive notifications whenever any selected item is diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 4614adb87..f3ad2849c 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -291,7 +291,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s // but as a snap source we still need some nodes though! _snap_points.clear(); _snap_points = selection->getSnapPoints(&local_snapprefs); - std::vector snap_points_hull = selection->getSnapPointsConvexHull(&local_snapprefs); + std::vector > snap_points_hull = selection->getSnapPointsConvexHull(&local_snapprefs); if (_snap_points.size() > 100) { /* Snapping a huge number of nodes will take way too long, so limit the number of snappable nodes An average user would rarely ever try to snap such a large number of nodes anyway, because @@ -305,11 +305,11 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s // any other special points Geom::Rect snap_points_bbox; if ( snap_points_hull.empty() == false ) { - std::vector::iterator i = snap_points_hull.begin(); - snap_points_bbox = Geom::Rect(*i, *i); + std::vector >::iterator i = snap_points_hull.begin(); + snap_points_bbox = Geom::Rect((*i).first, (*i).first); i++; while (i != snap_points_hull.end()) { - snap_points_bbox.expandTo(*i); + snap_points_bbox.expandTo((*i).first); i++; } } @@ -317,7 +317,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s _bbox_points.clear(); if (_bbox) { if (m.snapprefs.getSnapModeBBox()) { - getBBoxPoints(_bbox, &_bbox_points, true, m.snapprefs.getSnapBBoxEdgeMidpoints(), m.snapprefs.getSnapBBoxMidpoints()); + getBBoxPoints(_bbox, &_bbox_points, false, true, m.snapprefs.getSnapBBoxEdgeMidpoints(), m.snapprefs.getSnapBBoxMidpoints()); } // There are two separate "opposites" (i.e. opposite w.r.t. the handle being dragged): // - one for snapping the boundingbox, which can be either visual or geometric @@ -350,7 +350,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s g_assert(_bbox_points.size() < 2 && _snap_points.size() < 2); if (_snap_points.size() == 1 && _bbox_points.size() == 1) { //both vectors can only have either one or zero elements // So we have exactly one bbox corner and one node left; now find out which is closest and delete the other one - if (Geom::L2(_snap_points.at(0) - p) < Geom::L2(_bbox_points.at(0) - p)) { + if (Geom::L2((_snap_points.at(0)).first - p) < Geom::L2((_bbox_points.at(0)).first - p)) { _bbox_points.clear(); } else { _snap_points.clear(); @@ -370,20 +370,6 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s sp_canvas_set_snap_delay_active(_desktop->canvas, true); - // The lines below are useful for debugging any snapping issues, as they'll spit out all points that are considered for snapping - - /*std::cout << "Number of snap points: " << _snap_points.size() << std::endl; - for (std::vector::const_iterator i = _snap_points.begin(); i != _snap_points.end(); i++) - { - std::cout << " " << *i << std::endl; - } - - std::cout << "Number of bbox points: " << _bbox_points.size() << std::endl; - for (std::vector::const_iterator i = _bbox_points.begin(); i != _bbox_points.end(); i++) - { - std::cout << " " << *i << std::endl; - }*/ - if ((x != -1) && (y != -1)) { sp_canvas_item_show(_norm); sp_canvas_item_show(_grip); @@ -1295,11 +1281,12 @@ gboolean Inkscape::SelTrans::rotateRequest(Geom::Point &pt, guint state) return TRUE; } +// Move the item's transformation center gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state) { SnapManager &m = _desktop->namedview->snap_manager; m.setup(_desktop); - m.freeSnapReturnByRef(SnapPreferences::SNAPPOINT_NODE, pt); + m.freeSnapReturnByRef(SnapPreferences::SNAPPOINT_NODE, pt, Inkscape::SNAPSOURCE_HANDLE); if (state & GDK_CONTROL_MASK) { if ( fabs(_point[Geom::X] - pt[Geom::X]) > fabs(_point[Geom::Y] - pt[Geom::Y]) ) { @@ -1407,7 +1394,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) */ m.setup(_desktop, true, _items_const); - m.freeSnapReturnByRef(SnapPreferences::SNAPPOINT_NODE, dxy); + m.freeSnapReturnByRef(SnapPreferences::SNAPPOINT_NODE, dxy, Inkscape::SNAPSOURCE_UNDEFINED); } else if (!shift) { @@ -1593,15 +1580,15 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale) return visual_bbox.min() + visual_bbox.dimensions() * Geom::Scale(_handle_x, _handle_y); } -void Inkscape::SelTrans::_keepClosestPointOnly(std::vector &points, const Geom::Point &reference) +void Inkscape::SelTrans::_keepClosestPointOnly(std::vector > &points, const Geom::Point &reference) { if (points.size() < 2) return; - Geom::Point closest_point = Geom::Point(NR_HUGE, NR_HUGE); + std::pair closest_point = std::make_pair(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED); Geom::Coord closest_dist = NR_HUGE; - for(std::vector::const_iterator i = points.begin(); i != points.end(); i++) { - Geom::Coord dist = Geom::L2(*i - reference); + for(std::vector >::const_iterator i = points.begin(); i != points.end(); i++) { + Geom::Coord dist = Geom::L2((*i).first - reference); if (i == points.begin() || dist < closest_dist) { closest_point = *i; closest_dist = dist; diff --git a/src/seltrans.h b/src/seltrans.h index 42effff7c..4f47d8e20 100644 --- a/src/seltrans.h +++ b/src/seltrans.h @@ -86,7 +86,7 @@ public: return _empty; } bool isGrabbed() { - return _grabbed; + return _grabbed; } bool centerIsVisible() { return ( _chandle && SP_KNOT_IS_VISIBLE (_chandle) ); @@ -102,24 +102,24 @@ private: Geom::Point _getGeomHandlePos(Geom::Point const &visual_handle_pos); Geom::Point _calcAbsAffineDefault(Geom::Scale const default_scale); Geom::Point _calcAbsAffineGeom(Geom::Scale const geom_scale); - void _keepClosestPointOnly(std::vector &points, const Geom::Point &reference); + void _keepClosestPointOnly(std::vector > &points, const Geom::Point &reference); void _display_snapsource(); enum State { STATE_SCALE, //scale or stretch STATE_ROTATE //rotate or skew }; - + SPDesktop *_desktop; std::vector _items; std::vector _items_const; std::vector _items_affines; std::vector _items_centers; - - std::vector _snap_points; - std::vector _bbox_points; - + + std::vector > _snap_points; + std::vector > _bbox_points; + Inkscape::SelCue _selcue; Inkscape::Selection *_selection; @@ -132,12 +132,12 @@ private: bool _changed; SPItem::BBoxType _snap_bbox_type; - + Geom::OptRect _bbox; Geom::OptRect _approximate_bbox; Geom::OptRect _geometric_bbox; gdouble _strokewidth; - + Geom::Matrix _current_relative_affine; Geom::Matrix _absolute_affine; Geom::Matrix _relative_affine; @@ -146,8 +146,8 @@ private: * lines into straight lines and parallel lines into parallel lines but may alter distance between points * and angles between lines */ - - Geom::Point _opposite; ///< opposite point to where a scale is taking place + + Geom::Point _opposite; ///< opposite point to where a scale is taking place Geom::Point _opposite_for_specpoints; Geom::Point _opposite_for_bboxpoints; Geom::Point _origin_for_specpoints; diff --git a/src/snap.cpp b/src/snap.cpp index 548741455..a170046c2 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -137,14 +137,16 @@ bool SnapManager::gridSnapperMightSnap() const */ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, - Geom::Point &p, - bool first_point, + Geom::Point &p, + Inkscape::SnapSourceType const source_type, + bool first_point, Geom::OptRect const &bbox_to_snap) const { - Inkscape::SnappedPoint const s = freeSnap(point_type, p, first_point, bbox_to_snap); + Inkscape::SnappedPoint const s = freeSnap(point_type, p, source_type, first_point, bbox_to_snap); s.getPoint(p); } + /** * Try to snap a point to any of the specified snappers. * @@ -157,8 +159,9 @@ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point */ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - bool first_point, + Geom::Point const &p, + Inkscape::SnapSourceType const &source_type, + bool first_point, Geom::OptRect const &bbox_to_snap) const { if (_desktop->canvas->context_snap_delay_active == false) { @@ -167,7 +170,7 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp } if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(p, source_type, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } std::vector *items_to_ignore; @@ -184,14 +187,14 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, point_type, p, first_point, bbox_to_snap, items_to_ignore, _unselected_nodes); + (*i)->freeSnap(sc, point_type, p, source_type, first_point, bbox_to_snap, items_to_ignore, _unselected_nodes); } if (_item_to_ignore) { delete items_to_ignore; } - return findBestSnap(p, sc, false); + return findBestSnap(p, source_type, sc, false); } // When pasting, we would like to snap to the grid. Problem is that we don't know which nodes were @@ -199,7 +202,7 @@ Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointTyp // unaligned node to the grid, previously aligned nodes would become unaligned. That's undesirable. // Instead we will make sure that the offset between the source and the copy is a multiple of the grid // pitch. If the source was aligned, then the copy will therefore also be aligned -// PS: Wether we really find a multiple also depends on the snapping range! +// PS: Whether we really find a multiple also depends on the snapping range! Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const { if (!snapprefs.getSnapEnabledGlobally()) // No need to check for snapprefs.getSnapPostponedGlobally() here @@ -229,9 +232,9 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const Geom::Point const t_offset = t + grid->origin; SnappedConstraints sc; // Only the first three parameters are being used for grid snappers - snapper->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_NODE, t_offset, TRUE, Geom::OptRect(), NULL, NULL); + snapper->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_NODE, t_offset, Inkscape::SNAPSOURCE_UNDEFINED, TRUE, Geom::OptRect(), NULL, NULL); // Find the best snap for this grid, including intersections of the grid-lines - Inkscape::SnappedPoint s = findBestSnap(t_offset, sc, false); + Inkscape::SnappedPoint s = findBestSnap(t_offset, Inkscape::SNAPSOURCE_UNDEFINED, sc, false); if (s.getSnapped() && (s.getSnapDistance() < nearest_distance)) { // use getSnapDistance() instead of getWeightedDistance() here because the pointer's position // doesn't tell us anything about which node to snap @@ -262,15 +265,17 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const */ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, - Geom::Point &p, + Geom::Point &p, + Inkscape::SnapSourceType const source_type, Inkscape::Snapper::ConstraintLine const &constraint, bool first_point, Geom::OptRect const &bbox_to_snap) const { - Inkscape::SnappedPoint const s = constrainedSnap(point_type, p, constraint, first_point, bbox_to_snap); + Inkscape::SnappedPoint const s = constrainedSnap(point_type, p, source_type, constraint, first_point, bbox_to_snap); s.getPoint(p); } + /** * Try to snap a point to any interested snappers. A snap will only occur along * a line described by a Inkscape::Snapper::ConstraintLine. @@ -284,7 +289,8 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp */ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, + Geom::Point const &p, + Inkscape::SnapSourceType const &source_type, Inkscape::Snapper::ConstraintLine const &constraint, bool first_point, Geom::OptRect const &bbox_to_snap) const @@ -295,7 +301,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P } if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(p, source_type, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } std::vector *items_to_ignore; @@ -311,14 +317,14 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P SnappedConstraints sc; SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, point_type, p, first_point, bbox_to_snap, constraint, items_to_ignore); + (*i)->constrainedSnap(sc, point_type, p, source_type, first_point, bbox_to_snap, constraint, items_to_ignore); } if (_item_to_ignore) { delete items_to_ignore; } - return findBestSnap(p, sc, true); + return findBestSnap(p, source_type, sc, true); } void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) const @@ -337,7 +343,7 @@ void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) con SnappedConstraints sc; object.guideSnap(sc, p, guide_normal); - Inkscape::SnappedPoint const s = findBestSnap(p, sc, false); + Inkscape::SnappedPoint const s = findBestSnap(p, Inkscape::SNAPSOURCE_GUIDE, sc, false); s.getPoint(p); } @@ -361,7 +367,7 @@ void SnapManager::guideSnap(Geom::Point &p, Geom::Point const &guide_normal) con Inkscape::SnappedPoint SnapManager::_snapTransformed( Inkscape::SnapPreferences::PointType type, - std::vector const &points, + std::vector > const &points, Geom::Point const &pointer, bool constrained, Inkscape::Snapper::ConstraintLine const &constraint, @@ -383,10 +389,10 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( return Inkscape::SnappedPoint(); } - std::vector transformed_points; + std::vector > transformed_points; Geom::Rect bbox; - for (std::vector::const_iterator i = points.begin(); i != points.end(); i++) { + for (std::vector >::const_iterator i = points.begin(); i != points.end(); i++) { /* Work out the transformed version of this point */ Geom::Point transformed = _transformPoint(*i, transformation_type, transformation, origin, dim, uniform); @@ -398,7 +404,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( bbox.expandTo(transformed); } - transformed_points.push_back(transformed); + transformed_points.push_back(std::make_pair(transformed, (*i).second)); } /* The current best transformation */ @@ -412,15 +418,15 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( g_assert(best_snapped_point.getAlwaysSnap() == false); // Check initialization of snapped point g_assert(best_snapped_point.getAtIntersection() == false); - std::vector::const_iterator j = transformed_points.begin(); + std::vector >::const_iterator j = transformed_points.begin(); // std::cout << std::endl; - for (std::vector::const_iterator i = points.begin(); i != points.end(); i++) { + for (std::vector >::const_iterator i = points.begin(); i != points.end(); i++) { /* Snap it */ Inkscape::SnappedPoint snapped_point; Inkscape::Snapper::ConstraintLine dedicated_constraint = constraint; - Geom::Point const b = (*i - origin); // vector to original point + Geom::Point const b = ((*i).first - origin); // vector to original point if (constrained) { if ((transformation_type == SCALE || transformation_type == STRETCH) && uniform) { @@ -429,18 +435,18 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // calculate that line here dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, b); } else if (transformation_type == STRETCH) { // when non-uniform stretching { - dedicated_constraint = Inkscape::Snapper::ConstraintLine((*i), component_vectors[dim]); + dedicated_constraint = Inkscape::Snapper::ConstraintLine((*i).first, component_vectors[dim]); } else if (transformation_type == TRANSLATION) { // When doing a constrained translation, all points will move in the same direction, i.e. // either horizontally or vertically. The lines along which they move are therefore all // parallel, but might not be colinear. Therefore we will have to set the point through // which the constraint-line runs here, for each point individually. - dedicated_constraint.setPoint(*i); + dedicated_constraint.setPoint((*i).first); } // else: leave the original constraint, e.g. for skewing if (transformation_type == SCALE && !uniform) { g_warning("Non-uniform constrained scaling is not supported!"); } - snapped_point = constrainedSnap(type, *j, dedicated_constraint, i == points.begin(), bbox); + snapped_point = constrainedSnap(type, (*j).first, static_cast((*j).second), dedicated_constraint, i == points.begin(), bbox); } else { bool const c1 = fabs(b[Geom::X]) < 1e-6; bool const c2 = fabs(b[Geom::Y]) < 1e-6; @@ -449,13 +455,13 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // move in that specific direction; therefore it should only snap in that direction, otherwise // we will get snapped points with an invalid transformation dedicated_constraint = Inkscape::Snapper::ConstraintLine(origin, component_vectors[c1]); - snapped_point = constrainedSnap(type, *j, dedicated_constraint, i == points.begin(), bbox); + snapped_point = constrainedSnap(type, (*j).first, static_cast((*j).second), dedicated_constraint, i == points.begin(), bbox); } else { - snapped_point = freeSnap(type, *j, i == points.begin(), bbox); + snapped_point = freeSnap(type, (*j).first, static_cast((*j).second), i == points.begin(), bbox); } } // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl; - snapped_point.setPointerDistance(Geom::L2(pointer - *i)); + snapped_point.setPointerDistance(Geom::L2(pointer - (*i).first)); Geom::Point result; Geom::Point scale_metric(NR_HUGE, NR_HUGE); @@ -469,7 +475,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( switch (transformation_type) { case TRANSLATION: - result = snapped_point.getPoint() - *i; + result = snapped_point.getPoint() - (*i).first; /* Consider the case in which a box is almost aligned with a grid in both * horizontal and vertical directions. The distance to the intersection of * the grid lines will always be larger then the distance to a single grid @@ -519,7 +525,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( snapped_point.setSecondSnapDistance(NR_HUGE); break; case SKEW: - result[0] = (snapped_point.getPoint()[dim] - (*i)[dim]) / ((*i)[1 - dim] - origin[1 - dim]); // skew factor + result[0] = (snapped_point.getPoint()[dim] - ((*i).first)[dim]) / (((*i).first)[1 - dim] - origin[1 - dim]); // skew factor result[1] = transformation[1]; // scale factor // Store the metric for this transformation as a virtual distance snapped_point.setSnapDistance(std::abs(result[0] - transformation[0])); @@ -600,12 +606,12 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( */ Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Geom::Point const &tr) const { if (p.size() == 1) { - _displaySnapsource(point_type, _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false)); + _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false), (p.at(0)).second)); } return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); @@ -625,13 +631,13 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslation(Inkscape::SnapPreference */ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Inkscape::Snapper::ConstraintLine const &constraint, Geom::Point const &tr) const { if (p.size() == 1) { - _displaySnapsource(point_type, _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false)); + _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false), (p.at(0)).second)); } return _snapTransformed(point_type, p, pointer, true, constraint, TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); @@ -650,13 +656,13 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslation(Inkscape::SnapPre */ Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Geom::Scale const &s, Geom::Point const &o) const { if (p.size() == 1) { - _displaySnapsource(point_type, _transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false)); + _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false), (p.at(0)).second)); } return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); @@ -676,14 +682,14 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(Inkscape::SnapPreferences::Poi */ Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Geom::Scale const &s, Geom::Point const &o) const { // When constrained scaling, only uniform scaling is supported. if (p.size() == 1) { - _displaySnapsource(point_type, _transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true)); + _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true), (p.at(0)).second)); } return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); @@ -704,7 +710,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapScale(Inkscape::SnapPreferenc */ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Geom::Coord const &s, Geom::Point const &o, @@ -712,7 +718,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPrefere bool u) const { if (p.size() == 1) { - _displaySnapsource(point_type, _transformPoint(p.at(0), STRETCH, Geom::Point(s, s), o, d, u)); + _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), STRETCH, Geom::Point(s, s), o, d, u), (p.at(0)).second)); } return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), STRETCH, Geom::Point(s, s), o, d, u); @@ -732,7 +738,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPrefere */ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Inkscape::Snapper::ConstraintLine const &constraint, Geom::Point const &s, @@ -749,13 +755,13 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference g_assert(!(point_type & Inkscape::SnapPreferences::SNAPPOINT_BBOX)); if (p.size() == 1) { - _displaySnapsource(point_type, _transformPoint(p.at(0), SKEW, s, o, d, false)); + _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), SKEW, s, o, d, false), (p.at(0)).second)); } return _snapTransformed(point_type, p, pointer, true, constraint, SKEW, s, o, d, false); } -Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, SnappedConstraints &sc, bool constrained) const +Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, Inkscape::SnapSourceType const source_type, SnappedConstraints &sc, bool constrained) const { /* @@ -786,7 +792,8 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, SnappedCo // search for the closest snapped intersection of curves Inkscape::SnappedPoint closestCurvesIntersection; if (getClosestIntersectionCS(sc.curves, p, closestCurvesIntersection, _desktop->dt2doc())) { - sp_list.push_back(closestCurvesIntersection); + closestCurvesIntersection.setSource(source_type); + sp_list.push_back(closestCurvesIntersection); } } @@ -814,14 +821,16 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, SnappedCo // search for the closest snapped intersection of grid lines Inkscape::SnappedPoint closestGridPoint; if (getClosestIntersectionSL(sc.grid_lines, closestGridPoint)) { - closestGridPoint.setTarget(Inkscape::SNAPTARGET_GRID_INTERSECTION); + closestGridPoint.setSource(source_type); + closestGridPoint.setTarget(Inkscape::SNAPTARGET_GRID_INTERSECTION); sp_list.push_back(closestGridPoint); } // search for the closest snapped intersection of guide lines Inkscape::SnappedPoint closestGuidePoint; if (getClosestIntersectionSL(sc.guide_lines, closestGuidePoint)) { - closestGuidePoint.setTarget(Inkscape::SNAPTARGET_GUIDE_INTERSECTION); + closestGuidePoint.setSource(source_type); + closestGuidePoint.setTarget(Inkscape::SNAPTARGET_GUIDE_INTERSECTION); sp_list.push_back(closestGuidePoint); } @@ -829,14 +838,15 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, SnappedCo if (snapprefs.getSnapIntersectionGG()) { Inkscape::SnappedPoint closestGridGuidePoint; if (getClosestIntersectionSL(sc.grid_lines, sc.guide_lines, closestGridGuidePoint)) { - closestGridGuidePoint.setTarget(Inkscape::SNAPTARGET_GRID_GUIDE_INTERSECTION); + closestGridGuidePoint.setSource(source_type); + closestGridGuidePoint.setTarget(Inkscape::SNAPTARGET_GRID_GUIDE_INTERSECTION); sp_list.push_back(closestGridGuidePoint); } } } // now let's see which snapped point gets a thumbs up - Inkscape::SnappedPoint bestSnappedPoint = Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + Inkscape::SnappedPoint bestSnappedPoint = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); // std::cout << "Finding the best snap..." << std::endl; for (std::list::const_iterator i = sp_list.begin(); i != sp_list.end(); i++) { // first find out if this snapped point is within snapping range @@ -864,7 +874,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, SnappedCo return bestSnappedPoint; } -void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem const *item_to_ignore, std::vector *unselected_nodes) +void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem const *item_to_ignore, std::vector > *unselected_nodes) { g_assert(desktop != NULL); _item_to_ignore = item_to_ignore; @@ -874,7 +884,7 @@ void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem con _unselected_nodes = unselected_nodes; } -void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, std::vector *unselected_nodes) +void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, std::vector > *unselected_nodes) { g_assert(desktop != NULL); _item_to_ignore = NULL; @@ -889,7 +899,7 @@ SPDocument *SnapManager::getDocument() const return _named_view->document; } -Geom::Point SnapManager::_transformPoint(Geom::Point const &p, +Geom::Point SnapManager::_transformPoint(std::pair const &p, Transformation const transformation_type, Geom::Point const &transformation, Geom::Point const &origin, @@ -900,10 +910,10 @@ Geom::Point SnapManager::_transformPoint(Geom::Point const &p, Geom::Point transformed; switch (transformation_type) { case TRANSLATION: - transformed = p + transformation; + transformed = p.first + transformation; break; case SCALE: - transformed = (p - origin) * Geom::Scale(transformation[Geom::X], transformation[Geom::Y]) + origin; + transformed = (p.first - origin) * Geom::Scale(transformation[Geom::X], transformation[Geom::Y]) + origin; break; case STRETCH: { @@ -914,15 +924,15 @@ Geom::Point SnapManager::_transformPoint(Geom::Point const &p, s[dim] = transformation[dim]; s[1 - dim] = 1; } - transformed = ((p - origin) * s) + origin; + transformed = ((p.first - origin) * s) + origin; break; } case SKEW: // Apply the skew factor - transformed[dim] = p[dim] + transformation[0] * (p[1 - dim] - origin[1 - dim]); + transformed[dim] = (p.first)[dim] + transformation[0] * ((p.first)[1 - dim] - origin[1 - dim]); // While skewing, mirroring and scaling (by integer multiples) in the opposite direction is also allowed. // Apply that scale factor here - transformed[1-dim] = (p - origin)[1 - dim] * transformation[1] + origin[1 - dim]; + transformed[1-dim] = (p.first - origin)[1 - dim] * transformation[1] + origin[1 - dim]; break; default: g_assert_not_reached(); @@ -931,7 +941,7 @@ Geom::Point SnapManager::_transformPoint(Geom::Point const &p, return transformed; } -void SnapManager::_displaySnapsource(Inkscape::SnapPreferences::PointType point_type, Geom::Point const &p) const { +void SnapManager::_displaySnapsource(Inkscape::SnapPreferences::PointType point_type, std::pair const &p) const { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/options/snapclosestonly/value")) { diff --git a/src/snap.h b/src/snap.h index b86ceb8b0..b6ec3a5d7 100644 --- a/src/snap.h +++ b/src/snap.h @@ -56,64 +56,69 @@ public: bool someSnapperMightSnap() const; bool gridSnapperMightSnap() const; - void setup(SPDesktop const *desktop, bool snapindicator = true, SPItem const *item_to_ignore = NULL, std::vector *unselected_nodes = NULL); - void setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, std::vector *unselected_nodes = NULL); + void setup(SPDesktop const *desktop, bool snapindicator = true, SPItem const *item_to_ignore = NULL, std::vector > *unselected_nodes = NULL); + void setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, std::vector > *unselected_nodes = NULL); // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a - // point if snapping has occured (by overwriting p); otherwise p is untouched + // point if snapping has occurred (by overwriting p); otherwise p is untouched void freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, - Geom::Point &p, - bool first_point = true, - Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; + Geom::Point &p, + Inkscape::SnapSourceType const source_type, + bool first_point = true, + Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; + Inkscape::SnappedPoint freeSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - bool first_point = true, + Geom::Point const &p, + Inkscape::SnapSourceType const &source_type, + bool first_point = true, Geom::OptRect const &bbox_to_snap = Geom::OptRect() ) const; Geom::Point multipleOfGridPitch(Geom::Point const &t) const; // constrainedSnapReturnByRef() is preferred over constrainedSnap(), because it only returns a - // point, by overwriting p, if snapping has occured; otherwise p is untouched + // point, by overwriting p, if snapping has occurred; otherwise p is untouched void constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, - Geom::Point &p, - Inkscape::Snapper::ConstraintLine const &constraint, - bool first_point = true, - Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; + Geom::Point &p, + Inkscape::SnapSourceType const source_type, + Inkscape::Snapper::ConstraintLine const &constraint, + bool first_point = true, + Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; Inkscape::SnappedPoint constrainedSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::Snapper::ConstraintLine const &constraint, + Geom::Point const &p, + Inkscape::SnapSourceType const &source_type, + Inkscape::Snapper::ConstraintLine const &constraint, bool first_point = true, Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; void guideSnap(Geom::Point &p, Geom::Point const &guide_normal) const; Inkscape::SnappedPoint freeSnapTranslation(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Geom::Point const &tr) const; Inkscape::SnappedPoint constrainedSnapTranslation(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Inkscape::Snapper::ConstraintLine const &constraint, Geom::Point const &tr) const; Inkscape::SnappedPoint freeSnapScale(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Geom::Scale const &s, Geom::Point const &o) const; Inkscape::SnappedPoint constrainedSnapScale(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Geom::Scale const &s, Geom::Point const &o) const; Inkscape::SnappedPoint constrainedSnapStretch(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Geom::Coord const &s, Geom::Point const &o, @@ -121,7 +126,7 @@ public: bool uniform) const; Inkscape::SnappedPoint constrainedSnapSkew(Inkscape::SnapPreferences::PointType point_type, - std::vector const &p, + std::vector > const &p, Geom::Point const &pointer, Inkscape::Snapper::ConstraintLine const &constraint, Geom::Point const &s, // s[0] = skew factor, s[1] = scale factor @@ -149,10 +154,10 @@ private: SPItem const *_item_to_ignore; SPDesktop const *_desktop; bool _snapindicator; - std::vector *_unselected_nodes; + std::vector > *_unselected_nodes; Inkscape::SnappedPoint _snapTransformed(Inkscape::SnapPreferences::PointType type, - std::vector const &points, + std::vector > const &points, Geom::Point const &pointer, bool constrained, Inkscape::Snapper::ConstraintLine const &constraint, @@ -162,16 +167,16 @@ private: Geom::Dim2 dim, bool uniform) const; - Geom::Point _transformPoint(Geom::Point const &p, + Geom::Point _transformPoint(std::pair const &p, Transformation const transformation_type, Geom::Point const &transformation, Geom::Point const &origin, Geom::Dim2 const dim, bool const uniform) const; - void _displaySnapsource(Inkscape::SnapPreferences::PointType point_type, Geom::Point const &p) const; + void _displaySnapsource(Inkscape::SnapPreferences::PointType point_type, std::pair const &p) const; - Inkscape::SnappedPoint findBestSnap(Geom::Point const &p, SnappedConstraints &sc, bool constrained) const; + Inkscape::SnappedPoint findBestSnap(Geom::Point const &p, Inkscape::SnapSourceType const source_type, SnappedConstraints &sc, bool constrained) const; }; #endif /* !SEEN_SNAP_H */ diff --git a/src/snapped-curve.cpp b/src/snapped-curve.cpp index 34cc4dad2..e66b44401 100644 --- a/src/snapped-curve.cpp +++ b/src/snapped-curve.cpp @@ -14,7 +14,7 @@ #include <2geom/path-intersection.h> #include -Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapTargetType target) +Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, SnapTargetType target) { _distance = snapped_distance; _tolerance = std::max(snapped_tolerance, 1.0); @@ -26,6 +26,7 @@ Inkscape::SnappedCurve::SnappedCurve(Geom::Point const &snapped_point, Geom::Coo _point = snapped_point; _at_intersection = false; _fully_constrained = fully_constrained; + _source = source; _target = target; } @@ -41,6 +42,7 @@ Inkscape::SnappedCurve::SnappedCurve() _point = Geom::Point(0,0); _at_intersection = false; _fully_constrained = false; + _source = SNAPSOURCE_UNDEFINED; _target = SNAPTARGET_UNDEFINED; } @@ -83,12 +85,12 @@ Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &cur // TODO: Investigate whether it is possible to use document coordinates everywhere // in the snapper code. Only the mouse position should be in desktop coordinates, I guess. // All paths are already in document coords and we are certainly not going to change THAT. - return SnappedPoint(best_p, Inkscape::SNAPTARGET_PATH_INTERSECTION, primaryDist, primaryC->getTolerance(), primaryC->getAlwaysSnap(), true, true, + return SnappedPoint(best_p, Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_PATH_INTERSECTION, primaryDist, primaryC->getTolerance(), primaryC->getAlwaysSnap(), true, true, secondaryDist, secondaryC->getTolerance(), secondaryC->getAlwaysSnap()); } // No intersection - return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); } // search for the closest snapped line diff --git a/src/snapped-curve.h b/src/snapped-curve.h index d3dcd0238..60f5fa0d9 100644 --- a/src/snapped-curve.h +++ b/src/snapped-curve.h @@ -27,7 +27,7 @@ class SnappedCurve : public SnappedPoint { public: SnappedCurve(); - SnappedCurve(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapTargetType target); + SnappedCurve(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, SnapTargetType target); ~SnappedCurve(); Inkscape::SnappedPoint intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Matrix dt2doc) const; //intersect with another SnappedCurve diff --git a/src/snapped-line.cpp b/src/snapped-line.cpp index 5f7d5407b..706893673 100644 --- a/src/snapped-line.cpp +++ b/src/snapped-line.cpp @@ -12,10 +12,12 @@ #include <2geom/geom.h> #include "libnr/nr-values.h" -Inkscape::SnappedLineSegment::SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line) +Inkscape::SnappedLineSegment::SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line) : _start_point_of_line(start_point_of_line), _end_point_of_line(end_point_of_line) { _point = snapped_point; + _source = source; + _target = target; _distance = snapped_distance; _tolerance = std::max(snapped_tolerance, 1.0); _always_snap = always_snap; @@ -30,6 +32,8 @@ Inkscape::SnappedLineSegment::SnappedLineSegment() _start_point_of_line = Geom::Point(0,0); _end_point_of_line = Geom::Point(0,0); _point = Geom::Point(0,0); + _source = SNAPSOURCE_UNDEFINED; + _target = SNAPTARGET_UNDEFINED; _distance = NR_HUGE; _tolerance = 1; _always_snap = false; @@ -69,20 +73,22 @@ Inkscape::SnappedPoint Inkscape::SnappedLineSegment::intersect(SnappedLineSegmen Inkscape::SnappedLineSegment const *secondarySLS = use_this_as_primary ? &line : this; Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(intersection_2geom - this->getPoint()) : Geom::L2(intersection_2geom - line.getPoint()); Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(intersection_2geom - line.getPoint()) : Geom::L2(intersection_2geom - this->getPoint()); - return SnappedPoint(intersection, SNAPTARGET_PATH_INTERSECTION, primaryDist, primarySLS->getTolerance(), primarySLS->getAlwaysSnap(), true, true, + return SnappedPoint(intersection, SNAPSOURCE_UNDEFINED, SNAPTARGET_PATH_INTERSECTION, primaryDist, primarySLS->getTolerance(), primarySLS->getAlwaysSnap(), true, true, secondaryDist, secondarySLS->getTolerance(), secondarySLS->getAlwaysSnap()); } // No intersection - return SnappedPoint(intersection, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(intersection, SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); }; -Inkscape::SnappedLine::SnappedLine(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &normal_to_line, Geom::Point const &point_on_line) +Inkscape::SnappedLine::SnappedLine(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &normal_to_line, Geom::Point const &point_on_line) : _normal_to_line(normal_to_line), _point_on_line(point_on_line) { - _distance = snapped_distance; + _source = source; + _target = target; + _distance = snapped_distance; _tolerance = std::max(snapped_tolerance, 1.0); _always_snap = always_snap; _second_distance = NR_HUGE; @@ -96,6 +102,8 @@ Inkscape::SnappedLine::SnappedLine() { _normal_to_line = Geom::Point(0,0); _point_on_line = Geom::Point(0,0); + _source = SNAPSOURCE_UNDEFINED; + _target = SNAPTARGET_UNDEFINED; _distance = NR_HUGE; _tolerance = 1; _always_snap = false; @@ -137,14 +145,14 @@ Inkscape::SnappedPoint Inkscape::SnappedLine::intersect(SnappedLine const &line) Inkscape::SnappedLine const *secondarySL = use_this_as_primary ? &line : this; Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(intersection_2geom - this->getPoint()) : Geom::L2(intersection_2geom - line.getPoint()); Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(intersection_2geom - line.getPoint()) : Geom::L2(intersection_2geom - this->getPoint()); - return SnappedPoint(intersection, Inkscape::SNAPTARGET_UNDEFINED, primaryDist, primarySL->getTolerance(), primarySL->getAlwaysSnap(), true, true, + return SnappedPoint(intersection, Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED, primaryDist, primarySL->getTolerance(), primarySL->getAlwaysSnap(), true, true, secondaryDist, secondarySL->getTolerance(), secondarySL->getAlwaysSnap()); // The type of the snap target is yet undefined, as we cannot tell whether // we're snapping to grid or the guide lines; must be set by on a higher level } // No intersection - return SnappedPoint(intersection, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(intersection, SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); } // search for the closest snapped line segment diff --git a/src/snapped-line.h b/src/snapped-line.h index ea18baefc..3d6668311 100644 --- a/src/snapped-line.h +++ b/src/snapped-line.h @@ -26,13 +26,13 @@ class SnappedLineSegment : public SnappedPoint { public: SnappedLineSegment(); - SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line); + SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance,bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line); ~SnappedLineSegment(); Inkscape::SnappedPoint intersect(SnappedLineSegment const &line) const; //intersect with another SnappedLineSegment - + private: Geom::Point _start_point_of_line; - Geom::Point _end_point_of_line; + Geom::Point _end_point_of_line; }; @@ -41,7 +41,7 @@ class SnappedLine : public SnappedPoint { public: SnappedLine(); - SnappedLine(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &normal_to_line, Geom::Point const &point_on_line); + SnappedLine(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &normal_to_line, Geom::Point const &point_on_line); ~SnappedLine(); Inkscape::SnappedPoint intersect(SnappedLine const &line) const; //intersect with another SnappedLine // This line is described by this equation: @@ -49,10 +49,10 @@ public: Geom::Point getNormal() const {return _normal_to_line;} // n = (nx, ny) Geom::Point getPointOnLine() const {return _point_on_line;} // p = (px, py) Geom::Coord getConstTerm() const {return dot(_normal_to_line, _point_on_line);} // c = n.p = nx*px + ny*py; - + private: Geom::Point _normal_to_line; - Geom::Point _point_on_line; + Geom::Point _point_on_line; }; } @@ -62,7 +62,7 @@ bool getClosestIntersectionSLS(std::list const &li bool getClosestSL(std::list const &list, Inkscape::SnappedLine &result); bool getClosestIntersectionSL(std::list const &list, Inkscape::SnappedPoint &result); bool getClosestIntersectionSL(std::list const &list1, std::list const &list2, Inkscape::SnappedPoint &result); - + #endif /* !SEEN_SNAPPEDLINE_H */ diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp index 44b69050f..d7f13d82f 100644 --- a/src/snapped-point.cpp +++ b/src/snapped-point.cpp @@ -14,8 +14,8 @@ #include "preferences.h" // overloaded constructor -Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained) - : _point(p), _target(target), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a) +Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained) + : _point(p), _source(source), _target(target), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a) { // tolerance should never be smaller than 1 px, as it is used for normalization in isOtherSnapBetter. We don't want a division by zero. _at_intersection = false; @@ -27,8 +27,8 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapTargetType const _pointer_distance = NR_HUGE; } -Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2) - : _point(p), _target(target), _at_intersection(at_intersection), _fully_constrained(fully_constrained), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a), +Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2) + : _point(p), _source(source), _target(target), _at_intersection(at_intersection), _fully_constrained(fully_constrained), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a), _second_distance(d2), _second_tolerance(std::max(t2,1.0)), _second_always_snap(a2) { // tolerance should never be smaller than 1 px, as it is used for normalization in @@ -40,6 +40,7 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapTargetType const Inkscape::SnappedPoint::SnappedPoint() { _point = Geom::Point(0,0); + _source = SNAPSOURCE_UNDEFINED, _target = SNAPTARGET_UNDEFINED, _at_intersection = false; _fully_constrained = false; diff --git a/src/snapped-point.h b/src/snapped-point.h index 7085ccae8..f8ef50ff3 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -22,29 +22,57 @@ namespace Inkscape { enum SnapTargetType { - SNAPTARGET_UNDEFINED, + SNAPTARGET_UNDEFINED = 0, SNAPTARGET_GRID, SNAPTARGET_GRID_INTERSECTION, SNAPTARGET_GUIDE, SNAPTARGET_GUIDE_INTERSECTION, SNAPTARGET_GRID_GUIDE_INTERSECTION, - SNAPTARGET_NODE, + SNAPTARGET_NODE_SMOOTH, + SNAPTARGET_NODE_CUSP, + SNAPTARGET_LINE_MIDPOINT, + SNAPTARGET_OBJECT_MIDPOINT, + SNAPTARGET_ROTATION_CENTER, + SNAPTARGET_HANDLE, //e.g. center of ellipse, corner of rectangle SNAPTARGET_PATH, SNAPTARGET_PATH_INTERSECTION, SNAPTARGET_BBOX_CORNER, SNAPTARGET_BBOX_EDGE, + SNAPTARGET_BBOX_EDGE_MIDPOINT, + SNAPTARGET_BBOX_MIDPOINT, SNAPTARGET_GRADIENT, - SNAPTARGET_PAGE_BORDER + SNAPTARGET_PAGE_BORDER, + SNAPTARGET_PAGE_CORNER, + SNAPTARGET_CONVEX_HULL_CORNER, + SNAPTARGET_ELLIPSE_QUADRANT_POINT, }; +enum SnapSourceType { + SNAPSOURCE_UNDEFINED = 0, + SNAPSOURCE_BBOX_CORNER, + SNAPSOURCE_BBOX_MIDPOINT, + SNAPSOURCE_BBOX_EDGE_MIDPOINT, + SNAPSOURCE_NODE_SMOOTH, + SNAPSOURCE_NODE_CUSP, + SNAPSOURCE_LINE_MIDPOINT, + SNAPSOURCE_OBJECT_MIDPOINT, + SNAPSOURCE_ROTATION_CENTER, + SNAPSOURCE_HANDLE, + SNAPSOURCE_PATH_INTERSECTION, + SNAPSOURCE_GUIDE, + SNAPSOURCE_CONVEX_HULL_CORNER, + SNAPSOURCE_ELLIPSE_QUADRANT_POINT +}; + + /// Class describing the result of an attempt to snap. class SnappedPoint { public: SnappedPoint(); - SnappedPoint(Geom::Point const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2); - SnappedPoint(Geom::Point const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained); + SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2); + SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained); ~SnappedPoint(); Geom::Coord getSnapDistance() const {return _distance;} @@ -79,11 +107,14 @@ public: void setTransformation(Geom::Point const t) {_transformation = t;} void setTarget(SnapTargetType const target) {_target = target;} SnapTargetType getTarget() const {return _target;} + void setSource(SnapSourceType const source) {_source = source;} + SnapSourceType getSource() const {return _source;} bool isOtherSnapBetter(SnappedPoint const &other_one, bool weighted) const; /*void dump() const { std::cout << "_point = " << _point << std::endl; + std::cout << "_source = " << _source << std::endl; std::cout << "_target = " << _target << std::endl; std::cout << "_at_intersection = " << _at_intersection << std::endl; std::cout << "_fully_constrained = " << _fully_constrained << std::endl; @@ -99,6 +130,7 @@ public: protected: Geom::Point _point; // Location of the snapped point + SnapSourceType _source; // Describes what snapped SnapTargetType _target; // Describes to what we've snapped to bool _at_intersection; // If true, the snapped point is at an intersection bool _fully_constrained; // When snapping for example to a node, then the snap will be "fully constrained". diff --git a/src/snapper.h b/src/snapper.h index 49f277411..08b10e41b 100644 --- a/src/snapper.h +++ b/src/snapper.h @@ -59,10 +59,11 @@ public: virtual void freeSnap(SnappedConstraints &/*sc*/, SnapPreferences::PointType const &/*t*/, Geom::Point const &/*p*/, + SnapSourceType const &/*source_type*/, bool const &/*first_point*/, Geom::OptRect const &/*bbox_to_snap*/, std::vector const */*it*/, - std::vector */*unselected_nodes*/) const {}; + std::vector > */*unselected_nodes*/) const {}; class ConstraintLine { @@ -97,6 +98,7 @@ public: virtual void constrainedSnap(SnappedConstraints &/*sc*/, SnapPreferences::PointType const &/*t*/, Geom::Point const &/*p*/, + SnapSourceType const &/*source_type*/, bool const &/*first_point*/, Geom::OptRect const &/*bbox_to_snap*/, ConstraintLine const &/*c*/, diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index ce1343272..976563754 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -72,7 +72,7 @@ static void sp_genericellipse_init(SPGenericEllipse *ellipse); static void sp_genericellipse_update(SPObject *object, SPCtx *ctx, guint flags); -static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_genericellipse_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_genericellipse_set_shape(SPShape *shape); static void sp_genericellipse_update_patheffect (SPLPEItem *lpeitem, bool write); @@ -260,7 +260,7 @@ static void sp_genericellipse_set_shape(SPShape *shape) curve->unref(); } -static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +static void sp_genericellipse_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { g_assert(item != NULL); g_assert(SP_IS_GENERICELLIPSE(item)); @@ -290,31 +290,37 @@ static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p, I double cx = ellipse->cx.computed; double cy = ellipse->cy.computed; + Geom::Point pt; + // Snap to the 4 quadrant points of the ellipse, but only if the arc // spans far enough to include them if (snapprefs->getSnapToItemNode()) { //TODO: Make a separate snap option toggle for this? double angle = 0; for (angle = 0; angle < SP_2PI; angle += M_PI_2) { if (angle >= ellipse->start && angle <= ellipse->end) { - *p = Geom::Point(cx + cos(angle)*rx, cy + sin(angle)*ry) * i2d; + pt = Geom::Point(cx + cos(angle)*rx, cy + sin(angle)*ry) * i2d; + p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_ELLIPSE_QUADRANT_POINT) : int(Inkscape::SNAPSOURCE_ELLIPSE_QUADRANT_POINT))); } } } // Add the centre, if we have a closed slice or when explicitly asked for if ((snapprefs->getSnapToItemNode() && slice && ellipse->closed) || snapprefs->getSnapObjectMidpoints()) { - *p = Geom::Point(cx, cy) * i2d; + pt = Geom::Point(cx, cy) * i2d; + p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_HANDLE) : int(Inkscape::SNAPSOURCE_HANDLE))); } // And if we have a slice, also snap to the endpoints if (snapprefs->getSnapToItemNode() && slice) { // Add the start point, if it's not coincident with a quadrant point if (fmod(ellipse->start, M_PI_2) != 0.0 ) { - *p = Geom::Point(cx + cos(ellipse->start)*rx, cy + sin(ellipse->start)*ry) * i2d; + pt = Geom::Point(cx + cos(ellipse->start)*rx, cy + sin(ellipse->start)*ry) * i2d; + p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_NODE_CUSP) : int(Inkscape::SNAPSOURCE_NODE_CUSP))); } // Add the end point, if it's not coincident with a quadrant point if (fmod(ellipse->end, M_PI_2) != 0.0 ) { - *p = Geom::Point(cx + cos(ellipse->end)*rx, cy + sin(ellipse->end)*ry) * i2d; + pt = Geom::Point(cx + cos(ellipse->end)*rx, cy + sin(ellipse->end)*ry) * i2d; + p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_NODE_CUSP) : int(Inkscape::SNAPSOURCE_NODE_CUSP))); } } } diff --git a/src/sp-image.cpp b/src/sp-image.cpp index 75be3bea2..e23dddaf6 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -76,7 +76,7 @@ static Inkscape::XML::Node *sp_image_write (SPObject *object, Inkscape::XML::Doc static void sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); static void sp_image_print (SPItem * item, SPPrintContext *ctx); static gchar * sp_image_description (SPItem * item); -static void sp_image_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_image_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static NRArenaItem *sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); static Geom::Matrix sp_image_set_transform (SPItem *item, Geom::Matrix const &xform); static void sp_image_set_curve(SPImage *image); @@ -1305,7 +1305,7 @@ sp_image_update_canvas_image (SPImage *image) } } -static void sp_image_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const */*snapprefs*/) +static void sp_image_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const */*snapprefs*/) { /* An image doesn't have any nodes to snap, but still we want to be able snap one image to another. Therefore we will create some snappoints at the corner, similar to a rect. If @@ -1327,10 +1327,12 @@ static void sp_image_snappoints(SPItem const *item, SnapPointsIter p, Inkscape:: double const x1 = x0 + image.width.computed; double const y1 = y0 + image.height.computed; Geom::Matrix const i2d (sp_item_i2d_affine (item)); - *p = Geom::Point(x0, y0) * i2d; - *p = Geom::Point(x0, y1) * i2d; - *p = Geom::Point(x1, y1) * i2d; - *p = Geom::Point(x1, y0) * i2d; + Geom::Point pt; + int type = target ? int(Inkscape::SNAPTARGET_HANDLE) : int(Inkscape::SNAPSOURCE_HANDLE); + p.push_back(std::make_pair(Geom::Point(x0, y0) * i2d, type)); + p.push_back(std::make_pair(Geom::Point(x0, y1) * i2d, type)); + p.push_back(std::make_pair(Geom::Point(x1, y1) * i2d, type)); + p.push_back(std::make_pair(Geom::Point(x1, y0) * i2d, type)); } } diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 862a36cb0..ed5382fae 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -68,7 +68,7 @@ static gchar * sp_group_description (SPItem * item); static Geom::Matrix sp_group_set_transform(SPItem *item, Geom::Matrix const &xform); static NRArenaItem *sp_group_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); static void sp_group_hide (SPItem * item, unsigned int key); -static void sp_group_snappoints (SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_group_snappoints (SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_group_update_patheffect(SPLPEItem *lpeitem, bool write); static void sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup); @@ -338,14 +338,14 @@ sp_group_hide (SPItem *item, unsigned int key) SP_GROUP(item)->group->hide(key); } -static void sp_group_snappoints (SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +static void sp_group_snappoints (SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { for (SPObject const *o = sp_object_first_child(SP_OBJECT(item)); o != NULL; o = SP_OBJECT_NEXT(o)) { if (SP_IS_ITEM(o)) { - sp_item_snappoints(SP_ITEM(o), p, snapprefs); + sp_item_snappoints(SP_ITEM(o), target, p, snapprefs); } } } diff --git a/src/sp-item-notify-moveto.cpp b/src/sp-item-notify-moveto.cpp index 5cc169221..0bc08a235 100644 --- a/src/sp-item-notify-moveto.cpp +++ b/src/sp-item-notify-moveto.cpp @@ -24,11 +24,11 @@ void sp_item_notify_moveto(SPItem &item, SPGuide const &mv_g, int const snappoin double const dir_lensq(dot(dir, dir)); g_return_if_fail( dir_lensq != 0 ); - std::vector snappoints; - sp_item_snappoints(&item, SnapPointsIter(snappoints), NULL); + SnapPointsWithType snappoints; + sp_item_snappoints(&item, false, snappoints, NULL); g_return_if_fail( snappoint_ix < int(snappoints.size()) ); - double const pos0 = dot(dir, snappoints[snappoint_ix]); + double const pos0 = dot(dir, snappoints[snappoint_ix].first); /// \todo effic: skip if mv_g is already satisfied. /* Translate along dir to make dot(dir, snappoints(item)[snappoint_ix]) == position. */ diff --git a/src/sp-item-rm-unsatisfied-cns.cpp b/src/sp-item-rm-unsatisfied-cns.cpp index 6d7ab2fda..246453241 100644 --- a/src/sp-item-rm-unsatisfied-cns.cpp +++ b/src/sp-item-rm-unsatisfied-cns.cpp @@ -14,14 +14,14 @@ void sp_item_rm_unsatisfied_cns(SPItem &item) if (item.constraints.empty()) { return; } - std::vector snappoints; - sp_item_snappoints(&item, SnapPointsIter(snappoints), NULL); + SnapPointsWithType snappoints; + sp_item_snappoints(&item, false, snappoints, NULL); for (unsigned i = item.constraints.size(); i--;) { g_assert( i < item.constraints.size() ); SPGuideConstraint const &cn = item.constraints[i]; int const snappoint_ix = cn.snappoint_ix; g_assert( snappoint_ix < int(snappoints.size()) ); - if (!approx_equal( sp_guide_distance_from_pt(cn.g, snappoints[snappoint_ix]), 0) ) { + if (!approx_equal( sp_guide_distance_from_pt(cn.g, snappoints[snappoint_ix].first), 0) ) { remove_last(cn.g->attached_items, SPGuideAttachment(&item, cn.snappoint_ix)); g_assert( i < item.constraints.size() ); vector::iterator const ei(&item.constraints[i]); diff --git a/src/sp-item-update-cns.cpp b/src/sp-item-update-cns.cpp index f7329bd45..bebd65021 100644 --- a/src/sp-item-update-cns.cpp +++ b/src/sp-item-update-cns.cpp @@ -9,8 +9,8 @@ using std::vector; void sp_item_update_cns(SPItem &item, SPDesktop const &desktop) { - std::vector snappoints; - sp_item_snappoints(&item, SnapPointsIter(snappoints), NULL); + SnapPointsWithType snappoints; + sp_item_snappoints(&item, false, snappoints, NULL); /* TODO: Implement the ordering. */ vector found_cns; satisfied_guide_cns(desktop, snappoints, found_cns); diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 2ac480341..996804cd3 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -90,7 +90,7 @@ static void sp_item_update(SPObject *object, SPCtx *ctx, guint flags); static Inkscape::XML::Node *sp_item_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static gchar *sp_item_private_description(SPItem *item); -static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_item_private_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static SPItemView *sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, NRArenaItem *arenaitem); static SPItemView *sp_item_view_list_remove(SPItemView *list, SPItemView *view); @@ -939,7 +939,7 @@ Geom::OptRect sp_item_bbox_desktop(SPItem *item, SPItem::BBoxType type) return rect; } -static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const */*snapprefs*/) +static void sp_item_private_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const */*snapprefs*/) { /* This will only be called if the derived class doesn't override this. * see for example sp_genericellipse_snappoints in sp-ellipse.cpp @@ -952,15 +952,16 @@ static void sp_item_private_snappoints(SPItem const *item, SnapPointsIter p, Ink Geom::Point p1, p2; p1 = bbox->min(); p2 = bbox->max(); - *p = p1; - *p = Geom::Point(p1[Geom::X], p2[Geom::Y]); - *p = p2; - *p = Geom::Point(p1[Geom::Y], p2[Geom::X]); + int type = target ? int(Inkscape::SNAPSOURCE_CONVEX_HULL_CORNER) : int(Inkscape::SNAPSOURCE_CONVEX_HULL_CORNER); + p.push_back(std::make_pair(p1, type)); + p.push_back(std::make_pair(Geom::Point(p1[Geom::X], p2[Geom::Y]), type)); + p.push_back(std::make_pair(p2, type)); + p.push_back(std::make_pair(Geom::Point(p1[Geom::Y], p2[Geom::X]), type)); } } -void sp_item_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +void sp_item_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { g_assert (item != NULL); g_assert (SP_IS_ITEM(item)); @@ -968,12 +969,12 @@ void sp_item_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPref // Get the snappoints of the item SPItemClass const &item_class = *(SPItemClass const *) G_OBJECT_GET_CLASS(item); if (item_class.snappoints) { - item_class.snappoints(item, p, snapprefs); + item_class.snappoints(item, target, p, snapprefs); } // Get the snappoints at the item's center if (snapprefs != NULL && snapprefs->getIncludeItemCenter()) { - *p = item->getCenter(); + p.push_back(std::make_pair(item->getCenter(), target ? int(Inkscape::SNAPTARGET_OBJECT_MIDPOINT) : int(Inkscape::SNAPSOURCE_OBJECT_MIDPOINT))); } // Get the snappoints of clipping paths and mask, if any @@ -988,14 +989,15 @@ void sp_item_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPref // obj is a group object, the children are the actual clippers for (SPObject *child = (*o)->children ; child ; child = child->next) { if (SP_IS_ITEM(child)) { - std::vector p_clip_or_mask; + SnapPointsWithType p_clip_or_mask; // Please note the recursive call here! - sp_item_snappoints(SP_ITEM(child), SnapPointsIter(p_clip_or_mask), snapprefs); + sp_item_snappoints(SP_ITEM(child), target, p_clip_or_mask, snapprefs); // Take into account the transformation of the item being clipped or masked - for (std::vector::const_iterator p_orig = p_clip_or_mask.begin(); p_orig != p_clip_or_mask.end(); p_orig++) { + for (SnapPointsWithType::const_iterator p_orig = p_clip_or_mask.begin(); p_orig != p_clip_or_mask.end(); p_orig++) { // All snappoints are in desktop coordinates, but the item's transformation is // in document coordinates. Hence the awkward construction below - *p = desktop->dt2doc(*p_orig) * sp_item_i2d_affine(item); + Geom::Point pt = desktop->dt2doc((*p_orig).first) * sp_item_i2d_affine(item); + p.push_back(std::make_pair(pt, (*p_orig).second)); } } } diff --git a/src/sp-item.h b/src/sp-item.h index d95fc2486..639a1b4a2 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -26,6 +26,7 @@ #include <2geom/forward.h> #include #include +#include class SPGuideConstraint; struct SPClipPathReference; @@ -33,7 +34,7 @@ struct SPMaskReference; struct SPAvoidRef; struct SPPrintContext; namespace Inkscape { class URIReference; } - + enum { SP_EVENT_INVALID, SP_EVENT_NONE, @@ -72,7 +73,7 @@ struct SPItemView { #define SP_ITEM_SHOW_DISPLAY (1 << 0) /** - * Flag for referenced views (i.e. markers, clippaths, masks and patterns); + * Flag for referenced views (i.e. markers, clippaths, masks and patterns); currently unused, does the same as DISPLAY */ #define SP_ITEM_REFERENCE_FLAGS (1 << 1) @@ -92,7 +93,7 @@ struct SPItemCtx { struct SPItem : public SPObject { enum BBoxType { // legacy behavior: includes crude stroke, markers; excludes long miters, blur margin; is known to be wrong for caps - APPROXIMATE_BBOX, + APPROXIMATE_BBOX, // includes only the bare path bbox, no stroke, no nothing GEOMETRIC_BBOX, // includes everything: correctly done stroke (with proper miters and caps), markers, filter margins (e.g. blur) @@ -105,34 +106,34 @@ struct SPItem : public SPObject { double transform_center_y; Geom::Matrix transform; - + SPClipPathReference *clip_ref; SPMaskReference *mask_ref; - + // Used for object-avoiding connectors SPAvoidRef *avoidRef; - + SPItemView *display; - + std::vector constraints; - + sigc::signal _transformed_signal; - void init(); + void init(); bool isLocked() const; void setLocked(bool lock); - + bool isHidden() const; void setHidden(bool hidden); bool isEvaluated() const; void setEvaluated(bool visible); void resetEvaluated(); - + bool isHidden(unsigned display_key) const; - + bool isExplicitlyHidden() const; - + void setExplicitlyHidden(bool val); void setCenter(Geom::Point object_centre); @@ -141,11 +142,11 @@ struct SPItem : public SPObject { Geom::Point getCenter() const; bool isVisibleAndUnlocked() const; - + bool isVisibleAndUnlocked(unsigned display_key) const; - + Geom::Matrix getRelativeTransform(SPObject const *obj) const; - + void raiseOne(); void lowerOne(); void raiseToTop(); @@ -170,7 +171,7 @@ private: mutable EvaluatedStatus _evaluated_status; }; -typedef std::back_insert_iterator > SnapPointsIter; +typedef std::vector > SnapPointsWithType; // int is either of these enums: Inkscape::SnapTargetType or Inkscape::SnapSourceType /// The SPItem vtable. struct SPItemClass { @@ -178,28 +179,28 @@ struct SPItemClass { /** BBox union in given coordinate system */ void (* bbox) (SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); - + /** Printing method. Assumes ctm is set to item affine matrix */ /* \todo Think about it, and maybe implement generic export method instead (Lauris) */ void (* print) (SPItem *item, SPPrintContext *ctx); - + /** Give short description of item (for status display) */ gchar * (* description) (SPItem * item); - + NRArenaItem * (* show) (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); void (* hide) (SPItem *item, unsigned int key); - + /** Write to an iterator the points that should be considered for snapping * as the item's `nodes'. */ - void (* snappoints) (SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); - + void (* snappoints) (SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); + /** Apply the transform optimally, and return any residual transformation */ Geom::Matrix (* set_transform)(SPItem *item, Geom::Matrix const &transform); /** Convert the item to guidelines */ void (* convert_to_guides)(SPItem *item); - + /** Emit event, if applicable */ gint (* event) (SPItem *item, SPEvent *event); }; @@ -225,7 +226,7 @@ unsigned int sp_item_display_key_new(unsigned int numkeys); NRArenaItem *sp_item_invoke_show(SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); void sp_item_invoke_hide(SPItem *item, unsigned int key); -void sp_item_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +void sp_item_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); void sp_item_adjust_pattern(SPItem *item, /* Geom::Matrix const &premul, */ Geom::Matrix const &postmul, bool set = false); void sp_item_adjust_gradient(SPItem *item, /* Geom::Matrix const &premul, */ Geom::Matrix const &postmul, bool set = false); diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp index 39b8227a4..ae0f7bf19 100644 --- a/src/sp-offset.cpp +++ b/src/sp-offset.cpp @@ -83,7 +83,7 @@ static void sp_offset_update (SPObject * object, SPCtx * ctx, guint flags); static void sp_offset_release (SPObject * object); static gchar *sp_offset_description (SPItem * item); -static void sp_offset_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_offset_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_offset_set_shape (SPShape * shape); static void refresh_offset_source(SPOffset* offset); @@ -718,10 +718,10 @@ sp_offset_set_shape(SPShape *shape) /** * Virtual snappoints function. */ -static void sp_offset_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +static void sp_offset_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { if (((SPItemClass *) parent_class)->snappoints) { - ((SPItemClass *) parent_class)->snappoints (item, p, snapprefs); + ((SPItemClass *) parent_class)->snappoints (item, target, p, snapprefs); } } diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp index c88b9eb38..4f8dbbbce 100644 --- a/src/sp-rect.cpp +++ b/src/sp-rect.cpp @@ -45,7 +45,7 @@ static Geom::Matrix sp_rect_set_transform(SPItem *item, Geom::Matrix const &xfor static void sp_rect_convert_to_guides(SPItem *item); static void sp_rect_set_shape(SPShape *shape); -static void sp_rect_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_rect_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static SPShapeClass *parent_class; @@ -543,7 +543,7 @@ sp_rect_get_visible_height(SPRect *rect) /** * Sets the snappoint p to the unrounded corners of the rectangle */ -static void sp_rect_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +static void sp_rect_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { /* This method overrides sp_shape_snappoints, which is the default for any shape. The default method returns all eight points along the path of a rounded rectangle, but not the real corners. Snapping @@ -569,22 +569,27 @@ static void sp_rect_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::S Geom::Point p2 = Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed + rect->height.computed) * i2d; Geom::Point p3 = Geom::Point(rect->x.computed + rect->width.computed, rect->y.computed) * i2d; + int type; + if (snapprefs->getSnapToItemNode()) { - *p = p0; - *p = p1; - *p = p2; - *p = p3; + type = target ? int(Inkscape::SNAPTARGET_HANDLE) : int(Inkscape::SNAPSOURCE_HANDLE); + p.push_back(std::make_pair(p0, type)); + p.push_back(std::make_pair(p1, type)); + p.push_back(std::make_pair(p2, type)); + p.push_back(std::make_pair(p3, type)); } if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping) - *p = (p0 + p1)/2; - *p = (p1 + p2)/2; - *p = (p2 + p3)/2; - *p = (p3 + p0)/2; + type = target ? int(Inkscape::SNAPTARGET_LINE_MIDPOINT) : int(Inkscape::SNAPSOURCE_LINE_MIDPOINT); + p.push_back(std::make_pair((p0 + p1)/2, type)); + p.push_back(std::make_pair((p1 + p2)/2, type)); + p.push_back(std::make_pair((p2 + p3)/2, type)); + p.push_back(std::make_pair((p3 + p0)/2, type)); } if (snapprefs->getSnapObjectMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping) - *p = (p0 + p2)/2; + type = target ? int(Inkscape::SNAPTARGET_OBJECT_MIDPOINT) : int(Inkscape::SNAPSOURCE_OBJECT_MIDPOINT); + p.push_back(std::make_pair((p0 + p2)/2, type)); } } diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 178ca89a8..7b4663908 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -68,7 +68,7 @@ static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const & void sp_shape_print (SPItem * item, SPPrintContext * ctx); static NRArenaItem *sp_shape_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); static void sp_shape_hide (SPItem *item, unsigned int key); -static void sp_shape_snappoints (SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_shape_snappoints (SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai); @@ -1057,7 +1057,7 @@ sp_shape_set_curve_insync (SPShape *shape, SPCurve *curve, unsigned int owner) /** * Return all nodes in a path that are to be considered for snapping */ -static void sp_shape_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +static void sp_shape_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { g_assert(item != NULL); g_assert(SP_IS_SHAPE(item)); @@ -1078,16 +1078,20 @@ static void sp_shape_snappoints(SPItem const *item, SnapPointsIter p, Inkscape:: Geom::Matrix const i2d (sp_item_i2d_affine (item)); + int type; + if (snapprefs->getSnapObjectMidpoints()) { Geom::OptRect bbox = item->getBounds(sp_item_i2d_affine(item)); if (bbox) { - *p = bbox->midpoint(); + type = target ? int(Inkscape::SNAPTARGET_OBJECT_MIDPOINT) : int(Inkscape::SNAPSOURCE_OBJECT_MIDPOINT); + p.push_back(std::make_pair(bbox->midpoint(), type)); } } for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { if (snapprefs->getSnapToItemNode()) { - *p = path_it->initialPoint() * i2d; + type = target ? int(Inkscape::SNAPTARGET_NODE_CUSP) : int(Inkscape::SNAPSOURCE_NODE_CUSP); + p.push_back(std::make_pair(path_it->initialPoint() * i2d, type)); } Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve @@ -1106,13 +1110,15 @@ static void sp_shape_snappoints(SPItem const *item, SnapPointsIter p, Inkscape:: bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); if (c1 || c2) { - *p = curve_it1->finalPoint() * i2d; + type = target ? int(Inkscape::SNAPTARGET_NODE_CUSP) : int(Inkscape::SNAPSOURCE_NODE_CUSP); + p.push_back(std::make_pair(curve_it1->finalPoint() * i2d, type)); } // Consider midpoints of line segments for snapping if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping) if (Geom::LineSegment const* line_segment = dynamic_cast(&(*curve_it1))) { - *p = Geom::middle_point(*line_segment) * i2d; + type = target ? int(Inkscape::SNAPTARGET_LINE_MIDPOINT) : int(Inkscape::SNAPSOURCE_LINE_MIDPOINT); + p.push_back(std::make_pair(Geom::middle_point(*line_segment) * i2d, type)); } } @@ -1128,7 +1134,8 @@ static void sp_shape_snappoints(SPItem const *item, SnapPointsIter p, Inkscape:: if (cs.size() > 0) { // There might be multiple intersections... for (Geom::Crossings::const_iterator i = cs.begin(); i != cs.end(); i++) { Geom::Point p_ix = (*path_it).pointAt((*i).ta); - *p = p_ix * i2d; + type = target ? int(Inkscape::SNAPTARGET_PATH_INTERSECTION) : int(Inkscape::SNAPSOURCE_PATH_INTERSECTION); + p.push_back(std::make_pair(p_ix * i2d, type)); } } } diff --git a/src/sp-spiral.cpp b/src/sp-spiral.cpp index 624c5ae18..872607c27 100644 --- a/src/sp-spiral.cpp +++ b/src/sp-spiral.cpp @@ -36,7 +36,7 @@ static void sp_spiral_set (SPObject *object, unsigned int key, const gchar *valu static void sp_spiral_update (SPObject *object, SPCtx *ctx, guint flags); static gchar * sp_spiral_description (SPItem * item); -static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_spiral_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_spiral_set_shape (SPShape *shape); static void sp_spiral_update_patheffect (SPLPEItem *lpeitem, bool write); @@ -503,7 +503,7 @@ sp_spiral_position_set (SPSpiral *spiral, /** * Virtual snappoints callback. */ -static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +static void sp_spiral_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { // We will determine the spiral's midpoint ourselves, instead of trusting on the base class // Therefore setSnapObjectMidpoints() is set to false temporarily @@ -511,7 +511,7 @@ static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape: local_snapprefs.setSnapObjectMidpoints(false); if (((SPItemClass *) parent_class)->snappoints) { - ((SPItemClass *) parent_class)->snappoints (item, p, &local_snapprefs); + ((SPItemClass *) parent_class)->snappoints (item, target, p, &local_snapprefs); } // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes @@ -522,7 +522,8 @@ static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape: if (snapprefs->getSnapObjectMidpoints()) { Geom::Matrix const i2d (sp_item_i2d_affine (item)); SPSpiral *spiral = SP_SPIRAL(item); - *p = Geom::Point(spiral->cx, spiral->cy) * i2d; + int type = target ? int(Inkscape::SNAPTARGET_OBJECT_MIDPOINT) : int(Inkscape::SNAPSOURCE_OBJECT_MIDPOINT); + p.push_back(std::make_pair(Geom::Point(spiral->cx, spiral->cy) * i2d, type)); // This point is the start-point of the spiral, which is also returned when _snap_to_itemnode has been set // in the object snapper. In that case we will get a duplicate! } diff --git a/src/sp-star.cpp b/src/sp-star.cpp index c1581a6d6..3c8754a11 100644 --- a/src/sp-star.cpp +++ b/src/sp-star.cpp @@ -39,7 +39,7 @@ static void sp_star_set (SPObject *object, unsigned int key, const gchar *value) static void sp_star_update (SPObject *object, SPCtx *ctx, guint flags); static gchar * sp_star_description (SPItem * item); -static void sp_star_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_star_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_star_set_shape (SPShape *shape); static void sp_star_update_patheffect (SPLPEItem *lpeitem, bool write); @@ -528,7 +528,7 @@ sp_star_position_set (SPStar *star, gint sides, Geom::Point center, gdouble r1, SP_OBJECT(star)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } -static void sp_star_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +static void sp_star_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { // We will determine the star's midpoint ourselves, instead of trusting on the base class // Therefore setSnapObjectMidpoints() is set to false temporarily @@ -536,7 +536,7 @@ static void sp_star_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::S local_snapprefs.setSnapObjectMidpoints(false); if (((SPItemClass *) parent_class)->snappoints) { - ((SPItemClass *) parent_class)->snappoints (item, p, &local_snapprefs); + ((SPItemClass *) parent_class)->snappoints (item, target, p, &local_snapprefs); } // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes @@ -546,7 +546,8 @@ static void sp_star_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::S if (snapprefs->getSnapObjectMidpoints()) { Geom::Matrix const i2d (sp_item_i2d_affine (item)); - *p = SP_STAR(item)->center * i2d; + int type = target ? int(Inkscape::SNAPTARGET_OBJECT_MIDPOINT) : int(Inkscape::SNAPSOURCE_OBJECT_MIDPOINT); + p.push_back(std::make_pair(SP_STAR(item)->center * i2d, type)); } } diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 8627e179f..abfb9ca65 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -74,7 +74,7 @@ static void sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &t static NRArenaItem *sp_text_show (SPItem *item, NRArena *arena, unsigned key, unsigned flags); static void sp_text_hide (SPItem *item, unsigned key); static char *sp_text_description (SPItem *item); -static void sp_text_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_text_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static Geom::Matrix sp_text_set_transform(SPItem *item, Geom::Matrix const &xform); static void sp_text_print (SPItem *item, SPPrintContext *gpc); @@ -428,12 +428,13 @@ sp_text_description(SPItem *item) return ret; } -static void sp_text_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const */*snapprefs*/) +static void sp_text_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const */*snapprefs*/) { // the baseline anchor of the first char Inkscape::Text::Layout const *layout = te_get_layout((SPItem *) item); if(layout != NULL) { - *p = layout->characterAnchorPoint(layout->begin()) * sp_item_i2d_affine(item); + int type = target ? int(Inkscape::SNAPTARGET_HANDLE) : int(Inkscape::SNAPSOURCE_HANDLE); + p.push_back(std::make_pair(layout->characterAnchorPoint(layout->begin()) * sp_item_i2d_affine(item), type)); } } diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 36372e67b..990407f95 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -52,7 +52,7 @@ static void sp_use_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_use_modified(SPObject *object, guint flags); static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); -static void sp_use_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs); +static void sp_use_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); static void sp_use_print(SPItem *item, SPPrintContext *ctx); static gchar *sp_use_description(SPItem *item); static NRArenaItem *sp_use_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags); @@ -741,19 +741,19 @@ sp_use_get_original(SPUse *use) } static void -sp_use_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs) +sp_use_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) { g_assert (item != NULL); g_assert (SP_IS_ITEM(item)); g_assert (SP_IS_USE(item)); - + SPUse *use = SP_USE(item); SPItem *root = sp_use_root(use); g_return_if_fail(root); - + SPItemClass const &item_class = *(SPItemClass const *) G_OBJECT_GET_CLASS(root); if (item_class.snappoints) { - item_class.snappoints(root, p, snapprefs); + item_class.snappoints(root, target, p, snapprefs); } } diff --git a/src/spiral-context.cpp b/src/spiral-context.cpp index 35d5144a7..3689ae4af 100644 --- a/src/spiral-context.cpp +++ b/src/spiral-context.cpp @@ -227,7 +227,7 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event) SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop); Geom::Point pt2g = to_2geom(sc->center); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE); sc->center = from_2geom(pt2g); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), @@ -258,7 +258,7 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event) SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true, sc->item); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, motion_dt); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, motion_dt, Inkscape::SNAPSOURCE_HANDLE); sp_spiral_drag(sc, from_2geom(motion_dt), event->motion.state); gobble_motion_events(GDK_BUTTON1_MASK); @@ -404,7 +404,7 @@ sp_spiral_drag(SPSpiralContext *sc, Geom::Point p, guint state) SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true, sc->item); Geom::Point pt2g = to_2geom(p); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE); Geom::Point const p0 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, sc->center)); Geom::Point const p1 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, from_2geom(pt2g))); diff --git a/src/star-context.cpp b/src/star-context.cpp index da79d4719..54c431e2c 100644 --- a/src/star-context.cpp +++ b/src/star-context.cpp @@ -243,7 +243,7 @@ static gint sp_star_context_root_handler(SPEventContext *event_context, GdkEvent SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true); Geom::Point pt2g = to_2geom(sc->center); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE); sc->center = from_2geom(pt2g); sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate), @@ -416,7 +416,7 @@ static void sp_star_drag(SPStarContext *sc, Geom::Point p, guint state) SnapManager &m = desktop->namedview->snap_manager; m.setup(desktop, true, sc->item); Geom::Point pt2g = to_2geom(p); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g); + m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g, Inkscape::SNAPSOURCE_HANDLE); Geom::Point const p0 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, sc->center)); Geom::Point const p1 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, from_2geom(pt2g)));