Code

Refactor snapping of gradient handles; now behaves like all other snapping, i.e....
authorDiederik van Lierop <mailat-signdiedenrezidotnl>
Fri, 1 Jan 2010 20:06:51 +0000 (21:06 +0100)
committerDiederik van Lierop <mailat-signdiedenrezidotnl>
Fri, 1 Jan 2010 20:06:51 +0000 (21:06 +0100)
src/display/snap-indicator.cpp
src/gradient-drag.cpp
src/libnr/nr-point-fns.cpp
src/libnr/nr-point-fns.h
src/object-snapper.cpp
src/snap-preferences.cpp
src/snap-preferences.h
src/snap.cpp
src/snap.h
src/snapped-point.h

index fdea9cbbfae1ecf3433bcbefee0c61e9f3664706..7df9b31ff8c2c9e84a858fa3f9bd8dabc1a3a351 100644 (file)
@@ -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;
index e61bd95527212f795b3a0824156637b4b1f0b5ef..98ea35b4eab548ef2561bee2abccd45ef06e4dcf 100644 (file)
@@ -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);
index 5082c3a109950a09e5e7dbcf83d4e367456512f5..0142655f2ff44df786eedcb80585984b36b91cba 100644 (file)
@@ -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)
 {
index e927725b480973afafcb2ba6630b5cf0f099b1d2..9ef7205c6a72ac25be81d43c8e607798121e36e8 100644 (file)
@@ -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);
index 88c2607822d16ddb0af335940992f9019902ab50..4a70e27063aaa369f6ea1fd348f1d3785d04fc66 100644 (file)
@@ -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);
 
 }
 
index 3e396a216c17a8ec1f5da444c77f99c98c566e25..0ba3b15dc6e4663d135e078f0b4f6bdee378623a 100644 (file)
@@ -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);
 }
 
 /**
index 63d7fba15215bffbbf26ac60d7e2f4ff91ff08b4..c88503e7da28d6ceaa51d7812e16d858297cb688 100644 (file)
@@ -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);
index 2e38e4f146d9db8bc610ff049e10cb93e82ce35b..bf4c928adb4b4b0348d8949c46c4523e51f69e9a 100644 (file)
@@ -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);
index a3e463092cc4f8b1ddd570257db0c6073a9dd0df..413b753d125d6f14f24b5725fb69f9bc7ee55697 100644 (file)
@@ -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<Geom::Point, int> 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 */
index 70d353a7366ca2a28f94f8f8352f05a4c1d50e91..c793ffa8d97ca5141728817fb2a0010551e603a7 100644 (file)
@@ -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 {