Code

merge gsoc2008_johan_path2geom into trunk
authorjohanengelen <johanengelen@users.sourceforge.net>
Fri, 6 Jun 2008 01:43:35 +0000 (01:43 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Fri, 6 Jun 2008 01:43:35 +0000 (01:43 +0000)
48 files changed:
src/display/bezier-utils.cpp
src/display/canvas-bpath.cpp
src/display/curve.cpp
src/display/curve.h
src/display/nr-arena-shape.cpp
src/display/nr-filter-composite.cpp
src/display/nr-filter-gaussian.cpp
src/draw-context.cpp
src/dyna-draw-context.cpp
src/eraser-context.cpp
src/isnan.h
src/libcola/cola.cpp
src/libcola/gradient_projection.cpp
src/libnr/in-svg-plane-test.cpp
src/libnr/in-svg-plane-test.h
src/libnr/n-art-bpath-2geom.cpp
src/libnr/n-art-bpath-2geom.h
src/libnr/nr-convert2geom.h
src/libnr/nr-point-fns-test.cpp
src/libnr/nr-point-fns-test.h
src/libnr/nr-point-fns.cpp
src/libnr/nr-types.cpp
src/libvpsc/generate-constraints.cpp
src/live_effects/effect.cpp
src/live_effects/effect.h
src/live_effects/lpe-curvestitch.cpp
src/live_effects/lpe-knot.h
src/live_effects/lpe-test-doEffect-stack.cpp
src/live_effects/lpe-test-doEffect-stack.h
src/live_effects/lpe-vonkoch.cpp
src/live_effects/parameter/parameter.h
src/live_effects/parameter/path.cpp
src/nodepath.cpp
src/path-chemistry.cpp
src/pen-context.cpp
src/sp-ellipse.cpp
src/sp-item-group.cpp
src/sp-namedview.cpp
src/sp-path.cpp
src/sp-polygon.cpp
src/sp-polygon.h
src/sp-shape.cpp
src/sp-spiral.cpp
src/sp-star.cpp
src/style.cpp
src/svg/svg-path.cpp
src/svg/svg.h
src/ui/clipboard.cpp

index 7957ef56c594e43f51e856e64334f99b1a7b77da..b01e31b1411581945919753002c9a60241387264 100644 (file)
@@ -148,8 +148,8 @@ copy_without_nans_or_adjacent_duplicates(NR::Point const src[], unsigned src_len
         if ( si == src_len ) {
             return 0;
         }
-        if (!isNaN(src[si][NR::X]) &&
-            !isNaN(src[si][NR::Y])) {
+        if (!IS_NAN(src[si][NR::X]) &&
+            !IS_NAN(src[si][NR::Y])) {
             dest[0] = NR::Point(src[si]);
             ++si;
             break;
@@ -160,8 +160,8 @@ copy_without_nans_or_adjacent_duplicates(NR::Point const src[], unsigned src_len
     for (; si < src_len; ++si) {
         NR::Point const src_pt = NR::Point(src[si]);
         if ( src_pt != dest[di]
-             && !isNaN(src_pt[NR::X])
-             && !isNaN(src_pt[NR::Y])) {
+             && !IS_NAN(src_pt[NR::X])
+             && !IS_NAN(src_pt[NR::Y])) {
             dest[++di] = src_pt;
         }
     }
@@ -201,7 +201,7 @@ sp_bezier_fit_cubic_full(NR::Point bezier[], int split_points[],
         double const dist = ( L2( data[len - 1]
                                   - data[0] )
                               / 3.0 );
-        if (isNaN(dist)) {
+        if (IS_NAN(dist)) {
             /* Numerical problem, fall back to straight line segment. */
             bezier[1] = bezier[0];
             bezier[2] = bezier[3];
@@ -604,7 +604,7 @@ NewtonRaphsonRootFind(BezierCurve const Q, NR::Point const &P, gdouble const u)
         }
     }
 
-    if (!isFinite(improved_u)) {
+    if (!IS_FINITE(improved_u)) {
         improved_u = u;
     } else if ( improved_u < 0.0 ) {
         improved_u = 0.0;
@@ -835,7 +835,7 @@ chord_length_parameterize(NR::Point const d[], gdouble u[], unsigned const len)
     /* Then scale to [0.0 .. 1.0]. */
     gdouble tot_len = u[len - 1];
     g_return_if_fail( tot_len != 0 );
-    if (isFinite(tot_len)) {
+    if (IS_FINITE(tot_len)) {
         for (unsigned i = 1; i < len; ++i) {
             u[i] /= tot_len;
         }
@@ -849,7 +849,7 @@ chord_length_parameterize(NR::Point const d[], gdouble u[], unsigned const len)
     /** \todo
      * It's been reported that u[len - 1] can differ from 1.0 on some 
      * systems (amd64), despite it having been calculated as x / x where x 
-     * is isFinite and non-zero.
+     * is IS_FINITE and non-zero.
      */
     if (u[len - 1] != 1) {
         double const diff = u[len - 1] - 1;
index a3327308c6e1eb7a58f6c57f509fd42537d0b569..3c46a9049d6c4fbf824c607fdd1cb240847c17bc 100644 (file)
@@ -142,7 +142,7 @@ sp_canvas_bpath_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned i
         Path*  thePath=new Path;
         thePath->LoadArtBPath(SP_CURVE_BPATH(cbp->curve), affine, true);
         thePath->Convert(0.25);
-        if ((cbp->fill_rgba & 0xff) && (cbp->curve->_end > 2)) {
+        if ((cbp->fill_rgba & 0xff) && (cbp->curve->get_length() > 2)) {
             Shape* theShape=new Shape;
             thePath->Fill(theShape,0);
             if ( cbp->fill_shp == NULL ) cbp->fill_shp=new Shape;
@@ -165,7 +165,7 @@ sp_canvas_bpath_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned i
                 }
             }
         }
-        if ((cbp->stroke_rgba & 0xff) && (cbp->curve->_end > 1)) {
+        if ((cbp->stroke_rgba & 0xff) && (cbp->curve->get_length() > 1)) {
             JoinType join=join_straight;
 //      Shape* theShape=new Shape;
             ButtType butt=butt_straight;
index 966a35f5bd01ddf01f0e08c4b01c6773adda09f8..eb86773f91dbdf76b5bced293e25063e71377274 100644 (file)
 #include <libnr/n-art-bpath.h>
 #include <libnr/nr-point-matrix-ops.h>
 #include <libnr/nr-translate-ops.h>
+#include <libnr/n-art-bpath-2geom.h>
+#include <libnr/nr-convert2geom.h>
 #include <cstring>
 #include <string>
+#include <2geom/pathvector.h>
+#include <2geom/sbasis-geometric.h>
+#include <2geom/sbasis-to-bezier.h>
+#include "svg/svg.h"
 
 static unsigned sp_bpath_length(NArtBpath const bpath[]);
 static bool sp_bpath_closed(NArtBpath const bpath[]);
 
+#define NO_CHECKS
+
+static void debug_out( char const * text, Geom::PathVector const & pathv) {
+#ifndef NO_CHECKS
+    char * str = sp_svg_write_path(pathv);
+    g_message("%s : %s", text, str);
+    g_free(str);
+#endif
+}
+static void debug_out( char const * text, NArtBpath const * bpath) {
+#ifndef NO_CHECKS
+    char * str = sp_svg_write_path(bpath);
+    g_message("%s : %s", text, str);
+    g_free(str);
+#endif
+}
+void SPCurve::debug_check( char const * text, SPCurve const * curve) {
+#ifndef NO_CHECKS
+    char * pathv_str = sp_svg_write_path(curve->_pathv);
+    char * bpath_str = sp_svg_write_path(curve->_bpath);
+    if ( strcmp(pathv_str, bpath_str) ) {
+        g_message("%s : unequal paths", text);
+        g_message("bpath : %s", bpath_str);
+        g_message("pathv : %s", pathv_str);
+    }
+    g_free(pathv_str);
+    g_free(bpath_str);
+#endif
+}
+void SPCurve::debug_check( char const * text, bool a) {
+#ifndef NO_CHECKS
+    if ( !a ) {
+        g_message("%s : bool fail", text);
+    }
+#endif
+}
+
 /* Constructors */
 
 /**
  * The returned curve's state is as if SPCurve::reset has just been called on it.
  * \param length Initial number of NArtBpath elements allocated for bpath (including NR_END
  *    element).
+ * 2GEOMproof
  */
 SPCurve::SPCurve(guint length)
-  : _end(0),
+  : _refcount(1),
+    _bpath(NULL),
+    _pathv(),
+    _end(0),
     _length(length),
     _substart(0),
     _hascpt(false),
     _posSet(false),
     _moving(false),
-    _closed(false),
-    _refcount(1),
-    _bpath(NULL)
+    _closed(false)
 {
     if (length <= 0) {
         g_error("SPCurve::SPCurve called with invalid length parameter");
@@ -56,8 +101,41 @@ SPCurve::SPCurve(guint length)
 
     _bpath = g_new(NArtBpath, length);
     _bpath->code = NR_END;
+
+    _pathv.clear();
+
+    debug_check("SPCurve::SPCurve(guint length)", this);
 }
 
+SPCurve::SPCurve(Geom::PathVector const& pathv)
+  : _refcount(1),
+    _bpath(NULL),
+    _pathv(pathv),
+    _end(0),
+    _length(0),
+    _substart(0),
+    _hascpt(false),
+    _posSet(false),
+    _moving(false),
+    _closed(false)
+{
+    // temporary code to convert to _bpath as well:
+    _bpath = BPath_from_2GeomPath(_pathv);
+    unsigned const len = sp_bpath_length(_bpath);
+    _length = len;
+    _end = _length - 1;
+    gint i = _end;
+    for (; i > 0; i--)
+        if ((_bpath[i].code == NR_MOVETO) ||
+            (_bpath[i].code == NR_MOVETO_OPEN))
+            break;
+    _substart = i;
+    _closed = sp_bpath_closed(_bpath);
+
+    debug_check("SPCurve::SPCurve(Geom::PathVector const& pathv)", this);
+}
+
+// * 2GEOMproof
 SPCurve *
 SPCurve::new_from_foreign_bpath(NArtBpath const *bpath)
 {
@@ -81,6 +159,10 @@ SPCurve::new_from_foreign_bpath(NArtBpath const *bpath)
     curve->_substart = i;
     curve->_closed = sp_bpath_closed(new_bpath);
 
+    curve->_pathv = BPath_to_2GeomPath(curve->_bpath);
+
+    debug_check("SPCurve::new_from_foreign_bpath", curve);
+
     return curve;
 }
 
@@ -88,6 +170,7 @@ SPCurve::new_from_foreign_bpath(NArtBpath const *bpath)
  * Convert NArtBpath object to SPCurve object.
  *
  * \return new SPCurve, or NULL if the curve was not created for some reason.
+ * 2GEOMproof
  */
 SPCurve *
 SPCurve::new_from_bpath(NArtBpath *bpath)
@@ -96,9 +179,13 @@ SPCurve::new_from_bpath(NArtBpath *bpath)
 
     SPCurve *curve = SPCurve::new_from_foreign_bpath(bpath);
     g_free(bpath);
+
+    debug_check("SPCurve::new_from_bpath", curve);
+
     return curve;
 }
 
+// * 2GEOMproof
 SPCurve *
 SPCurve::new_from_rect(NR::Maybe<NR::Rect> const &rect)
 {
@@ -114,9 +201,12 @@ SPCurve::new_from_rect(NR::Maybe<NR::Rect> const &rect)
     }
     c->closepath_current();
 
+    debug_check("SPCurve::new_from_rect", c);
+
     return c;
 }
 
+// * 2GEOMproof
 SPCurve::~SPCurve()
 {
     if (_bpath) {
@@ -127,19 +217,33 @@ SPCurve::~SPCurve()
 
 /* Methods */
 
-/**
- * Frees old path and sets new path
- * This does not copy the bpath, so the new_bpath should not be deleted by caller
- */
 void
-SPCurve::set_bpath(NArtBpath * new_bpath)
+SPCurve::set_pathv(Geom::PathVector const & new_pathv)
 {
-    if (new_bpath && new_bpath != _bpath) {        // FIXME, add function to SPCurve to change bpath? or a copy function?
-        if (_bpath) {
-            g_free(_bpath); //delete old bpath
-        }
-        _bpath = new_bpath;
+    _pathv = new_pathv;
+
+    _hascpt = false;
+    _posSet = false;
+    _moving = false;
+
+    // temporary code to convert to _bpath as well:
+    if (_bpath) {
+        g_free(_bpath);
+        _bpath = NULL;
     }
+    _bpath = BPath_from_2GeomPath(_pathv);
+    unsigned const len = sp_bpath_length(_bpath);
+    _length = len;
+    _end = _length - 1;
+    gint i = _end;
+    for (; i > 0; i--)
+        if ((_bpath[i].code == NR_MOVETO) ||
+            (_bpath[i].code == NR_MOVETO_OPEN))
+            break;
+    _substart = i;
+    _closed = sp_bpath_closed(_bpath);
+
+    debug_check("SPCurve::set_pathv", this);
 }
 
 /**
@@ -150,18 +254,30 @@ SPCurve::get_bpath() const
 {
     return _bpath;
 };
-/*
-NArtBpath *
-SPCurve::get_bpath()
+
+Geom::PathVector const &
+SPCurve::get_pathvector() const
 {
-    return _bpath;
-};
-*/
+    return _pathv;
+}
+
+/**
+ *Returns index in bpath[] of NR_END element.
+ * remove for 2geom
+ */
+guint
+SPCurve::get_length() const
+{
+//    g_message("SPCurve::get_length must be removed");
+
+    return _end;
+}
 
 /**
  * Increase _refcount of curve.
  *
  * \todo should this be shared with other refcounting code?
+ * 2GEOMproof
  */
 SPCurve *
 SPCurve::ref()
@@ -177,6 +293,7 @@ SPCurve::ref()
  * Decrease refcount of curve, with possible destruction.
  *
  * \todo should this be shared with other refcounting code?
+ * 2GEOMproof
  */
 SPCurve *
 SPCurve::unref()
@@ -186,10 +303,6 @@ SPCurve::unref()
     _refcount -= 1;
 
     if (_refcount < 1) {
-        if (_bpath) {
-            g_free(_bpath);
-            _bpath = NULL;
-        }
         delete this;
     }
 
@@ -198,6 +311,8 @@ SPCurve::unref()
 
 /**
  * Add space for more paths in curve.
+ * This function has no meaning for 2geom representation, other than maybe for optimization issues (enlargening the vector for what is to come)
+ * 2GEOMproof
  */
 void
 SPCurve::ensure_space(guint space)
@@ -218,6 +333,7 @@ SPCurve::ensure_space(guint space)
 
 /**
  * Create new curve from its own bpath array.
+ * 2GEOMproof
  */
 SPCurve *
 SPCurve::copy() const
@@ -229,6 +345,7 @@ SPCurve::copy() const
 
 /**
  * Return new curve that is the concatenation of all curves in list.
+ * 2GEOMified
  */
 SPCurve *
 SPCurve::concat(GSList const *list)
@@ -264,11 +381,19 @@ SPCurve::concat(GSList const *list)
 
     new_curve->_substart = i;
 
+    for (GSList const *l = list; l != NULL; l = l->next) {
+        SPCurve *c = (SPCurve *) l->data;
+        new_curve->_pathv.insert( new_curve->_pathv.end(), c->get_pathvector().begin(), c->get_pathvector().end() );
+    }
+
+    debug_check("SPCurve::concat", new_curve);
+
     return new_curve;
 }
 
 /**
  * Returns a list of new curves corresponding to the subpaths in \a curve.
+ * 2geomified
  */
 GSList *
 SPCurve::split() const
@@ -278,6 +403,7 @@ SPCurve::split() const
     guint p = 0;
     GSList *l = NULL;
 
+    gint pathnr = 0;
     while (p < _end) {
         gint i = 1;
         while ((_bpath[p + i].code == NR_LINETO) ||
@@ -290,8 +416,10 @@ SPCurve::split() const
         new_curve->_substart = 0;
         new_curve->_closed = (new_curve->_bpath->code == NR_MOVETO);
         new_curve->_hascpt = (new_curve->_bpath->code == NR_MOVETO_OPEN);
+        new_curve->_pathv = Geom::PathVector(1, _pathv[pathnr]);
         l = g_slist_prepend(l, new_curve);
         p += i;
+        pathnr++;
     }
 
     return l;
@@ -302,7 +430,7 @@ SPCurve::split() const
  */
 template<class M>
 static void
-tmpl_curve_transform(SPCurve *const curve, M const &m)
+tmpl_curve_transform(SPCurve * curve, M const &m)
 {
     g_return_if_fail(curve != NULL);
 
@@ -329,24 +457,44 @@ tmpl_curve_transform(SPCurve *const curve, M const &m)
 
 /**
  * Transform all paths in curve using matrix.
+ * 2GEOMified, can be deleted when completely 2geom
  */
 void
 SPCurve::transform(NR::Matrix const &m)
 {
     tmpl_curve_transform<NR::Matrix>(this, m);
+
+    transform(to_2geom(m));
+
+    debug_check("SPCurve::transform", this);
+}
+
+/**
+ * Transform all paths in curve using matrix.
+ */
+void
+SPCurve::transform(Geom::Matrix const &m)
+{
+    _pathv = _pathv * m;
 }
 
 /**
  * Transform all paths in curve using NR::translate.
+ * 2GEOMified, can be deleted when completely 2geom
  */
 void
 SPCurve::transform(NR::translate const &m)
 {
     tmpl_curve_transform<NR::translate>(this, m);
+
+    transform(to_2geom(m));
+
+    debug_check("SPCurve::transform translate", this);
 }
 
 /**
  * Set curve to empty curve.
+ * 2GEOMified
  */
 void
 SPCurve::reset()
@@ -360,6 +508,10 @@ SPCurve::reset()
     _posSet = false;
     _moving = false;
     _closed = false;
+
+    _pathv.clear();
+
+    debug_check("SPCurve::reset", this);
 }
 
 /* Several consecutive movetos are ALLOWED */
@@ -372,9 +524,17 @@ SPCurve::moveto(gdouble x, gdouble y)
 {
     moveto(NR::Point(x, y));
 }
-
+/**
+ * Calls SPCurve::moveto() with point made of given coordinates.
+ */
+void
+SPCurve::moveto(Geom::Point const &p)
+{
+    moveto(from_2geom(p));
+}
 /**
  * Perform a moveto to a point, thus starting a new subpath.
+ * 2GEOMified
  */
 void
 SPCurve::moveto(NR::Point const &p)
@@ -386,8 +546,21 @@ SPCurve::moveto(NR::Point const &p)
     _hascpt = true;
     _posSet = true;
     _movePos = p;
+    _pathv.push_back( Geom::Path() );  // for some reason Geom::Path(p) does not work...
+    _pathv.back().start(to_2geom(p));
+
+    // the output is not the same. This is because SPCurve *incorrectly* coaslesces multiple moveto's into one for NArtBpath.
+//    debug_check("SPCurve::moveto", this);
 }
 
+/**
+ * Calls SPCurve::lineto() with a point's coordinates.
+ */
+void
+SPCurve::lineto(Geom::Point const &p)
+{
+    lineto(p[Geom::X], p[Geom::Y]);
+}
 /**
  * Calls SPCurve::lineto() with a point's coordinates.
  */
@@ -396,9 +569,9 @@ SPCurve::lineto(NR::Point const &p)
 {
     lineto(p[NR::X], p[NR::Y]);
 }
-
 /**
  * Adds a line to the current subpath.
+ * 2GEOMified
  */
 void
 SPCurve::lineto(gdouble x, gdouble y)
@@ -415,10 +588,14 @@ SPCurve::lineto(gdouble x, gdouble y)
         bp->x3 = x;
         bp->y3 = y;
         _moving = false;
-        return;
-    }
 
-    if (_posSet) {
+        Geom::Path::iterator it = _pathv.back().end();
+        if ( Geom::LineSegment const *last_line_segment = dynamic_cast<Geom::LineSegment const *>( &(*it) )) {
+            Geom::LineSegment new_seg( *last_line_segment );
+            new_seg.setFinal( Geom::Point(x,y) );
+            _pathv.back().replace(it, new_seg);
+        }
+    } else if (_posSet) {
         /* start a new segment */
         ensure_space(2);
         NArtBpath *bp = _bpath + _end;
@@ -433,73 +610,39 @@ SPCurve::lineto(gdouble x, gdouble y)
         _end += 2;
         _posSet = false;
         _closed = false;
-        return;
-    }
-
-    /* add line */
-
-    g_return_if_fail(_end > 1);
-    ensure_space(1);
-    NArtBpath *bp = _bpath + _end;
-    bp->code = NR_LINETO;
-    bp->x3 = x;
-    bp->y3 = y;
-    bp++;
-    bp->code = NR_END;
-    _end++;
-}
 
-/// Unused
-void
-SPCurve::lineto_moving(gdouble x, gdouble y)
-{
-    g_return_if_fail(this != NULL);
-    g_return_if_fail(_hascpt);
-
-    if (_moving) {
-        /* change endpoint */
-        g_return_if_fail(!_posSet);
-        g_return_if_fail(_end > 1);
-        NArtBpath *bp = _bpath + _end - 1;
-        g_return_if_fail(bp->code == NR_LINETO);
-        bp->x3 = x;
-        bp->y3 = y;
+        _pathv.back().appendNew<Geom::LineSegment>( Geom::Point(x,y) );
         return;
-    }
+    } else {
+        /* add line */
 
-    if (_posSet) {
-        /* start a new segment */
-        ensure_space(2);
+        g_return_if_fail(_end > 1);
+        ensure_space(1);
         NArtBpath *bp = _bpath + _end;
-        bp->code = NR_MOVETO_OPEN;
-        bp->setC(3, _movePos);
-        bp++;
         bp->code = NR_LINETO;
         bp->x3 = x;
         bp->y3 = y;
         bp++;
         bp->code = NR_END;
-        _end += 2;
-        _posSet = false;
-        _moving = true;
-        _closed = false;
-        return;
+        _end++;
+        _pathv.back().appendNew<Geom::LineSegment>( Geom::Point(x,y) );
     }
 
-    /* add line */
-
-    g_return_if_fail(_end > 1);
-    ensure_space(1);
-    NArtBpath *bp = _bpath + _end;
-    bp->code = NR_LINETO;
-    bp->x3 = x;
-    bp->y3 = y;
-    bp++;
-    bp->code = NR_END;
-    _end++;
-    _moving = true;
+    debug_check("SPCurve::lineto", this);
 }
 
+/**
+ * Calls SPCurve::curveto() with coordinates of three points.
+ */
+void
+SPCurve::curveto(Geom::Point const &p0, Geom::Point const &p1, Geom::Point const &p2)
+{
+    using Geom::X;
+    using Geom::Y;
+    curveto( p0[X], p0[Y],
+             p1[X], p1[Y],
+             p2[X], p2[Y] );
+}
 /**
  * Calls SPCurve::curveto() with coordinates of three points.
  */
@@ -512,9 +655,9 @@ SPCurve::curveto(NR::Point const &p0, NR::Point const &p1, NR::Point const &p2)
              p1[X], p1[Y],
              p2[X], p2[Y] );
 }
-
 /**
  * Adds a bezier segment to the current subpath.
+ * 2GEOMified
  */
 void
 SPCurve::curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdouble y2)
@@ -542,28 +685,33 @@ SPCurve::curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdo
         _end += 2;
         _posSet = false;
         _closed = false;
-        return;
+        _pathv.back().appendNew<Geom::CubicBezier>( Geom::Point(x0,y0), Geom::Point(x1,y1), Geom::Point(x2,y2) );
+    } else {
+        /* add curve */
+
+        g_return_if_fail(_end > 1);
+        ensure_space(1);
+        NArtBpath *bp = _bpath + _end;
+        bp->code = NR_CURVETO;
+        bp->x1 = x0;
+        bp->y1 = y0;
+        bp->x2 = x1;
+        bp->y2 = y1;
+        bp->x3 = x2;
+        bp->y3 = y2;
+        bp++;
+        bp->code = NR_END;
+        _end++;
+        if (_pathv.empty())  g_message("leeg");
+        else _pathv.back().appendNew<Geom::CubicBezier>( Geom::Point(x0,y0), Geom::Point(x1,y1), Geom::Point(x2,y2) );
     }
 
-    /* add curve */
-
-    g_return_if_fail(_end > 1);
-    ensure_space(1);
-    NArtBpath *bp = _bpath + _end;
-    bp->code = NR_CURVETO;
-    bp->x1 = x0;
-    bp->y1 = y0;
-    bp->x2 = x1;
-    bp->y2 = y1;
-    bp->x3 = x2;
-    bp->y3 = y2;
-    bp++;
-    bp->code = NR_END;
-    _end++;
+    debug_check("SPCurve::curveto", this);
 }
 
 /**
  * Close current subpath by possibly adding a line between start and end.
+  * 2GEOMified
  */
 void
 SPCurve::closepath()
@@ -587,8 +735,23 @@ SPCurve::closepath()
 
         bs->code = NR_MOVETO;
     }
+    // Inkscape always manually adds the closing line segment to SPCurve with a lineto.
+    // This lineto is removed in the writing function for NArtBpath, 
+    // so when path is closed and the last segment is a lineto, the closing line segment must really be removed first!
+    // TODO: fix behavior in Inkscape!
+    if ( /*Geom::LineSegment const *line_segment = */ dynamic_cast<Geom::LineSegment const  *>(&_pathv.back().back())) {
+        _pathv.back().erase_last();
+    }
+    _pathv.back().close(true);
     _closed = true;
 
+    for (Geom::PathVector::const_iterator it = _pathv.begin(); it != _pathv.end(); it++) {
+         if ( ! it->closed() ) {
+            _closed = false;
+            break;
+        }
+    }
+
     for (NArtBpath const *bp = _bpath; bp->code != NR_END; bp++) {
         /** \todo
          * effic: Maintain a count of NR_MOVETO_OPEN's (e.g. instead of
@@ -601,6 +764,8 @@ SPCurve::closepath()
     }
 
     _hascpt = false;
+
+    debug_check("SPCurve::closepath", this);
 }
 
 /** Like SPCurve::closepath() but sets the end point of the current
@@ -627,8 +792,23 @@ SPCurve::closepath_current()
 
         bs->code = NR_MOVETO;
     }
+    // Inkscape always manually adds the closing line segment to SPCurve with a lineto.
+    // This lineto is removed in the writing function for NArtBpath, 
+    // so when path is closed and the last segment is a lineto, the closing line segment must really be removed first!
+    // TODO: fix behavior in Inkscape!
+    if ( /*Geom::LineSegment const *line_segment = */ dynamic_cast<Geom::LineSegment const  *>(&_pathv.back().back())) {
+        _pathv.back().erase_last();
+    }
+    _pathv.back().close(true);
     _closed = true;
 
+    for (Geom::PathVector::const_iterator it = _pathv.begin(); it != _pathv.end(); it++) {
+         if ( ! it->closed() ) {
+            _closed = false;
+            break;
+        }
+    }
+
     for (NArtBpath const *bp = _bpath; bp->code != NR_END; bp++) {
         /** \todo
          * effic: Maintain a count of NR_MOVETO_OPEN's (e.g. instead of
@@ -642,6 +822,8 @@ SPCurve::closepath_current()
 
     _hascpt = false;
     _moving = false;
+
+    debug_check("SPCurve::closepath_current", this);
 }
 
 /**
@@ -652,6 +834,9 @@ SPCurve::is_empty() const
 {
     g_return_val_if_fail(this != NULL, TRUE);
 
+    bool empty = _pathv.empty(); /* || _pathv.front().empty(); */
+    debug_check("SPCurve::is_empty", (_bpath->code == NR_END)  ==  empty );
+
     return (_bpath->code == NR_END);
 }
 
@@ -661,13 +846,22 @@ SPCurve::is_empty() const
 bool
 SPCurve::is_closed() const
 {
+    bool closed = true;
+    for (Geom::PathVector::const_iterator it = _pathv.begin(); it != _pathv.end(); it++) {
+         if ( ! it->closed() ) {
+            closed = false;
+            break;
+        }
+    }
+    debug_check("SPCurve::is_closed", (closed)  ==  (_closed) );
+
     return _closed;
 }
 
 /**
  * Return last subpath or NULL.
  */
-NArtBpath *
+NArtBpath const *
 SPCurve::last_bpath() const
 {
     g_return_val_if_fail(this != NULL, NULL);
@@ -682,7 +876,7 @@ SPCurve::last_bpath() const
 /**
  * Return first subpath or NULL.
  */
-NArtBpath *
+NArtBpath const *
 SPCurve::first_bpath() const
 {
     g_return_val_if_fail(this != NULL, NULL);
@@ -695,14 +889,20 @@ SPCurve::first_bpath() const
 }
 
 /**
- * Return first point of first subpath or (0,0).
+ * Return first point of first subpath or (0,0).  TODO: shouldn't this be (NR_HUGE, NR_HUGE) to be able to tell it apart from normal (0,0) ?
  */
 NR::Point
 SPCurve::first_point() const
 {
-    NArtBpath *const bpath = first_bpath();
+    NArtBpath const * bpath = first_bpath();
     g_return_val_if_fail(bpath != NULL, NR::Point(0, 0));
+    if (is_empty())
+        return NR::Point(0, 0);
+
+    debug_check("SPCurve::first_point", bpath->c(3) == _pathv.front().initialPoint() );
+
     return bpath->c(3);
+    // return from_2geom( _pathv.front().initialPoint() );
 }
 
 /**
@@ -724,6 +924,9 @@ SPCurve::second_point() const
         bpath = _bpath + 1;
     }
     g_return_val_if_fail(bpath != NULL, NR::Point(0, 0));
+
+    debug_check("SPCurve::second_point", bpath->c(3) == _pathv.front()[0].finalPoint() );
+
     return bpath->c(3);
 }
 
@@ -741,18 +944,33 @@ SPCurve::penultimate_point() const
 
     NArtBpath *const bpath = _bpath + _end - 2;
     g_return_val_if_fail(bpath != NULL, NR::Point(0, 0));
+    
+    Geom::Point p(NR_HUGE, NR_HUGE);
+    Geom::Curve const& back = _pathv.back().back();
+    if (_pathv.back().closed()) {
+        p = back.finalPoint();
+    } else {
+        p = back.initialPoint();
+    }
+
+    debug_check("SPCurve::penultimate_point", bpath->c(3) == p );
     return bpath->c(3);
 }
 
 /**
- * Return last point of last subpath or (0,0).
+ * Return last point of last subpath or (0,0).  TODO: shouldn't this be (NR_HUGE, NR_HUGE) to be able to tell it apart from normal (0,0) ?
  */
 NR::Point
 SPCurve::last_point() const
 {
-    NArtBpath *const bpath = last_bpath();
+    NArtBpath const * bpath = last_bpath();
     g_return_val_if_fail(bpath != NULL, NR::Point(0, 0));
+    if (is_empty())
+        return NR::Point(0, 0);
+
+    debug_check("SPCurve::last_point", bpath->c(3) == _pathv.back().finalPoint() );
     return bpath->c(3);
+    // return from_2geom( _pathv.back().finalPoint() );
 }
 
 inline static bool
@@ -765,6 +983,8 @@ is_moveto(NRPathcode const c)
  * Returns a *new* \a curve but drawn in the opposite direction.
  * Should result in the same shape, but
  * with all its markers drawn facing the other direction.
+ * Reverses the order of subpaths as well
+ * 2GEOMified
  **/
 SPCurve *
 SPCurve::create_reverse() const
@@ -806,10 +1026,17 @@ SPCurve::create_reverse() const
                 g_assert_not_reached();
         }
     }
+
+    new_curve->_pathv = Geom::reverse_paths_and_order(_pathv);
+
+    debug_check("SPCurve::create_reverse", new_curve);
 }
 
 /**
- * Append \a curve2 to \a curve.
+ * Append \a curve2 to \a this.
+ * If \a use_lineto is false, simply add all paths in \a curve2 to \a this;
+ * if \a use_lineto is true, combine \a this's last path and \a curve2's first path and add the rest of the paths in \a curve2 to \a this.
+ * 2GEOMified
  */
 void
 SPCurve::append(SPCurve const *curve2,
@@ -818,6 +1045,8 @@ SPCurve::append(SPCurve const *curve2,
     g_return_if_fail(this != NULL);
     g_return_if_fail(curve2 != NULL);
 
+    if (curve2->is_empty())
+        return;
     if (curve2->_end < 1)
         return;
 
@@ -865,6 +1094,29 @@ SPCurve::append(SPCurve const *curve2,
     if (closed) {
         closepath();
     }
+
+    debug_check("SPCurve::append", this);
+
+    /* 2GEOM code when code above is removed:
+    if (use_lineto) {
+        Geom::PathVector::const_iterator it = curve2->_pathv.begin();
+        if ( ! _pathv.empty() ) {
+            Geom::Path & lastpath = _pathv.back();
+            lastpath.appendNew<Geom::LineSegment>( (*it).initialPoint() );
+            lastpath.append( (*it) );
+        } else {
+            _pathv.push_back( (*it) );
+        }
+
+        for (it++; it != curve2->_pathv.end(); it++) {
+            _pathv.push_back( (*it) );
+        }
+    } else {
+        for (Geom::PathVector::const_iterator it = curve2->_pathv.begin(); it != curve2->_pathv.end(); it++) {
+            _pathv.push_back( (*it) );
+        }
+    }
+    */
 }
 
 /**
@@ -882,7 +1134,9 @@ SPCurve::append_continuous(SPCurve const *c1, gdouble tolerance)
         return this;
     }
 
-    NArtBpath *be = last_bpath();
+    debug_check("SPCurve::append_continuous 11", this);
+
+    NArtBpath const *be = last_bpath();
     if (be) {
         NArtBpath const *bs = c1->first_bpath();
         if ( bs
@@ -923,17 +1177,23 @@ SPCurve::append_continuous(SPCurve const *c1, gdouble tolerance)
         append(c1, TRUE);
     }
 
+    debug_check("SPCurve::append_continuous", this);
+
     return this;
 }
 
 /**
  * Remove last segment of curve.
+ * (Only used once in /src/pen-context.cpp)
  */
 void
 SPCurve::backspace()
 {
     g_return_if_fail(this != NULL);
 
+    if ( is_empty() )
+        return;
+
     if (_end > 0) {
         _end -= 1;
         if (_end > 0) {
@@ -950,6 +1210,13 @@ SPCurve::backspace()
         }
         _bpath[_end].code = NR_END;
     }
+
+    if ( !_pathv.back().empty() ) {
+        _pathv.back().erase_last();
+        _pathv.back().close(false);
+    }
+
+    debug_check("SPCurve::backspace", this);
 }
 
 /* Private methods */
@@ -1089,6 +1356,9 @@ sp_curve_nonzero_distance_including_space(SPCurve const *const curve, double seg
     }
 }
 
+/**
+ * 
+ */
 void
 SPCurve::stretch_endpoints(NR::Point const &new_p0, NR::Point const &new_p1)
 {
@@ -1130,8 +1400,29 @@ SPCurve::stretch_endpoints(NR::Point const &new_p0, NR::Point const &new_p1)
     /* Explicit set for better numerical properties. */
     _bpath[nSegs].setC(3, new_p1);
     delete [] seg2len;
+
+    Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2 = _pathv.front().toPwSb();
+    Geom::Piecewise<Geom::SBasis> arclength = Geom::arcLengthSb(pwd2);
+    if ( arclength.lastValue() <= 0 ) {
+        g_error("SPCurve::stretch_endpoints - arclength <= 0");
+        throw;
+    }
+    arclength *= 1./arclength.lastValue();
+    Geom::Point const A( to_2geom(offset0) );
+    Geom::Point const B( to_2geom(offset1) );
+    Geom::Piecewise<Geom::SBasis> offsetx = (arclength*-1.+1)*A[0] + arclength*B[0];
+    Geom::Piecewise<Geom::SBasis> offsety = (arclength*-1.+1)*A[1] + arclength*B[1];
+    Geom::Piecewise<Geom::D2<Geom::SBasis> > offsetpath = Geom::sectionize( Geom::D2<Geom::Piecewise<Geom::SBasis> >(offsetx, offsety) );
+    pwd2 += offsetpath;
+    _pathv = Geom::path_from_piecewise( pwd2, 0.001 );
+
+    debug_check("SPCurve::stretch_endpoints", this);
 }
 
+/**
+ *  sets start of first path to new_p0, and end of first path to  new_p1
+ * 2GEOMified
+ */
 void
 SPCurve::move_endpoints(NR::Point const &new_p0, NR::Point const &new_p1)
 {
@@ -1143,8 +1434,72 @@ SPCurve::move_endpoints(NR::Point const &new_p0, NR::Point const &new_p1)
 
     _bpath->setC(3, new_p0);
     _bpath[nSegs].setC(3, new_p1);
+
+    _pathv.front().setInitial(to_2geom(new_p0));
+    _pathv.front().setFinal(to_2geom(new_p1));
+
+    debug_check("SPCurve::move_endpoints", this);
+}
+
+/**
+ * returns the number of nodes in a path, used for statusbar text when selecting an spcurve.
+ * 2GEOMified
+ */
+guint
+SPCurve::nodes_in_path() const
+{
+    gint r = _end;
+    gint i = _length - 1;
+    if (i > r) i = r; // sometimes after switching from node editor length is wrong, e.g. f6 - draw - f2 - tab - f1, this fixes it
+    for (; i >= 0; i --)
+        if (_bpath[i].code == NR_MOVETO)
+            r --;
+
+    guint nr = 0;
+    for(Geom::PathVector::const_iterator it = _pathv.begin(); it != _pathv.end(); ++it) {
+        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
+    }
+
+    debug_check("SPCurve::nodes_in_path", r == (gint)nr);
+
+    return r;
 }
 
+/**
+ *  Adds p to the last point (and last handle if present) of the last path
+ */
+void
+SPCurve::last_point_additive_move(Geom::Point const & p)
+{
+    if (is_empty()) {
+        return;
+    }
+    if (_end == 0) {
+        return;
+    }
+    NArtBpath * path = _bpath + _end - 1;
+
+    if (path->code == NR_CURVETO) {
+        path->x2 += p[Geom::X];
+        path->y2 += p[Geom::Y];
+    }
+    path->x3 += p[Geom::X];
+    path->y3 += p[Geom::Y];
+
+    _pathv.back().setFinal( _pathv.back().finalPoint() + p );
+
+    // Move handle as well when the last segment is a cubic bezier segment:
+    // TODO: what to do for quadratic beziers?
+    if ( Geom::CubicBezier const *lastcube = dynamic_cast<Geom::CubicBezier const *>(&_pathv.back().back()) ) {
+        Geom::CubicBezier newcube( *lastcube );
+        newcube.setPoint(2, newcube[2] + p);
+        _pathv.back().replace( --_pathv.back().end(), newcube );
+    }
+
+    debug_check("SPCurve::last_point_additive_move", this);
+}
 
 /*
   Local Variables:
index 5cd8bb12cadd1b04ca241308b3d890340e049b07..4e94578ed975084cfead90f3a42082238efb5734 100644 (file)
 #include <glib/gtypes.h>
 #include <glib/gslist.h>
 
+#include <2geom/forward.h>
+#include <2geom/point.h>
+
 #include "libnr/nr-forward.h"
 #include "libnr/nr-rect.h"
 
 #define SP_CURVE_LENSTEP 32
 
-/// Wrapper around NArtBpath.
+struct SPObject;
+
+/// Wrapper around Geom::PathVector.
 class SPCurve {
 public:
     /* Constructors */
     SPCurve(guint length = SP_CURVE_LENSTEP);
+    SPCurve(Geom::PathVector const& pathv);
     static SPCurve * new_from_bpath(NArtBpath *bpath);
     static SPCurve * new_from_foreign_bpath(NArtBpath const *bpath);
     static SPCurve * new_from_rect(NR::Maybe<NR::Rect> const &rect);
 
     virtual ~SPCurve();
 
-    void set_bpath(NArtBpath * new_bpath);
+    void set_pathv(Geom::PathVector const & new_pathv);
     NArtBpath const * get_bpath() const;
+    Geom::PathVector const & get_pathvector() const;
 
-    /// Index in bpath[] of NR_END element.
-    guint _end;
-
-    /// Allocated size (i.e., capacity) of bpath[] array.  Not to be confused 
-    /// with the SP_CURVE_LENGTH macro, which returns the logical length of 
-    /// the path (i.e., index of NR_END).
-    guint _length;
-
-    /// Index in bpath[] of the start (i.e., moveto element) of the last 
-    /// subpath in this path.
-    guint _substart;
-
-    /// Previous moveto position.
-    /// \note This is used for coalescing moveto's, whereas if we're to 
-    /// conform to the SVG spec then we mustn't coalesce movetos if we have 
-    /// midpoint markers.  Ref:
-    /// http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
-    /// (first subitem of the item about zero-length path segments)
-    NR::Point _movePos;
-
-    /// True iff current point is defined.  Initially false for a new curve; 
-    /// becomes true after moveto; becomes false on closepath.  Curveto, 
-    /// lineto etc. require hascpt; hascpt remains true after lineto/curveto.
-    bool _hascpt : 1;
-    
-    /// True iff previous was moveto.
-    bool _posSet : 1;
-
-    /// True iff bpath end is moving.
-    bool _moving : 1;
-    
-    /// True iff all subpaths are closed.
-    bool _closed : 1;
+    guint get_length() const;
 
     SPCurve * ref();
     SPCurve * unref();
@@ -77,18 +52,22 @@ public:
     SPCurve * copy() const;
 
     GSList * split() const;
+    void transform(Geom::Matrix const &m);
     void transform(NR::Matrix const &);
     void transform(NR::translate const &);
     void stretch_endpoints(NR::Point const &, NR::Point const &);
     void move_endpoints(NR::Point const &, NR::Point const &);
+    void last_point_additive_move(Geom::Point const & p);
 
     void reset();
 
+    void moveto(Geom::Point const &p);
     void moveto(NR::Point const &p);
     void moveto(gdouble x, gdouble y);
+    void lineto(Geom::Point const &p);
     void lineto(NR::Point const &p);
     void lineto(gdouble x, gdouble y);
-    void lineto_moving(gdouble x, gdouble y);
+    void curveto(Geom::Point const &p0, Geom::Point const &p1, Geom::Point const &p2);
     void curveto(NR::Point const &p0, NR::Point const &p1, NR::Point const &p2);
     void curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdouble y2);
     void closepath();
@@ -98,12 +77,13 @@ public:
 
     bool is_empty() const;
     bool is_closed() const;
-    NArtBpath * last_bpath() const;
-    NArtBpath * first_bpath() const;
+    NArtBpath const * last_bpath() const;
+    NArtBpath const * first_bpath() const;
     NR::Point first_point() const;
     NR::Point last_point() const;
     NR::Point second_point() const;
     NR::Point penultimate_point() const;
+    guint nodes_in_path() const;
 
     void append(SPCurve const *curve2, bool use_lineto);
     SPCurve * create_reverse() const;
@@ -117,20 +97,61 @@ protected:
     gint _refcount;
 
     NArtBpath *_bpath;
+    Geom::PathVector _pathv;
+
+    /// Index in bpath[] of NR_END element.
+    guint _end;
+
+    /// Allocated size (i.e., capacity) of bpath[] array.  Not to be confused 
+    /// with the SP_CURVE_LENGTH macro, which returns the logical length of 
+    /// the path (i.e., index of NR_END).
+    guint _length;
+
+    /// Index in bpath[] of the start (i.e., moveto element) of the last 
+    /// subpath in this path.
+    guint _substart;
+
+    /// Previous moveto position.
+    /// \note This is used for coalescing moveto's, whereas if we're to 
+    /// conform to the SVG spec then we mustn't coalesce movetos if we have 
+    /// midpoint markers.  Ref:
+    /// http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes
+    /// (first subitem of the item about zero-length path segments)
+    NR::Point _movePos;
+
+    /// True iff current point is defined.  Initially false for a new curve; 
+    /// becomes true after moveto; becomes false on closepath.  Curveto, 
+    /// lineto etc. require hascpt; hascpt remains true after lineto/curveto.
+    bool _hascpt : 1;
+    
+    /// True iff previous was moveto.
+    bool _posSet : 1;
+
+    /// True iff bpath end is moving.
+    bool _moving : 1;
+    
+    /// True iff all subpaths are closed.
+    bool _closed : 1;
 
 private:
     // Don't implement these:
     SPCurve(const SPCurve&);
     SPCurve& operator=(const SPCurve&);
 
+//friends:
     friend double sp_curve_distance_including_space(SPCurve const *const curve, double seg2len[]);
     friend double sp_curve_nonzero_distance_including_space(SPCurve const *const curve, double seg2len[]);
     template<class M> friend void tmpl_curve_transform(SPCurve *const curve, M const &m);
+    // this function is the only one who needs read access to _movePos and _posSet
+    friend void sp_polygon_set(SPObject *object, unsigned int key, const gchar *value);
+
+    static void debug_check( char const * text, SPCurve const * curve);
+    static void debug_check( char const * text, bool a);
 };
 
-#define SP_CURVE_LENGTH(c) (((SPCurve const *)(c))->_end)
-#define SP_CURVE_BPATH(c) ((c)->get_bpath())
-#define SP_CURVE_SEGMENT(c,i) ((c)->get_bpath() + (i))
+#define SP_CURVE_LENGTH(c) (((SPCurve const *)(c))->get_length())
+#define SP_CURVE_BPATH(c) (((SPCurve const *)(c))->get_bpath())
+#define SP_CURVE_SEGMENT(c,i) (((SPCurve const *)(c))->get_bpath() + (i))
 
 #endif /* !SEEN_DISPLAY_CURVE_H */
 
@@ -143,4 +164,4 @@ private:
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
index 0ff7132e189d419b11abc94c154a3d2feb4d86bb..0cd0de2bb6715c16ae9298adfd575987ce1b220c 100644 (file)
@@ -432,7 +432,7 @@ void
 nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool force_shape)
 {
     if ((shape->_fill.paint.type() != NRArenaShape::Paint::NONE || force_shape) &&
-        ((shape->curve->_end > 2) || (SP_CURVE_BPATH(shape->curve)[1].code == NR_CURVETO)) ) {
+        ((shape->curve->get_length() > 2) || (SP_CURVE_BPATH(shape->curve)[1].code == NR_CURVETO)) ) {
         if (TRUE || !shape->fill_shp) {
             NR::Matrix  cached_to_new = NR::identity();
             int isometry = 0;
index 8670f61b29ac604cb47396de534f141825ec255a..02a195bb0cbfef4d1176a254c2ba558b6032c8c7 100644 (file)
@@ -207,7 +207,7 @@ void FilterComposite::set_operator(FeCompositeOperator op) {
 }
 
 void FilterComposite::set_arithmetic(double k1, double k2, double k3, double k4) {
-    if (!isFinite(k1) || !isFinite(k2) || !isFinite(k3) || !isFinite(k4)) {
+    if (!IS_FINITE(k1) || !IS_FINITE(k2) || !IS_FINITE(k3) || !IS_FINITE(k4)) {
         g_warning("Non-finite parameter for feComposite arithmetic operator");
         return;
     }
index 5ef43039475e1570cb7c745693270805e98d3d79..3113332476e40a62df6f523573d6e16a694ebaa0 100644 (file)
@@ -792,14 +792,14 @@ FilterTraits FilterGaussian::get_input_traits() {
 
 void FilterGaussian::set_deviation(double deviation)
 {
-    if(isFinite(deviation) && deviation >= 0) {
+    if(IS_FINITE(deviation) && deviation >= 0) {
         _deviation_x = _deviation_y = deviation;
     }
 }
 
 void FilterGaussian::set_deviation(double x, double y)
 {
-    if(isFinite(x) && x >= 0 && isFinite(y) && y >= 0) {
+    if(IS_FINITE(x) && x >= 0 && IS_FINITE(y) && y >= 0) {
         _deviation_x = x;
         _deviation_y = y;
     }
index 6e919d81d1a7f186aceca886dabd2c994b95b142..33c3898a735168100cbd9296580422efe038eda7 100644 (file)
@@ -312,9 +312,9 @@ spdc_attach_selection(SPDrawContext *dc, Inkscape::Selection */*sel*/)
         for (GSList *l = dc->white_curves; l != NULL; l = l->next) {
             SPCurve *c;
             c = (SPCurve*)l->data;
-            g_return_if_fail( c->_end > 1 );
+            g_return_if_fail( c->get_length() > 1 );
             if ( SP_CURVE_BPATH(c)->code == NR_MOVETO_OPEN ) {
-                NArtBpath *s, *e;
+                NArtBpath const *s, *e;
                 SPDrawAnchor *a;
                 s = c->first_bpath();
                 e = c->last_bpath();
index 7f3c41c2ec94ebc0939b3a249d1ba2bdcb772ad2..c6140d17d08e30ce0ae78699df481b84b05b9788 100644 (file)
@@ -704,7 +704,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                                 // so _gradually_ let go attraction to prevent jerks
                                 target = (dc->hatch_spacing * speed + hatch_dist * (SPEED_NORMAL - speed))/SPEED_NORMAL;                            
                             }
-                            if (!isNaN(dot) && dot < -0.5) {// flip
+                            if (!IS_NAN(dot) && dot < -0.5) {// flip
                                 target = -target;
                             }
 
@@ -775,7 +775,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                 } else {
                     // Not drawing but spacing set: gray, center snapped, fixed radius
                     NR::Point c = (nearest + dc->hatch_spacing * hatch_unit_vector) * motion_to_curve.inverse();
-                    if (!isNaN(c[NR::X]) && !isNaN(c[NR::Y])) {
+                    if (!IS_NAN(c[NR::X]) && !IS_NAN(c[NR::Y])) {
                         NR::Matrix const sm (NR::scale(dc->hatch_spacing, dc->hatch_spacing) * NR::translate(c));
                         sp_canvas_item_affine_absolute(dc->hatch_area, sm);
                         sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x7f7f7fff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
@@ -989,7 +989,7 @@ set_to_accumulated(SPDynaDrawContext *dc, bool unionize)
             item->transform = SP_ITEM(desktop->currentRoot())->getRelativeTransform(desktop->currentLayer());
             item->updateRepr();
         }
-        abp = nr_artpath_affine(dc->accumulated->first_bpath(), sp_desktop_dt2root_affine(desktop));
+        abp = nr_artpath_affine(dc->accumulated->get_bpath(), sp_desktop_dt2root_affine(desktop));
         str = sp_svg_write_path(abp);
         g_assert( str != NULL );
         g_free(abp);
@@ -1053,22 +1053,22 @@ accumulate_calligraphic(SPDynaDrawContext *dc)
         dc->accumulated->reset(); /*  Is this required ?? */
         SPCurve *rev_cal2 = dc->cal2->create_reverse();
 
-        g_assert(dc->cal1->_end > 1);
-        g_assert(rev_cal2->_end > 1);
+        g_assert(dc->cal1->get_length() > 1);
+        g_assert(rev_cal2->get_length() > 1);
         g_assert(SP_CURVE_SEGMENT(dc->cal1, 0)->code == NR_MOVETO_OPEN);
         g_assert(SP_CURVE_SEGMENT(rev_cal2, 0)->code == NR_MOVETO_OPEN);
         g_assert(SP_CURVE_SEGMENT(dc->cal1, 1)->code == NR_CURVETO);
         g_assert(SP_CURVE_SEGMENT(rev_cal2, 1)->code == NR_CURVETO);
-        g_assert(SP_CURVE_SEGMENT(dc->cal1, dc->cal1->_end-1)->code == NR_CURVETO);
-        g_assert(SP_CURVE_SEGMENT(rev_cal2, rev_cal2->_end-1)->code == NR_CURVETO);
+        g_assert(SP_CURVE_SEGMENT(dc->cal1, dc->cal1->get_length()-1)->code == NR_CURVETO);
+        g_assert(SP_CURVE_SEGMENT(rev_cal2, rev_cal2->get_length()-1)->code == NR_CURVETO);
 
         dc->accumulated->append(dc->cal1, FALSE);
 
-        add_cap(dc->accumulated, SP_CURVE_SEGMENT(dc->cal1, dc->cal1->_end-1)->c(2), SP_CURVE_SEGMENT(dc->cal1, dc->cal1->_end-1)->c(3), SP_CURVE_SEGMENT(rev_cal2, 0)->c(3), SP_CURVE_SEGMENT(rev_cal2, 1)->c(1), dc->cap_rounding);
+        add_cap(dc->accumulated, SP_CURVE_SEGMENT(dc->cal1, dc->cal1->get_length()-1)->c(2), SP_CURVE_SEGMENT(dc->cal1, dc->cal1->get_length()-1)->c(3), SP_CURVE_SEGMENT(rev_cal2, 0)->c(3), SP_CURVE_SEGMENT(rev_cal2, 1)->c(1), dc->cap_rounding);
 
         dc->accumulated->append(rev_cal2, TRUE);
 
-        add_cap(dc->accumulated, SP_CURVE_SEGMENT(rev_cal2, rev_cal2->_end-1)->c(2), SP_CURVE_SEGMENT(rev_cal2, rev_cal2->_end-1)->c(3), SP_CURVE_SEGMENT(dc->cal1, 0)->c(3), SP_CURVE_SEGMENT(dc->cal1, 1)->c(1), dc->cap_rounding);
+        add_cap(dc->accumulated, SP_CURVE_SEGMENT(rev_cal2, rev_cal2->get_length()-1)->c(2), SP_CURVE_SEGMENT(rev_cal2, rev_cal2->get_length()-1)->c(3), SP_CURVE_SEGMENT(dc->cal1, 0)->c(3), SP_CURVE_SEGMENT(dc->cal1, 1)->c(1), dc->cap_rounding);
 
         dc->accumulated->closepath();
 
@@ -1107,7 +1107,7 @@ fit_and_split(SPDynaDrawContext *dc, gboolean release)
 #endif
 
         /* Current calligraphic */
-        if ( dc->cal1->_end == 0 || dc->cal2->_end == 0 ) {
+        if ( dc->cal1->get_length() == 0 || dc->cal2->get_length() == 0 ) {
             /* dc->npoints > 0 */
             /* g_print("calligraphics(1|2) reset\n"); */
             dc->cal1->reset();
index 88496b06554c157517467a9da66f607b869c206b..36cfb0d15a945406aa91f1195c9db9c50fd3f3cd 100644 (file)
@@ -736,7 +736,7 @@ set_to_accumulated(SPEraserContext *dc)
             item->transform = SP_ITEM(desktop->currentRoot())->getRelativeTransform(desktop->currentLayer());
             item->updateRepr();
         }
-        abp = nr_artpath_affine(dc->accumulated->first_bpath(), sp_desktop_dt2root_affine(desktop));
+        abp = nr_artpath_affine(dc->accumulated->get_bpath(), sp_desktop_dt2root_affine(desktop));
         str = sp_svg_write_path(abp);
         g_assert( str != NULL );
         g_free(abp);
@@ -879,22 +879,22 @@ accumulate_eraser(SPEraserContext *dc)
         dc->accumulated->reset(); /*  Is this required ?? */
         SPCurve *rev_cal2 = dc->cal2->create_reverse();
 
-        g_assert(dc->cal1->_end > 1);
-        g_assert(rev_cal2->_end > 1);
+        g_assert(dc->cal1->get_length() > 1);
+        g_assert(rev_cal2->get_length() > 1);
         g_assert(SP_CURVE_SEGMENT(dc->cal1, 0)->code == NR_MOVETO_OPEN);
         g_assert(SP_CURVE_SEGMENT(rev_cal2, 0)->code == NR_MOVETO_OPEN);
         g_assert(SP_CURVE_SEGMENT(dc->cal1, 1)->code == NR_CURVETO);
         g_assert(SP_CURVE_SEGMENT(rev_cal2, 1)->code == NR_CURVETO);
-        g_assert(SP_CURVE_SEGMENT(dc->cal1, dc->cal1->_end-1)->code == NR_CURVETO);
-        g_assert(SP_CURVE_SEGMENT(rev_cal2, rev_cal2->_end-1)->code == NR_CURVETO);
+        g_assert(SP_CURVE_SEGMENT(dc->cal1, dc->cal1->get_length()-1)->code == NR_CURVETO);
+        g_assert(SP_CURVE_SEGMENT(rev_cal2, rev_cal2->get_length()-1)->code == NR_CURVETO);
 
         dc->accumulated->append(dc->cal1, FALSE);
 
-        add_cap(dc->accumulated, SP_CURVE_SEGMENT(dc->cal1, dc->cal1->_end-1)->c(2), SP_CURVE_SEGMENT(dc->cal1, dc->cal1->_end-1)->c(3), SP_CURVE_SEGMENT(rev_cal2, 0)->c(3), SP_CURVE_SEGMENT(rev_cal2, 1)->c(1), dc->cap_rounding);
+        add_cap(dc->accumulated, SP_CURVE_SEGMENT(dc->cal1, dc->cal1->get_length()-1)->c(2), SP_CURVE_SEGMENT(dc->cal1, dc->cal1->get_length()-1)->c(3), SP_CURVE_SEGMENT(rev_cal2, 0)->c(3), SP_CURVE_SEGMENT(rev_cal2, 1)->c(1), dc->cap_rounding);
 
         dc->accumulated->append(rev_cal2, TRUE);
 
-        add_cap(dc->accumulated, SP_CURVE_SEGMENT(rev_cal2, rev_cal2->_end-1)->c(2), SP_CURVE_SEGMENT(rev_cal2, rev_cal2->_end-1)->c(3), SP_CURVE_SEGMENT(dc->cal1, 0)->c(3), SP_CURVE_SEGMENT(dc->cal1, 1)->c(1), dc->cap_rounding);
+        add_cap(dc->accumulated, SP_CURVE_SEGMENT(rev_cal2, rev_cal2->get_length()-1)->c(2), SP_CURVE_SEGMENT(rev_cal2, rev_cal2->get_length()-1)->c(3), SP_CURVE_SEGMENT(dc->cal1, 0)->c(3), SP_CURVE_SEGMENT(dc->cal1, 1)->c(1), dc->cap_rounding);
 
         dc->accumulated->closepath();
 
@@ -933,7 +933,7 @@ fit_and_split(SPEraserContext *dc, gboolean release)
 #endif
 
         /* Current eraser */
-        if ( dc->cal1->_end == 0 || dc->cal2->_end == 0 ) {
+        if ( dc->cal1->get_length() == 0 || dc->cal2->get_length() == 0 ) {
             /* dc->npoints > 0 */
             /* g_print("erasers(1|2) reset\n"); */
             dc->cal1->reset();
index 608f9bb561fe3b1182c32cfccb7c34a432421327..57c221fce5381969ac86b5bf21dac7219dae0b68 100644 (file)
  */
 
 #if defined(__isnan)
-# define isNaN(_a) (__isnan(_a))
+# define IS_NAN(_a) (__isnan(_a))
 #elif defined(__APPLE__) && __GNUC__ == 3
-# define isNaN(_a) (__isnan(_a))       /* MacOSX/Darwin definition < 10.4 */
+# define IS_NAN(_a) (__isnan(_a))      /* MacOSX/Darwin definition < 10.4 */
 #elif defined(WIN32) || defined(_isnan)
-# define isNaN(_a) (_isnan(_a))        /* Win32 definition */
+# define IS_NAN(_a) (_isnan(_a))       /* Win32 definition */
 #elif defined(isnan) || defined(__FreeBSD__) || defined(__osf__)
-# define isNaN(_a) (isnan(_a))         /* GNU definition */
+# define IS_NAN(_a) (isnan(_a))                /* GNU definition */
 #elif defined (SOLARIS_2_8) && __GNUC__ == 3 && __GNUC_MINOR__ == 2
-# define isNaN(_a) (isnan(_a))         /* GNU definition */
+# define IS_NAN(_a) (isnan(_a))                /* GNU definition */
 #else
-# define isNaN(_a) (std::isnan(_a))
+# define IS_NAN(_a) (std::isnan(_a))
 #endif
 /* If the above doesn't work, then try (a != a).
  * Also, please report a bug as per http://www.inkscape.org/report_bugs.php,
 
 
 #if defined(__isfinite)
-# define isFinite(_a) (__isfinite(_a))
+# define IS_FINITE(_a) (__isfinite(_a))
 #elif defined(__APPLE__) && __GNUC__ == 3
-# define isFinite(_a) (__isfinite(_a)) /* MacOSX/Darwin definition < 10.4 */
+# define IS_FINITE(_a) (__isfinite(_a))        /* MacOSX/Darwin definition < 10.4 */
 #elif defined(__sgi)
-# define isFinite(_a) (_isfinite(_a))
+# define IS_FINITE(_a) (_isfinite(_a))
 #elif defined(isfinite)
-# define isFinite(_a) (isfinite(_a))
+# define IS_FINITE(_a) (isfinite(_a))
 #elif defined(__osf__)
-# define isFinite(_a) (finite(_a) && !isNaN(_a))
+# define IS_FINITE(_a) (finite(_a) && !IS_NAN(_a))
 #elif defined (SOLARIS_2_8) && __GNUC__ == 3 && __GNUC_MINOR__ == 2
 #include  <ieeefp.h>
-#define isFinite(_a) (finite(_a) && !isNaN(_a))
+#define IS_FINITE(_a) (finite(_a) && !IS_NAN(_a))
 #else
-# define isFinite(_a) (std::isfinite(_a))
+# define IS_FINITE(_a) (std::isfinite(_a))
 #endif
-/* If the above doesn't work, then try (finite(_a) && !isNaN(_a)) or (!isNaN((_a) - (_a))).
+/* If the above doesn't work, then try (finite(_a) && !IS_NAN(_a)) or (!IS_NAN((_a) - (_a))).
  * Also, please report a bug as per http://www.inkscape.org/report_bugs.php,
  * giving information about what platform and compiler version you're using.
  */
index afad49eb2f59ba786375d60b5b386a4217e0e408..2119ea981d847de9aa758b1a972b2cd4b3e5b287 100644 (file)
@@ -132,7 +132,7 @@ void ConstrainedMajorizationLayout::majlayout(
             }
             b[i] += degree * coords[i];
         }
-        assert(!isNaN(b[i]));
+        assert(!IS_NAN(b[i]));
     }
     if(constrainedLayout) {
         setupDummyVars();
index 94844ca881c0bda3b8c95c308eb785234e0f2df2..237cb94af377fef8011cf04aeb126299dd945bb6 100644 (file)
@@ -50,7 +50,7 @@ unsigned GradientProjection::solve(double * b) {
     solver = setupVPSC();
     //cerr << "in gradient projection: n=" << n << endl;
     for (i=0;i<n;i++) {
-        assert(!isNaN(place[i]));
+        assert(!IS_NAN(place[i]));
         assert(!isinf(place[i]));
         vars[i]->desiredPosition=place[i];
     }
@@ -98,7 +98,7 @@ unsigned GradientProjection::solve(double * b) {
         // move to new unconstrained position
                for (i=0; i<n; i++) {
                        place[i]-=alpha*g[i];
-            assert(!isNaN(place[i]));
+            assert(!IS_NAN(place[i]));
             assert(!isinf(place[i]));
             vars[i]->desiredPosition=place[i];
                }
index f5620c32bf94053a0878eec1ebdfba8ec97c818b..138812655077cf9dcd316e29f815f47f3a2ad9f5 100644 (file)
@@ -19,8 +19,8 @@ int main(int argc, char *argv[])
     NR::Point const small_n3_4(-3.0 * small, 4.0 * small);
     NR::Point const part_nan(3., nan);
 
-    assert(isNaN(nan));
-    assert(!isNaN(small));
+    assert(IS_NAN(nan));
+    assert(!IS_NAN(small));
 
     UTEST_TEST("in_svg_plane") {
         UTEST_ASSERT(in_svg_plane(p3n4));
index 6cd29bd6ab9431b73fa38534fa6aebd01e1fab76..ced9f978ca619f85804ad86753f797aee1220331 100644 (file)
@@ -21,8 +21,8 @@ public:
         small_n3_4( -3.0 * small, 4.0 * small ),
         part_nan( 3., nan )
     {
-        setupValid &= isNaN(nan);
-        setupValid &= !isNaN(small);
+        setupValid &= IS_NAN(nan);
+        setupValid &= !IS_NAN(small);
     }
     virtual ~InSvgPlaneTest() {}
 
index 89ac85b2b34832a1bdc25269d0e730595db868a9..e9dd9f5a625c93f01441cd1d04e6fc027328b568 100644 (file)
@@ -3,91 +3,18 @@
 /** \file
  * Contains functions to convert from NArtBpath to 2geom's Path
  *
- * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ * Copyright (C) Johan Engelen 2007-2008 <j.b.c.engelen@utwente.nl>
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
  
-
 #include "libnr/n-art-bpath-2geom.h"
+
 #include "svg/svg.h"
 #include <glib.h>
 #include <2geom/path.h>
 #include <2geom/svg-path.h>
 #include <2geom/svg-path-parser.h>
-#include <2geom/sbasis-to-bezier.h>
-
-//##########################################################
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <boost/format.hpp>
-
-static void curve_to_svgd(std::ostream & f, Geom::Curve const* c) {
-    if(Geom::LineSegment const *line_segment = dynamic_cast<Geom::LineSegment const  *>(c)) {
-        f << boost::format("L %g,%g ") % (*line_segment)[1][0] % (*line_segment)[1][1];
-    }
-    else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const  *>(c)) {
-        f << boost::format("Q %g,%g %g,%g ") % (*quadratic_bezier)[1][0] % (*quadratic_bezier)[1][0]  
-                % (*quadratic_bezier)[2][0] % (*quadratic_bezier)[2][1];
-    }
-    else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const  *>(c)) {
-        f << boost::format("C %g,%g %g,%g %g,%g ") 
-                % (*cubic_bezier)[1][0] % (*cubic_bezier)[1][1] 
-                % (*cubic_bezier)[2][0] % (*cubic_bezier)[2][1] 
-                % (*cubic_bezier)[3][0] % (*cubic_bezier)[3][1];
-    }
-//    else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::SVGEllipticalArc *>(c)) {
-//        //get at the innards and spit them out as svgd
-//    }
-    else { 
-        //this case handles sbasis as well as all other curve types
-        Geom::Path sbasis_path = Geom::path_from_sbasis(c->toSBasis(), 0.1);
-
-        //recurse to convert the new path resulting from the sbasis to svgd
-        for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
-            curve_to_svgd(f, &(*iter));
-        }
-    }
-}
-
-static void write_svgd(std::ostream & f, Geom::Path const &p) {
-    if(f == NULL) {
-        f << "ERRRRRRORRRRR";
-        return;
-    }
-
-    f << boost::format("M %g,%g ") % p.initialPoint()[0] % p.initialPoint()[1];
-    
-    for(Geom::Path::const_iterator iter(p.begin()), end(p.end()); iter != end; ++iter) {
-        curve_to_svgd(f, &(*iter));
-    }
-    if(p.closed())
-        f << "Z ";
-}
-
-static void write_svgd(std::ostream & f, std::vector<Geom::Path> const &p) {
-    std::vector<Geom::Path>::const_iterator it(p.begin());
-    for(; it != p.end(); it++) {
-        write_svgd(f, *it);
-    }
-}
-
-std::vector<Geom::Path>  
-SVGD_to_2GeomPath (char const *svgd)
-{
-    std::vector<Geom::Path> pathv;
-
-    try {
-        pathv = Geom::parse_svg_path(svgd);
-    }
-    catch (std::runtime_error e) {
-        g_warning("SVGPathParseError: %s", e.what());
-    }
-
-    return pathv;
-}
 
 
 std::vector<Geom::Path>
@@ -99,26 +26,15 @@ BPath_to_2GeomPath(NArtBpath const * bpath)
         g_warning("BPath_to_2GeomPath - empty path returned");
         return pathv;
     }
-    pathv = SVGD_to_2GeomPath(svgpath);
+    pathv = sp_svg_read_pathv(svgpath);
     g_free(svgpath);
     return pathv;
 }
 
-char *
-SVGD_from_2GeomPath(std::vector<Geom::Path> const & path)
-{
-    std::ostringstream ss;
-    write_svgd(ss, path);
-    ss.flush();
-    std::string str = ss.str();
-    char * svgd = g_strdup(str.c_str());
-    return svgd;
-}
-
 NArtBpath *
 BPath_from_2GeomPath(std::vector<Geom::Path> const & path)
 {
-    char * svgd = SVGD_from_2GeomPath(path);
+    char * svgd = sp_svg_write_path(path);
     NArtBpath *bpath = sp_svg_read_path(svgd);
     g_free(svgd);
     return bpath;
index 21995656b88cf13b148661f8590b077f27586ef4..bf1592e2827a6fc63685bb93fa3cbfc00b9f9522 100644 (file)
@@ -13,9 +13,7 @@
 #include <2geom/path.h>
 #include <libnr/n-art-bpath.h>
 
-std::vector<Geom::Path>  SVGD_to_2GeomPath (char const *svgd);
 std::vector<Geom::Path>  BPath_to_2GeomPath (NArtBpath const *bpath);
-char *                   SVGD_from_2GeomPath(std::vector<Geom::Path> const & path);
 NArtBpath *              BPath_from_2GeomPath (std::vector<Geom::Path> const & path);
 
 
index 7741e7782b8ff57aad00ec87bb891043c7cee912..5e60215696d921ec68bc6552199771f827dfd555 100644 (file)
@@ -9,16 +9,36 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-#include <2geom/matrix.h>
 #include <libnr/nr-matrix.h>
-#include <2geom/d2.h>
 #include <libnr/nr-rect.h>
+#include <libnr/nr-point.h>
+#include <2geom/matrix.h>
+#include <2geom/d2.h>
+#include <2geom/transforms.h>
+#include <2geom/point.h>
+
+inline Geom::Point to_2geom(NR::Point const & _pt) {
+    return Geom::Point(_pt[0], _pt[1]);
+}
+
+inline NR::Point from_2geom(Geom::Point const & _pt) {
+    return NR::Point(_pt[0], _pt[1]);
+}
 
 inline Geom::Matrix to_2geom(NR::Matrix const & mat) {
     Geom::Matrix mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
     return mat2geom;
 }
 
+inline NR::Matrix from_2geom(Geom::Matrix const & mat) {
+    NR::Matrix mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]);
+    return mat2geom;
+}
+
+inline Geom::Translate to_2geom(NR::translate const & mat) {
+    return Geom::Translate( mat.offset[0], mat.offset[1] );
+}
+
 inline NR::Rect from_2geom(Geom::Rect const & rect2geom) {
     NR::Rect rect(rect2geom.min(), rect2geom.max());
     return rect;
index 11181436bd2d5106de47f5f5cb78a4f656f07914..00a704b596cfda1ac7cf5cf88fa29b4fc9cca061 100644 (file)
@@ -24,8 +24,8 @@ int main(int argc, char *argv[])
     Point const part_nan(3., nan);
     Point const inf_left(-inf, 5.0);
 
-    assert(isNaN(nan));
-    assert(!isNaN(small));
+    assert(IS_NAN(nan));
+    assert(!IS_NAN(small));
 
     UTEST_TEST("L1") {
         UTEST_ASSERT( NR::L1(p0) == 0.0 );
@@ -33,7 +33,7 @@ int main(int argc, char *argv[])
         UTEST_ASSERT( NR::L1(small_left) == small );
         UTEST_ASSERT( NR::L1(inf_left) == inf );
         UTEST_ASSERT( NR::L1(small_n3_4) == 7.0 * small );
-        UTEST_ASSERT(isNaN(NR::L1(part_nan)));
+        UTEST_ASSERT(IS_NAN(NR::L1(part_nan)));
     }
 
     UTEST_TEST("L2") {
@@ -42,7 +42,7 @@ int main(int argc, char *argv[])
         UTEST_ASSERT( NR::L2(small_left) == small );
         UTEST_ASSERT( NR::L2(inf_left) == inf );
         UTEST_ASSERT( NR::L2(small_n3_4) == 5.0 * small );
-        UTEST_ASSERT(isNaN(NR::L2(part_nan)));
+        UTEST_ASSERT(IS_NAN(NR::L2(part_nan)));
     }
 
     UTEST_TEST("LInfty") {
@@ -51,7 +51,7 @@ int main(int argc, char *argv[])
         UTEST_ASSERT( NR::LInfty(small_left) == small );
         UTEST_ASSERT( NR::LInfty(inf_left) == inf );
         UTEST_ASSERT( NR::LInfty(small_n3_4) == 4.0 * small );
-        UTEST_ASSERT(isNaN(NR::LInfty(part_nan)));
+        UTEST_ASSERT(IS_NAN(NR::LInfty(part_nan)));
     }
 
     UTEST_TEST("is_zero") {
index 509d9d2fab931d06eb4d37c00e02633b8e96e64d..a94ef1b7368d860d5f2c28cd3e315e961e9ee1e6 100644 (file)
@@ -26,11 +26,11 @@ public:
         part_nan( 3., nan ),
         inf_left( -inf, 5.0 )
     {
-        TS_ASSERT( isNaN(nan) );
-        TS_ASSERT( !isNaN(small) );
+        TS_ASSERT( IS_NAN(nan) );
+        TS_ASSERT( !IS_NAN(small) );
 
-        setupValid &= isNaN(nan);
-        setupValid &= !isNaN(small);
+        setupValid &= IS_NAN(nan);
+        setupValid &= !IS_NAN(small);
     }
     virtual ~NrPointFnsTest() {}
 
@@ -65,7 +65,7 @@ public:
         TS_ASSERT_EQUALS( NR::L1(small_left), small  );
         TS_ASSERT_EQUALS( NR::L1(inf_left), inf  );
         TS_ASSERT_EQUALS( NR::L1(small_n3_4), 7.0 * small  );
-        TS_ASSERT(isNaN(NR::L1(part_nan)));
+        TS_ASSERT(IS_NAN(NR::L1(part_nan)));
     }
 
     void testL2(void)
@@ -75,7 +75,7 @@ public:
         TS_ASSERT_EQUALS( NR::L2(small_left), small );
         TS_ASSERT_EQUALS( NR::L2(inf_left), inf );
         TS_ASSERT_EQUALS( NR::L2(small_n3_4), 5.0 * small );
-        TS_ASSERT( isNaN(NR::L2(part_nan)) );
+        TS_ASSERT( IS_NAN(NR::L2(part_nan)) );
     }
 
     void testLInfty(void)
@@ -85,7 +85,7 @@ public:
         TS_ASSERT_EQUALS( NR::LInfty(small_left), small );
         TS_ASSERT_EQUALS( NR::LInfty(inf_left), inf );
         TS_ASSERT_EQUALS( NR::LInfty(small_n3_4), 4.0 * small );
-        TS_ASSERT( isNaN(NR::LInfty(part_nan)) );
+        TS_ASSERT( IS_NAN(NR::LInfty(part_nan)) );
     }
 
     void testIsZero(void)
index a7b128bdbeaf597201dbcb7617984712600a8987..f73f71e3bb0388b912fcb8c4f8dce1b4fc87fb6e 100644 (file)
@@ -7,7 +7,7 @@ using NR::Point;
 NR::Coord NR::LInfty(Point const &p) {
     NR::Coord const a(fabs(p[0]));
     NR::Coord const b(fabs(p[1]));
-    return ( a < b || isNaN(b)
+    return ( a < b || IS_NAN(b)
              ? b
              : a );
 }
index 98054a55177b32b0ebb9096fe27432c70b2ff445..a4e16d1278b636e7c5b641f48d596e0d49dd8d75 100644 (file)
@@ -18,7 +18,7 @@
 void NR::Point::normalize() {
        double len = hypot(_pt[0], _pt[1]);
        g_return_if_fail(len != 0);
-       g_return_if_fail(!isNaN(len));
+       g_return_if_fail(!IS_NAN(len));
        static double const inf = 1e400;
        if(len != inf) {
                *this /= len;
index 3574a2743b3ac1f39ee4698e8a7f9bae106f06d1..f3bc65eed858f5d7cdca322f8632277f72627808 100644 (file)
@@ -79,8 +79,8 @@ bool CmpNodePos::operator() (const Node* u, const Node* v) const {
        if (v->pos < u->pos) {
                return false;
        }
-       if (isNaN(u->pos) != isNaN(v->pos)) {
-               return isNaN(u->pos);
+       if (IS_NAN(u->pos) != IS_NAN(v->pos)) {
+               return IS_NAN(u->pos);
        }
        return u < v;
 
@@ -153,9 +153,9 @@ int compare_events(const void *a, const void *b) {
                return 1;
        } else if(ea->pos < eb->pos) {
                return -1;
-       } else if(isNaN(ea->pos) != isNaN(ea->pos)) {
+       } else if(IS_NAN(ea->pos) != IS_NAN(ea->pos)) {
                /* See comment in CmpNodePos. */
-               return ( isNaN(ea->pos)
+               return ( IS_NAN(ea->pos)
                         ? -1
                         : 1 );
        }
index 765d0a59bb2d21866dd48a27af8d63656d104b72..0749e4e93b250117d6dfe9c1ff757807408c7cb6 100644 (file)
@@ -221,40 +221,22 @@ Effect::doBeforeEffect (SPLPEItem */*lpeitem*/)
 void
 Effect::doEffect (SPCurve * curve)
 {
-    NArtBpath *new_bpath = doEffect_nartbpath(curve->get_bpath());
+    NArtBpath const *bpath_in = curve->get_bpath();
 
-    curve->set_bpath(new_bpath);
-}
+    std::vector<Geom::Path> result_pathv;
 
-NArtBpath *
-Effect::doEffect_nartbpath (NArtBpath const * path_in)
-{
     try {
-        std::vector<Geom::Path> orig_pathv = BPath_to_2GeomPath(path_in);
-
-        std::vector<Geom::Path> result_pathv = doEffect_path(orig_pathv);
+        std::vector<Geom::Path> orig_pathv = BPath_to_2GeomPath(bpath_in);
 
-        NArtBpath *new_bpath = BPath_from_2GeomPath(result_pathv);
-
-        return new_bpath;
+        result_pathv = doEffect_path(orig_pathv);
     }
     catch (std::exception & e) {
         g_warning("Exception during LPE %s execution. \n %s", getName().c_str(), e.what());
         SP_ACTIVE_DESKTOP->messageStack()->flash( Inkscape::WARNING_MESSAGE,
             _("An exception occurred during execution of the Path Effect.") );
-
-        NArtBpath *path_out;
-
-        unsigned ret = 0;
-        while ( path_in[ret].code != NR_END ) {
-            ++ret;
-        }
-        unsigned len = ++ret;
-
-        path_out = g_new(NArtBpath, len);
-        memcpy(path_out, path_in, len * sizeof(NArtBpath));
-        return path_out;
     }
+
+    curve->set_pathv(result_pathv);
 }
 
 std::vector<Geom::Path>
index c04f248e331a3716162a2859357e22001b75a032..a8cb525b8f500b915fa73f1d3ab05826bbac2d8f 100644 (file)
@@ -125,8 +125,6 @@ protected:
     // the order in which they appear is the order in which they are
     // called by this base class. (i.e. doEffect(SPCurve * curve) defaults to calling
     // doEffect(std::vector<Geom::Path> )
-    virtual NArtBpath *
-            doEffect_nartbpath (NArtBpath const * path_in) __attribute__ ((deprecated));
     virtual std::vector<Geom::Path>
             doEffect_path (std::vector<Geom::Path> const & path_in);
     virtual Geom::Piecewise<Geom::D2<Geom::SBasis> >
index 9cf9f2f26fe16311555bf41fa3ff815c7bb7fafb..814a381af6ede23ae2c1914369576d9786d7608b 100644 (file)
@@ -17,7 +17,7 @@
 
 #include "sp-item.h"
 #include "sp-path.h"
-#include "libnr/n-art-bpath-2geom.h"
+#include "svg/svg.h"
 #include "xml/repr.h"
 
 #include <2geom/path.h>
@@ -158,7 +158,7 @@ LPECurveStitch::resetDefaults(SPItem * item)
     
     // calculate bounding box:  (isn't there a simpler way?)
     Piecewise<D2<SBasis> > pwd2;
-    std::vector<Geom::Path> temppath = SVGD_to_2GeomPath( SP_OBJECT_REPR(item)->attribute("inkscape:original-d"));
+    std::vector<Geom::Path> temppath = sp_svg_read_pathv( SP_OBJECT_REPR(item)->attribute("inkscape:original-d"));
     for (unsigned int i=0; i < temppath.size(); i++) {
         pwd2.concat( temppath[i].toPwSb() );
     }
index 521c2d7c96e7e4dcedd676c8bb33dda43044a774..a68888105c70314a3c15292d24de267c196afcd5 100644 (file)
@@ -27,7 +27,6 @@ public:
 
 //  Choose to implement one of the doEffect functions. You can delete or comment out the others.
 //    virtual void doEffect (SPCurve * curve);
-//    virtual NArtBpath * doEffect_nartbpath (NArtBpath * path_in);
     virtual std::vector<Geom::Path> doEffect_path (std::vector<Geom::Path> const & input_path);
 //    virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > & pwd2_in);
 
index f3fb346fe1ebee095cb3099ccebea7d37b72be18..3b578b2c6c4096c8aca20f16e69cb9232929c087 100644 (file)
@@ -45,31 +45,10 @@ LPEdoEffectStackTest::doEffect (SPCurve * curve)
     }
 }
 
-NArtBpath *
-LPEdoEffectStackTest::doEffect_nartbpath (NArtBpath const * path_in)
-{
-    if (step >= 2) {
-        return Effect::doEffect_nartbpath(path_in);
-    } else {
-        // return here
-        NArtBpath *path_out;
-
-        unsigned ret = 0;
-        while ( path_in[ret].code != NR_END ) {
-            ++ret;
-        }
-        unsigned len = ++ret;
-
-        path_out = g_new(NArtBpath, len);
-        memcpy(path_out, path_in, len * sizeof(NArtBpath));
-        return path_out;
-    }
-}
-
 std::vector<Geom::Path>
 LPEdoEffectStackTest::doEffect_path (std::vector<Geom::Path> const & path_in)
 {
-    if (step >= 3) {
+    if (step >= 2) {
         return Effect::doEffect_path(path_in);
     } else {
         // return here
index cf2d480b1f7fa7c9f9f25a6ebff7ed792c2cc1a2..7c22a3b37cddcda79b8aabab9f61b762d6500cc4 100644 (file)
@@ -26,7 +26,6 @@ public:
     virtual ~LPEdoEffectStackTest();
 
     virtual void                                     doEffect (SPCurve * curve);
-    virtual NArtBpath *                              doEffect_nartbpath (NArtBpath const * path_in);
     virtual std::vector<Geom::Path>                  doEffect_path (std::vector<Geom::Path> const & path_in);
     virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
 
index ee09221ed5668c28c07a1545f630eb200dcb9dd0..114dd726306165610eec3397a3334457998927a7 100644 (file)
@@ -159,7 +159,7 @@ LPEVonKoch::resetDefaults(SPItem * item)
 
     // set the bend path to run horizontally in the middle of the bounding box of the original path
     Piecewise<D2<SBasis> > pwd2;
-    std::vector<Geom::Path> temppath = SVGD_to_2GeomPath( SP_OBJECT_REPR(item)->attribute("inkscape:original-d"));
+    std::vector<Geom::Path> temppath = sp_svg_read_pathv( SP_OBJECT_REPR(item)->attribute("inkscape:original-d"));
     for (unsigned int i=0; i < temppath.size(); i++) {
         pwd2.concat( temppath[i].toPwSb() );
     }
index d3afec3af4ffd625c3ac42a03a05ae573de66a00..511ce46a23edfd8fa8f17764c9cc978973f10ea7 100644 (file)
@@ -10,8 +10,7 @@
  */
 
 #include <glibmm/ustring.h>
-#include <2geom/point.h>
-#include <2geom/path.h>
+#include <2geom/forward.h>
 
 struct SPDesktop;
 struct SPItem;
index 376e61beefbe94b618e2b6779e89ee955c2ad970..759e9f788c148083a306a1d9c54939ef3b0a1c98 100644 (file)
@@ -113,10 +113,10 @@ PathParam::param_readSVGValue(const gchar * strvalue)
             } catch (Inkscape::BadURIException &e) {
                 g_warning("%s", e.what());
                 ref.detach();
-                _pathvector = SVGD_to_2GeomPath(defvalue);
+                _pathvector = sp_svg_read_pathv(defvalue);
             }
         } else {
-            _pathvector = SVGD_to_2GeomPath(strvalue);
+            _pathvector = sp_svg_read_pathv(strvalue);
         }
 
         signal_path_changed.emit();
@@ -132,7 +132,7 @@ PathParam::param_getSVGValue() const
     if (href) {
         return href;
     } else {
-        gchar * svgd = SVGD_from_2GeomPath( _pathvector );
+        gchar * svgd = sp_svg_write_path( _pathvector );
         return svgd;
     }
 }
@@ -233,7 +233,7 @@ PathParam::param_set_and_write_new_value (Geom::Piecewise<Geom::D2<Geom::SBasis>
 {
     remove_link();
     _pathvector = Geom::path_from_piecewise(newpath, LPE_CONVERSION_TOLERANCE);
-    gchar * svgd = SVGD_from_2GeomPath( _pathvector );
+    gchar * svgd = sp_svg_write_path( _pathvector );
     param_write_to_repr(svgd);
     g_free(svgd);
     // force value upon pwd2 and don't recalculate.
@@ -248,7 +248,7 @@ PathParam::param_set_and_write_new_value (std::vector<Geom::Path> const & newpat
     _pathvector = newpath;
     must_recalculate_pwd2 = true;
 
-    gchar * svgd = SVGD_from_2GeomPath( _pathvector );
+    gchar * svgd = sp_svg_write_path( _pathvector );
     param_write_to_repr(svgd);
     g_free(svgd);
 }
@@ -324,7 +324,7 @@ PathParam::linked_modified(SPObject *linked_obj, guint /*flags*/)
 
     if (curve == NULL) {
         // curve invalid, set default value
-        _pathvector = SVGD_to_2GeomPath(defvalue);
+        _pathvector = sp_svg_read_pathv(defvalue);
     } else {
         _pathvector = BPath_to_2GeomPath(SP_CURVE_BPATH(curve));
         curve->unref();
index e827f9fb07dafa522d5c39433d58eefd700fa48c..249721cfaba134849578428dc4ef98e323d1b823 100644 (file)
@@ -95,7 +95,7 @@ static GMemChunk *nodechunk = NULL;
 
 /* Creation from object */
 
-static NArtBpath *subpath_from_bpath(Inkscape::NodePath::Path *np, NArtBpath *b, gchar const *t);
+static NArtBpath const * subpath_from_bpath(Inkscape::NodePath::Path *np, NArtBpath const *b, gchar const *t);
 static gchar *parse_nodetypes(gchar const *types, gint length);
 
 /* Object updating */
@@ -181,8 +181,8 @@ Inkscape::NodePath::Path *sp_nodepath_new(SPDesktop *desktop, SPObject *object,
     if (curve == NULL)
         return NULL;
 
-    NArtBpath *bpath = curve->first_bpath();
-    gint length = curve->_end;
+    NArtBpath const *bpath = curve->get_bpath();
+    gint length = curve->get_length();
     if (length == 0) {
         curve->unref();
         return NULL; // prevent crash for one-node paths
@@ -250,7 +250,7 @@ Inkscape::NodePath::Path *sp_nodepath_new(SPDesktop *desktop, SPObject *object,
     gchar *typestr = parse_nodetypes(nodetypes, length);
 
     // create the subpath(s) from the bpath
-    NArtBpath *b = bpath;
+    NArtBpath const *b = bpath;
     while (b->code != NR_END) {
         b = subpath_from_bpath(np, b, typestr + (b - bpath));
     }
@@ -444,7 +444,7 @@ static void sp_nodepath_cleanup(Inkscape::NodePath::Path *nodepath)
  * \param t The node type.
  * \todo Fixme: t should be a proper type, rather than gchar
  */
-static NArtBpath *subpath_from_bpath(Inkscape::NodePath::Path *np, NArtBpath *b, gchar const *t)
+static NArtBpath const * subpath_from_bpath(Inkscape::NodePath::Path *np, NArtBpath const *b, gchar const *t)
 {
     NR::Point ppos, pos, npos;
 
index 996ae3fd5203afc8521730305ee0fb363620766f..05ea6c1300fb77dd97ae0e776db29b16de6d771b 100644 (file)
@@ -435,7 +435,7 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/)
 
     // Prevent empty paths from being added to the document
     // otherwise we end up with zomby markup in the SVG file
-    if(curve->_end <= 0)
+    if(curve->get_length() <= 0)
     {
         curve->unref();
         return NULL;
index 8d7ac08192fc343a203bb947228379d5002394da..7dc489540bb4e60eec6e298e562e34c8cc71151f 100644 (file)
@@ -806,7 +806,7 @@ pen_redraw_all (SPPenContext *const pc)
         sp_canvas_item_hide (pc->cl1);
     }
 
-    NArtBpath *const bpath = pc->green_curve->last_bpath();
+    NArtBpath const * bpath = pc->green_curve->last_bpath();
     if (bpath) {
         if (bpath->code == NR_CURVETO && NR::Point(bpath->x2, bpath->y2) != pc->p[0]) {
             SP_CTRL(pc->c0)->moveto(NR::Point(bpath->x2, bpath->y2));
@@ -827,14 +827,9 @@ pen_lastpoint_move (SPPenContext *const pc, gdouble x, gdouble y)
         return;
 
     // green
-    NArtBpath *const bpath = pc->green_curve->last_bpath();
+    NArtBpath const * bpath = pc->green_curve->last_bpath();
     if (bpath) {
-        if (bpath->code == NR_CURVETO) {
-            bpath->x2 += x;
-            bpath->y2 += y;
-        }
-        bpath->x3 += x;
-        bpath->y3 += y;
+        pc->green_curve->last_point_additive_move( Geom::Point(x,y) );
     } else {
         // start anchor too
         if (pc->green_anchor) {
@@ -861,7 +856,7 @@ pen_lastpoint_tocurve (SPPenContext *const pc)
         return;
 
     // red
-    NArtBpath *const bpath = pc->green_curve->last_bpath();
+    NArtBpath const * bpath = pc->green_curve->last_bpath();
     if (bpath && bpath->code == NR_CURVETO) {
         pc->p[1] = pc->p[0] + (NR::Point(bpath->x3, bpath->y3) - NR::Point(bpath->x2, bpath->y2));
     } else {
index e25be12af91eb9fcf517918433bdf31693a7c212..e7a42ab7f2027d3aae65c624e46ce3632941f6ef 100644 (file)
@@ -167,7 +167,7 @@ sp_genericellipse_update_patheffect(SPLPEItem *lpeitem, bool write)
     if (write) {
         Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape);
         if ( shape->curve != NULL ) {
-            NArtBpath *abp = shape->curve->first_bpath();
+            NArtBpath const *abp = shape->curve->get_bpath();
             if (abp) {
                 gchar *str = sp_svg_write_path(abp);
                 repr->setAttribute("d", str);
index 20efd8fe72c76e4c370d84f51eb9e015b1ab8bdb..347f50491454b596e88d1077f4b6e86bb720621e 100644 (file)
@@ -853,7 +853,7 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup)
             
             Inkscape::XML::Node *repr = SP_OBJECT_REPR(subitem);
  
-                NArtBpath *abp = c->first_bpath();
+                NArtBpath const *abp = c->first_bpath();
                 if (abp) {
                     gchar *str = sp_svg_write_path(abp);
                     repr->setAttribute("d", str);
index 3f52232cb52d78f1cca3c5aced43c7a5732ceb05..9851e146af4b119c9d1d1cc69479f5c29d76849c 100644 (file)
@@ -766,9 +766,9 @@ void sp_namedview_window_from_document(SPDesktop *desktop)
     }
 
     // restore zoom and view
-    if (nv->zoom != 0 && nv->zoom != HUGE_VAL && !isNaN(nv->zoom)
-        && nv->cx != HUGE_VAL && !isNaN(nv->cx)
-        && nv->cy != HUGE_VAL && !isNaN(nv->cy)) {
+    if (nv->zoom != 0 && nv->zoom != HUGE_VAL && !IS_NAN(nv->zoom)
+        && nv->cx != HUGE_VAL && !IS_NAN(nv->cx)
+        && nv->cy != HUGE_VAL && !IS_NAN(nv->cy)) {
         desktop->zoom_absolute(nv->cx, nv->cy, nv->zoom);
     } else if (sp_desktop_document(desktop)) { // document without saved zoom, zoom to its page
         desktop->zoom_page();
index 511e1efc5584ed6cb346592c744b88d4f6f49290..81d05ebef05a3b904c843ea0f690d43428417ac9 100644 (file)
@@ -122,14 +122,9 @@ gint
 sp_nodes_in_path(SPPath *path)
 {
     SPCurve *curve = SP_SHAPE(path)->curve;
-    if (!curve) return 0;
-    gint r = curve->_end;
-    gint i = curve->_length - 1;
-    if (i > r) i = r; // sometimes after switching from node editor length is wrong, e.g. f6 - draw - f2 - tab - f1, this fixes it
-    for (; i >= 0; i --)
-        if (SP_CURVE_BPATH(curve)[i].code == NR_MOVETO)
-            r --;
-    return r;
+    if (!curve)
+        return 0;
+    return curve->nodes_in_path();
 }
 
 static gchar *
@@ -313,7 +308,7 @@ sp_path_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
     }
 
     if ( shape->curve != NULL ) {
-        NArtBpath *abp = shape->curve->first_bpath();
+        NArtBpath const * abp = shape->curve->get_bpath();
         if (abp) {
             gchar *str = sp_svg_write_path(abp);
             repr->setAttribute("d", str);
@@ -327,7 +322,7 @@ sp_path_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
 
     SPPath *path = (SPPath *) object;
     if ( path->original_curve != NULL ) {
-        NArtBpath *abp = path->original_curve->first_bpath();
+        NArtBpath const * abp = path->original_curve->get_bpath();
         if (abp) {
             gchar *str = sp_svg_write_path(abp);
             repr->setAttribute("inkscape:original-d", str);
@@ -419,7 +414,7 @@ sp_path_update_patheffect(SPLPEItem *lpeitem, bool write)
             // could also do SP_OBJECT(shape)->updateRepr();  but only the d attribute needs updating.
             Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape);
             if ( shape->curve != NULL ) {
-                NArtBpath *abp = shape->curve->first_bpath();
+                NArtBpath const *abp = shape->curve->get_bpath();
                 if (abp) {
                     gchar *str = sp_svg_write_path(abp);
                     repr->setAttribute("d", str);
index 6012e065d4a11c492c95b4f876c173c3d22820ad..d90f829b943e292c53a8c1ae636fc5ac73197bf6 100644 (file)
@@ -28,7 +28,6 @@ static void sp_polygon_init(SPPolygon *polygon);
 
 static void sp_polygon_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
 static Inkscape::XML::Node *sp_polygon_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
-static void sp_polygon_set(SPObject *object, unsigned int key, const gchar *value);
 
 static gchar *sp_polygon_description(SPItem *item);
 
@@ -128,7 +127,7 @@ static Inkscape::XML::Node *sp_polygon_write(SPObject *object, Inkscape::XML::No
     }
 
     /* We can safely write points here, because all subclasses require it too (Lauris) */
-    NArtBpath *abp = shape->curve->first_bpath();
+    NArtBpath const * abp = shape->curve->get_bpath();
     gchar *str = sp_svg_write_polygon(abp);
     repr->setAttribute("points", str);
     g_free(str);
@@ -162,7 +161,7 @@ static gboolean polygon_get_value(gchar const **p, gdouble *v)
 }
 
 
-static void sp_polygon_set(SPObject *object, unsigned int key, const gchar *value)
+void sp_polygon_set(SPObject *object, unsigned int key, const gchar *value)
 {
     SPPolygon *polygon = SP_POLYGON(object);
 
index 0da720fc2111bf43e1d83108e98463b652182ca8..3ea91be761cca57a7a7f7b18d43ee45e5597f968 100644 (file)
@@ -30,4 +30,7 @@ struct SPPolygonClass {
 
 GType sp_polygon_get_type (void);
 
+// made 'public' so that SPCurve can set it as friend:
+void sp_polygon_set(SPObject *object, unsigned int key, const gchar *value);
+
 #endif
index 991381bda87a3b6ae5a54ad72fdea7cb449ff426..99e4ed485940b0cca5bf586ca3f388e2efaf8d2c 100644 (file)
@@ -546,8 +546,8 @@ NR::Matrix
 sp_shape_marker_get_transform(SPShape const *shape, NArtBpath const *bp)
 {
     g_return_val_if_fail(( is_moveto(SP_CURVE_BPATH(shape->curve)[0].code)
-                           && ( 0 < shape->curve->_end )
-                           && ( SP_CURVE_BPATH(shape->curve)[shape->curve->_end].code == NR_END ) ),
+                           && ( 0 < shape->curve->get_length() )
+                           && ( SP_CURVE_BPATH(shape->curve)[shape->curve->get_length()].code == NR_END ) ),
                          NR::Matrix(NR::translate(bp->c(3))));
     double const angle1 = incoming_tangent(bp);
     double const angle2 = outgoing_tangent(bp);
index 60f2bbc92efc24708f006450d2318ef8ce6796f1..7351ff61fdd71950501e97855fe238a8965d7852 100644 (file)
@@ -308,7 +308,7 @@ sp_spiral_update_patheffect(SPLPEItem *lpeitem, bool write)
     if (write) {
         Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape);
         if ( shape->curve != NULL ) {
-            NArtBpath *abp = shape->curve->first_bpath();
+            NArtBpath const * abp = shape->curve->get_bpath();
             if (abp) {
                 gchar *str = sp_svg_write_path(abp);
                 repr->setAttribute("d", str);
index 4c5f9623b0f525e917c33375a0a146c076f30fd6..6543a98660040dea094e7a27d9bc5585b1c161a7 100644 (file)
@@ -285,7 +285,7 @@ sp_star_update_patheffect(SPLPEItem *lpeitem, bool write)
     if (write) {
         Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape);
         if ( shape->curve != NULL ) {
-            NArtBpath *abp = shape->curve->first_bpath();
+            NArtBpath const * abp = shape->curve->get_bpath();
             if (abp) {
                 gchar *str = sp_svg_write_path(abp);
                 repr->setAttribute("d", str);
index fd6b17892fe718c2767f048285c8510900020947..a67b86167221ecf6ef0e562a228906819e6dc103 100644 (file)
@@ -1672,7 +1672,7 @@ sp_style_merge_length_prop_from_dying_parent(LengthT &child, LengthT const &pare
                  * fixme: Have separate ex ratio parameter.
                  * Get x height from libnrtype or pango.
                  */
-                if (!isFinite(child.value)) {
+                if (!IS_FINITE(child.value)) {
                     child.value = child.computed;
                     child.unit = SP_CSS_UNIT_NONE;
                 }
index bd0d4a4f5ff1dbb7c7af872f8ff6779a4ec20dba..d610b9212eb0a4baf1ed46b43bb5489614e3c241 100644 (file)
 #include "gnome-canvas-bpath-util.h"
 #include "svg/path-string.h"
 
+#include <2geom/pathvector.h>
+#include <2geom/path.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/svg-path.h>
+#include <2geom/svg-path-parser.h>
 
 /* This module parses an SVG path element into an RsvgBpathDef.
 
@@ -668,6 +673,21 @@ NArtBpath *sp_svg_read_path(gchar const *str)
     return bpath;
 }
 
+Geom::PathVector sp_svg_read_pathv(char const * str)
+{
+    std::vector<Geom::Path> pathv;
+
+    // TODO: enable this exception catching. don't catch now to better see when things go wrong
+//    try {
+        pathv = Geom::parse_svg_path(str);
+//    }
+//    catch (std::runtime_error e) {
+//        g_warning("SVGPathParseError: %s", e.what());
+//    }
+
+    return pathv;
+}
+
 gchar *sp_svg_write_path(NArtBpath const *bpath)
 {
     bool closed=false;
@@ -710,6 +730,53 @@ gchar *sp_svg_write_path(NArtBpath const *bpath)
     return g_strdup(str.c_str());
 }
 
+static void sp_svg_write_curve(Inkscape::SVG::PathString & str, Geom::Curve const * c) {
+    if(Geom::LineSegment const *line_segment = dynamic_cast<Geom::LineSegment const  *>(c)) {
+        str.lineTo( (*line_segment)[1][0], (*line_segment)[1][1] );
+    }
+    else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const  *>(c)) {
+        str.quadTo( (*quadratic_bezier)[1][0], (*quadratic_bezier)[1][0],
+                    (*quadratic_bezier)[2][0], (*quadratic_bezier)[2][1] );
+    }
+    else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const  *>(c)) {
+        str.curveTo( (*cubic_bezier)[1][0], (*cubic_bezier)[1][1],
+                     (*cubic_bezier)[2][0], (*cubic_bezier)[2][1],
+                     (*cubic_bezier)[3][0], (*cubic_bezier)[3][1] );
+    }
+    else if(Geom::EllipticalArc const *svg_elliptical_arc = dynamic_cast<Geom::EllipticalArc const *>(c)) {
+        str.arcTo( svg_elliptical_arc->ray(0), svg_elliptical_arc->ray(1),
+                   svg_elliptical_arc->rotation_angle(),
+                   svg_elliptical_arc->large_arc_flag(), svg_elliptical_arc->sweep_flag(),
+                   svg_elliptical_arc->finalPoint() );
+    } else { 
+        //this case handles sbasis as well as all other curve types
+        Geom::Path sbasis_path = Geom::path_from_sbasis(c->toSBasis(), 0.1);
+
+        //recurse to convert the new path resulting from the sbasis to svgd
+        for(Geom::Path::iterator iter = sbasis_path.begin(); iter != sbasis_path.end(); ++iter) {
+            sp_svg_write_curve(str, &(*iter));
+        }
+    }
+}
+
+gchar * sp_svg_write_path(Geom::PathVector const &p) {
+    Inkscape::SVG::PathString str;
+
+    for(Geom::PathVector::const_iterator pit = p.begin(); pit != p.end(); pit++) {
+        str.moveTo( pit->initialPoint()[0], pit->initialPoint()[1] );
+
+        for(Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); cit++) {
+            sp_svg_write_curve(str, &(*cit));
+        }
+
+        if (pit->closed()) {
+            str.closePath();
+        }
+    }
+
+    return g_strdup(str.c_str());
+}
+
 /*
   Local Variables:
   mode:c++
index 4b2dea9940e975a3474f2cc4b6a32fcf5efff838..0e5b4d5d5ee57df4b0ee30dfdbe1f31933f665c9 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "svg/svg-length.h"
 #include "libnr/nr-forward.h"
+#include <2geom/forward.h>
 
 /* Generic */
 
@@ -63,8 +64,9 @@ double sp_svg_read_percentage (const char * str, double def);
 /* NB! As paths can be long, we use here dynamic string */
 
 NArtBpath * sp_svg_read_path (const char * str);
-char * sp_svg_write_path (const NArtBpath * bpath);
-
+Geom::PathVector sp_svg_read_pathv (char const * str);
+gchar * sp_svg_write_path (const NArtBpath * bpath);
+gchar * sp_svg_write_path (Geom::PathVector const &p);
 
 #endif
 
index 2d38f5ccd227909ed44b289618749aa962f99972..227d57a964f240a2b141ce9e7dab20d4e4fbec70 100644 (file)
@@ -222,7 +222,7 @@ void ClipboardManagerImpl::copy()
 void ClipboardManagerImpl::copyPathParameter(Inkscape::LivePathEffect::PathParam *pp)
 {
     if ( pp == NULL ) return;
-    gchar *svgd = SVGD_from_2GeomPath( pp->get_pathvector() );
+    gchar *svgd = sp_svg_write_path( pp->get_pathvector() );
     if ( svgd == NULL || *svgd == '\0' ) return;
 
     _discardInternalClipboard();