From: Diederik van Lierop Date: Sat, 9 Jan 2010 21:14:38 +0000 (+0100) Subject: Refactoring the snapping API (making it easier to maintain and understand for the... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=a863e835ebdabf37c059e325ba54d689ff0dd752;p=inkscape.git Refactoring the snapping API (making it easier to maintain and understand for the devs) --- diff --git a/src/context-fns.cpp b/src/context-fns.cpp index 8e4b6384c..67a7d6baa 100644 --- a/src/context-fns.cpp +++ b/src/context-fns.cpp @@ -131,12 +131,12 @@ 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]), Inkscape::SNAPSOURCE_HANDLE, - Inkscape::Snapper::ConstraintLine(p[0] - p[1]), false); + s[0] = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(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]), Inkscape::SNAPSOURCE_HANDLE, - Inkscape::Snapper::ConstraintLine(p[1] - p[0]), false); + s[1] = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(p[1], Inkscape::SNAPSOURCE_HANDLE), + Inkscape::Snapper::ConstraintLine(p[1] - p[0])); /* Choose the best snap and update points accordingly */ if (s[0].getSnapDistance() < s[1].getSnapDistance()) { @@ -156,8 +156,8 @@ 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]), Inkscape::SNAPSOURCE_HANDLE, - Inkscape::Snapper::ConstraintLine(p[1] - p[0]), false); + snappoint = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(p[1], Inkscape::SNAPSOURCE_HANDLE), + Inkscape::Snapper::ConstraintLine(p[1] - p[0])); if (snappoint.getSnapped()) { p[1] = snappoint.getPoint(); } @@ -174,8 +174,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]), Inkscape::SNAPSOURCE_HANDLE); - s[1] = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p[1]), Inkscape::SNAPSOURCE_HANDLE); + s[0] = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(p[0], Inkscape::SNAPSOURCE_HANDLE)); + s[1] = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(p[1], Inkscape::SNAPSOURCE_HANDLE)); if (s[0].getSnapDistance() < s[1].getSnapDistance()) { if (s[0].getSnapped()) { @@ -196,7 +196,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), Inkscape::SNAPSOURCE_HANDLE); + snappoint = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_HANDLE)); if (snappoint.getSnapped()) { p[1] = snappoint.getPoint(); } diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index 7df9b31ff..84bc1709b 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -40,7 +40,7 @@ SnapIndicator::~SnapIndicator() } void -SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const p) +SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const &p) { remove_snaptarget(); //only display one snaptarget at a time @@ -264,7 +264,7 @@ SnapIndicator::remove_snaptarget() } void -SnapIndicator::set_new_snapsource(std::pair const p) +SnapIndicator::set_new_snapsource(Inkscape::SnapCandidatePoint const &p) { remove_snapsource(); @@ -284,7 +284,7 @@ SnapIndicator::set_new_snapsource(std::pair const p) "shape", SP_KNOT_SHAPE_CIRCLE, NULL ); - SP_CTRL(canvasitem)->moveto(p.first); + SP_CTRL(canvasitem)->moveto(p.getPoint()); _snapsource = _desktop->add_temporary_canvasitem(canvasitem, 1000); } } diff --git a/src/display/snap-indicator.h b/src/display/snap-indicator.h index 4391ca6d6..d896042a2 100644 --- a/src/display/snap-indicator.h +++ b/src/display/snap-indicator.h @@ -26,10 +26,10 @@ public: SnapIndicator(SPDesktop *desktop); virtual ~SnapIndicator(); - void set_new_snaptarget(Inkscape::SnappedPoint const p); + void set_new_snaptarget(Inkscape::SnappedPoint const &p); void remove_snaptarget(); - void set_new_snapsource(std::pair const p); + void set_new_snapsource(Inkscape::SnapCandidatePoint const &p); void remove_snapsource(); protected: diff --git a/src/draw-context.cpp b/src/draw-context.cpp index de9a7c7e5..3334c82de 100644 --- a/src/draw-context.cpp +++ b/src/draw-context.cpp @@ -511,9 +511,7 @@ void spdc_endpoint_snap_rotation(SPEventContext const *const ec, Geom::Point &p, /* Snap it along best vector */ 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::SNAPSOURCE_HANDLE, Inkscape::Snapper::ConstraintLine(best), false); - p = from_2geom(pt2g); + m.constrainedSnapReturnByRef( Inkscape::SnapPreferences::SNAPPOINT_NODE, p, Inkscape::SNAPSOURCE_HANDLE, Inkscape::Snapper::ConstraintLine(best)); } } } diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 98ea35b4e..726f4d78a 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -596,7 +596,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp m.setup(desktop); if (!((state & GDK_SHIFT_MASK) || (state & GDK_CONTROL_MASK))) { - Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, Inkscape::SNAPSOURCE_HANDLE); + Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_OTHER, Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_HANDLE)); if (s.getSnapped()) { p = s.getPoint(); sp_knot_moveto (knot, p); @@ -659,7 +659,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp } if (snap_vector) { Inkscape::Snapper::ConstraintLine cl(dr_snap, p + *snap_vector - dr_snap); - Inkscape::SnappedPoint s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_OTHER, p + *snap_vector, Inkscape::SNAPSOURCE_HANDLE, cl); + Inkscape::SnappedPoint s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_OTHER, Inkscape::SnapCandidatePoint(p + *snap_vector, Inkscape::SNAPSOURCE_HANDLE), cl); if (s.getSnapped()) { s.setTransformation(s.getPoint() - p); sc.points.push_back(s); @@ -672,7 +672,7 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp } } - Inkscape::SnappedPoint bsp = m.findBestSnap(p, Inkscape::SNAPSOURCE_HANDLE, sc, true); // snap indicator will be displayed if needed + Inkscape::SnappedPoint bsp = m.findBestSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_HANDLE), sc, true); // snap indicator will be displayed if needed if (bsp.getSnapped()) { p += bsp.getTransformation(); diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index 31fa07515..696f92405 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -23,21 +23,17 @@ 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, - long source_num, + Inkscape::SnapCandidatePoint const &p, 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; } /* Get the lines that we will try to snap to */ - const LineList lines = _getSnapLines(p); - - // std::cout << "snap point " << p << " to: " << std::endl; + const LineList lines = _getSnapLines(p.getPoint()); for (LineList::const_iterator i = lines.begin(); i != lines.end(); i++) { Geom::Point const p1 = i->second; // point at guide/grid line @@ -45,17 +41,17 @@ void Inkscape::LineSnapper::freeSnap(SnappedConstraints &sc, // std::cout << " line through " << i->second << " with normal " << i->first; g_assert(i->first != Geom::Point(0,0)); // we cannot project on an linesegment of zero length - Geom::Point const p_proj = Geom::projection(p, Geom::Line(p1, p2)); - Geom::Coord const dist = Geom::L2(p_proj - p); + Geom::Point const p_proj = Geom::projection(p.getPoint(), Geom::Line(p1, p2)); + Geom::Coord const dist = Geom::L2(p_proj - p.getPoint()); //Store any line that's within snapping range if (dist < getSnapperTolerance()) { - _addSnappedLine(sc, p_proj, dist, source_type, source_num, i->first, i->second); + _addSnappedLine(sc, p_proj, dist, p.getSourceType(), p.getSourceNum(), i->first, i->second); // For any line that's within range, we will also look at it's "point on line" p1. For guides // this point coincides with its origin; for grids this is of no use, but we cannot // discern between grids and guides here - Geom::Coord const dist_p1 = Geom::L2(p1 - p); + Geom::Coord const dist_p1 = Geom::L2(p1 - p.getPoint()); if (dist_p1 < getSnapperTolerance()) { - _addSnappedLinesOrigin(sc, p1, dist_p1, source_type, source_num); + _addSnappedLinesOrigin(sc, p1, dist_p1, p.getSourceType(), p.getSourceNum()); // Only relevant for guides; grids don't have an origin per line // Therefore _addSnappedLinesOrigin() will only be implemented for guides } @@ -67,9 +63,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, - long source_num, + Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &/*bbox_to_snap*/, ConstraintLine const &c, std::vector const */*it*/) const @@ -80,12 +74,12 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, } /* Get the lines that we will try to snap to */ - const LineList lines = _getSnapLines(p); + const LineList lines = _getSnapLines(p.getPoint()); for (LineList::const_iterator i = lines.begin(); i != lines.end(); i++) { if (Geom::L2(c.getDirection()) > 0) { // Can't do a constrained snap without a constraint // constraint line - Geom::Point const point_on_line = c.hasPoint() ? c.getPoint() : p; + Geom::Point const point_on_line = c.hasPoint() ? c.getPoint() : p.getPoint(); Geom::Line line1(point_on_line, point_on_line + c.getDirection()); // grid/guide line @@ -106,19 +100,19 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, if (inters) { Geom::Point t = line1.pointAt((*inters).ta); - const Geom::Coord dist = Geom::L2(t - p); + const Geom::Coord dist = Geom::L2(t - p.getPoint()); if (dist < getSnapperTolerance()) { // When doing a constrained snap, we're already at an intersection. // 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 - _addSnappedPoint(sc, t, dist, source_type, source_num); + _addSnappedPoint(sc, t, dist, p.getSourceType(), p.getSourceNum()); // For any line that's within range, we will also look at it's "point on line" p1. For guides // this point coincides with its origin; for grids this is of no use, but we cannot // discern between grids and guides here - Geom::Coord const dist_p1 = Geom::L2(p1 - p); + Geom::Coord const dist_p1 = Geom::L2(p1 - p.getPoint()); if (dist_p1 < getSnapperTolerance()) { - _addSnappedLinesOrigin(sc, p1, dist_p1, source_type, source_num); + _addSnappedLinesOrigin(sc, p1, dist_p1, p.getSourceType(), p.getSourceNum()); // Only relevant for guides; grids don't have an origin per line // Therefore _addSnappedLinesOrigin() will only be implemented for guides } diff --git a/src/line-snapper.h b/src/line-snapper.h index af36b8330..5845e081e 100644 --- a/src/line-snapper.h +++ b/src/line-snapper.h @@ -18,6 +18,7 @@ namespace Inkscape { +class SnapCandidatePoint; class LineSnapper : public Snapper { @@ -26,18 +27,14 @@ public: void freeSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, - Geom::Point const &p, - SnapSourceType const &source_type, - long source_num, + Inkscape::SnapCandidatePoint const &p, 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, - long source_num, + Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap, ConstraintLine const &c, std::vector const *it) const; diff --git a/src/nodepath.cpp b/src/nodepath.cpp index 1881dd72b..069b3c5bc 100644 --- a/src/nodepath.cpp +++ b/src/nodepath.cpp @@ -1367,13 +1367,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(std::make_pair(to_2geom(node->pos), node->type == Inkscape::NodePath::NODE_SMOOTH ? Inkscape::SNAPTARGET_NODE_SMOOTH : Inkscape::SNAPTARGET_NODE_CUSP)); + unselected_nodes.push_back(Inkscape::SnapCandidatePoint(node->pos, Inkscape::SNAPSOURCE_UNDEFINED, node->type == Inkscape::NodePath::NODE_SMOOTH ? Inkscape::SNAPTARGET_NODE_SMOOTH : Inkscape::SNAPTARGET_NODE_CUSP)); } } } @@ -1409,9 +1409,9 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath, 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), source_type, dedicated_constraint, false); + s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(n->pos + delta, source_type), dedicated_constraint); } else { - s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(n->pos + delta), source_type); + s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(n->pos + delta, source_type)); } if (s.getSnapped()) { @@ -3975,16 +3975,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, source_type, Inkscape::Snapper::ConstraintLine(p, ndelta), false); + s = m.constrainedSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(p, source_type), Inkscape::Snapper::ConstraintLine(p, ndelta)); } } else { if ((state & GDK_SHIFT_MASK) == 0) { - s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, source_type); + s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(p, source_type)); } } } else { if ((state & GDK_SHIFT_MASK) == 0) { - s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, p, source_type); + s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(p, source_type)); } } diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 4a70e2706..11685e25c 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -33,21 +33,12 @@ #include "helper/geom-curves.h" #include "desktop.h" -Inkscape::SnapCandidate::SnapCandidate(SPItem* item, bool clip_or_mask, Geom::Matrix additional_affine) - : item(item), clip_or_mask(clip_or_mask), additional_affine(additional_affine) -{ -} - -Inkscape::SnapCandidate::~SnapCandidate() -{ -} - Inkscape::ObjectSnapper::ObjectSnapper(SnapManager *sm, Geom::Coord const d) : Snapper(sm, d) { - _candidates = new std::vector; - _points_to_snap_to = new std::vector >; - _paths_to_snap_to = new std::vector >; + _candidates = new std::vector; + _points_to_snap_to = new std::vector; + _paths_to_snap_to = new std::vector; } Inkscape::ObjectSnapper::~ObjectSnapper() @@ -158,7 +149,7 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, // See if the item is within range if (bbox_to_snap_incl.intersects(*bbox_of_item)) { // This item is within snapping range, so record it as a candidate - _candidates->push_back(SnapCandidate(item, clip_or_mask, additional_affine)); + _candidates->push_back(SnapCandidateItem(item, clip_or_mask, additional_affine)); // For debugging: print the id of the candidate to the console //SPObject *obj = (SPObject*)item; //std::cout << "Snap candidate added: " << obj->id << std::endl; @@ -202,7 +193,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType _getBorderNodes(_points_to_snap_to); } - for (std::vector::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) { + for (std::vector::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) { //Geom::Matrix i2doc(Geom::identity()); SPItem *root_item = (*i).item; if (SP_IS_USE((*i).item)) { @@ -236,7 +227,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType _snapmanager->snapprefs.setSnapIntersectionCS(false); } - sp_item_snappoints(root_item, true, *_points_to_snap_to, &_snapmanager->snapprefs); + sp_item_snappoints(root_item, *_points_to_snap_to, &_snapmanager->snapprefs); if (_snapmanager->snapprefs.getSnapToItemPath()) { _snapmanager->snapprefs.setSnapIntersectionCS(old_pref); @@ -258,14 +249,12 @@ 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, - long source_num, - std::vector > *unselected_nodes) const + Inkscape::SnapCandidatePoint const &p, + std::vector *unselected_nodes) const { // Iterate through all nodes, find out which one is the closest to p, and snap to it! - _collectNodes(t, source_num == 0); + _collectNodes(t, p.getSourceNum() == 0); if (unselected_nodes != NULL) { _points_to_snap_to->insert(_points_to_snap_to->end(), unselected_nodes->begin(), unselected_nodes->end()); @@ -274,10 +263,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).first - 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).getPoint() - p.getPoint()); if (dist < getSnapperTolerance() && dist < s.getSnapDistance()) { - s = SnappedPoint((*k).first, source_type, source_num, static_cast((*k).second), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + s = SnappedPoint((*k).getPoint(), p.getSourceType(), p.getSourceNum(), (*k).getTargetType(), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); success = true; } } @@ -298,7 +287,7 @@ void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &s // Although we won't snap to paths here (which would give us under constrained snaps) we can still snap to intersections of paths. if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { _collectPaths(t, true); - _snapPaths(sc, t, p, SNAPSOURCE_GUIDE, 0, NULL, NULL); + _snapPaths(sc, t, Inkscape::SnapCandidatePoint(p, SNAPSOURCE_GUIDE), NULL, NULL); // The paths themselves should be discarded in findBestSnap(), as we should only snap to their intersections } @@ -306,13 +295,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 = Geom::projection((*k).first, Geom::Line(p, p + Geom::rot90(guide_normal))); - Geom::Coord dist = Geom::L2((*k).first - p_proj); // distance from node to the guide + Geom::Point p_proj = Geom::projection((*k).getPoint(), Geom::Line(p, p + Geom::rot90(guide_normal))); + Geom::Coord dist = Geom::L2((*k).getPoint() - 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()) { - s = SnappedPoint((*k).first, SNAPSOURCE_GUIDE, 0, static_cast((*k).second), dist, tol, getSnapperAlwaysSnap(), true); + s = SnappedPoint((*k).getPoint(), SNAPSOURCE_GUIDE, 0, (*k).getTargetType(), dist, tol, getSnapperAlwaysSnap(), true); sc.points.push_back(s); } } @@ -349,11 +338,11 @@ 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(Inkscape::SnapCandidatePath(border_path, SNAPTARGET_PAGE_BORDER)); } } - for (std::vector::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) { + for (std::vector::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) { /* Transform the requested snap point to this item's coordinates */ Geom::Matrix i2doc(Geom::identity()); @@ -397,7 +386,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(Inkscape::SnapCandidatePath(borderpathv, SNAPTARGET_PATH)); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it. curve->unref(); } } @@ -414,7 +403,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(Inkscape::SnapCandidatePath(path, SNAPTARGET_BBOX_EDGE)); } } } @@ -425,47 +414,40 @@ 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, - long source_num, - std::vector > *unselected_nodes, + Inkscape::SnapCandidatePoint const &p, + std::vector *unselected_nodes, SPPath const *selected_path) const { - _collectPaths(t, source_num == 0); + _collectPaths(t, p.getSourceNum() == 0); // Now we can finally do the real snapping, using the paths collected above g_assert(_snapmanager->getDesktop() != NULL); - Geom::Point const p_doc = _snapmanager->getDesktop()->dt2doc(p); + Geom::Point const p_doc = _snapmanager->getDesktop()->dt2doc(p.getPoint()); bool const node_tool_active = _snapmanager->snapprefs.getSnapToItemPath() && selected_path != NULL; - if (source_num == 0) { + if (p.getSourceNum() == 0) { /* findCandidates() is used for snapping to both paths and nodes. It ignores the path that is * currently being edited, because that path requires special care: when snapping to nodes * only the unselected nodes of that path should be considered, and these will be passed on separately. * This path must not be ignored however when snapping to the paths, so we add it here * manually when applicable. - * - * Note that this path must be the last in line! * */ if (node_tool_active) { 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(Inkscape::SnapCandidatePath(pathv, SNAPTARGET_PATH, true)); curve->unref(); } } } - for (std::vector >::const_iterator it_p = _paths_to_snap_to->begin(); it_p != _paths_to_snap_to->end(); it_p++) { - bool const being_edited = (node_tool_active && (*it_p) == _paths_to_snap_to->back()); + for (std::vector::const_iterator it_p = _paths_to_snap_to->begin(); it_p != _paths_to_snap_to->end(); it_p++) { + bool const being_edited = node_tool_active && (*it_p).currently_being_edited; //if true then this pathvector it_pv is currently being edited in the node tool - // char * svgd = sp_svg_write_path(**it_p->first); - // std::cout << "Dumping the pathvector: " << svgd << std::endl; - - for(Geom::PathVector::iterator it_pv = (it_p->first)->begin(); it_pv != (it_p->first)->end(); ++it_pv) { + for(Geom::PathVector::iterator it_pv = (it_p->path_vector)->begin(); it_pv != (it_p->path_vector)->end(); ++it_pv) { // Find a nearest point for each curve within this path // n curves will return n time values with 0 <= t <= 1 std::vector anp = (*it_pv).nearestPointPerCurve(p_doc); @@ -502,7 +484,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, source_type, source_num, it_p->second)); + sc.curves.push_back(Inkscape::SnappedCurve(sp_dt, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), false, curve, p.getSourceType(), p.getSourceNum(), it_p->target_type)); } } } @@ -511,7 +493,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; @@ -521,8 +503,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).first) < 1e-4) { + for (std::vector::const_iterator i = unselected_nodes->begin(); i != unselected_nodes->end(); i++) { + if (Geom::L2(point - (*i).getPoint()) < 1e-4) { return true; } } @@ -532,18 +514,16 @@ 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, - long source_num, + Inkscape::SnapCandidatePoint const &p, ConstraintLine const &c) const { - _collectPaths(t, source_num == 0); + _collectPaths(t, p.getSourceNum() == 0); // Now we can finally do the real snapping, using the paths collected above g_assert(_snapmanager->getDesktop() != NULL); - Geom::Point const p_doc = _snapmanager->getDesktop()->dt2doc(p); + Geom::Point const p_doc = _snapmanager->getDesktop()->dt2doc(p.getPoint()); Geom::Point direction_vector = c.getDirection(); if (!is_zero(direction_vector)) { @@ -553,7 +533,7 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, // The intersection point of the constraint line with any path, // must lie within two points on the constraintline: p_min_on_cl and p_max_on_cl // The distance between those points is twice the snapping tolerance - Geom::Point const p_proj_on_cl = p; // projection has already been taken care of in constrainedSnap in the snapmanager; + Geom::Point const p_proj_on_cl = p.getPoint(); // projection has already been taken care of in constrainedSnap in the snapmanager; Geom::Point const p_min_on_cl = _snapmanager->getDesktop()->dt2doc(p_proj_on_cl - getSnapperTolerance() * direction_vector); Geom::Point const p_max_on_cl = _snapmanager->getDesktop()->dt2doc(p_proj_on_cl + getSnapperTolerance() * direction_vector); @@ -563,9 +543,9 @@ void Inkscape::ObjectSnapper::_snapPathsConstrained(SnappedConstraints &sc, cl.appendNew(p_max_on_cl); clv.push_back(cl); - for (std::vector >::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) { - if (k->first) { - Geom::CrossingSet cs = Geom::crossings(clv, *(k->first)); + for (std::vector::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) { + if (k->path_vector) { + Geom::CrossingSet cs = Geom::crossings(clv, *(k->path_vector)); if (cs.size() > 0) { // We need only the first element of cs, because cl is only a single straight linesegment // This first element contains a vector filled with crossings of cl with k->first @@ -576,7 +556,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), source_type, source_num, k->second, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); + SnappedPoint s(_snapmanager->getDesktop()->doc2dt(p_inters), p.getSourceType(), p.getSourceNum(), k->target_type, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), true); sc.points.push_back(s); } } @@ -588,21 +568,19 @@ 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, - long source_num, + Inkscape::SnapCandidatePoint const &p, 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; } /* Get a list of all the SPItems that we will try to snap to */ - if (source_num == 0) { - Geom::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : Geom::Rect(p, p); - _findCandidates(sp_document_root(_snapmanager->getDocument()), it, source_num == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); + if (p.getSourceNum() == 0) { + Geom::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : Geom::Rect(p.getPoint(), p.getPoint()); + _findCandidates(sp_document_root(_snapmanager->getDocument()), it, p.getSourceNum() == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); } if (_snapmanager->snapprefs.getSnapToItemNode() || _snapmanager->snapprefs.getSnapSmoothNodes() @@ -610,7 +588,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, source_type, source_num, unselected_nodes); + _snapNodes(sc, t, p, unselected_nodes); } if (_snapmanager->snapprefs.getSnapToItemPath() || _snapmanager->snapprefs.getSnapToBBoxPath() || _snapmanager->snapprefs.getSnapToPageBorder()) { @@ -628,18 +606,16 @@ void Inkscape::ObjectSnapper::freeSnap(SnappedConstraints &sc, } // else: *it->begin() might be a SPGroup, e.g. when editing a LPE of text that has been converted to a group of paths // as reported in bug #356743. In that case we can just ignore it, i.e. not snap to this item } - _snapPaths(sc, t, p, source_type, source_num, unselected_nodes, path); + _snapPaths(sc, t, p, unselected_nodes, path); } else { - _snapPaths(sc, t, p, source_type, source_num, NULL, NULL); + _snapPaths(sc, t, p, NULL, NULL); } } } void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, - Geom::Point const &p, - SnapSourceType const &source_type, - long source_num, + Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap, ConstraintLine const &c, std::vector const *it) const @@ -649,9 +625,9 @@ void Inkscape::ObjectSnapper::constrainedSnap( SnappedConstraints &sc, } /* Get a list of all the SPItems that we will try to snap to */ - if (source_num == 0) { - Geom::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : Geom::Rect(p, p); - _findCandidates(sp_document_root(_snapmanager->getDocument()), it, source_num == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); + if (p.getSourceNum() == 0) { + Geom::Rect const local_bbox_to_snap = bbox_to_snap ? *bbox_to_snap : Geom::Rect(p.getPoint(), p.getPoint()); + _findCandidates(sp_document_root(_snapmanager->getDocument()), it, p.getSourceNum() == 0, local_bbox_to_snap, TRANSL_SNAP_XY, false, Geom::identity()); } // A constrained snap, is a snap in only one degree of freedom (specified by the constraint line). @@ -664,7 +640,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, source_type, 0, c); + _snapPathsConstrained(sc, t, p, c); } } @@ -748,8 +724,8 @@ bool Inkscape::ObjectSnapper::GuidesMightSnap() const // almost the same as This void Inkscape::ObjectSnapper::_clear_paths() const { - for (std::vector >::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) { - g_free(k->first); + for (std::vector::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) { + g_free(k->path_vector); } _paths_to_snap_to->clear(); } @@ -771,31 +747,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(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)); + points->push_back(Inkscape::SnapCandidatePoint(Geom::Point(0,0), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); + points->push_back(Inkscape::SnapCandidatePoint(Geom::Point(0,h), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); + points->push_back(Inkscape::SnapCandidatePoint(Geom::Point(w,h), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); + points->push_back(Inkscape::SnapCandidatePoint(Geom::Point(w,0), SNAPSOURCE_UNDEFINED, SNAPTARGET_PAGE_CORNER)); } -void Inkscape::getBBoxPoints(Geom::OptRect const bbox, std::vector > *points, bool const isTarget, 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(std::make_pair((bbox->corner(k)), isTarget ? int(Inkscape::SNAPTARGET_BBOX_CORNER) : int(Inkscape::SNAPSOURCE_BBOX_CORNER))); + points->push_back(Inkscape::SnapCandidatePoint(bbox->corner(k), Inkscape::SNAPSOURCE_BBOX_CORNER, 0, Inkscape::SNAPTARGET_BBOX_CORNER, *bbox)); } // optionally, collect the midpoints of the bounding box's edges too if (includeLineMidpoints) { - 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))); + points->push_back(Inkscape::SnapCandidatePoint((bbox->corner(k) + bbox->corner((k+1) % 4))/2, Inkscape::SNAPSOURCE_BBOX_EDGE_MIDPOINT, 0, Inkscape::SNAPTARGET_BBOX_EDGE_MIDPOINT, *bbox)); } } if (includeObjectMidpoints) { - points->push_back(std::make_pair(bbox->midpoint(), isTarget ? int(Inkscape::SNAPTARGET_BBOX_MIDPOINT) : int(Inkscape::SNAPSOURCE_BBOX_MIDPOINT))); + points->push_back(Inkscape::SnapCandidatePoint(bbox->midpoint(), Inkscape::SNAPSOURCE_BBOX_MIDPOINT, 0, Inkscape::SNAPTARGET_BBOX_MIDPOINT, *bbox)); } } } diff --git a/src/object-snapper.h b/src/object-snapper.h index 2fcafb79a..556ff86de 100644 --- a/src/object-snapper.h +++ b/src/object-snapper.h @@ -17,6 +17,7 @@ #include "snapper.h" #include "sp-path.h" #include "splivarot.h" +#include "snap-candidate.h" struct SPNamedView; struct SPItem; @@ -25,23 +26,6 @@ struct SPObject; namespace Inkscape { -class SnapCandidate - -{ -public: - SnapCandidate(SPItem* item, bool clip_or_mask, Geom::Matrix _additional_affine); - ~SnapCandidate(); - - SPItem* item; // An item that is to be considered for snapping to - bool clip_or_mask; // If true, then item refers to a clipping path or a mask - - /* To find out the absolute position of a clipping path or mask, we not only need to know - * the transformation of the clipping path or mask itself, but also the transformation of - * the object to which the clip or mask is being applied; that transformation is stored here - */ - Geom::Matrix additional_affine; -}; - class ObjectSnapper : public Snapper { @@ -72,27 +56,23 @@ public: void freeSnap(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, - Geom::Point const &p, - SnapSourceType const &source_type, - long source_num, + Inkscape::SnapCandidatePoint const &p, 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, - long source_num, + Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap, ConstraintLine const &c, std::vector const *it) const; 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 > *_paths_to_snap_to; + std::vector *_candidates; + std::vector *_points_to_snap_to; + std::vector *_paths_to_snap_to; void _findCandidates(SPObject* parent, std::vector const *it, @@ -104,10 +84,8 @@ private: void _snapNodes(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, - Geom::Point const &p, // in desktop coordinates - SnapSourceType const &source_type, - long source_num, - std::vector > *unselected_nodes) const; // in desktop coordinates + Inkscape::SnapCandidatePoint const &p, + std::vector *unselected_nodes) const; // in desktop coordinates void _snapTranslatingGuideToNodes(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, @@ -119,20 +97,16 @@ private: void _snapPaths(SnappedConstraints &sc, Inkscape::SnapPreferences::PointType const &t, - Geom::Point const &p, // in desktop coordinates - SnapSourceType const &source_type, - long source_num, - std::vector > *unselected_nodes, // in desktop coordinates + Inkscape::SnapCandidatePoint const &p, // 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 - SnapSourceType const source_type, - long source_num, + Inkscape::SnapCandidatePoint const &p, // in desktop coordinates 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; @@ -140,11 +114,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 isTarget, 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/satisfied-guide-cns.cpp b/src/satisfied-guide-cns.cpp index 505e18675..dcf635989 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, - SnapPointsWithType const &snappoints, + std::vector 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].first), 0) ) { + if (approx_equal( sp_guide_distance_from_pt(&g, snappoints[i].getPoint()), 0) ) { cns.push_back(SPGuideConstraint(&g, i)); } } diff --git a/src/satisfied-guide-cns.h b/src/satisfied-guide-cns.h index 99229f64c..7fba29161 100644 --- a/src/satisfied-guide-cns.h +++ b/src/satisfied-guide-cns.h @@ -9,7 +9,7 @@ class SPGuideConstraint; void satisfied_guide_cns(SPDesktop const &desktop, - SnapPointsWithType const &snappoints, + std::vector const &snappoints, std::vector &cns); diff --git a/src/selection.cpp b/src/selection.cpp index 7b936587c..1e14591fa 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -426,48 +426,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, false, p, &snapprefs_dummy); + sp_item_snappoints(this_item, 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(std::make_pair(this_item->getCenter(), SNAPSOURCE_ROTATION_CENTER)); + p.push_back(Inkscape::SnapCandidatePoint(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), false, p, snapprefs); + sp_item_snappoints(SP_ITEM(iter->data), p, snapprefs); } - std::vector > pHull; + std::vector pHull; if (!p.empty()) { - std::vector >::iterator i; - Geom::RectHull cvh((p.front()).first); + std::vector::iterator i; + Geom::RectHull cvh((p.front()).getPoint()); for (i = p.begin(); i != p.end(); i++) { // these are the points we get back - cvh.add((*i).first); + cvh.add((*i).getPoint()); } Geom::OptRect rHull = cvh.bounds(); if (rHull) { for ( unsigned i = 0 ; i < 4 ; ++i ) { - pHull.push_back(std::make_pair(rHull->corner(i), SNAPSOURCE_CONVEX_HULL_CORNER)); + pHull.push_back(Inkscape::SnapCandidatePoint(rHull->corner(i), SNAPSOURCE_CONVEX_HULL_CORNER)); } } } diff --git a/src/selection.h b/src/selection.h index 5e035fb60..b5a511e96 100644 --- a/src/selection.h +++ b/src/selection.h @@ -272,13 +272,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 diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 8ff00d60a..5b129f8d8 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -295,7 +295,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() > 200) { /* 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 @@ -313,11 +313,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).first, (*i).first); + std::vector::iterator i = snap_points_hull.begin(); + snap_points_bbox = Geom::Rect((*i).getPoint(), (*i).getPoint()); i++; while (i != snap_points_hull.end()) { - snap_points_bbox.expandTo((*i).first); + snap_points_bbox.expandTo((*i).getPoint()); i++; } } @@ -381,9 +381,9 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s } // Now let's reduce this to a single closest snappoint - Geom::Coord dsp = _snap_points.size() == 1 ? Geom::L2((_snap_points.at(0)).first - p) : NR_HUGE; - Geom::Coord dbbp = _bbox_points.size() == 1 ? Geom::L2((_bbox_points.at(0)).first - p) : NR_HUGE; - Geom::Coord dbbpft = _bbox_points_for_translating.size() == 1 ? Geom::L2((_bbox_points_for_translating.at(0)).first - p) : NR_HUGE; + Geom::Coord dsp = _snap_points.size() == 1 ? Geom::L2((_snap_points.at(0)).getPoint() - p) : NR_HUGE; + Geom::Coord dbbp = _bbox_points.size() == 1 ? Geom::L2((_bbox_points.at(0)).getPoint() - p) : NR_HUGE; + Geom::Coord dbbpft = _bbox_points_for_translating.size() == 1 ? Geom::L2((_bbox_points_for_translating.at(0)).getPoint() - p) : NR_HUGE; if (translating) { _bbox_points.clear(); @@ -1513,6 +1513,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) } } } + if (best_snapped_point.getSnapped()) { _desktop->snapindicator->set_new_snaptarget(best_snapped_point); } else { @@ -1643,15 +1644,15 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale) return _calcAbsAffineDefault(geom_scale); // this is bogus, but we must return _something_ } -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; - std::pair closest_point = std::make_pair(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED); + Inkscape::SnapCandidatePoint closest_point = Inkscape::SnapCandidatePoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_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).first - reference); + for(std::vector::const_iterator i = points.begin(); i != points.end(); i++) { + Geom::Coord dist = Geom::L2((*i).getPoint() - 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 d0ac5dccf..8b2810621 100644 --- a/src/seltrans.h +++ b/src/seltrans.h @@ -102,7 +102,7 @@ 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 { @@ -117,9 +117,9 @@ private: std::vector _items_affines; std::vector _items_centers; - std::vector > _snap_points; - std::vector > _bbox_points; // the bbox point of the selection as a whole, i.e. max. 4 corners plus optionally some midpoints - std::vector > _bbox_points_for_translating; // the bbox points of each selected item, only to be used for translating + std::vector _snap_points; + std::vector _bbox_points; // the bbox point of the selection as a whole, i.e. max. 4 corners plus optionally some midpoints + std::vector _bbox_points_for_translating; // the bbox points of each selected item, only to be used for translating Inkscape::SelCue _selcue; diff --git a/src/snap-candidate.h b/src/snap-candidate.h new file mode 100644 index 000000000..39386c1ee --- /dev/null +++ b/src/snap-candidate.h @@ -0,0 +1,147 @@ +#ifndef SEEN_SNAP_CANDIDATE_H +#define SEEN_SNAP_CANDIDATE_H + +/** + * \file snap-candidate.h + * \brief some utility classes to store various kinds of snap candidates. + * + * Authors: + * Diederik van Lierop + * + * Copyright (C) 2010 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +//#include "snapped-point.h" +struct SPItem; // forward declaration + +namespace Inkscape { + +enum SnapTargetType { + SNAPTARGET_UNDEFINED = 0, + SNAPTARGET_GRID, + SNAPTARGET_GRID_INTERSECTION, + SNAPTARGET_GUIDE, + SNAPTARGET_GUIDE_INTERSECTION, + SNAPTARGET_GUIDE_ORIGIN, + SNAPTARGET_GRID_GUIDE_INTERSECTION, + SNAPTARGET_NODE_SMOOTH, + SNAPTARGET_NODE_CUSP, + SNAPTARGET_LINE_MIDPOINT, + SNAPTARGET_OBJECT_MIDPOINT, + SNAPTARGET_ROTATION_CENTER, + SNAPTARGET_HANDLE, + SNAPTARGET_PATH, + SNAPTARGET_PATH_INTERSECTION, + SNAPTARGET_BBOX_CORNER, + SNAPTARGET_BBOX_EDGE, + SNAPTARGET_BBOX_EDGE_MIDPOINT, + SNAPTARGET_BBOX_MIDPOINT, + SNAPTARGET_PAGE_BORDER, + SNAPTARGET_PAGE_CORNER, + SNAPTARGET_CONVEX_HULL_CORNER, + SNAPTARGET_ELLIPSE_QUADRANT_POINT, + SNAPTARGET_CENTER, // of ellipse + SNAPTARGET_CORNER, // of image or of rectangle + SNAPTARGET_TEXT_BASELINE, + SNAPTARGET_CONSTRAINED_ANGLE +}; + +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_GUIDE_ORIGIN, + SNAPSOURCE_CONVEX_HULL_CORNER, + SNAPSOURCE_ELLIPSE_QUADRANT_POINT, + SNAPSOURCE_CENTER, // of ellipse + SNAPSOURCE_CORNER, // of image or of rectangle + SNAPSOURCE_TEXT_BASELINE +}; + +/// Class to store data for points which are snap candidates, either as a source or as a target +class SnapCandidatePoint +{ +public: + SnapCandidatePoint(Geom::Point const &point, Inkscape::SnapSourceType const source, long const source_num, Inkscape::SnapTargetType const target, Geom::Rect const &bbox) + : _point(point), _source_type(source), _target_type(target), _source_num(source_num), _target_bbox(bbox) {}; + + SnapCandidatePoint(Geom::Point const &point, Inkscape::SnapSourceType const source, Inkscape::SnapTargetType const target) + : _point(point), _source_type(source), _target_type(target) + { + _source_num = 0; + _target_bbox = Geom::Rect(); + } + + SnapCandidatePoint(Geom::Point const &point, Inkscape::SnapSourceType const source, long const source_num = 0) + : _point(point), _source_type(source), _target_type(Inkscape::SNAPTARGET_UNDEFINED), _source_num(source_num) {_target_bbox = Geom::Rect();} + + inline Geom::Point const & getPoint() const {return _point;} + inline Inkscape::SnapSourceType getSourceType() const {return _source_type;} + inline Inkscape::SnapTargetType getTargetType() const {return _target_type;} + inline long getSourceNum() const {return _source_num;} + inline Geom::Rect const & getTargetBBox() const {return _target_bbox;} + +private: + // Coordinates of the point + Geom::Point _point; + + // If this SnapCandidatePoint is a snap source, then _source_type must be defined. If it + // is a snap target, then _target_type must be defined. If it's yet unknown whether it will + // be a source or target, then both may be defined + Inkscape::SnapSourceType _source_type; + Inkscape::SnapTargetType _target_type; + + //Sequence number of the source point within the set of points that is to be snapped. Starting at zero + long _source_num; + + // If this is a target and it belongs to a bounding box, e.g. when the target type is + // SNAPTARGET_BBOX_EDGE_MIDPOINT, then _target_bbox stores the relevant bounding box + Geom::Rect _target_bbox; +}; + +class SnapCandidateItem +{ +public: + SnapCandidateItem(SPItem* item, bool clip_or_mask, Geom::Matrix _additional_affine) + : item(item), clip_or_mask(clip_or_mask), additional_affine(additional_affine) {} + ~SnapCandidateItem() {}; + + SPItem* item; // An item that is to be considered for snapping to + bool clip_or_mask; // If true, then item refers to a clipping path or a mask + + /* To find out the absolute position of a clipping path or mask, we not only need to know + * the transformation of the clipping path or mask itself, but also the transformation of + * the object to which the clip or mask is being applied; that transformation is stored here + */ + Geom::Matrix additional_affine; +} +; + +class SnapCandidatePath +{ + +public: + SnapCandidatePath(Geom::PathVector* path, SnapTargetType target, bool edited = false) + : path_vector(path), target_type(target), currently_being_edited(edited) {} + ~SnapCandidatePath() {}; + + Geom::PathVector* path_vector; + SnapTargetType target_type; + bool currently_being_edited; // true for the path that's currently being edited in the node tool (if any) + +}; + +} // end of namespace Inkscape + +#endif /* !SEEN_SNAP_CANDIDATE_H */ diff --git a/src/snap.cpp b/src/snap.cpp index bf4c928ad..970f29ece 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -13,7 +13,7 @@ * * Copyright (C) 2006-2007 Johan Engelen * Copyrigth (C) 2004 Nathan Hurst - * Copyright (C) 1999-2009 Authors + * Copyright (C) 1999-2010 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -158,24 +158,25 @@ bool SnapManager::gridSnapperMightSnap() const * because the original position should not be touched, then freeSnap() should be * called instead. * - * PS: SnapManager::setup() must have been called before calling this method, + * PS: + * 1) SnapManager::setup() must have been called before calling this method, * but only once for a set of points + * 2) Only to be used when a single source point is to be snapped; it assumes + * that source_num = 0, which is inefficient when snapping sets our source points * * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred * \param source_type Detailed description of the source type, will be used by the snap indicator - * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, Geom::Point &p, Inkscape::SnapSourceType const source_type, - long source_num, Geom::OptRect const &bbox_to_snap) const { - //TODO: PointType and source_type are somewhat redundant; can't we get rid of the point_type parameter? - Inkscape::SnappedPoint const s = freeSnap(point_type, p, source_type, source_num, bbox_to_snap); + //TODO: SnapCandidatePoint and point_type are somewhat redundant; can't we get rid of the point_type parameter? + Inkscape::SnappedPoint const s = freeSnap(point_type, Inkscape::SnapCandidatePoint(p, source_type), bbox_to_snap); s.getPoint(p); } @@ -192,22 +193,18 @@ void SnapManager::freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point * but only once for a set of points * * \param point_type Category of points to which the source point belongs: node, guide or bounding box - * \param p Current position of the snap source - * \param source_type Detailed description of the source type, will be used by the snap indicator - * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero + * \param p Source point to be snapped * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics */ -Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::SnapSourceType const &source_type, - long source_num, +Inkscape::SnappedPoint SnapManager::freeSnap(Inkscape::SnapPreferences::PointType const point_type, + Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap) const { if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, source_type, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } std::vector *items_to_ignore; @@ -224,14 +221,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, source_type, source_num, bbox_to_snap, items_to_ignore, _unselected_nodes); + (*i)->freeSnap(sc, point_type, p, bbox_to_snap, items_to_ignore, _unselected_nodes); } if (_item_to_ignore) { delete items_to_ignore; } - return findBestSnap(p, source_type, sc, false); + return findBestSnap(p, sc, false); } /** @@ -280,9 +277,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, Inkscape::SNAPSOURCE_UNDEFINED, 0, Geom::OptRect(), NULL, NULL); + snapper->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_NODE, Inkscape::SnapCandidatePoint(t_offset, Inkscape::SNAPSOURCE_UNDEFINED),Geom::OptRect(), NULL, NULL); // Find the best snap for this grid, including intersections of the grid-lines - Inkscape::SnappedPoint s = findBestSnap(t_offset, Inkscape::SNAPSOURCE_UNDEFINED, sc, false); + Inkscape::SnappedPoint s = findBestSnap(Inkscape::SnapCandidatePoint(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 @@ -316,14 +313,17 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t) const * because the original position should not be touched, then constrainedSnap() should * be called instead. * - * PS: SnapManager::setup() must have been called before calling this method, + * PS: + * 1) SnapManager::setup() must have been called before calling this method, * but only once for a set of points + * 2) Only to be used when a single source point is to be snapped; it assumes + * that source_num = 0, which is inefficient when snapping sets our source points + * * \param point_type Category of points to which the source point belongs: node, guide or bounding box * \param p Current position of the snap source; will be overwritten by the position of the snap target if snapping has occurred * \param source_type Detailed description of the source type, will be used by the snap indicator * \param constraint The direction or line along which snapping must occur - * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ @@ -331,10 +331,9 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp Geom::Point &p, Inkscape::SnapSourceType const source_type, Inkscape::Snapper::ConstraintLine const &constraint, - long source_num, Geom::OptRect const &bbox_to_snap) const { - Inkscape::SnappedPoint const s = constrainedSnap(point_type, p, source_type, constraint, source_num, bbox_to_snap); + Inkscape::SnappedPoint const s = constrainedSnap(point_type, Inkscape::SnapCandidatePoint(p, source_type, 0), constraint, bbox_to_snap); s.getPoint(p); } @@ -350,22 +349,18 @@ void SnapManager::constrainedSnapReturnByRef(Inkscape::SnapPreferences::PointTyp * but only once for a set of points * * \param point_type Category of points to which the source point belongs: node, guide or bounding box - * \param p Current position of the snap source - * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param p Source point to be snapped * \param constraint The direction or line along which snapping must occur - * \param source_num Sequence number of the source point within the set of points that is to be snapped. Starting at zero * \param bbox_to_snap Bounding box hulling the set of points, all from the same selection and having the same transformation */ -Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::SnapSourceType const &source_type, +Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::PointType const point_type, + Inkscape::SnapCandidatePoint const &p, Inkscape::Snapper::ConstraintLine const &constraint, - long source_num, Geom::OptRect const &bbox_to_snap) const { if (!someSnapperMightSnap()) { - return Inkscape::SnappedPoint(p, source_type, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + return Inkscape::SnappedPoint(p, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); } std::vector *items_to_ignore; @@ -380,20 +375,21 @@ Inkscape::SnappedPoint SnapManager::constrainedSnap(Inkscape::SnapPreferences::P // First project the mouse pointer onto the constraint - Geom::Point pp = constraint.projection(p); + Geom::Point pp = constraint.projection(p.getPoint()); // Then try to snap the projected point + Inkscape::SnapCandidatePoint candidate(pp, p.getSourceType(), p.getSourceNum(), Inkscape::SNAPTARGET_UNDEFINED, Geom::Rect()); SnappedConstraints sc; SnapperList const snappers = getSnappers(); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, point_type, pp, source_type, source_num, bbox_to_snap, constraint, items_to_ignore); + (*i)->constrainedSnap(sc, point_type, candidate, bbox_to_snap, constraint, items_to_ignore); } if (_item_to_ignore) { delete items_to_ignore; } - return findBestSnap(pp, source_type, sc, true); + return findBestSnap(candidate, sc, true); } /** @@ -418,9 +414,9 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, return; } - Inkscape::SnapSourceType source_type = Inkscape::SNAPSOURCE_GUIDE_ORIGIN; + Inkscape::SnapCandidatePoint candidate(p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN); if (drag_type == SP_DRAG_ROTATE) { - source_type = Inkscape::SNAPSOURCE_GUIDE; + candidate = Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_GUIDE); } // Snap to nodes @@ -433,11 +429,11 @@ void SnapManager::guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), NULL, NULL); + (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), NULL, NULL); } // Snap to intersections of curves, but not to the curves themselves! (see _snapTranslatingGuideToNodes in object-snapper.cpp) - Inkscape::SnappedPoint const s = findBestSnap(p, source_type, sc, false, true); + Inkscape::SnappedPoint const s = findBestSnap(candidate, sc, false, true); s.getPoint(p); } @@ -466,23 +462,23 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) return; } - Inkscape::SnapSourceType source_type = Inkscape::SNAPSOURCE_GUIDE_ORIGIN; + Inkscape::SnapCandidatePoint candidate(p, Inkscape::SNAPSOURCE_GUIDE_ORIGIN, Inkscape::SNAPTARGET_UNDEFINED); // Snap to nodes or paths SnappedConstraints sc; Inkscape::Snapper::ConstraintLine cl(guideline.point_on_line, Geom::rot90(guideline.normal_to_line)); if (object.ThisSnapperMightSnap()) { - object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), cl, NULL); + object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), cl, NULL); } // Snap to guides & grid lines SnapperList snappers = getGridSnappers(); snappers.push_back(&guide); for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); i++) { - (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), cl, NULL); + (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, candidate, Geom::OptRect(), cl, NULL); } - Inkscape::SnappedPoint const s = findBestSnap(p, source_type, sc, false); + Inkscape::SnappedPoint const s = findBestSnap(candidate, sc, false); s.getPoint(p); } @@ -514,7 +510,7 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) 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, @@ -533,13 +529,14 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( ** Also used to globally disable all snapping */ if (someSnapperMightSnap() == false) { - return Inkscape::SnappedPoint(); + return Inkscape::SnappedPoint(pointer); } - std::vector > transformed_points; + std::vector transformed_points; Geom::Rect bbox; - for (std::vector >::const_iterator i = points.begin(); i != points.end(); i++) { + long source_num = 0; + 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); @@ -551,7 +548,8 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( bbox.expandTo(transformed); } - transformed_points.push_back(std::make_pair(transformed, (*i).second)); + transformed_points.push_back(Inkscape::SnapCandidatePoint(transformed, (*i).getSourceType(), source_num)); + source_num++; } /* The current best transformation */ @@ -565,16 +563,16 @@ 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(); - long source_num = 0; + 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).first - origin); // vector to original point + Geom::Point const b = ((*i).getPoint() - origin); // vector to original point if (constrained) { if ((transformation_type == SCALE || transformation_type == STRETCH) && uniform) { @@ -583,18 +581,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).first, component_vectors[dim]); + dedicated_constraint = Inkscape::Snapper::ConstraintLine((*i).getPoint(), 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).first); + dedicated_constraint.setPoint((*i).getPoint()); } // 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).first, static_cast((*j).second), dedicated_constraint, source_num, bbox); + snapped_point = constrainedSnap(type, *j, dedicated_constraint, bbox); } else { bool const c1 = fabs(b[Geom::X]) < 1e-6; bool const c2 = fabs(b[Geom::Y]) < 1e-6; @@ -603,13 +601,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).first, static_cast((*j).second), dedicated_constraint, source_num, bbox); + snapped_point = constrainedSnap(type, *j, dedicated_constraint, bbox); } else { - snapped_point = freeSnap(type, (*j).first, static_cast((*j).second), source_num, bbox); + snapped_point = freeSnap(type, *j, bbox); } } // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl; - snapped_point.setPointerDistance(Geom::L2(pointer - (*i).first)); + snapped_point.setPointerDistance(Geom::L2(pointer - (*i).getPoint())); Geom::Point result; Geom::Point scale_metric(NR_HUGE, NR_HUGE); @@ -623,7 +621,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( switch (transformation_type) { case TRANSLATION: - result = snapped_point.getPoint() - (*i).first; + result = snapped_point.getPoint() - (*i).getPoint(); /* 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 @@ -673,7 +671,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( snapped_point.setSecondSnapDistance(NR_HUGE); break; case SKEW: - result[0] = (snapped_point.getPoint()[dim] - ((*i).first)[dim]) / (((*i).first)[1 - dim] - origin[1 - dim]); // skew factor + result[0] = (snapped_point.getPoint()[dim] - ((*i).getPoint())[dim]) / (((*i).getPoint())[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])); @@ -716,7 +714,6 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( } j++; - source_num++; } Geom::Coord best_metric; @@ -755,12 +752,13 @@ 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, std::make_pair(_transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); @@ -778,13 +776,14 @@ 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, std::make_pair(_transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, true, constraint, TRANSLATION, tr, Geom::Point(0,0), Geom::X, false); @@ -803,13 +802,14 @@ 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, std::make_pair(_transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, false, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); @@ -828,14 +828,15 @@ 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, std::make_pair(_transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); @@ -855,7 +856,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, @@ -863,7 +864,8 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(Inkscape::SnapPrefere bool u) const { if (p.size() == 1) { - _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), STRETCH, Geom::Point(s, s), o, d, u), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), STRETCH, Geom::Point(s, s), o, d, u); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, true, Geom::Point(0,0), STRETCH, Geom::Point(s, s), o, d, u); @@ -883,7 +885,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, @@ -900,7 +902,8 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference g_assert(!(point_type & Inkscape::SnapPreferences::SNAPPOINT_BBOX)); if (p.size() == 1) { - _displaySnapsource(point_type, std::make_pair(_transformPoint(p.at(0), SKEW, s, o, d, false), (p.at(0)).second)); + Geom::Point pt = _transformPoint(p.at(0), SKEW, s, o, d, false); + _displaySnapsource(point_type, Inkscape::SnapCandidatePoint(pt, p.at(0).getSourceType())); } return _snapTransformed(point_type, p, pointer, true, constraint, SKEW, s, o, d, false); @@ -910,17 +913,15 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapSkew(Inkscape::SnapPreference * \brief Given a set of possible snap targets, find the best target (which is not necessarily * also the nearest target), and show the snap indicator if requested * - * \param p Current position of the snap source - * \param source_type Detailed description of the source type, will be used by the snap indicator + * \param p Source point to be snapped * \param sc A structure holding all snap targets that have been found so far * \param constrained True if the snap is constrained, e.g. for stretching or for purely horizontal translation. - * \param noCurves If true, then do consider snapping to intersections of curves, but not to the curves themself + * \param noCurves If true, then do consider snapping to intersections of curves, but not to the curves themselves * \return An instance of the SnappedPoint class, which holds data on the snap source, snap target, and various metrics */ -Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, - Inkscape::SnapSourceType const source_type, - SnappedConstraints &sc, +Inkscape::SnappedPoint SnapManager::findBestSnap(Inkscape::SnapCandidatePoint const &p, + SnappedConstraints const &sc, bool constrained, bool noCurves) const { @@ -954,8 +955,8 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, if (snapprefs.getSnapIntersectionCS()) { // search for the closest snapped intersection of curves Inkscape::SnappedPoint closestCurvesIntersection; - if (getClosestIntersectionCS(sc.curves, p, closestCurvesIntersection, _desktop->dt2doc())) { - closestCurvesIntersection.setSource(source_type); + if (getClosestIntersectionCS(sc.curves, p.getPoint(), closestCurvesIntersection, _desktop->dt2doc())) { + closestCurvesIntersection.setSource(p.getSourceType()); sp_list.push_back(closestCurvesIntersection); } } @@ -982,7 +983,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, // search for the closest snapped intersection of grid lines Inkscape::SnappedPoint closestGridPoint; if (getClosestIntersectionSL(sc.grid_lines, closestGridPoint)) { - closestGridPoint.setSource(source_type); + closestGridPoint.setSource(p.getSourceType()); closestGridPoint.setTarget(Inkscape::SNAPTARGET_GRID_INTERSECTION); sp_list.push_back(closestGridPoint); } @@ -990,7 +991,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, // search for the closest snapped intersection of guide lines Inkscape::SnappedPoint closestGuidePoint; if (getClosestIntersectionSL(sc.guide_lines, closestGuidePoint)) { - closestGuidePoint.setSource(source_type); + closestGuidePoint.setSource(p.getSourceType()); closestGuidePoint.setTarget(Inkscape::SNAPTARGET_GUIDE_INTERSECTION); sp_list.push_back(closestGuidePoint); } @@ -999,7 +1000,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, if (snapprefs.getSnapIntersectionGG()) { Inkscape::SnappedPoint closestGridGuidePoint; if (getClosestIntersectionSL(sc.grid_lines, sc.guide_lines, closestGridGuidePoint)) { - closestGridGuidePoint.setSource(source_type); + closestGridGuidePoint.setSource(p.getSourceType()); closestGridGuidePoint.setTarget(Inkscape::SNAPTARGET_GRID_GUIDE_INTERSECTION); sp_list.push_back(closestGridGuidePoint); } @@ -1007,11 +1008,11 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, } // now let's see which snapped point gets a thumbs up - Inkscape::SnappedPoint bestSnappedPoint = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_UNDEFINED, 0, Inkscape::SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false); + Inkscape::SnappedPoint bestSnappedPoint(p.getPoint()); // 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 - // std::cout << "sp = " << from_2geom((*i).getPoint()); + // std::cout << "sp = " << (*i).getPoint() << " | source = " << (*i).getSource() << " | target = " << (*i).getTarget(); if ((*i).getSnapDistance() <= (*i).getTolerance()) { // if it's the first point, or if it is closer than the best snapped point so far if (i == sp_list.begin() || bestSnappedPoint.isOtherSnapBetter(*i, false)) { @@ -1054,7 +1055,7 @@ Inkscape::SnappedPoint SnapManager::findBestSnap(Geom::Point const &p, void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, SPItem const *item_to_ignore, - std::vector > *unselected_nodes, + std::vector *unselected_nodes, SPGuide *guide_to_ignore) { g_assert(desktop != NULL); @@ -1085,7 +1086,7 @@ void SnapManager::setup(SPDesktop const *desktop, void SnapManager::setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, - std::vector > *unselected_nodes, + std::vector *unselected_nodes, SPGuide *guide_to_ignore) { g_assert(desktop != NULL); @@ -1114,7 +1115,7 @@ SPDocument *SnapManager::getDocument() const * \return The position of the point after transformation */ -Geom::Point SnapManager::_transformPoint(std::pair const &p, +Geom::Point SnapManager::_transformPoint(Inkscape::SnapCandidatePoint const &p, Transformation const transformation_type, Geom::Point const &transformation, Geom::Point const &origin, @@ -1125,10 +1126,10 @@ Geom::Point SnapManager::_transformPoint(std::pair const &p, Geom::Point transformed; switch (transformation_type) { case TRANSLATION: - transformed = p.first + transformation; + transformed = p.getPoint() + transformation; break; case SCALE: - transformed = (p.first - origin) * Geom::Scale(transformation[Geom::X], transformation[Geom::Y]) + origin; + transformed = (p.getPoint() - origin) * Geom::Scale(transformation[Geom::X], transformation[Geom::Y]) + origin; break; case STRETCH: { @@ -1139,15 +1140,15 @@ Geom::Point SnapManager::_transformPoint(std::pair const &p, s[dim] = transformation[dim]; s[1 - dim] = 1; } - transformed = ((p.first - origin) * s) + origin; + transformed = ((p.getPoint() - origin) * s) + origin; break; } case SKEW: // Apply the skew factor - transformed[dim] = (p.first)[dim] + transformation[0] * ((p.first)[1 - dim] - origin[1 - dim]); + transformed[dim] = (p.getPoint())[dim] + transformation[0] * ((p.getPoint())[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.first - origin)[1 - dim] * transformation[1] + origin[1 - dim]; + transformed[1-dim] = (p.getPoint() - origin)[1 - dim] * transformation[1] + origin[1 - dim]; break; default: g_assert_not_reached(); @@ -1163,7 +1164,7 @@ Geom::Point SnapManager::_transformPoint(std::pair const &p, * \param p The transformed position of the source point, paired with an identifier of the type of the snap source. */ -void SnapManager::_displaySnapsource(Inkscape::SnapPreferences::PointType point_type, std::pair const &p) const { +void SnapManager::_displaySnapsource(Inkscape::SnapPreferences::PointType point_type, Inkscape::SnapCandidatePoint 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 413b753d1..40bf0996e 100644 --- a/src/snap.h +++ b/src/snap.h @@ -20,7 +20,7 @@ * * Copyright (C) 2006-2007 Johan Engelen * Copyright (C) 2000-2002 Lauris Kaplinski - * Copyright (C) 2000-2009 Authors + * Copyright (C) 2000-2010 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -69,13 +69,13 @@ public: void setup(SPDesktop const *desktop, bool snapindicator = true, SPItem const *item_to_ignore = NULL, - std::vector > *unselected_nodes = NULL, + std::vector *unselected_nodes = NULL, SPGuide *guide_to_ignore = NULL); void setup(SPDesktop const *desktop, bool snapindicator, std::vector &items_to_ignore, - std::vector > *unselected_nodes = NULL, + std::vector *unselected_nodes = NULL, SPGuide *guide_to_ignore = NULL); // freeSnapReturnByRef() is preferred over freeSnap(), because it only returns a @@ -83,14 +83,10 @@ public: void freeSnapReturnByRef(Inkscape::SnapPreferences::PointType point_type, Geom::Point &p, Inkscape::SnapSourceType const source_type, - long source_num = 0, Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; - - Inkscape::SnappedPoint freeSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::SnapSourceType const &source_type, - long source_num = 0, + Inkscape::SnappedPoint freeSnap(Inkscape::SnapPreferences::PointType const point_type, + Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap = Geom::OptRect() ) const; Geom::Point multipleOfGridPitch(Geom::Point const &t) const; @@ -101,44 +97,41 @@ public: Geom::Point &p, Inkscape::SnapSourceType const source_type, Inkscape::Snapper::ConstraintLine const &constraint, - long source_num = 0, Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; - Inkscape::SnappedPoint constrainedSnap(Inkscape::SnapPreferences::PointType point_type, - Geom::Point const &p, - Inkscape::SnapSourceType const &source_type, + Inkscape::SnappedPoint constrainedSnap(Inkscape::SnapPreferences::PointType const point_type, + Inkscape::SnapCandidatePoint const &p, Inkscape::Snapper::ConstraintLine const &constraint, - long source_num = 0, Geom::OptRect const &bbox_to_snap = Geom::OptRect()) const; void guideFreeSnap(Geom::Point &p, Geom::Point const &guide_normal, SPGuideDragType drag_type) const; void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) 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, @@ -146,7 +139,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 @@ -167,7 +160,7 @@ public: bool getSnapIndicator() const {return _snapindicator;} - Inkscape::SnappedPoint findBestSnap(Geom::Point const &p, Inkscape::SnapSourceType const source_type, SnappedConstraints &sc, bool constrained, bool noCurves = false) const; + Inkscape::SnappedPoint findBestSnap(Inkscape::SnapCandidatePoint const &p, SnappedConstraints const &sc, bool constrained, bool noCurves = false) const; protected: SPNamedView const *_named_view; @@ -178,13 +171,13 @@ private: SPGuide *_guide_to_ignore; ///< A guide that should not be snapped to, e.g. the guide that is currently being dragged SPDesktop const *_desktop; bool _snapindicator; ///< When true, an indicator will be drawn at the position that was being snapped to - std::vector > *_unselected_nodes; ///< Nodes of the path that is currently being edited and which have not been selected and which will therefore be stationary. Only these nodes will be considered for snapping to. Of each unselected node both the position (Geom::Point) and the type (Inkscape::SnapTargetType) will be stored + std::vector *_unselected_nodes; ///< Nodes of the path that is currently being edited and which have not been selected and which will therefore be stationary. Only these nodes will be considered for snapping to. Of each unselected node both the position (Geom::Point) and the type (Inkscape::SnapTargetType) will be stored //TODO: Make _unselected_nodes type safe; in the line above int is used for Inkscape::SnapTargetType, but if I remember //correctly then in other cases the int is being used for Inkscape::SnapSourceType, or for both. How to make //this type safe? 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, @@ -194,14 +187,14 @@ private: Geom::Dim2 dim, bool uniform) const; - Geom::Point _transformPoint(std::pair const &p, + Geom::Point _transformPoint(Inkscape::SnapCandidatePoint 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, std::pair const &p) const; + void _displaySnapsource(Inkscape::SnapPreferences::PointType point_type, Inkscape::SnapCandidatePoint const &p) const; }; #endif /* !SEEN_SNAP_H */ diff --git a/src/snapped-point.cpp b/src/snapped-point.cpp index 102e761b9..e3559d655 100644 --- a/src/snapped-point.cpp +++ b/src/snapped-point.cpp @@ -25,6 +25,24 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const _second_always_snap = false; _transformation = Geom::Point(1,1); _pointer_distance = NR_HUGE; + _target_bbox = Geom::Rect(); +} + +Inkscape::SnappedPoint::SnappedPoint(Inkscape::SnapCandidatePoint const &p, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained) + : _target(target), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a) +{ + _point = p.getPoint(); + _source = p.getSourceType(); + _source_num = p.getSourceNum(); + _at_intersection = false; + _fully_constrained = fully_constrained; + _second_distance = NR_HUGE; + _second_tolerance = 1; + _second_always_snap = false; + _transformation = Geom::Point(1,1); + _pointer_distance = NR_HUGE; + _target_bbox = Geom::Rect(); + } Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, 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) @@ -35,6 +53,7 @@ Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const // isOtherSnapBetter. We don't want a division by zero. _transformation = Geom::Point(1,1); _pointer_distance = NR_HUGE; + _target_bbox = Geom::Rect(); } Inkscape::SnappedPoint::SnappedPoint() @@ -53,6 +72,26 @@ Inkscape::SnappedPoint::SnappedPoint() _second_always_snap = false; _transformation = Geom::Point(1,1); _pointer_distance = NR_HUGE; + _target_bbox = Geom::Rect(); +} + +Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p) +{ + _point = p; + _source = SNAPSOURCE_UNDEFINED, + _source_num = 0, + _target = SNAPTARGET_UNDEFINED, + _at_intersection = false; + _fully_constrained = false; + _distance = NR_HUGE; + _tolerance = 1; + _always_snap = false; + _second_distance = NR_HUGE; + _second_tolerance = 1; + _second_always_snap = false; + _transformation = Geom::Point(1,1); + _pointer_distance = NR_HUGE; + _target_bbox = Geom::Rect(); } Inkscape::SnappedPoint::~SnappedPoint() @@ -69,7 +108,7 @@ void Inkscape::SnappedPoint::getPoint(Geom::Point &p) const } // search for the closest snapped point -bool getClosestSP(std::list &list, Inkscape::SnappedPoint &result) +bool getClosestSP(std::list const &list, Inkscape::SnappedPoint &result) { bool success = false; @@ -86,6 +125,10 @@ bool getClosestSP(std::list &list, Inkscape::SnappedPoin bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &other_one, bool weighted) const { + if (!other_one.getSnapped()) { + return false; + } + double dist_other = other_one.getSnapDistance(); double dist_this = getSnapDistance(); diff --git a/src/snapped-point.h b/src/snapped-point.h index c793ffa8d..1497802c0 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -16,70 +16,21 @@ #include #include //Because of NR_HUGE #include <2geom/geom.h> +#include namespace Inkscape { -enum SnapTargetType { - SNAPTARGET_UNDEFINED = 0, - SNAPTARGET_GRID, - SNAPTARGET_GRID_INTERSECTION, - SNAPTARGET_GUIDE, - SNAPTARGET_GUIDE_INTERSECTION, - SNAPTARGET_GUIDE_ORIGIN, - SNAPTARGET_GRID_GUIDE_INTERSECTION, - SNAPTARGET_NODE_SMOOTH, - SNAPTARGET_NODE_CUSP, - SNAPTARGET_LINE_MIDPOINT, - SNAPTARGET_OBJECT_MIDPOINT, - SNAPTARGET_ROTATION_CENTER, - SNAPTARGET_HANDLE, - SNAPTARGET_PATH, - SNAPTARGET_PATH_INTERSECTION, - SNAPTARGET_BBOX_CORNER, - SNAPTARGET_BBOX_EDGE, - SNAPTARGET_BBOX_EDGE_MIDPOINT, - SNAPTARGET_BBOX_MIDPOINT, - SNAPTARGET_PAGE_BORDER, - SNAPTARGET_PAGE_CORNER, - SNAPTARGET_CONVEX_HULL_CORNER, - SNAPTARGET_ELLIPSE_QUADRANT_POINT, - SNAPTARGET_CENTER, // of ellipse - SNAPTARGET_CORNER, // of image or of rectangle - SNAPTARGET_TEXT_BASELINE, - SNAPTARGET_CONSTRAINED_ANGLE -}; - -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_GUIDE_ORIGIN, - SNAPSOURCE_CONVEX_HULL_CORNER, - SNAPSOURCE_ELLIPSE_QUADRANT_POINT, - SNAPSOURCE_CENTER, // of ellipse - SNAPSOURCE_CORNER, // of image or of rectangle - SNAPSOURCE_TEXT_BASELINE -}; - - /// Class describing the result of an attempt to snap. class SnappedPoint { public: SnappedPoint(); + SnappedPoint(Geom::Point const &p); SnappedPoint(Geom::Point const &p, SnapSourceType const &source, long source_num, 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, long source_num, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained); + SnappedPoint(SnapCandidatePoint const &p, 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;} @@ -114,6 +65,8 @@ public: void setTransformation(Geom::Point const t) {_transformation = t;} void setTarget(SnapTargetType const target) {_target = target;} SnapTargetType getTarget() const {return _target;} + void setTargetBBox(Geom::Rect const target) {_target_bbox = target;} + Geom::Rect & getTargetBBox() {return _target_bbox;} void setSource(SnapSourceType const source) {_source = source;} SnapSourceType getSource() const {return _source;} long getSourceNum() const {return _source_num;} @@ -164,13 +117,15 @@ protected: bool _second_always_snap; /* The transformation (translation, scale, skew, or stretch) from the original point to the snapped point */ Geom::Point _transformation; + /* The bounding box we've snapped to (when applicable); will be used by the snapindicator */ + Geom::Rect _target_bbox; /* Distance from the un-transformed point to the mouse pointer, measured at the point in time when dragging started */ Geom::Coord _pointer_distance; }; }// end of namespace Inkscape -bool getClosestSP(std::list &list, Inkscape::SnappedPoint &result); +bool getClosestSP(std::list const &list, Inkscape::SnappedPoint &result); #endif /* !SEEN_SNAPPEDPOINT_H */ diff --git a/src/snapper.cpp b/src/snapper.cpp index 751b663e3..fb7281c30 100644 --- a/src/snapper.cpp +++ b/src/snapper.cpp @@ -19,9 +19,9 @@ * \param d Snap tolerance. */ Inkscape::Snapper::Snapper(SnapManager *sm, Geom::Coord const /*t*/) : - _snapmanager(sm), - _snap_enabled(true), - _snap_visible_only(true) + _snapmanager(sm), + _snap_enabled(true), + _snap_visible_only(true) { g_assert(_snapmanager != NULL); } diff --git a/src/snapper.h b/src/snapper.h index dcc0fbb81..dbbf7ebe9 100644 --- a/src/snapper.h +++ b/src/snapper.h @@ -20,6 +20,7 @@ #include "snapped-line.h" #include "snapped-curve.h" #include "snap-preferences.h" +#include "snap-candidate.h" struct SnappedConstraints { std::list points; @@ -34,7 +35,6 @@ struct SPItem; namespace Inkscape { - /// Parent for classes that can snap points to something class Snapper { @@ -59,12 +59,10 @@ public: virtual void freeSnap(SnappedConstraints &/*sc*/, SnapPreferences::PointType const &/*t*/, - Geom::Point const &/*p*/, - SnapSourceType const &/*source_type*/, - long /*source_num*/, + Inkscape::SnapCandidatePoint const &/*p*/, Geom::OptRect const &/*bbox_to_snap*/, std::vector const */*it*/, - std::vector > */*unselected_nodes*/) const {}; + std::vector */*unselected_nodes*/) const {}; class ConstraintLine { @@ -104,9 +102,7 @@ public: virtual void constrainedSnap(SnappedConstraints &/*sc*/, SnapPreferences::PointType const &/*t*/, - Geom::Point const &/*p*/, - SnapSourceType const &/*source_type*/, - long /*source_num*/, + Inkscape::SnapCandidatePoint const &/*p*/, Geom::OptRect const &/*bbox_to_snap*/, ConstraintLine const &/*c*/, std::vector const */*it*/) const {}; diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index 12ba0ed0e..88fc59f17 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -29,11 +29,10 @@ #include #include <2geom/transforms.h> #include <2geom/pathvector.h> - #include "document.h" #include "sp-ellipse.h" - #include "preferences.h" +#include "snap-candidate.h" /* Common parent class */ @@ -73,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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_genericellipse_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); static void sp_genericellipse_set_shape(SPShape *shape); static void sp_genericellipse_update_patheffect (SPLPEItem *lpeitem, bool write); @@ -270,15 +269,15 @@ static void sp_genericellipse_set_shape(SPShape *shape) curve->unref(); } -static void sp_genericellipse_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +static void sp_genericellipse_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs) { g_assert(item != NULL); g_assert(SP_IS_GENERICELLIPSE(item)); // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes - if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { - return; - } + if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { + return; + } SPGenericEllipse *ellipse = SP_GENERICELLIPSE(item); sp_genericellipse_normalize(ellipse); @@ -305,19 +304,19 @@ static void sp_genericellipse_snappoints(SPItem const *item, bool const target, // 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) { - 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))); - } - } + double angle = 0; + for (angle = 0; angle < SP_2PI; angle += M_PI_2) { + if (angle >= ellipse->start && angle <= ellipse->end) { + pt = Geom::Point(cx + cos(angle)*rx, cy + sin(angle)*ry) * i2d; + p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_ELLIPSE_QUADRANT_POINT, Inkscape::SNAPTARGET_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()) { - pt = Geom::Point(cx, cy) * i2d; - p.push_back(std::make_pair(pt, target ? int(Inkscape::SNAPTARGET_CENTER) : int(Inkscape::SNAPSOURCE_CENTER))); + pt = Geom::Point(cx, cy) * i2d; + p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_CENTER, Inkscape::SNAPTARGET_CENTER)); } // And if we have a slice, also snap to the endpoints @@ -325,12 +324,12 @@ static void sp_genericellipse_snappoints(SPItem const *item, bool const target, // Add the start point, if it's not coincident with a quadrant point if (fmod(ellipse->start, M_PI_2) != 0.0 ) { 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))); + p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } // Add the end point, if it's not coincident with a quadrant point if (fmod(ellipse->end, M_PI_2) != 0.0 ) { 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))); + p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } } } diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index 53bcd425d..b01146d60 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -49,7 +49,7 @@ static void sp_flowtext_set(SPObject *object, unsigned key, gchar const *value); static void sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); static void sp_flowtext_print(SPItem *item, SPPrintContext *ctx); static gchar *sp_flowtext_description(SPItem *item); -static void sp_flowtext_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_flowtext_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); static NRArenaItem *sp_flowtext_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags); static void sp_flowtext_hide(SPItem *item, unsigned key); @@ -384,7 +384,7 @@ static gchar *sp_flowtext_description(SPItem *item) } } -static void sp_flowtext_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const */*snapprefs*/) +static void sp_flowtext_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const */*snapprefs*/) { // Choose a point on the baseline for snapping from or to, with the horizontal position // of this point depending on the text alignment (left vs. right) @@ -392,8 +392,7 @@ static void sp_flowtext_snappoints(SPItem const *item, bool const target, SnapPo if (layout != NULL && layout->outputExists()) { boost::optional pt = layout->baselineAnchorPoint(); if (pt) { - int type = target ? int(Inkscape::SNAPTARGET_TEXT_BASELINE) : int(Inkscape::SNAPSOURCE_TEXT_BASELINE); - p.push_back(std::make_pair((*pt) * sp_item_i2d_affine(item), type)); + p.push_back(Inkscape::SnapCandidatePoint((*pt) * sp_item_i2d_affine(item), Inkscape::SNAPSOURCE_TEXT_BASELINE, Inkscape::SNAPTARGET_TEXT_BASELINE)); } } } diff --git a/src/sp-image.cpp b/src/sp-image.cpp index e3f708142..daf5e9e88 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -44,7 +44,7 @@ #include #include "xml/quote.h" #include - +#include "snap-candidate.h" #include "libnr/nr-matrix-fns.h" #include "io/sys.h" @@ -86,7 +86,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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_image_snappoints(SPItem const *item, std::vector &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); @@ -1332,7 +1332,7 @@ sp_image_update_canvas_image (SPImage *image) } } -static void sp_image_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const */*snapprefs*/) +static void sp_image_snappoints(SPItem const *item, std::vector &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 @@ -1354,12 +1354,10 @@ static void sp_image_snappoints(SPItem const *item, bool const target, SnapPoint double const x1 = x0 + image.width.computed; double const y1 = y0 + image.height.computed; Geom::Matrix const i2d (sp_item_i2d_affine (item)); - Geom::Point pt; - int type = target ? int(Inkscape::SNAPTARGET_CORNER) : int(Inkscape::SNAPSOURCE_CORNER); - 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)); + p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y0) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y1) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x1, y1) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x1, y0) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); } } diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 3845be232..a773bd4a2 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -69,7 +69,7 @@ static void sp_group_print (SPItem * item, SPPrintContext *ctx); static gchar * sp_group_description (SPItem * item); 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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_group_snappoints (SPItem const *item, std::vector &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, bool write); @@ -320,14 +320,14 @@ sp_group_hide (SPItem *item, unsigned int key) SP_GROUP(item)->group->hide(key); } -static void sp_group_snappoints (SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +static void sp_group_snappoints (SPItem const *item, std::vector &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), target, p, snapprefs); + sp_item_snappoints(SP_ITEM(o), p, snapprefs); } } } diff --git a/src/sp-item-notify-moveto.cpp b/src/sp-item-notify-moveto.cpp index 0bc08a235..628d77956 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 ); - SnapPointsWithType snappoints; - sp_item_snappoints(&item, false, snappoints, NULL); + std::vector snappoints; + sp_item_snappoints(&item, snappoints, NULL); g_return_if_fail( snappoint_ix < int(snappoints.size()) ); - double const pos0 = dot(dir, snappoints[snappoint_ix].first); + double const pos0 = dot(dir, snappoints[snappoint_ix].getPoint()); /// \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 246453241..792a9d3bf 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; } - SnapPointsWithType snappoints; - sp_item_snappoints(&item, false, snappoints, NULL); + std::vector snappoints; + sp_item_snappoints(&item, 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].first), 0) ) { + if (!approx_equal( sp_guide_distance_from_pt(cn.g, snappoints[snappoint_ix].getPoint()), 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 bebd65021..51da1679d 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) { - SnapPointsWithType snappoints; - sp_item_snappoints(&item, false, snappoints, NULL); + std::vector snappoints; + sp_item_snappoints(&item, 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 1a5ca6f77..c28940fca 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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_item_private_snappoints(SPItem const *item, std::vector &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); @@ -949,7 +949,7 @@ Geom::OptRect sp_item_bbox_desktop(SPItem *item, SPItem::BBoxType type) return rect; } -static void sp_item_private_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const */*snapprefs*/) +static void sp_item_private_snappoints(SPItem const *item, std::vector &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 @@ -962,16 +962,15 @@ static void sp_item_private_snappoints(SPItem const *item, bool const target, Sn Geom::Point p1, p2; p1 = bbox->min(); p2 = bbox->max(); - int type = target ? int(Inkscape::SNAPTARGET_BBOX_CORNER) : int(Inkscape::SNAPSOURCE_BBOX_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(p2[Geom::X], p1[Geom::Y]), type)); + p.push_back(Inkscape::SnapCandidatePoint(p1, Inkscape::SNAPSOURCE_BBOX_CORNER, Inkscape::SNAPTARGET_BBOX_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(p1[Geom::X], p2[Geom::Y]), Inkscape::SNAPSOURCE_BBOX_CORNER, Inkscape::SNAPTARGET_BBOX_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(p2, Inkscape::SNAPSOURCE_BBOX_CORNER, Inkscape::SNAPTARGET_BBOX_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(p2[Geom::X], p1[Geom::Y]), Inkscape::SNAPSOURCE_BBOX_CORNER, Inkscape::SNAPTARGET_BBOX_CORNER)); } } -void sp_item_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +void sp_item_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs) { g_assert (item != NULL); g_assert (SP_IS_ITEM(item)); @@ -979,12 +978,12 @@ void sp_item_snappoints(SPItem const *item, bool const target, SnapPointsWithTyp // 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, target, p, snapprefs); + item_class.snappoints(item, p, snapprefs); } // Get the snappoints at the item's center if (snapprefs != NULL && snapprefs->getIncludeItemCenter()) { - p.push_back(std::make_pair(item->getCenter(), target ? int(Inkscape::SNAPTARGET_ROTATION_CENTER) : int(Inkscape::SNAPSOURCE_ROTATION_CENTER))); + p.push_back(Inkscape::SnapCandidatePoint(item->getCenter(), Inkscape::SNAPSOURCE_ROTATION_CENTER, Inkscape::SNAPTARGET_ROTATION_CENTER)); } // Get the snappoints of clipping paths and mask, if any @@ -999,15 +998,15 @@ void sp_item_snappoints(SPItem const *item, bool const target, SnapPointsWithTyp // 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)) { - SnapPointsWithType p_clip_or_mask; + std::vector p_clip_or_mask; // Please note the recursive call here! - sp_item_snappoints(SP_ITEM(child), target, p_clip_or_mask, snapprefs); + sp_item_snappoints(SP_ITEM(child), p_clip_or_mask, snapprefs); // Take into account the transformation of the item being clipped or masked - for (SnapPointsWithType::const_iterator p_orig = p_clip_or_mask.begin(); p_orig != p_clip_or_mask.end(); p_orig++) { + for (std::vector::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 - Geom::Point pt = desktop->dt2doc((*p_orig).first) * sp_item_i2d_affine(item); - p.push_back(std::make_pair(pt, (*p_orig).second)); + Geom::Point pt = desktop->dt2doc((*p_orig).getPoint()) * sp_item_i2d_affine(item); + p.push_back(Inkscape::SnapCandidatePoint(pt, (*p_orig).getSourceType(), (*p_orig).getTargetType())); } } } diff --git a/src/sp-item.h b/src/sp-item.h index 639a1b4a2..faf64846e 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -26,14 +26,14 @@ #include <2geom/forward.h> #include #include -#include +#include "snap-candidate.h" class SPGuideConstraint; struct SPClipPathReference; struct SPMaskReference; struct SPAvoidRef; struct SPPrintContext; -namespace Inkscape { class URIReference; } +namespace Inkscape { class URIReference;} enum { SP_EVENT_INVALID, @@ -171,8 +171,6 @@ private: mutable EvaluatedStatus _evaluated_status; }; -typedef std::vector > SnapPointsWithType; // int is either of these enums: Inkscape::SnapTargetType or Inkscape::SnapSourceType - /// The SPItem vtable. struct SPItemClass { SPObjectClass parent_class; @@ -193,7 +191,7 @@ struct SPItemClass { /** Write to an iterator the points that should be considered for snapping * as the item's `nodes'. */ - void (* snappoints) (SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); + void (* snappoints) (SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); /** Apply the transform optimally, and return any residual transformation */ Geom::Matrix (* set_transform)(SPItem *item, Geom::Matrix const &transform); @@ -226,7 +224,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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +void sp_item_snappoints(SPItem const *item, std::vector &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 ae0f7bf19..556778676 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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_offset_snappoints(SPItem const *item, std::vector &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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +static void sp_offset_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs) { if (((SPItemClass *) parent_class)->snappoints) { - ((SPItemClass *) parent_class)->snappoints (item, target, p, snapprefs); + ((SPItemClass *) parent_class)->snappoints (item, p, snapprefs); } } diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp index aa026abb3..d42fd0e9f 100644 --- a/src/sp-rect.cpp +++ b/src/sp-rect.cpp @@ -46,7 +46,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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_rect_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); static SPShapeClass *parent_class; @@ -552,7 +552,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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +static void sp_rect_snappoints(SPItem const *item, std::vector &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 @@ -565,9 +565,9 @@ static void sp_rect_snappoints(SPItem const *item, bool const target, SnapPoints g_assert(SP_IS_RECT(item)); // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes - if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { - return; - } + if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { + return; + } SPRect *rect = SP_RECT(item); @@ -578,28 +578,23 @@ static void sp_rect_snappoints(SPItem const *item, bool const target, SnapPoints 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()) { - type = target ? int(Inkscape::SNAPTARGET_CORNER) : int(Inkscape::SNAPSOURCE_CORNER); - 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)); + p.push_back(Inkscape::SnapCandidatePoint(p0, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(p1, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(p2, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); + p.push_back(Inkscape::SnapCandidatePoint(p3, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); } - if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping) - 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) - type = target ? int(Inkscape::SNAPTARGET_OBJECT_MIDPOINT) : int(Inkscape::SNAPSOURCE_OBJECT_MIDPOINT); - p.push_back(std::make_pair((p0 + p2)/2, type)); - } + if (snapprefs->getSnapLineMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping) + p.push_back(Inkscape::SnapCandidatePoint((p0 + p1)/2, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + p.push_back(Inkscape::SnapCandidatePoint((p1 + p2)/2, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + p.push_back(Inkscape::SnapCandidatePoint((p2 + p3)/2, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + p.push_back(Inkscape::SnapCandidatePoint((p3 + p0)/2, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + } + + if (snapprefs->getSnapObjectMidpoints()) { // only do this when we're snapping nodes (enforce strict snapping) + p.push_back(Inkscape::SnapCandidatePoint((p0 + p2)/2, Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); + } } diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 519002e9e..de5648137 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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_shape_snappoints (SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); static void sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai); @@ -1149,7 +1149,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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +static void sp_shape_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs) { g_assert(item != NULL); g_assert(SP_IS_SHAPE(item)); @@ -1161,7 +1161,7 @@ static void sp_shape_snappoints(SPItem const *item, bool const target, SnapPoint // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { - return; + return; } Geom::PathVector const &pathv = shape->curve->get_pathvector(); @@ -1170,20 +1170,16 @@ static void sp_shape_snappoints(SPItem const *item, bool const target, SnapPoint 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) { - type = target ? int(Inkscape::SNAPTARGET_OBJECT_MIDPOINT) : int(Inkscape::SNAPSOURCE_OBJECT_MIDPOINT); - p.push_back(std::make_pair(bbox->midpoint(), type)); - } - } + if (snapprefs->getSnapObjectMidpoints()) { + Geom::OptRect bbox = item->getBounds(sp_item_i2d_affine(item)); + if (bbox) { + p.push_back(Inkscape::SnapCandidatePoint(bbox->midpoint(), Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); + } + } for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { if (snapprefs->getSnapToItemNode()) { - type = target ? int(Inkscape::SNAPTARGET_NODE_CUSP) : int(Inkscape::SNAPSOURCE_NODE_CUSP); - p.push_back(std::make_pair(path_it->initialPoint() * i2d, type)); + p.push_back(Inkscape::SnapCandidatePoint(path_it->initialPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve @@ -1202,17 +1198,15 @@ static void sp_shape_snappoints(SPItem const *item, bool const target, SnapPoint bool c2 = snapprefs->getSnapSmoothNodes() && (nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM); if (c1 || c2) { - type = target ? int(Inkscape::SNAPTARGET_NODE_CUSP) : int(Inkscape::SNAPSOURCE_NODE_CUSP); - p.push_back(std::make_pair(curve_it1->finalPoint() * i2d, type)); + p.push_back(Inkscape::SnapCandidatePoint(curve_it1->finalPoint() * i2d, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP)); } - // 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))) { - 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)); - } - } + // 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.push_back(Inkscape::SnapCandidatePoint(Geom::middle_point(*line_segment) * i2d, Inkscape::SNAPSOURCE_LINE_MIDPOINT, Inkscape::SNAPTARGET_LINE_MIDPOINT)); + } + } ++curve_it1; ++curve_it2; @@ -1226,8 +1220,7 @@ static void sp_shape_snappoints(SPItem const *item, bool const target, SnapPoint 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); - type = target ? int(Inkscape::SNAPTARGET_PATH_INTERSECTION) : int(Inkscape::SNAPSOURCE_PATH_INTERSECTION); - p.push_back(std::make_pair(p_ix * i2d, type)); + p.push_back(Inkscape::SnapCandidatePoint(p_ix * i2d, Inkscape::SNAPSOURCE_PATH_INTERSECTION, Inkscape::SNAPTARGET_PATH_INTERSECTION)); } } } diff --git a/src/sp-spiral.cpp b/src/sp-spiral.cpp index 629715332..11e84d9b2 100644 --- a/src/sp-spiral.cpp +++ b/src/sp-spiral.cpp @@ -37,7 +37,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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_spiral_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); static void sp_spiral_set_shape (SPShape *shape); static void sp_spiral_update_patheffect (SPLPEItem *lpeitem, bool write); @@ -52,24 +52,24 @@ static SPShapeClass *parent_class; GType sp_spiral_get_type (void) { - static GType spiral_type = 0; - - if (!spiral_type) { - GTypeInfo spiral_info = { - sizeof (SPSpiralClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) sp_spiral_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (SPSpiral), - 16, /* n_preallocs */ - (GInstanceInitFunc) sp_spiral_init, - NULL, /* value_table */ - }; - spiral_type = g_type_register_static (SP_TYPE_SHAPE, "SPSpiral", &spiral_info, (GTypeFlags)0); - } - return spiral_type; + static GType spiral_type = 0; + + if (!spiral_type) { + GTypeInfo spiral_info = { + sizeof (SPSpiralClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) sp_spiral_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (SPSpiral), + 16, /* n_preallocs */ + (GInstanceInitFunc) sp_spiral_init, + NULL, /* value_table */ + }; + spiral_type = g_type_register_static (SP_TYPE_SHAPE, "SPSpiral", &spiral_info, (GTypeFlags)0); + } + return spiral_type; } /** @@ -78,27 +78,27 @@ sp_spiral_get_type (void) static void sp_spiral_class_init (SPSpiralClass *klass) { - GObjectClass * gobject_class; - SPObjectClass * sp_object_class; - SPItemClass * item_class; - SPLPEItemClass * lpe_item_class; - SPShapeClass *shape_class; + GObjectClass * gobject_class; + SPObjectClass * sp_object_class; + SPItemClass * item_class; + SPLPEItemClass * lpe_item_class; + SPShapeClass *shape_class; - gobject_class = (GObjectClass *) klass; - sp_object_class = (SPObjectClass *) klass; - item_class = (SPItemClass *) klass; - lpe_item_class = (SPLPEItemClass *) klass; - shape_class = (SPShapeClass *) klass; + gobject_class = (GObjectClass *) klass; + sp_object_class = (SPObjectClass *) klass; + item_class = (SPItemClass *) klass; + lpe_item_class = (SPLPEItemClass *) klass; + shape_class = (SPShapeClass *) klass; - parent_class = (SPShapeClass *)g_type_class_ref (SP_TYPE_SHAPE); + parent_class = (SPShapeClass *)g_type_class_ref (SP_TYPE_SHAPE); - sp_object_class->build = sp_spiral_build; - sp_object_class->write = sp_spiral_write; - sp_object_class->set = sp_spiral_set; - sp_object_class->update = sp_spiral_update; + sp_object_class->build = sp_spiral_build; + sp_object_class->write = sp_spiral_write; + sp_object_class->set = sp_spiral_set; + sp_object_class->update = sp_spiral_update; - item_class->description = sp_spiral_description; - item_class->snappoints = sp_spiral_snappoints; + item_class->description = sp_spiral_description; + item_class->snappoints = sp_spiral_snappoints; lpe_item_class->update_patheffect = sp_spiral_update_patheffect; @@ -111,13 +111,13 @@ sp_spiral_class_init (SPSpiralClass *klass) static void sp_spiral_init (SPSpiral * spiral) { - spiral->cx = 0.0; - spiral->cy = 0.0; - spiral->exp = 1.0; - spiral->revo = 3.0; - spiral->rad = 1.0; - spiral->arg = 0.0; - spiral->t0 = 0.0; + spiral->cx = 0.0; + spiral->cy = 0.0; + spiral->exp = 1.0; + spiral->revo = 3.0; + spiral->rad = 1.0; + spiral->arg = 0.0; + spiral->t0 = 0.0; } /** @@ -126,16 +126,16 @@ sp_spiral_init (SPSpiral * spiral) static void sp_spiral_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * repr) { - if (((SPObjectClass *) parent_class)->build) - ((SPObjectClass *) parent_class)->build (object, document, repr); - - sp_object_read_attr (object, "sodipodi:cx"); - sp_object_read_attr (object, "sodipodi:cy"); - sp_object_read_attr (object, "sodipodi:expansion"); - sp_object_read_attr (object, "sodipodi:revolution"); - sp_object_read_attr (object, "sodipodi:radius"); - sp_object_read_attr (object, "sodipodi:argument"); - sp_object_read_attr (object, "sodipodi:t0"); + if (((SPObjectClass *) parent_class)->build) + ((SPObjectClass *) parent_class)->build (object, document, repr); + + sp_object_read_attr (object, "sodipodi:cx"); + sp_object_read_attr (object, "sodipodi:cy"); + sp_object_read_attr (object, "sodipodi:expansion"); + sp_object_read_attr (object, "sodipodi:revolution"); + sp_object_read_attr (object, "sodipodi:radius"); + sp_object_read_attr (object, "sodipodi:argument"); + sp_object_read_attr (object, "sodipodi:t0"); } /** @@ -144,25 +144,25 @@ sp_spiral_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * static Inkscape::XML::Node * sp_spiral_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { - SPSpiral *spiral = SP_SPIRAL (object); - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:path"); - } - - if (flags & SP_OBJECT_WRITE_EXT) { - /* Fixme: we may replace these attributes by - * sodipodi:spiral="cx cy exp revo rad arg t0" - */ - repr->setAttribute("sodipodi:type", "spiral"); - sp_repr_set_svg_double(repr, "sodipodi:cx", spiral->cx); - sp_repr_set_svg_double(repr, "sodipodi:cy", spiral->cy); - sp_repr_set_svg_double(repr, "sodipodi:expansion", spiral->exp); - sp_repr_set_svg_double(repr, "sodipodi:revolution", spiral->revo); - sp_repr_set_svg_double(repr, "sodipodi:radius", spiral->rad); - sp_repr_set_svg_double(repr, "sodipodi:argument", spiral->arg); - sp_repr_set_svg_double(repr, "sodipodi:t0", spiral->t0); - } + SPSpiral *spiral = SP_SPIRAL (object); + + if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = xml_doc->createElement("svg:path"); + } + + if (flags & SP_OBJECT_WRITE_EXT) { + /* Fixme: we may replace these attributes by + * sodipodi:spiral="cx cy exp revo rad arg t0" + */ + repr->setAttribute("sodipodi:type", "spiral"); + sp_repr_set_svg_double(repr, "sodipodi:cx", spiral->cx); + sp_repr_set_svg_double(repr, "sodipodi:cy", spiral->cy); + sp_repr_set_svg_double(repr, "sodipodi:expansion", spiral->exp); + sp_repr_set_svg_double(repr, "sodipodi:revolution", spiral->revo); + sp_repr_set_svg_double(repr, "sodipodi:radius", spiral->rad); + sp_repr_set_svg_double(repr, "sodipodi:argument", spiral->arg); + sp_repr_set_svg_double(repr, "sodipodi:t0", spiral->t0); + } // make sure the curve is rebuilt with all up-to-date parameters sp_spiral_set_shape ((SPShape *) spiral); @@ -190,61 +190,61 @@ sp_spiral_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::X static void sp_spiral_set (SPObject *object, unsigned int key, const gchar *value) { - SPSpiral *spiral; - SPShape *shape; - - spiral = SP_SPIRAL (object); - shape = SP_SHAPE (object); - - /// \todo fixme: we should really collect updates - switch (key) { - case SP_ATTR_SODIPODI_CX: - if (!sp_svg_length_read_computed_absolute (value, &spiral->cx)) { - spiral->cx = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_CY: - if (!sp_svg_length_read_computed_absolute (value, &spiral->cy)) { - spiral->cy = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_EXPANSION: - if (value) { - /** \todo + SPSpiral *spiral; + SPShape *shape; + + spiral = SP_SPIRAL (object); + shape = SP_SHAPE (object); + + /// \todo fixme: we should really collect updates + switch (key) { + case SP_ATTR_SODIPODI_CX: + if (!sp_svg_length_read_computed_absolute (value, &spiral->cx)) { + spiral->cx = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_CY: + if (!sp_svg_length_read_computed_absolute (value, &spiral->cy)) { + spiral->cy = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_EXPANSION: + if (value) { + /** \todo * FIXME: check that value looks like a (finite) * number. Create a routine that uses strtod, and * accepts a default value (if strtod finds an error). * N.B. atof/sscanf/strtod consider "nan" and "inf" * to be valid numbers. */ - spiral->exp = g_ascii_strtod (value, NULL); - spiral->exp = CLAMP (spiral->exp, 0.0, 1000.0); - } else { - spiral->exp = 1.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_REVOLUTION: - if (value) { - spiral->revo = g_ascii_strtod (value, NULL); - spiral->revo = CLAMP (spiral->revo, 0.05, 1024.0); - } else { - spiral->revo = 3.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_RADIUS: - if (!sp_svg_length_read_computed_absolute (value, &spiral->rad)) { - spiral->rad = MAX (spiral->rad, 0.001); - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_ARGUMENT: - if (value) { - spiral->arg = g_ascii_strtod (value, NULL); - /** \todo + spiral->exp = g_ascii_strtod (value, NULL); + spiral->exp = CLAMP (spiral->exp, 0.0, 1000.0); + } else { + spiral->exp = 1.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_REVOLUTION: + if (value) { + spiral->revo = g_ascii_strtod (value, NULL); + spiral->revo = CLAMP (spiral->revo, 0.05, 1024.0); + } else { + spiral->revo = 3.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_RADIUS: + if (!sp_svg_length_read_computed_absolute (value, &spiral->rad)) { + spiral->rad = MAX (spiral->rad, 0.001); + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_ARGUMENT: + if (value) { + spiral->arg = g_ascii_strtod (value, NULL); + /** \todo * FIXME: We still need some bounds on arg, for * numerical reasons. E.g., we don't want inf or NaN, * nor near-infinite numbers. I'm inclined to take @@ -252,32 +252,32 @@ sp_spiral_set (SPObject *object, unsigned int key, const gchar *value) * which use atan2 - revo*2*pi, which typically * results in very negative arg. */ - } else { - spiral->arg = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_T0: - if (value) { - spiral->t0 = g_ascii_strtod (value, NULL); - spiral->t0 = CLAMP (spiral->t0, 0.0, 0.999); - /** \todo + } else { + spiral->arg = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_T0: + if (value) { + spiral->t0 = g_ascii_strtod (value, NULL); + spiral->t0 = CLAMP (spiral->t0, 0.0, 0.999); + /** \todo * Have shared constants for the allowable bounds for * attributes. There was a bug here where we used -1.0 * as the minimum (which leads to NaN via, e.g., * pow(-1.0, 0.5); see sp_spiral_get_xy for * requirements. */ - } else { - spiral->t0 = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - default: - if (((SPObjectClass *) parent_class)->set) - ((SPObjectClass *) parent_class)->set (object, key, value); - break; - } + } else { + spiral->t0 = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + default: + if (((SPObjectClass *) parent_class)->set) + ((SPObjectClass *) parent_class)->set (object, key, value); + break; + } } /** @@ -286,12 +286,12 @@ sp_spiral_set (SPObject *object, unsigned int key, const gchar *value) static void sp_spiral_update (SPObject *object, SPCtx *ctx, guint flags) { - if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { - sp_shape_set_shape ((SPShape *) object); - } + if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { + sp_shape_set_shape ((SPShape *) object); + } - if (((SPObjectClass *) parent_class)->update) - ((SPObjectClass *) parent_class)->update (object, ctx, flags); + if (((SPObjectClass *) parent_class)->update) + ((SPObjectClass *) parent_class)->update (object, ctx, flags); } static void @@ -320,9 +320,9 @@ sp_spiral_update_patheffect(SPLPEItem *lpeitem, bool write) static gchar * sp_spiral_description (SPItem * item) { - // TRANSLATORS: since turn count isn't an integer, please adjust the - // string as needed to deal with an localized plural forms. - return g_strdup_printf (_("Spiral with %3f turns"), SP_SPIRAL(item)->revo); + // TRANSLATORS: since turn count isn't an integer, please adjust the + // string as needed to deal with an localized plural forms. + return g_strdup_printf (_("Spiral with %3f turns"), SP_SPIRAL(item)->revo); } @@ -335,34 +335,34 @@ sp_spiral_description (SPItem * item) **/ static void sp_spiral_fit_and_draw (SPSpiral const *spiral, - SPCurve *c, - double dstep, - Geom::Point darray[], - Geom::Point const &hat1, - Geom::Point &hat2, - double *t) + SPCurve *c, + double dstep, + Geom::Point darray[], + Geom::Point const &hat1, + Geom::Point &hat2, + double *t) { #define BEZIER_SIZE 4 #define FITTING_MAX_BEZIERS 4 #define BEZIER_LENGTH (BEZIER_SIZE * FITTING_MAX_BEZIERS) - g_assert (dstep > 0); - g_assert (is_unit_vector (hat1)); - - Geom::Point bezier[BEZIER_LENGTH]; - double d; - int depth, i; - - for (d = *t, i = 0; i <= SAMPLE_SIZE; d += dstep, i++) { - darray[i] = sp_spiral_get_xy(spiral, d); - - /* Avoid useless adjacent dups. (Otherwise we can have all of darray filled with - the same value, which upsets chord_length_parameterize.) */ - if ((i != 0) - && (darray[i] == darray[i - 1]) - && (d < 1.0)) { - i--; - d += dstep; - /** We mustn't increase dstep for subsequent values of + g_assert (dstep > 0); + g_assert (is_unit_vector (hat1)); + + Geom::Point bezier[BEZIER_LENGTH]; + double d; + int depth, i; + + for (d = *t, i = 0; i <= SAMPLE_SIZE; d += dstep, i++) { + darray[i] = sp_spiral_get_xy(spiral, d); + + /* Avoid useless adjacent dups. (Otherwise we can have all of darray filled with + the same value, which upsets chord_length_parameterize.) */ + if ((i != 0) + && (darray[i] == darray[i - 1]) + && (d < 1.0)) { + i--; + d += dstep; + /** We mustn't increase dstep for subsequent values of * i: for large spiral.exp values, rate of growth * increases very rapidly. */ @@ -378,48 +378,48 @@ sp_spiral_fit_and_draw (SPSpiral const *spiral, * value for next iteration to avoid the problem * mentioned above. */ - } - } + } + } - double const next_t = d - 2 * dstep; - /* == t + (SAMPLE_SIZE - 1) * dstep, in absence of dups. */ + double const next_t = d - 2 * dstep; + /* == t + (SAMPLE_SIZE - 1) * dstep, in absence of dups. */ - hat2 = -sp_spiral_get_tangent (spiral, next_t); + hat2 = -sp_spiral_get_tangent (spiral, next_t); - /** \todo + /** \todo * We should use better algorithm to specify maximum error. */ - depth = Geom::bezier_fit_cubic_full (bezier, NULL, darray, SAMPLE_SIZE, - hat1, hat2, - SPIRAL_TOLERANCE*SPIRAL_TOLERANCE, - FITTING_MAX_BEZIERS); - g_assert(depth * BEZIER_SIZE <= gint(G_N_ELEMENTS(bezier))); + depth = Geom::bezier_fit_cubic_full (bezier, NULL, darray, SAMPLE_SIZE, + hat1, hat2, + SPIRAL_TOLERANCE*SPIRAL_TOLERANCE, + FITTING_MAX_BEZIERS); + g_assert(depth * BEZIER_SIZE <= gint(G_N_ELEMENTS(bezier))); #ifdef SPIRAL_DEBUG - if (*t == spiral->t0 || *t == 1.0) - g_print ("[%s] depth=%d, dstep=%g, t0=%g, t=%g, arg=%g\n", - debug_state, depth, dstep, spiral->t0, *t, spiral->arg); + if (*t == spiral->t0 || *t == 1.0) + g_print ("[%s] depth=%d, dstep=%g, t0=%g, t=%g, arg=%g\n", + debug_state, depth, dstep, spiral->t0, *t, spiral->arg); #endif - if (depth != -1) { - for (i = 0; i < 4*depth; i += 4) { - c->curveto(bezier[i + 1], - bezier[i + 2], - bezier[i + 3]); - } - } else { + if (depth != -1) { + for (i = 0; i < 4*depth; i += 4) { + c->curveto(bezier[i + 1], + bezier[i + 2], + bezier[i + 3]); + } + } else { #ifdef SPIRAL_VERBOSE - g_print ("cant_fit_cubic: t=%g\n", *t); + g_print ("cant_fit_cubic: t=%g\n", *t); #endif - for (i = 1; i < SAMPLE_SIZE; i++) - c->lineto(darray[i]); - } - *t = next_t; - g_assert (is_unit_vector (hat2)); + for (i = 1; i < SAMPLE_SIZE; i++) + c->lineto(darray[i]); + } + *t = next_t; + g_assert (is_unit_vector (hat2)); } static void sp_spiral_set_shape (SPShape *shape) { - SPSpiral *spiral = SP_SPIRAL(shape); + SPSpiral *spiral = SP_SPIRAL(shape); if (sp_lpe_item_has_broken_path_effect(SP_LPE_ITEM(shape))) { g_warning ("The spiral shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as spiral will remove the bad LPE"); @@ -433,40 +433,40 @@ sp_spiral_set_shape (SPShape *shape) return; } - Geom::Point darray[SAMPLE_SIZE + 1]; - double t; + Geom::Point darray[SAMPLE_SIZE + 1]; + double t; - SP_OBJECT (spiral)->requestModified(SP_OBJECT_MODIFIED_FLAG); + SP_OBJECT (spiral)->requestModified(SP_OBJECT_MODIFIED_FLAG); - SPCurve *c = new SPCurve (); + SPCurve *c = new SPCurve (); #ifdef SPIRAL_VERBOSE - g_print ("cx=%g, cy=%g, exp=%g, revo=%g, rad=%g, arg=%g, t0=%g\n", - spiral->cx, - spiral->cy, - spiral->exp, - spiral->revo, - spiral->rad, - spiral->arg, - spiral->t0); + g_print ("cx=%g, cy=%g, exp=%g, revo=%g, rad=%g, arg=%g, t0=%g\n", + spiral->cx, + spiral->cy, + spiral->exp, + spiral->revo, + spiral->rad, + spiral->arg, + spiral->t0); #endif - /* Initial moveto. */ - c->moveto(sp_spiral_get_xy(spiral, spiral->t0)); + /* Initial moveto. */ + c->moveto(sp_spiral_get_xy(spiral, spiral->t0)); - double const tstep = SAMPLE_STEP / spiral->revo; - double const dstep = tstep / (SAMPLE_SIZE - 1); + double const tstep = SAMPLE_STEP / spiral->revo; + double const dstep = tstep / (SAMPLE_SIZE - 1); - Geom::Point hat1 = sp_spiral_get_tangent (spiral, spiral->t0); - Geom::Point hat2; - for (t = spiral->t0; t < (1.0 - tstep);) { - sp_spiral_fit_and_draw (spiral, c, dstep, darray, hat1, hat2, &t); + Geom::Point hat1 = sp_spiral_get_tangent (spiral, spiral->t0); + Geom::Point hat2; + for (t = spiral->t0; t < (1.0 - tstep);) { + sp_spiral_fit_and_draw (spiral, c, dstep, darray, hat1, hat2, &t); - hat1 = -hat2; - } - if ((1.0 - t) > SP_EPSILON) - sp_spiral_fit_and_draw (spiral, c, (1.0 - t)/(SAMPLE_SIZE - 1.0), - darray, hat1, hat2, &t); + hat1 = -hat2; + } + if ((1.0 - t) > SP_EPSILON) + sp_spiral_fit_and_draw (spiral, c, (1.0 - t)/(SAMPLE_SIZE - 1.0), + darray, hat1, hat2, &t); /* Reset the shape'scurve to the "original_curve" * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/ @@ -487,59 +487,58 @@ sp_spiral_set_shape (SPShape *shape) */ void sp_spiral_position_set (SPSpiral *spiral, - gdouble cx, - gdouble cy, - gdouble exp, - gdouble revo, - gdouble rad, - gdouble arg, - gdouble t0) + gdouble cx, + gdouble cy, + gdouble exp, + gdouble revo, + gdouble rad, + gdouble arg, + gdouble t0) { - g_return_if_fail (spiral != NULL); - g_return_if_fail (SP_IS_SPIRAL (spiral)); + g_return_if_fail (spiral != NULL); + g_return_if_fail (SP_IS_SPIRAL (spiral)); - /** \todo + /** \todo * Consider applying CLAMP or adding in-bounds assertions for * some of these parameters. */ - spiral->cx = cx; - spiral->cy = cy; - spiral->exp = exp; - spiral->revo = revo; - spiral->rad = MAX (rad, 0.0); - spiral->arg = arg; - spiral->t0 = CLAMP(t0, 0.0, 0.999); - - ((SPObject *)spiral)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + spiral->cx = cx; + spiral->cy = cy; + spiral->exp = exp; + spiral->revo = revo; + spiral->rad = MAX (rad, 0.0); + spiral->arg = arg; + spiral->t0 = CLAMP(t0, 0.0, 0.999); + + ((SPObject *)spiral)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } /** * Virtual snappoints callback. */ -static void sp_spiral_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +static void sp_spiral_snappoints(SPItem const *item, std::vector &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 - Inkscape::SnapPreferences local_snapprefs = *snapprefs; - local_snapprefs.setSnapObjectMidpoints(false); - - if (((SPItemClass *) parent_class)->snappoints) { - ((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 - if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { - return; - } - - if (snapprefs->getSnapObjectMidpoints()) { - Geom::Matrix const i2d (sp_item_i2d_affine (item)); - SPSpiral *spiral = SP_SPIRAL(item); - 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! - } + // We will determine the spiral's midpoint ourselves, instead of trusting on the base class + // Therefore setSnapObjectMidpoints() is set to false temporarily + Inkscape::SnapPreferences local_snapprefs = *snapprefs; + local_snapprefs.setSnapObjectMidpoints(false); + + if (((SPItemClass *) parent_class)->snappoints) { + ((SPItemClass *) parent_class)->snappoints (item, p, &local_snapprefs); + } + + // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes + if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { + return; + } + + if (snapprefs->getSnapObjectMidpoints()) { + Geom::Matrix const i2d (sp_item_i2d_affine (item)); + SPSpiral *spiral = SP_SPIRAL(item); + p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(spiral->cx, spiral->cy) * i2d, Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); + // 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! + } } /** @@ -552,19 +551,19 @@ static void sp_spiral_snappoints(SPItem const *item, bool const target, SnapPoin */ Geom::Point sp_spiral_get_xy (SPSpiral const *spiral, gdouble t) { - g_assert (spiral != NULL); - g_assert (SP_IS_SPIRAL(spiral)); - g_assert (spiral->exp >= 0.0); - /* Otherwise we get NaN for t==0. */ - g_assert (spiral->exp <= 1000.0); - /* Anything much more results in infinities. Even allowing 1000 is somewhat overkill. */ - g_assert (t >= 0.0); - /* Any callers passing -ve t will have a bug for non-integral values of exp. */ - - double const rad = spiral->rad * pow(t, (double) spiral->exp); - double const arg = 2.0 * M_PI * spiral->revo * t + spiral->arg; - - return Geom::Point(rad * cos (arg) + spiral->cx, + g_assert (spiral != NULL); + g_assert (SP_IS_SPIRAL(spiral)); + g_assert (spiral->exp >= 0.0); + /* Otherwise we get NaN for t==0. */ + g_assert (spiral->exp <= 1000.0); + /* Anything much more results in infinities. Even allowing 1000 is somewhat overkill. */ + g_assert (t >= 0.0); + /* Any callers passing -ve t will have a bug for non-integral values of exp. */ + + double const rad = spiral->rad * pow(t, (double) spiral->exp); + double const arg = 2.0 * M_PI * spiral->revo * t + spiral->arg; + + return Geom::Point(rad * cos (arg) + spiral->cx, rad * sin (arg) + spiral->cy); } @@ -581,58 +580,58 @@ Geom::Point sp_spiral_get_xy (SPSpiral const *spiral, gdouble t) static Geom::Point sp_spiral_get_tangent (SPSpiral const *spiral, gdouble t) { - Geom::Point ret(1.0, 0.0); - g_return_val_if_fail (( ( spiral != NULL ) - && SP_IS_SPIRAL(spiral) ), - ret); - g_assert (t >= 0.0); - g_assert (spiral->exp >= 0.0); - /* See above for comments on these assertions. */ - - double const t_scaled = 2.0 * M_PI * spiral->revo * t; - double const arg = t_scaled + spiral->arg; - double const s = sin (arg); - double const c = cos (arg); - - if (spiral->exp == 0.0) { - ret = Geom::Point(-s, c); - } else if (t_scaled == 0.0) { - ret = Geom::Point(c, s); - } else { - Geom::Point unrotated(spiral->exp, t_scaled); - double const s_len = L2 (unrotated); - g_assert (s_len != 0); - /** \todo + Geom::Point ret(1.0, 0.0); + g_return_val_if_fail (( ( spiral != NULL ) + && SP_IS_SPIRAL(spiral) ), + ret); + g_assert (t >= 0.0); + g_assert (spiral->exp >= 0.0); + /* See above for comments on these assertions. */ + + double const t_scaled = 2.0 * M_PI * spiral->revo * t; + double const arg = t_scaled + spiral->arg; + double const s = sin (arg); + double const c = cos (arg); + + if (spiral->exp == 0.0) { + ret = Geom::Point(-s, c); + } else if (t_scaled == 0.0) { + ret = Geom::Point(c, s); + } else { + Geom::Point unrotated(spiral->exp, t_scaled); + double const s_len = L2 (unrotated); + g_assert (s_len != 0); + /** \todo * Check that this isn't being too hopeful of the hypot * function. E.g. test with numbers around 2**-1070 * (denormalized numbers), preferably on a few different * platforms. However, njh says that the usual implementation * does handle both very big and very small numbers. */ - unrotated /= s_len; + unrotated /= s_len; - /* ret = spiral->exp * (c, s) + t_scaled * (-s, c); - alternatively ret = (spiral->exp, t_scaled) * (( c, s), - (-s, c)).*/ - ret = Geom::Point(dot(unrotated, Geom::Point(c, -s)), + /* ret = spiral->exp * (c, s) + t_scaled * (-s, c); + alternatively ret = (spiral->exp, t_scaled) * (( c, s), + (-s, c)).*/ + ret = Geom::Point(dot(unrotated, Geom::Point(c, -s)), dot(unrotated, Geom::Point(s, c))); - /* ret should already be approximately normalized: the - matrix ((c, -s), (s, c)) is orthogonal (it just - rotates by arg), and unrotated has been normalized, - so ret is already of unit length other than numerical - error in the above matrix multiplication. */ + /* ret should already be approximately normalized: the + matrix ((c, -s), (s, c)) is orthogonal (it just + rotates by arg), and unrotated has been normalized, + so ret is already of unit length other than numerical + error in the above matrix multiplication. */ - /** \todo + /** \todo * I haven't checked how important it is for ret to be very * near unit length; we could get rid of the below. */ - ret.normalize(); - /* Proof that ret length is non-zero: see above. (Should be near 1.) */ - } + ret.normalize(); + /* Proof that ret length is non-zero: see above. (Should be near 1.) */ + } - g_assert (is_unit_vector (ret)); - return ret; + g_assert (is_unit_vector (ret)); + return ret; } /** @@ -641,13 +640,13 @@ sp_spiral_get_tangent (SPSpiral const *spiral, gdouble t) void sp_spiral_get_polar (SPSpiral const *spiral, gdouble t, gdouble *rad, gdouble *arg) { - g_return_if_fail (spiral != NULL); - g_return_if_fail (SP_IS_SPIRAL(spiral)); + g_return_if_fail (spiral != NULL); + g_return_if_fail (SP_IS_SPIRAL(spiral)); - if (rad) - *rad = spiral->rad * pow(t, (double) spiral->exp); - if (arg) - *arg = 2.0 * M_PI * spiral->revo * t + spiral->arg; + if (rad) + *rad = spiral->rad * pow(t, (double) spiral->exp); + if (arg) + *arg = 2.0 * M_PI * spiral->revo * t + spiral->arg; } /** @@ -656,19 +655,19 @@ sp_spiral_get_polar (SPSpiral const *spiral, gdouble t, gdouble *rad, gdouble *a bool sp_spiral_is_invalid (SPSpiral const *spiral) { - gdouble rad; - - sp_spiral_get_polar (spiral, 0.0, &rad, NULL); - if (rad < 0.0 || rad > SP_HUGE) { - g_print ("rad(t=0)=%g\n", rad); - return TRUE; - } - sp_spiral_get_polar (spiral, 1.0, &rad, NULL); - if (rad < 0.0 || rad > SP_HUGE) { - g_print ("rad(t=1)=%g\n", rad); - return TRUE; - } - return FALSE; + gdouble rad; + + sp_spiral_get_polar (spiral, 0.0, &rad, NULL); + if (rad < 0.0 || rad > SP_HUGE) { + g_print ("rad(t=0)=%g\n", rad); + return TRUE; + } + sp_spiral_get_polar (spiral, 1.0, &rad, NULL); + if (rad < 0.0 || rad > SP_HUGE) { + g_print ("rad(t=1)=%g\n", rad); + return TRUE; + } + return FALSE; } /* diff --git a/src/sp-star.cpp b/src/sp-star.cpp index 9cffd952c..6bced87e8 100644 --- a/src/sp-star.cpp +++ b/src/sp-star.cpp @@ -41,7 +41,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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_star_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); static void sp_star_set_shape (SPShape *shape); static void sp_star_update_patheffect (SPLPEItem *lpeitem, bool write); @@ -51,230 +51,230 @@ static SPShapeClass *parent_class; GType sp_star_get_type (void) { - static GType type = 0; - - if (!type) { - GTypeInfo info = { - sizeof (SPStarClass), - NULL, NULL, - (GClassInitFunc) sp_star_class_init, - NULL, NULL, - sizeof (SPStar), - 16, - (GInstanceInitFunc) sp_star_init, - NULL, /* value_table */ - }; - type = g_type_register_static (SP_TYPE_SHAPE, "SPStar", &info, (GTypeFlags)0); - } - return type; + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (SPStarClass), + NULL, NULL, + (GClassInitFunc) sp_star_class_init, + NULL, NULL, + sizeof (SPStar), + 16, + (GInstanceInitFunc) sp_star_init, + NULL, /* value_table */ + }; + type = g_type_register_static (SP_TYPE_SHAPE, "SPStar", &info, (GTypeFlags)0); + } + return type; } static void sp_star_class_init (SPStarClass *klass) { - GObjectClass * gobject_class; - SPObjectClass * sp_object_class; - SPItemClass * item_class; - SPLPEItemClass * lpe_item_class; - SPShapeClass * shape_class; + GObjectClass * gobject_class; + SPObjectClass * sp_object_class; + SPItemClass * item_class; + SPLPEItemClass * lpe_item_class; + SPShapeClass * shape_class; - gobject_class = (GObjectClass *) klass; - sp_object_class = (SPObjectClass *) klass; - item_class = (SPItemClass *) klass; - lpe_item_class = (SPLPEItemClass *) klass; - shape_class = (SPShapeClass *) klass; + gobject_class = (GObjectClass *) klass; + sp_object_class = (SPObjectClass *) klass; + item_class = (SPItemClass *) klass; + lpe_item_class = (SPLPEItemClass *) klass; + shape_class = (SPShapeClass *) klass; - parent_class = (SPShapeClass *)g_type_class_ref (SP_TYPE_SHAPE); + parent_class = (SPShapeClass *)g_type_class_ref (SP_TYPE_SHAPE); - sp_object_class->build = sp_star_build; - sp_object_class->write = sp_star_write; - sp_object_class->set = sp_star_set; - sp_object_class->update = sp_star_update; + sp_object_class->build = sp_star_build; + sp_object_class->write = sp_star_write; + sp_object_class->set = sp_star_set; + sp_object_class->update = sp_star_update; - item_class->description = sp_star_description; - item_class->snappoints = sp_star_snappoints; + item_class->description = sp_star_description; + item_class->snappoints = sp_star_snappoints; lpe_item_class->update_patheffect = sp_star_update_patheffect; - shape_class->set_shape = sp_star_set_shape; + shape_class->set_shape = sp_star_set_shape; } static void sp_star_init (SPStar * star) { - star->sides = 5; - star->center = Geom::Point(0, 0); - star->r[0] = 1.0; - star->r[1] = 0.001; - star->arg[0] = star->arg[1] = 0.0; - star->flatsided = 0; - star->rounded = 0.0; - star->randomized = 0.0; + star->sides = 5; + star->center = Geom::Point(0, 0); + star->r[0] = 1.0; + star->r[1] = 0.001; + star->arg[0] = star->arg[1] = 0.0; + star->flatsided = 0; + star->rounded = 0.0; + star->randomized = 0.0; } static void sp_star_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * repr) { - if (((SPObjectClass *) parent_class)->build) - ((SPObjectClass *) parent_class)->build (object, document, repr); - - sp_object_read_attr (object, "sodipodi:cx"); - sp_object_read_attr (object, "sodipodi:cy"); - sp_object_read_attr (object, "sodipodi:sides"); - sp_object_read_attr (object, "sodipodi:r1"); - sp_object_read_attr (object, "sodipodi:r2"); - sp_object_read_attr (object, "sodipodi:arg1"); - sp_object_read_attr (object, "sodipodi:arg2"); - sp_object_read_attr (object, "inkscape:flatsided"); - sp_object_read_attr (object, "inkscape:rounded"); - sp_object_read_attr (object, "inkscape:randomized"); + if (((SPObjectClass *) parent_class)->build) + ((SPObjectClass *) parent_class)->build (object, document, repr); + + sp_object_read_attr (object, "sodipodi:cx"); + sp_object_read_attr (object, "sodipodi:cy"); + sp_object_read_attr (object, "sodipodi:sides"); + sp_object_read_attr (object, "sodipodi:r1"); + sp_object_read_attr (object, "sodipodi:r2"); + sp_object_read_attr (object, "sodipodi:arg1"); + sp_object_read_attr (object, "sodipodi:arg2"); + sp_object_read_attr (object, "inkscape:flatsided"); + sp_object_read_attr (object, "inkscape:rounded"); + sp_object_read_attr (object, "inkscape:randomized"); } static Inkscape::XML::Node * sp_star_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) { - SPStar *star = SP_STAR (object); - - if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { - repr = xml_doc->createElement("svg:path"); - } - - if (flags & SP_OBJECT_WRITE_EXT) { - repr->setAttribute("sodipodi:type", "star"); - sp_repr_set_int (repr, "sodipodi:sides", star->sides); - sp_repr_set_svg_double(repr, "sodipodi:cx", star->center[Geom::X]); - sp_repr_set_svg_double(repr, "sodipodi:cy", star->center[Geom::Y]); - sp_repr_set_svg_double(repr, "sodipodi:r1", star->r[0]); - sp_repr_set_svg_double(repr, "sodipodi:r2", star->r[1]); - sp_repr_set_svg_double(repr, "sodipodi:arg1", star->arg[0]); - sp_repr_set_svg_double(repr, "sodipodi:arg2", star->arg[1]); - sp_repr_set_boolean (repr, "inkscape:flatsided", star->flatsided); - sp_repr_set_svg_double(repr, "inkscape:rounded", star->rounded); - sp_repr_set_svg_double(repr, "inkscape:randomized", star->randomized); - } + SPStar *star = SP_STAR (object); + + if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) { + repr = xml_doc->createElement("svg:path"); + } + + if (flags & SP_OBJECT_WRITE_EXT) { + repr->setAttribute("sodipodi:type", "star"); + sp_repr_set_int (repr, "sodipodi:sides", star->sides); + sp_repr_set_svg_double(repr, "sodipodi:cx", star->center[Geom::X]); + sp_repr_set_svg_double(repr, "sodipodi:cy", star->center[Geom::Y]); + sp_repr_set_svg_double(repr, "sodipodi:r1", star->r[0]); + sp_repr_set_svg_double(repr, "sodipodi:r2", star->r[1]); + sp_repr_set_svg_double(repr, "sodipodi:arg1", star->arg[0]); + sp_repr_set_svg_double(repr, "sodipodi:arg2", star->arg[1]); + sp_repr_set_boolean (repr, "inkscape:flatsided", star->flatsided); + sp_repr_set_svg_double(repr, "inkscape:rounded", star->rounded); + sp_repr_set_svg_double(repr, "inkscape:randomized", star->randomized); + } sp_star_set_shape ((SPShape *) star); char *d = sp_svg_write_path (((SPShape *) star)->curve->get_pathvector()); repr->setAttribute("d", d); g_free (d); - if (((SPObjectClass *) (parent_class))->write) - ((SPObjectClass *) (parent_class))->write (object, xml_doc, repr, flags); + if (((SPObjectClass *) (parent_class))->write) + ((SPObjectClass *) (parent_class))->write (object, xml_doc, repr, flags); - return repr; + return repr; } static void sp_star_set (SPObject *object, unsigned int key, const gchar *value) { - SVGLength::Unit unit; - - SPStar *star = SP_STAR (object); - - /* fixme: we should really collect updates */ - switch (key) { - case SP_ATTR_SODIPODI_SIDES: - if (value) { - star->sides = atoi (value); - star->sides = NR_CLAMP(star->sides, 3, 1024); - } else { - star->sides = 5; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_CX: - if (!sp_svg_length_read_ldd (value, &unit, NULL, &star->center[Geom::X]) || - (unit == SVGLength::EM) || - (unit == SVGLength::EX) || - (unit == SVGLength::PERCENT)) { - star->center[Geom::X] = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_CY: - if (!sp_svg_length_read_ldd (value, &unit, NULL, &star->center[Geom::Y]) || - (unit == SVGLength::EM) || - (unit == SVGLength::EX) || - (unit == SVGLength::PERCENT)) { - star->center[Geom::Y] = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_R1: - if (!sp_svg_length_read_ldd (value, &unit, NULL, &star->r[0]) || - (unit == SVGLength::EM) || - (unit == SVGLength::EX) || - (unit == SVGLength::PERCENT)) { - star->r[0] = 1.0; - } - /* fixme: Need CLAMP (Lauris) */ - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_R2: - if (!sp_svg_length_read_ldd (value, &unit, NULL, &star->r[1]) || - (unit == SVGLength::EM) || - (unit == SVGLength::EX) || - (unit == SVGLength::PERCENT)) { - star->r[1] = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - return; - case SP_ATTR_SODIPODI_ARG1: - if (value) { - star->arg[0] = g_ascii_strtod (value, NULL); - } else { - star->arg[0] = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_SODIPODI_ARG2: - if (value) { - star->arg[1] = g_ascii_strtod (value, NULL); - } else { - star->arg[1] = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_INKSCAPE_FLATSIDED: - if (value && !strcmp (value, "true")) - star->flatsided = true; - else star->flatsided = false; - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_INKSCAPE_ROUNDED: - if (value) { - star->rounded = g_ascii_strtod (value, NULL); - } else { - star->rounded = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - case SP_ATTR_INKSCAPE_RANDOMIZED: - if (value) { - star->randomized = g_ascii_strtod (value, NULL); - } else { - star->randomized = 0.0; - } - object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); - break; - default: - if (((SPObjectClass *) parent_class)->set) - ((SPObjectClass *) parent_class)->set (object, key, value); - break; - } + SVGLength::Unit unit; + + SPStar *star = SP_STAR (object); + + /* fixme: we should really collect updates */ + switch (key) { + case SP_ATTR_SODIPODI_SIDES: + if (value) { + star->sides = atoi (value); + star->sides = NR_CLAMP(star->sides, 3, 1024); + } else { + star->sides = 5; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_CX: + if (!sp_svg_length_read_ldd (value, &unit, NULL, &star->center[Geom::X]) || + (unit == SVGLength::EM) || + (unit == SVGLength::EX) || + (unit == SVGLength::PERCENT)) { + star->center[Geom::X] = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_CY: + if (!sp_svg_length_read_ldd (value, &unit, NULL, &star->center[Geom::Y]) || + (unit == SVGLength::EM) || + (unit == SVGLength::EX) || + (unit == SVGLength::PERCENT)) { + star->center[Geom::Y] = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_R1: + if (!sp_svg_length_read_ldd (value, &unit, NULL, &star->r[0]) || + (unit == SVGLength::EM) || + (unit == SVGLength::EX) || + (unit == SVGLength::PERCENT)) { + star->r[0] = 1.0; + } + /* fixme: Need CLAMP (Lauris) */ + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_R2: + if (!sp_svg_length_read_ldd (value, &unit, NULL, &star->r[1]) || + (unit == SVGLength::EM) || + (unit == SVGLength::EX) || + (unit == SVGLength::PERCENT)) { + star->r[1] = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + return; + case SP_ATTR_SODIPODI_ARG1: + if (value) { + star->arg[0] = g_ascii_strtod (value, NULL); + } else { + star->arg[0] = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_SODIPODI_ARG2: + if (value) { + star->arg[1] = g_ascii_strtod (value, NULL); + } else { + star->arg[1] = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_INKSCAPE_FLATSIDED: + if (value && !strcmp (value, "true")) + star->flatsided = true; + else star->flatsided = false; + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_INKSCAPE_ROUNDED: + if (value) { + star->rounded = g_ascii_strtod (value, NULL); + } else { + star->rounded = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_INKSCAPE_RANDOMIZED: + if (value) { + star->randomized = g_ascii_strtod (value, NULL); + } else { + star->randomized = 0.0; + } + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + break; + default: + if (((SPObjectClass *) parent_class)->set) + ((SPObjectClass *) parent_class)->set (object, key, value); + break; + } } static void sp_star_update (SPObject *object, SPCtx *ctx, guint flags) { - if (flags & (SP_OBJECT_MODIFIED_FLAG | - SP_OBJECT_STYLE_MODIFIED_FLAG | - SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { - sp_shape_set_shape ((SPShape *) object); - } - - if (((SPObjectClass *) parent_class)->update) - ((SPObjectClass *) parent_class)->update (object, ctx, flags); + if (flags & (SP_OBJECT_MODIFIED_FLAG | + SP_OBJECT_STYLE_MODIFIED_FLAG | + SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { + sp_shape_set_shape ((SPShape *) object); + } + + if (((SPObjectClass *) parent_class)->update) + ((SPObjectClass *) parent_class)->update (object, ctx, flags); } static void @@ -306,13 +306,13 @@ sp_star_description (SPItem *item) // make calls to ngettext because the pluralization may be different // for various numbers >=3. The singular form is used as the index. if (star->flatsided == false ) - return g_strdup_printf (ngettext("Star with %d vertex", - "Star with %d vertices", - star->sides), star->sides); + return g_strdup_printf (ngettext("Star with %d vertex", + "Star with %d vertices", + star->sides), star->sides); else return g_strdup_printf (ngettext("Polygon with %d vertex", - "Polygon with %d vertices", - star->sides), star->sides); + "Polygon with %d vertices", + star->sides), star->sides); } /** @@ -321,7 +321,7 @@ Returns a unit-length vector at 90 degrees to the direction from o to n static Geom::Point rot90_rel (Geom::Point o, Geom::Point n) { - return ((1/Geom::L2(n - o)) * Geom::Point ((n - o)[Geom::Y], (o - n)[Geom::X])); + return ((1/Geom::L2(n - o)) * Geom::Point ((n - o)[Geom::Y], (o - n)[Geom::X])); } /** @@ -333,12 +333,12 @@ Obvious (but acceptable for my purposes) limits to uniqueness: static guint32 point_unique_int (Geom::Point o) { - return ((guint32) - 65536 * - (((int) floor (o[Geom::X] * 64)) % 1024 + ((int) floor (o[Geom::X] * 1024)) % 64) - + - (((int) floor (o[Geom::Y] * 64)) % 1024 + ((int) floor (o[Geom::Y] * 1024)) % 64) - ); + return ((guint32) + 65536 * + (((int) floor (o[Geom::X] * 64)) % 1024 + ((int) floor (o[Geom::X] * 1024)) % 64) + + + (((int) floor (o[Geom::Y] * 64)) % 1024 + ((int) floor (o[Geom::Y] * 1024)) % 64) + ); } /** @@ -349,7 +349,7 @@ i.e. it is guaranteed to go through all integers < 2^32 (see http://random.mat.s static inline guint32 lcg_next(guint32 const prev) { - return (guint32) ( 69069 * prev + 1 ); + return (guint32) ( 69069 * prev + 1 ); } /** @@ -357,68 +357,68 @@ Returns a random number in the range [-0.5, 0.5) from the given seed, stepping t */ static double rnd (guint32 const seed, unsigned steps) { - guint32 lcg = seed; - for (; steps > 0; steps --) - lcg = lcg_next (lcg); + guint32 lcg = seed; + for (; steps > 0; steps --) + lcg = lcg_next (lcg); - return ( lcg / 4294967296. ) - 0.5; + return ( lcg / 4294967296. ) - 0.5; } static Geom::Point sp_star_get_curvepoint (SPStar *star, SPStarPoint point, gint index, bool previ) { - // the point whose neighboring curve handle we're calculating - Geom::Point o = sp_star_get_xy (star, point, index); - - // indices of previous and next points - gint pi = (index > 0)? (index - 1) : (star->sides - 1); - gint ni = (index < star->sides - 1)? (index + 1) : 0; - - // the other point type - SPStarPoint other = (point == SP_STAR_POINT_KNOT2? SP_STAR_POINT_KNOT1 : SP_STAR_POINT_KNOT2); - - // the neighbors of o; depending on flatsided, they're either the same type (polygon) or the other type (star) - Geom::Point prev = (star->flatsided? sp_star_get_xy (star, point, pi) : sp_star_get_xy (star, other, point == SP_STAR_POINT_KNOT2? index : pi)); - Geom::Point next = (star->flatsided? sp_star_get_xy (star, point, ni) : sp_star_get_xy (star, other, point == SP_STAR_POINT_KNOT1? index : ni)); - - // prev-next midpoint - Geom::Point mid = 0.5 * (prev + next); - - // point to which we direct the bissector of the curve handles; - // it's far enough outside the star on the perpendicular to prev-next through mid - Geom::Point biss = mid + 100000 * rot90_rel (mid, next); - - // lengths of vectors to prev and next - gdouble prev_len = Geom::L2 (prev - o); - gdouble next_len = Geom::L2 (next - o); - - // unit-length vector perpendicular to o-biss - Geom::Point rot = rot90_rel (o, biss); - - // multiply rot by star->rounded coefficient and the distance to the star point; flip for next - Geom::Point ret; - if (previ) { - ret = (star->rounded * prev_len) * rot; - } else { - ret = (star->rounded * next_len * -1) * rot; - } - - if (star->randomized == 0) { - // add the vector to o to get the final curvepoint - return o + ret; - } else { - // the seed corresponding to the exact point - guint32 seed = point_unique_int (o); - - // randomly rotate (by step 3 from the seed) and scale (by step 4) the vector - ret = ret * Geom::Matrix (Geom::Rotate (star->randomized * M_PI * rnd (seed, 3))); - ret *= ( 1 + star->randomized * rnd (seed, 4)); - - // the randomized corner point - Geom::Point o_randomized = sp_star_get_xy (star, point, index, true); - - return o_randomized + ret; - } + // the point whose neighboring curve handle we're calculating + Geom::Point o = sp_star_get_xy (star, point, index); + + // indices of previous and next points + gint pi = (index > 0)? (index - 1) : (star->sides - 1); + gint ni = (index < star->sides - 1)? (index + 1) : 0; + + // the other point type + SPStarPoint other = (point == SP_STAR_POINT_KNOT2? SP_STAR_POINT_KNOT1 : SP_STAR_POINT_KNOT2); + + // the neighbors of o; depending on flatsided, they're either the same type (polygon) or the other type (star) + Geom::Point prev = (star->flatsided? sp_star_get_xy (star, point, pi) : sp_star_get_xy (star, other, point == SP_STAR_POINT_KNOT2? index : pi)); + Geom::Point next = (star->flatsided? sp_star_get_xy (star, point, ni) : sp_star_get_xy (star, other, point == SP_STAR_POINT_KNOT1? index : ni)); + + // prev-next midpoint + Geom::Point mid = 0.5 * (prev + next); + + // point to which we direct the bissector of the curve handles; + // it's far enough outside the star on the perpendicular to prev-next through mid + Geom::Point biss = mid + 100000 * rot90_rel (mid, next); + + // lengths of vectors to prev and next + gdouble prev_len = Geom::L2 (prev - o); + gdouble next_len = Geom::L2 (next - o); + + // unit-length vector perpendicular to o-biss + Geom::Point rot = rot90_rel (o, biss); + + // multiply rot by star->rounded coefficient and the distance to the star point; flip for next + Geom::Point ret; + if (previ) { + ret = (star->rounded * prev_len) * rot; + } else { + ret = (star->rounded * next_len * -1) * rot; + } + + if (star->randomized == 0) { + // add the vector to o to get the final curvepoint + return o + ret; + } else { + // the seed corresponding to the exact point + guint32 seed = point_unique_int (o); + + // randomly rotate (by step 3 from the seed) and scale (by step 4) the vector + ret = ret * Geom::Matrix (Geom::Rotate (star->randomized * M_PI * rnd (seed, 3))); + ret *= ( 1 + star->randomized * rnd (seed, 4)); + + // the randomized corner point + Geom::Point o_randomized = sp_star_get_xy (star, point, index, true); + + return o_randomized + ret; + } } @@ -428,7 +428,7 @@ sp_star_get_curvepoint (SPStar *star, SPStarPoint point, gint index, bool previ) static void sp_star_set_shape (SPShape *shape) { - SPStar *star = SP_STAR (shape); + SPStar *star = SP_STAR (shape); // perhaps we should convert all our shapes into LPEs without source path // and with knotholders for parameters, then this situation will be handled automatically @@ -445,67 +445,67 @@ sp_star_set_shape (SPShape *shape) return; } - SPCurve *c = new SPCurve (); - - gint sides = star->sides; - bool not_rounded = (fabs (star->rounded) < 1e-4); - - // note that we pass randomized=true to sp_star_get_xy, because the curve must be randomized; - // other places that call that function (e.g. the knotholder) need the exact point - - // draw 1st segment - c->moveto(sp_star_get_xy (star, SP_STAR_POINT_KNOT1, 0, true)); - if (star->flatsided == false) { - if (not_rounded) { - c->lineto(sp_star_get_xy (star, SP_STAR_POINT_KNOT2, 0, true)); - } else { - c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, 0, NEXT), - sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT2, 0, PREV), - sp_star_get_xy (star, SP_STAR_POINT_KNOT2, 0, true)); - } - } - - // draw all middle segments - for (gint i = 1; i < sides; i++) { - if (not_rounded) { - c->lineto(sp_star_get_xy (star, SP_STAR_POINT_KNOT1, i, true)); - } else { - if (star->flatsided == false) { - c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT2, i - 1, NEXT), - sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, i, PREV), - sp_star_get_xy (star, SP_STAR_POINT_KNOT1, i, true)); - } else { - c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, i - 1, NEXT), - sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, i, PREV), - sp_star_get_xy (star, SP_STAR_POINT_KNOT1, i, true)); - } - } - if (star->flatsided == false) { - - if (not_rounded) { + SPCurve *c = new SPCurve (); + + gint sides = star->sides; + bool not_rounded = (fabs (star->rounded) < 1e-4); + + // note that we pass randomized=true to sp_star_get_xy, because the curve must be randomized; + // other places that call that function (e.g. the knotholder) need the exact point + + // draw 1st segment + c->moveto(sp_star_get_xy (star, SP_STAR_POINT_KNOT1, 0, true)); + if (star->flatsided == false) { + if (not_rounded) { + c->lineto(sp_star_get_xy (star, SP_STAR_POINT_KNOT2, 0, true)); + } else { + c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, 0, NEXT), + sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT2, 0, PREV), + sp_star_get_xy (star, SP_STAR_POINT_KNOT2, 0, true)); + } + } + + // draw all middle segments + for (gint i = 1; i < sides; i++) { + if (not_rounded) { + c->lineto(sp_star_get_xy (star, SP_STAR_POINT_KNOT1, i, true)); + } else { + if (star->flatsided == false) { + c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT2, i - 1, NEXT), + sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, i, PREV), + sp_star_get_xy (star, SP_STAR_POINT_KNOT1, i, true)); + } else { + c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, i - 1, NEXT), + sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, i, PREV), + sp_star_get_xy (star, SP_STAR_POINT_KNOT1, i, true)); + } + } + if (star->flatsided == false) { + + if (not_rounded) { c->lineto(sp_star_get_xy (star, SP_STAR_POINT_KNOT2, i, true)); - } else { - c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, i, NEXT), - sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT2, i, PREV), - sp_star_get_xy (star, SP_STAR_POINT_KNOT2, i, true)); - } - } - } - - // draw last segment - if (not_rounded) { - c->lineto(sp_star_get_xy (star, SP_STAR_POINT_KNOT1, 0, true)); - } else { - if (star->flatsided == false) { - c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT2, sides - 1, NEXT), - sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, 0, PREV), - sp_star_get_xy (star, SP_STAR_POINT_KNOT1, 0, true)); - } else { - c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, sides - 1, NEXT), - sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, 0, PREV), - sp_star_get_xy (star, SP_STAR_POINT_KNOT1, 0, true)); - } - } + } else { + c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, i, NEXT), + sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT2, i, PREV), + sp_star_get_xy (star, SP_STAR_POINT_KNOT2, i, true)); + } + } + } + + // draw last segment + if (not_rounded) { + c->lineto(sp_star_get_xy (star, SP_STAR_POINT_KNOT1, 0, true)); + } else { + if (star->flatsided == false) { + c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT2, sides - 1, NEXT), + sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, 0, PREV), + sp_star_get_xy (star, SP_STAR_POINT_KNOT1, 0, true)); + } else { + c->curveto(sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, sides - 1, NEXT), + sp_star_get_curvepoint (star, SP_STAR_POINT_KNOT1, 0, PREV), + sp_star_get_xy (star, SP_STAR_POINT_KNOT1, 0, true)); + } + } c->closepath(); @@ -526,46 +526,45 @@ sp_star_set_shape (SPShape *shape) void sp_star_position_set (SPStar *star, gint sides, Geom::Point center, gdouble r1, gdouble r2, gdouble arg1, gdouble arg2, bool isflat, double rounded, double randomized) { - g_return_if_fail (star != NULL); - g_return_if_fail (SP_IS_STAR (star)); - - star->sides = NR_CLAMP(sides, 3, 1024); - star->center = center; - star->r[0] = MAX (r1, 0.001); - if (isflat == false) { - star->r[1] = NR_CLAMP(r2, 0.0, star->r[0]); - } else { - star->r[1] = NR_CLAMP( r1*cos(M_PI/sides) ,0.0, star->r[0] ); - } - star->arg[0] = arg1; - star->arg[1] = arg2; - star->flatsided = isflat; - star->rounded = rounded; - star->randomized = randomized; - SP_OBJECT(star)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + g_return_if_fail (star != NULL); + g_return_if_fail (SP_IS_STAR (star)); + + star->sides = NR_CLAMP(sides, 3, 1024); + star->center = center; + star->r[0] = MAX (r1, 0.001); + if (isflat == false) { + star->r[1] = NR_CLAMP(r2, 0.0, star->r[0]); + } else { + star->r[1] = NR_CLAMP( r1*cos(M_PI/sides) ,0.0, star->r[0] ); + } + star->arg[0] = arg1; + star->arg[1] = arg2; + star->flatsided = isflat; + star->rounded = rounded; + star->randomized = randomized; + SP_OBJECT(star)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } -static void sp_star_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +static void sp_star_snappoints(SPItem const *item, std::vector &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 - Inkscape::SnapPreferences local_snapprefs = *snapprefs; - local_snapprefs.setSnapObjectMidpoints(false); - - if (((SPItemClass *) parent_class)->snappoints) { - ((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 - if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { - return; - } - - if (snapprefs->getSnapObjectMidpoints()) { - Geom::Matrix const i2d (sp_item_i2d_affine (item)); - 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)); - } + // We will determine the star's midpoint ourselves, instead of trusting on the base class + // Therefore setSnapObjectMidpoints() is set to false temporarily + Inkscape::SnapPreferences local_snapprefs = *snapprefs; + local_snapprefs.setSnapObjectMidpoints(false); + + if (((SPItemClass *) parent_class)->snappoints) { + ((SPItemClass *) parent_class)->snappoints (item, p, &local_snapprefs); + } + + // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes + if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) { + return; + } + + if (snapprefs->getSnapObjectMidpoints()) { + Geom::Matrix const i2d (sp_item_i2d_affine (item)); + p.push_back(Inkscape::SnapCandidatePoint(SP_STAR(item)->center * i2d,Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); + } } /** @@ -582,26 +581,26 @@ static void sp_star_snappoints(SPItem const *item, bool const target, SnapPoints Geom::Point sp_star_get_xy (SPStar *star, SPStarPoint point, gint index, bool randomized) { - gdouble darg = 2.0 * M_PI / (double) star->sides; - - double arg = star->arg[point]; - arg += index * darg; - - Geom::Point xy = star->r[point] * Geom::Point(cos(arg), sin(arg)) + star->center; - - if (!randomized || star->randomized == 0) { - // return the exact point - return xy; - } else { // randomize the point - // find out the seed, unique for this point so that randomization is the same so long as the original point is stationary - guint32 seed = point_unique_int (xy); - // the full range (corresponding to star->randomized == 1.0) is equal to the star's diameter - double range = 2 * MAX (star->r[0], star->r[1]); - // find out the random displacement; x is controlled by step 1 from the seed, y by the step 2 - Geom::Point shift (star->randomized * range * rnd (seed, 1), star->randomized * range * rnd (seed, 2)); - // add the shift to the exact point - return xy + shift; - } + gdouble darg = 2.0 * M_PI / (double) star->sides; + + double arg = star->arg[point]; + arg += index * darg; + + Geom::Point xy = star->r[point] * Geom::Point(cos(arg), sin(arg)) + star->center; + + if (!randomized || star->randomized == 0) { + // return the exact point + return xy; + } else { // randomize the point + // find out the seed, unique for this point so that randomization is the same so long as the original point is stationary + guint32 seed = point_unique_int (xy); + // the full range (corresponding to star->randomized == 1.0) is equal to the star's diameter + double range = 2 * MAX (star->r[0], star->r[1]); + // find out the random displacement; x is controlled by step 1 from the seed, y by the step 2 + Geom::Point shift (star->randomized * range * rnd (seed, 1), star->randomized * range * rnd (seed, 2)); + // add the shift to the exact point + return xy + shift; + } } /* diff --git a/src/sp-text.cpp b/src/sp-text.cpp index b45f8cbb6..55da52f1a 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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_text_snappoints(SPItem const *item, std::vector &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); @@ -434,7 +434,7 @@ sp_text_description(SPItem *item) return ret; } -static void sp_text_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const */*snapprefs*/) +static void sp_text_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const */*snapprefs*/) { // Choose a point on the baseline for snapping from or to, with the horizontal position // of this point depending on the text alignment (left vs. right) @@ -442,8 +442,7 @@ static void sp_text_snappoints(SPItem const *item, bool const target, SnapPoints if (layout != NULL && layout->outputExists()) { boost::optional pt = layout->baselineAnchorPoint(); if (pt) { - int type = target ? int(Inkscape::SNAPTARGET_TEXT_BASELINE) : int(Inkscape::SNAPSOURCE_TEXT_BASELINE); - p.push_back(std::make_pair((*pt) * sp_item_i2d_affine(item), type)); + p.push_back(Inkscape::SnapCandidatePoint((*pt) * sp_item_i2d_affine(item), Inkscape::SNAPSOURCE_TEXT_BASELINE, Inkscape::SNAPTARGET_TEXT_BASELINE)); } } } diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 76930086c..7962390c2 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, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs); +static void sp_use_snappoints(SPItem const *item, std::vector &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); @@ -742,7 +742,7 @@ sp_use_get_original(SPUse *use) } static void -sp_use_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, Inkscape::SnapPreferences const *snapprefs) +sp_use_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs) { g_assert (item != NULL); g_assert (SP_IS_ITEM(item)); @@ -755,7 +755,7 @@ sp_use_snappoints(SPItem const *item, bool const target, SnapPointsWithType &p, SPItemClass const &item_class = *(SPItemClass const *) G_OBJECT_GET_CLASS(root); if (item_class.snappoints) { - item_class.snappoints(root, target, p, snapprefs); + item_class.snappoints(root, p, snapprefs); } }