Code

Node tool: fix Tab and Shift+Tab
[inkscape.git] / src / display / curve.cpp
index 0b560883bd367b2df6de89107e12821469e87fcd..303d1bb4d26bacb5831896628858c8011c0e5d9b 100644 (file)
@@ -44,17 +44,26 @@ SPCurve::SPCurve(Geom::PathVector const& pathv)
 }
 
 SPCurve *
-SPCurve::new_from_rect(Geom::Rect const &rect)
+SPCurve::new_from_rect(Geom::Rect const &rect, bool all_four_sides)
 {
     SPCurve *c =  new SPCurve();
 
     Geom::Point p = rect.corner(0);
     c->moveto(p);
 
-    for (int i=3; i>=0; i--) {
+    for (int i=3; i>=1; i--) {
         c->lineto(rect.corner(i));
     }
-    c->closepath_current();
+
+    if (all_four_sides) {
+        // When _constrained_ snapping to a path, the 2geom::SimpleCrosser will be invoked which doesn't consider the closing segment.
+        // of a path. Consequently, in case we want to snap to for example the page border, we must provide all four sides of the
+        // rectangle explicitly
+        c->lineto(rect.corner(0));
+    } else {
+        // ... instead of just three plus a closing segment
+        c->closepath();
+    }
 
     return c;
 }
@@ -200,6 +209,7 @@ SPCurve::moveto(gdouble x, gdouble y)
 }
 /**
  * Perform a moveto to a point, thus starting a new subpath.
+ * Point p must be finite.
  */
 void
 SPCurve::moveto(Geom::Point const &p)
@@ -209,16 +219,17 @@ SPCurve::moveto(Geom::Point const &p)
 }
 
 /**
- * Calls SPCurve::lineto() with a point's coordinates.
+ * Adds a line to the current subpath.
+ * Point p must be finite.
  */
 void
 SPCurve::lineto(Geom::Point const &p)
 {
-    if (_pathv.empty())  g_message("SPCurve::lineto path is empty!");
+    if (_pathv.empty())  g_message("SPCurve::lineto path is empty!");
     else _pathv.back().appendNew<Geom::LineSegment>( p );
 }
 /**
- * Adds a line to the current subpath.
+ * Calls SPCurve::lineto( Geom::Point(x,y) )
  */
 void
 SPCurve::lineto(gdouble x, gdouble y)
@@ -227,16 +238,38 @@ SPCurve::lineto(gdouble x, gdouble y)
 }
 
 /**
- * Calls SPCurve::curveto() with coordinates of three points.
+ * Adds a quadratic bezier segment to the current subpath.
+ * All points must be finite.
+ */
+void
+SPCurve::quadto(Geom::Point const &p1, Geom::Point const &p2)
+{
+    if (_pathv.empty())  g_message("SPCurve::quadto - path is empty!");
+    else _pathv.back().appendNew<Geom::QuadraticBezier>( p1, p2);
+}
+/**
+ * Calls SPCurve::quadto( Geom::Point(x1,y1), Geom::Point(x2,y2) )
+ * All coordinates must be finite.
+ */
+void
+SPCurve::quadto(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
+{
+    quadto( Geom::Point(x1,y1), Geom::Point(x2,y2) );
+}
+
+/**
+ * Adds a bezier segment to the current subpath.
+ * All points must be finite.
  */
 void
 SPCurve::curveto(Geom::Point const &p0, Geom::Point const &p1, Geom::Point const &p2)
 {
-    if (_pathv.empty())  g_message("SPCurve::lineto path is empty!");
+    if (_pathv.empty())  g_message("SPCurve::curveto - path is empty!");
     else _pathv.back().appendNew<Geom::CubicBezier>( p0, p1, p2 );
 }
 /**
- * Adds a bezier segment to the current subpath.
+ * Calls SPCurve::curveto( Geom::Point(x0,y0), Geom::Point(x1,y1), Geom::Point(x2,y2) )
+ * All coordinates must be finite.
  */
 void
 SPCurve::curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdouble y2)
@@ -261,7 +294,11 @@ SPCurve::closepath()
 void
 SPCurve::closepath_current()
 {
-    _pathv.back().setFinal(_pathv.back().initialPoint());
+    if (_pathv.back().size() > 0 && dynamic_cast<Geom::LineSegment const *>(&_pathv.back().back_open())) {
+        _pathv.back().erase_last();
+    } else {
+        _pathv.back().setFinal(_pathv.back().initialPoint());
+    }
     _pathv.back().close(true);
 }
 
@@ -593,6 +630,8 @@ SPCurve::move_endpoints(Geom::Point const &new_p0, Geom::Point const &new_p1)
 
 /**
  * returns the number of nodes in a path, used for statusbar text when selecting an spcurve.
+ * Sum of nodes in all the paths. When a path is closed, and its closing line segment is of zero-length,
+ * this function will not count the closing knot double (so basically ignores the closing line segment when it has zero length)
  */
 guint
 SPCurve::nodes_in_path() const
@@ -602,6 +641,17 @@ SPCurve::nodes_in_path() const
         nr += (*it).size();
 
         nr++; // count last node (this works also for closed paths because although they don't have a 'last node', they do have an extra segment
+
+        // do not count closing knot double for zero-length closing line segments
+        // however, if the path is only a moveto, and is closed, do not subtract 1 (otherwise the result will be zero nodes)
+        if ( it->closed()
+             && ((*it).size() != 0) )
+        {
+            Geom::Curve const &c = it->back_closed();
+            if (are_near(c.initialPoint(), c.finalPoint())) {
+                nr--;   
+            }
+        }
     }
 
     return nr;
@@ -637,4 +687,4 @@ SPCurve::last_point_additive_move(Geom::Point const & p)
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :