From: Diederik van Lierop Date: Fri, 1 Jan 2010 20:06:51 +0000 (+0100) Subject: Refactor snapping of gradient handles; now behaves like all other snapping, i.e.... X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=640bacb96d4e571bf5a169eec557cb20db1962ce;p=inkscape.git Refactor snapping of gradient handles; now behaves like all other snapping, i.e. no more snapping to imaginary infinite lines along the bounding box --- diff --git a/src/display/snap-indicator.cpp b/src/display/snap-indicator.cpp index fdea9cbbf..7df9b31ff 100644 --- a/src/display/snap-indicator.cpp +++ b/src/display/snap-indicator.cpp @@ -97,9 +97,6 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const p) case SNAPTARGET_BBOX_EDGE: target_name = _("bounding box side"); break; - case SNAPTARGET_GRADIENTS_PARENT_BBOX: - target_name = _("bounding box"); - break; case SNAPTARGET_PAGE_BORDER: target_name = _("page border"); break; @@ -139,6 +136,9 @@ SnapIndicator::set_new_snaptarget(Inkscape::SnappedPoint const p) case SNAPTARGET_TEXT_BASELINE: target_name = _("text baseline"); break; + case SNAPTARGET_CONSTRAINED_ANGLE: + target_name = _("constrained angle"); + break; default: g_warning("Snap target has not yet been defined!"); break; diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index e61bd9552..98ea35b4e 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -594,49 +594,19 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp } } - if (!((state & GDK_SHIFT_MASK) || ((state & GDK_CONTROL_MASK) && (state & GDK_MOD1_MASK)))) { - // Try snapping to the grid or guides - m.setup(desktop); - Inkscape::SnappedPoint s = m.freeSnap(Inkscape::SnapPreferences::SNAPPOINT_NODE, to_2geom(p), Inkscape::SNAPSOURCE_HANDLE); + 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); if (s.getSnapped()) { p = s.getPoint(); sp_knot_moveto (knot, p); - } else if (m.snapprefs.getSnapEnabledGlobally() && m.snapprefs.getSnapModeNode() && !(m.snapprefs.getSnapPostponedGlobally())) { - bool was_snapped = false; - double dist = NR_HUGE; - // No snapping so far, let's see if we need to snap to any of the levels - for (guint i = 0; i < dragger->parent->hor_levels.size(); i++) { - dist = fabs(p[Geom::Y] - dragger->parent->hor_levels[i]); - if (dist < snap_dist) { - p[Geom::Y] = dragger->parent->hor_levels[i]; - s = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_HANDLE, 0, Inkscape::SNAPTARGET_GRADIENTS_PARENT_BBOX, dist, snap_dist, false, false); - was_snapped = true; - sp_knot_moveto (knot, p); - } - } - for (guint i = 0; i < dragger->parent->vert_levels.size(); i++) { - dist = fabs(p[Geom::X] - dragger->parent->vert_levels[i]); - if (dist < snap_dist) { - p[Geom::X] = dragger->parent->vert_levels[i]; - s = Inkscape::SnappedPoint(p, Inkscape::SNAPSOURCE_HANDLE, 0, Inkscape::SNAPTARGET_GRADIENTS_PARENT_BBOX, dist, snap_dist, false, false); - was_snapped = true; - sp_knot_moveto (knot, p); - } - } - if (was_snapped) { - desktop->snapindicator->set_new_snaptarget(s); - } } - } - - if (state & GDK_CONTROL_MASK) { + } else if (state & GDK_CONTROL_MASK) { + SnappedConstraints sc; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); unsigned snaps = abs(prefs->getInt("/options/rotationsnapsperpi/value", 12)); /* 0 means no snapping. */ - // This list will store snap vectors from all draggables of dragger - GSList *snap_vectors = NULL; - for (GSList const* i = dragger->draggables; i != NULL; i = i->next) { GrDraggable *draggable = (GrDraggable *) i->data; @@ -687,25 +657,27 @@ gr_knot_moved_handler(SPKnot *knot, Geom::Point const &ppointer, guint state, gp // with Ctrl, snap to M_PI/snaps snap_vector = get_snap_vector (p, dr_snap, M_PI/snaps, 0); } - } - if (snap_vector) { - snap_vectors = g_slist_prepend (snap_vectors, &(*snap_vector)); + 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); + if (s.getSnapped()) { + s.setTransformation(s.getPoint() - p); + sc.points.push_back(s); + } else { + Inkscape::SnappedPoint dummy(p + *snap_vector, Inkscape::SNAPSOURCE_HANDLE, 0, Inkscape::SNAPTARGET_CONSTRAINED_ANGLE, Geom::L2(*snap_vector), 10000, true, false); + dummy.setTransformation(*snap_vector); + sc.points.push_back(dummy); + } + } } } - // Move by the smallest of snap vectors: - Geom::Point move(9999, 9999); - for (GSList const *i = snap_vectors; i != NULL; i = i->next) { - Geom::Point *snap_vector = (Geom::Point *) i->data; - if (Geom::L2(*snap_vector) < Geom::L2(move)) - move = *snap_vector; - } - if (move[Geom::X] < 9999) { - p += move; + Inkscape::SnappedPoint bsp = m.findBestSnap(p, Inkscape::SNAPSOURCE_HANDLE, sc, true); // snap indicator will be displayed if needed + + if (bsp.getSnapped()) { + p += bsp.getTransformation(); sp_knot_moveto (knot, p); } - - g_slist_free(snap_vectors); } drag->keep_selection = (bool) g_list_find(drag->selected, dragger); diff --git a/src/libnr/nr-point-fns.cpp b/src/libnr/nr-point-fns.cpp index 5082c3a10..0142655f2 100644 --- a/src/libnr/nr-point-fns.cpp +++ b/src/libnr/nr-point-fns.cpp @@ -61,19 +61,6 @@ NR::Point abs(NR::Point const &b) return ret; } -NR::Point * -get_snap_vector (NR::Point p, NR::Point o, double snap, double initial) -{ - double r = NR::L2 (p - o); - if (r < 1e-3) - return NULL; - double angle = NR::atan2 (p - o); - // snap angle to snaps increments, starting from initial: - double a_snapped = initial + floor((angle - initial)/snap + 0.5) * snap; - // calculate the new position and subtract p to get the vector: - return new NR::Point (o + r * NR::Point(cos(a_snapped), sin(a_snapped)) - p); -} - NR::Point snap_vector_midpoint (NR::Point p, NR::Point begin, NR::Point end, double snap) { diff --git a/src/libnr/nr-point-fns.h b/src/libnr/nr-point-fns.h index e927725b4..9ef7205c6 100644 --- a/src/libnr/nr-point-fns.h +++ b/src/libnr/nr-point-fns.h @@ -90,8 +90,6 @@ Point abs(Point const &b); } /* namespace NR */ -NR::Point *get_snap_vector (NR::Point p, NR::Point o, double snap, double initial); - NR::Point snap_vector_midpoint (NR::Point p, NR::Point begin, NR::Point end, double snap); double get_offset_between_points (NR::Point p, NR::Point begin, NR::Point end); diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 88c260782..4a70e2706 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -185,10 +185,10 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType bool p_is_a_node = t & Inkscape::SnapPreferences::SNAPPOINT_NODE; bool p_is_a_bbox = t & Inkscape::SnapPreferences::SNAPPOINT_BBOX; - bool p_is_a_guide = t & Inkscape::SnapPreferences::SNAPPOINT_GUIDE; + bool p_is_other = t & Inkscape::SnapPreferences::SNAPPOINT_OTHER; // A point considered for snapping should be either a node, a bbox corner or a guide. Pick only ONE! - g_assert(!((p_is_a_node && p_is_a_bbox) || (p_is_a_bbox && p_is_a_guide) || (p_is_a_node && p_is_a_guide))); + g_assert(!((p_is_a_node && p_is_a_bbox) || (p_is_a_bbox && p_is_other) || (p_is_a_node && p_is_other))); if (_snapmanager->snapprefs.getSnapToBBoxNode() || _snapmanager->snapprefs.getSnapBBoxEdgeMidpoints() || _snapmanager->snapprefs.getSnapBBoxMidpoints()) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -211,7 +211,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType g_return_if_fail(root_item); //Collect all nodes so we can snap to them - if (p_is_a_node || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node) || p_is_a_guide) { + if (p_is_a_node || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node) || p_is_other) { // Note: there are two ways in which intersections are considered: // Method 1: Intersections are calculated for each shape individually, for both the // snap source and snap target (see sp_shape_snappoints) @@ -244,7 +244,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapPreferences::PointType } //Collect the bounding box's corners so we can snap to them - if (p_is_a_bbox || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_bbox) || p_is_a_guide) { + if (p_is_a_bbox || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_bbox) || p_is_other) { // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox // of the item AND the bbox of the clipping path at the same time if (!(*i).clip_or_mask) { @@ -336,7 +336,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType SPItem::BBoxType bbox_type = SPItem::GEOMETRIC_BBOX; bool p_is_a_node = t & Inkscape::SnapPreferences::SNAPPOINT_NODE; - bool p_is_a_guide = t & Inkscape::SnapPreferences::SNAPPOINT_GUIDE; + bool p_is_other = t & Inkscape::SnapPreferences::SNAPPOINT_OTHER; if (_snapmanager->snapprefs.getSnapToBBoxPath()) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -372,7 +372,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType //Add the item's path to snap to if (_snapmanager->snapprefs.getSnapToItemPath()) { - if (p_is_a_guide || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node)) { + if (p_is_other || !(_snapmanager->snapprefs.getStrictSnapping() && !p_is_a_node)) { // Snapping to the path of characters is very cool, but for a large // chunk of text this will take ages! So limit snapping to text paths // containing max. 240 characters. Snapping the bbox will not be affected @@ -406,7 +406,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::SnapPreferences::PointType //Add the item's bounding box to snap to if (_snapmanager->snapprefs.getSnapToBBoxPath()) { - if (p_is_a_guide || !(_snapmanager->snapprefs.getStrictSnapping() && p_is_a_node)) { + if (p_is_other || !(_snapmanager->snapprefs.getStrictSnapping() && p_is_a_node)) { // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox // of the item AND the bbox of the clipping path at the same time if (!(*i).clip_or_mask) { @@ -688,7 +688,7 @@ void Inkscape::ObjectSnapper::guideFreeSnap(SnappedConstraints &sc, } _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), snap_dim, false, Geom::identity()); - _snapTranslatingGuideToNodes(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, guide_normal); + _snapTranslatingGuideToNodes(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, guide_normal); } @@ -712,7 +712,7 @@ void Inkscape::ObjectSnapper::guideConstrainedSnap(SnappedConstraints &sc, } _findCandidates(sp_document_root(_snapmanager->getDocument()), &it, true, Geom::Rect(p, p), snap_dim, false, Geom::identity()); - _snapTranslatingGuideToNodes(sc, Inkscape::SnapPreferences::SNAPPOINT_GUIDE, p, guide_normal); + _snapTranslatingGuideToNodes(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, guide_normal); } diff --git a/src/snap-preferences.cpp b/src/snap-preferences.cpp index 3e396a216..0ba3b15dc 100644 --- a/src/snap-preferences.cpp +++ b/src/snap-preferences.cpp @@ -17,7 +17,7 @@ Inkscape::SnapPreferences::PointType const Inkscape::SnapPreferences::SNAPPOINT_NODE = 0x1; Inkscape::SnapPreferences::PointType const Inkscape::SnapPreferences::SNAPPOINT_BBOX = 0x2; -Inkscape::SnapPreferences::PointType const Inkscape::SnapPreferences::SNAPPOINT_GUIDE = 0x4; +Inkscape::SnapPreferences::PointType const Inkscape::SnapPreferences::SNAPPOINT_OTHER = 0x4; Inkscape::SnapPreferences::SnapPreferences() : @@ -32,7 +32,7 @@ Inkscape::SnapPreferences::SnapPreferences() : _snap_to_page_border(false), _strict_snapping(true) { - setSnapFrom(SNAPPOINT_BBOX | SNAPPOINT_NODE | SNAPPOINT_GUIDE, true); //Snap any point. In v0.45 and earlier, this was controlled in the preferences tab + setSnapFrom(SNAPPOINT_BBOX | SNAPPOINT_NODE | SNAPPOINT_OTHER, true); //Snap any point. In v0.45 and earlier, this was controlled in the preferences tab } /* @@ -86,15 +86,15 @@ bool Inkscape::SnapPreferences::getSnapModeAny() const void Inkscape::SnapPreferences::setSnapModeGuide(bool enabled) { if (enabled) { - _snap_from |= Inkscape::SnapPreferences::SNAPPOINT_GUIDE; + _snap_from |= Inkscape::SnapPreferences::SNAPPOINT_OTHER; } else { - _snap_from &= ~Inkscape::SnapPreferences::SNAPPOINT_GUIDE; + _snap_from &= ~Inkscape::SnapPreferences::SNAPPOINT_OTHER; } } bool Inkscape::SnapPreferences::getSnapModeGuide() const { - return (_snap_from & Inkscape::SnapPreferences::SNAPPOINT_GUIDE); + return (_snap_from & Inkscape::SnapPreferences::SNAPPOINT_OTHER); } /** diff --git a/src/snap-preferences.h b/src/snap-preferences.h index 63d7fba15..c88503e7d 100644 --- a/src/snap-preferences.h +++ b/src/snap-preferences.h @@ -24,10 +24,10 @@ public: SnapPreferences(); /// Point types to snap. - typedef int PointType; - static const PointType SNAPPOINT_NODE; - static const PointType SNAPPOINT_BBOX; - static const PointType SNAPPOINT_GUIDE; + typedef int PointType; // can be only one of the types below, never two or more at the same time + static const PointType SNAPPOINT_NODE; // will in general not snap to bounding boxes + static const PointType SNAPPOINT_BBOX; // will in general not snap to nodes + static const PointType SNAPPOINT_OTHER;// e.g. guides, gradient knots void setSnapModeBBox(bool enabled); void setSnapModeNode(bool enabled); diff --git a/src/snap.cpp b/src/snap.cpp index 2e38e4f14..bf4c928ad 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -433,7 +433,7 @@ 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_GUIDE, p, source_type, 0, Geom::OptRect(), NULL, NULL); + (*i)->freeSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), NULL, NULL); } // Snap to intersections of curves, but not to the curves themselves! (see _snapTranslatingGuideToNodes in object-snapper.cpp) @@ -472,14 +472,14 @@ void SnapManager::guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) 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_GUIDE, p, source_type, 0, Geom::OptRect(), cl, NULL); + object.constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, 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_GUIDE, p, source_type, 0, Geom::OptRect(), cl, NULL); + (*i)->constrainedSnap(sc, Inkscape::SnapPreferences::SNAPPOINT_OTHER, p, source_type, 0, Geom::OptRect(), cl, NULL); } Inkscape::SnappedPoint const s = findBestSnap(p, source_type, sc, false); diff --git a/src/snap.h b/src/snap.h index a3e463092..413b753d1 100644 --- a/src/snap.h +++ b/src/snap.h @@ -167,6 +167,8 @@ 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; + protected: SPNamedView const *_named_view; @@ -200,8 +202,6 @@ private: bool const uniform) const; void _displaySnapsource(Inkscape::SnapPreferences::PointType point_type, std::pair const &p) const; - - Inkscape::SnappedPoint findBestSnap(Geom::Point const &p, Inkscape::SnapSourceType const source_type, SnappedConstraints &sc, bool constrained, bool noCurves = false) const; }; #endif /* !SEEN_SNAP_H */ diff --git a/src/snapped-point.h b/src/snapped-point.h index 70d353a73..c793ffa8d 100644 --- a/src/snapped-point.h +++ b/src/snapped-point.h @@ -40,14 +40,14 @@ enum SnapTargetType { SNAPTARGET_BBOX_EDGE, SNAPTARGET_BBOX_EDGE_MIDPOINT, SNAPTARGET_BBOX_MIDPOINT, - SNAPTARGET_GRADIENTS_PARENT_BBOX, 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_TEXT_BASELINE, + SNAPTARGET_CONSTRAINED_ANGLE }; enum SnapSourceType {