Code

Rename LPE: mirror reflect --> mirror symmetry
[inkscape.git] / src / display / curve.cpp
index 3874fec590d7d34657784c81515f6c74419d0d1f..c229ec28a533ebc5b9b2ff28c7a4b366d50bead3 100644 (file)
@@ -5,8 +5,9 @@
  */
 
 /*
- * Author:
+ * Authors:
  *   Lauris Kaplinski <lauris@kaplinski.com>
+ *   Johan Engelen
  *
  * Copyright (C) 2000 Lauris Kaplinski
  * Copyright (C) 2000-2001 Ximian, Inc.
 #include <2geom/sbasis-geometric.h>
 #include <2geom/sbasis-to-bezier.h>
 #include "svg/svg.h"
+#include <2geom/point.h>
 
 static unsigned sp_bpath_length(NArtBpath const bpath[]);
 static bool sp_bpath_closed(NArtBpath const bpath[]);
 
-#define NO_CHECKS   // define this to disable the checking for unequal paths in SPCurve, improves performance by a lot!
-
-
-#ifndef NO_CHECKS
-static void debug_out( char const * text, Geom::PathVector const & pathv) {
-    char * str = sp_svg_write_path(pathv);
-    g_message("%s : %s", text, str);
-    g_free(str);
-}
-#endif
-
-#ifndef NO_CHECKS
-static void debug_out( char const * text, NArtBpath const * bpath) {
-    char * str = sp_svg_write_path(bpath);
-    g_message("%s : %s", text, str);
-    g_free(str);
-}
-#endif
-
-#ifndef NO_CHECKS
-void SPCurve::debug_check( char const * text, SPCurve const * curve) {
-    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);
-#else
-void SPCurve::debug_check( char const *, SPCurve const *) {
-#endif
-}
-
-#ifndef NO_CHECKS
-void SPCurve::debug_check( char const * text, bool a) {
-    if ( !a ) {
-        g_message("%s : bool fail", text);
-    }
-#else
-void SPCurve::debug_check( char const *, bool) {
-#endif
-}
-
 /* Constructors */
 
 /**
@@ -111,8 +68,6 @@ SPCurve::SPCurve(guint length)
     _bpath->code = NR_END;
 
     _pathv.clear();
-
-    debug_check("SPCurve::SPCurve(guint length)", this);
 }
 
 SPCurve::SPCurve(Geom::PathVector const& pathv)
@@ -139,8 +94,6 @@ SPCurve::SPCurve(Geom::PathVector const& pathv)
             break;
     _substart = i;
     _closed = sp_bpath_closed(_bpath);
-
-    debug_check("SPCurve::SPCurve(Geom::PathVector const& pathv)", this);
 }
 
 // * 2GEOMproof
@@ -169,8 +122,6 @@ SPCurve::new_from_foreign_bpath(NArtBpath const *bpath)
 
     curve->_pathv = BPath_to_2GeomPath(curve->_bpath);
 
-    debug_check("SPCurve::new_from_foreign_bpath", curve);
-
     return curve;
 }
 
@@ -188,29 +139,23 @@ 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)
+SPCurve::new_from_rect(Geom::Rect const &rect)
 {
-    g_return_val_if_fail(rect, NULL);
-
     SPCurve *c =  new SPCurve();
 
-    NR::Point p = rect->corner(0);
+    NR::Point p = rect.corner(0);
     c->moveto(p);
 
     for (int i=3; i>=0; i--) {
-        c->lineto(rect->corner(i));
+        c->lineto(rect.corner(i));
     }
     c->closepath_current();
 
-    debug_check("SPCurve::new_from_rect", c);
-
     return c;
 }
 
@@ -250,8 +195,6 @@ SPCurve::set_pathvector(Geom::PathVector const & new_pathv)
             break;
     _substart = i;
     _closed = sp_bpath_closed(_bpath);
-
-    debug_check("SPCurve::set_pathvector", this);
 }
 
 /**
@@ -260,14 +203,12 @@ SPCurve::set_pathvector(Geom::PathVector const & new_pathv)
 NArtBpath const *
 SPCurve::get_bpath() const
 {
-    debug_check("SPCurve::get_bpath", this);
     return _bpath;
 };
 
 Geom::PathVector const &
 SPCurve::get_pathvector() const
 {
-    debug_check("SPCurve::get_pathvector", this);
     return _pathv;
 }
 
@@ -298,18 +239,14 @@ SPCurve::get_segment_count() const
     return nr;
 }
 
-
 /**
  * Increase _refcount of curve.
  *
  * \todo should this be shared with other refcounting code?
- * 2GEOMproof
  */
 SPCurve *
 SPCurve::ref()
 {
-    g_return_val_if_fail(this != NULL, NULL);
-
     _refcount += 1;
 
     return this;
@@ -319,13 +256,10 @@ SPCurve::ref()
  * Decrease refcount of curve, with possible destruction.
  *
  * \todo should this be shared with other refcounting code?
- * 2GEOMproof
  */
 SPCurve *
 SPCurve::unref()
 {
-    g_return_val_if_fail(this != NULL, NULL);
-
     _refcount -= 1;
 
     if (_refcount < 1) {
@@ -364,8 +298,6 @@ SPCurve::ensure_space(guint space)
 SPCurve *
 SPCurve::copy() const
 {
-    g_return_val_if_fail(this != NULL, NULL);
-
     return SPCurve::new_from_foreign_bpath(_bpath);
 }
 
@@ -376,8 +308,6 @@ SPCurve::copy() const
 SPCurve *
 SPCurve::concat(GSList const *list)
 {
-    g_return_val_if_fail(list != NULL, NULL);
-
     gint length = 0;
 
     for (GSList const *l = list; l != NULL; l = l->next) {
@@ -412,8 +342,6 @@ SPCurve::concat(GSList const *list)
         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;
 }
 
@@ -424,8 +352,6 @@ SPCurve::concat(GSList const *list)
 GSList *
 SPCurve::split() const
 {
-    g_return_val_if_fail(this != NULL, NULL);
-
     guint p = 0;
     GSList *l = NULL;
 
@@ -481,20 +407,14 @@ tmpl_curve_transform(SPCurve * 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);
-
-    _pathv = _pathv * to_2geom(m);
-
-    debug_check("SPCurve::transform(NR::Matrix const &m)", this);
-}
+    transform(to_2geom(m));
+};
 
+    
 /**
  * Transform all paths in curve using matrix.
  */
@@ -504,22 +424,6 @@ SPCurve::transform(Geom::Matrix const &m)
     tmpl_curve_transform<NR::Matrix>(this, from_2geom(m));
 
     _pathv = _pathv * m;
-
-    debug_check("SPCurve::transform(Geom::Matrix const &m)", this);
-}
-
-/**
- * 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);
-
-    _pathv = _pathv * to_2geom(m);
-
-    debug_check("SPCurve::transform(NR::translate const &m)", this);
 }
 
 /**
@@ -529,8 +433,6 @@ SPCurve::transform(NR::translate const &m)
 void
 SPCurve::reset()
 {
-    g_return_if_fail(this != NULL);
-
     _bpath->code = NR_END;
     _end = 0;
     _substart = 0;
@@ -540,8 +442,6 @@ SPCurve::reset()
     _closed = false;
 
     _pathv.clear();
-
-    debug_check("SPCurve::reset", this);
 }
 
 /* Several consecutive movetos are ALLOWED */
@@ -569,7 +469,6 @@ SPCurve::moveto(Geom::Point const &p)
 void
 SPCurve::moveto(NR::Point const &p)
 {
-    g_return_if_fail(this != NULL);
     g_return_if_fail(!_moving);
 
     _substart = _end;
@@ -578,9 +477,6 @@ SPCurve::moveto(NR::Point const &p)
     _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);
 }
 
 /**
@@ -606,7 +502,6 @@ SPCurve::lineto(NR::Point const &p)
 void
 SPCurve::lineto(gdouble x, gdouble y)
 {
-    g_return_if_fail(this != NULL);
     g_return_if_fail(_hascpt);
 
     if (_moving) {
@@ -657,8 +552,6 @@ SPCurve::lineto(gdouble x, gdouble y)
         _end++;
         _pathv.back().appendNew<Geom::LineSegment>( Geom::Point(x,y) );
     }
-
-    debug_check("SPCurve::lineto", this);
 }
 
 /**
@@ -692,7 +585,6 @@ SPCurve::curveto(NR::Point const &p0, NR::Point const &p1, NR::Point const &p2)
 void
 SPCurve::curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdouble y2)
 {
-    g_return_if_fail(this != NULL);
     g_return_if_fail(_hascpt);
     g_return_if_fail(!_moving);
 
@@ -735,8 +627,6 @@ SPCurve::curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdo
         if (_pathv.empty())  g_message("leeg");
         else _pathv.back().appendNew<Geom::CubicBezier>( Geom::Point(x0,y0), Geom::Point(x1,y1), Geom::Point(x2,y2) );
     }
-
-    debug_check("SPCurve::curveto", this);
 }
 
 /**
@@ -746,7 +636,6 @@ SPCurve::curveto(gdouble x0, gdouble y0, gdouble x1, gdouble y1, gdouble x2, gdo
 void
 SPCurve::closepath()
 {
-    g_return_if_fail(this != NULL);
     g_return_if_fail(_hascpt);
     g_return_if_fail(!_posSet);
     g_return_if_fail(!_moving);
@@ -794,8 +683,6 @@ SPCurve::closepath()
     }
 
     _hascpt = false;
-
-    debug_check("SPCurve::closepath", this);
 }
 
 /** Like SPCurve::closepath() but sets the end point of the current
@@ -808,7 +695,6 @@ SPCurve::closepath()
 void
 SPCurve::closepath_current()
 {
-    g_return_if_fail(this != NULL);
     g_return_if_fail(_hascpt);
     g_return_if_fail(!_posSet);
     g_return_if_fail(!_closed);
@@ -854,31 +740,21 @@ SPCurve::closepath_current()
 
     _hascpt = false;
     _moving = false;
-
-    debug_check("SPCurve::closepath_current", this);
 }
 
 /**
  * True if no paths are in curve. If it only contains a path with only a moveto, the path is considered NON-empty
- * 2GEOMproof
  */
 bool
 SPCurve::is_empty() const
 {
-    g_return_val_if_fail(this != NULL, TRUE);
-
-    if (!_bpath)
-        return true;
-
     bool empty = _pathv.empty();
-    debug_check("SPCurve::is_empty", (_bpath->code == NR_END)  ==  empty );
 
     return empty;
 }
 
 /**
  * True iff all subpaths are closed.
- * 2GEOMproof
  */
 bool
 SPCurve::is_closed() const
@@ -890,7 +766,6 @@ SPCurve::is_closed() const
             break;
         }
     }
-    debug_check("SPCurve::is_closed", (closed)  ==  (_closed) );
 
     return closed;
 }
@@ -901,8 +776,6 @@ SPCurve::is_closed() const
 NArtBpath const *
 SPCurve::last_bpath() const
 {
-    g_return_val_if_fail(this != NULL, NULL);
-
     if (_end == 0) {
         return NULL;
     }
@@ -911,8 +784,8 @@ SPCurve::last_bpath() const
 }
 
 /**
- * Return last pathsegment (possibly the closing path segment) in PathVector or NULL.
- * equal in functionality to SPCurve::last_bpath()
+ * Return last pathsegment (possibly the closing path segment) of the last path in PathVector or NULL.
+ * If the last path is empty (contains only a moveto), the function returns NULL
  */
 Geom::Curve const *
 SPCurve::last_segment() const
@@ -933,8 +806,6 @@ SPCurve::last_segment() const
 Geom::Path const *
 SPCurve::last_path() const
 {
-    g_return_val_if_fail(this != NULL, NULL);
-
     if (is_empty()) {
         return NULL;
     }
@@ -965,8 +836,6 @@ SPCurve::first_segment() const
 Geom::Path const *
 SPCurve::first_path() const
 {
-    g_return_val_if_fail(this != NULL, NULL);
-
     if (is_empty()) {
         return NULL;
     }
@@ -980,14 +849,9 @@ SPCurve::first_path() const
 NR::Point
 SPCurve::first_point() const
 {
-    NArtBpath const * bpath = get_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() );
 }
 
@@ -997,27 +861,11 @@ SPCurve::first_point() const
  * returns the first point of the second path, if it exists. If there is no 2nd path, it returns the
  * first point of the first path.
  *
- * FIXME: for empty paths this should return (NR_HUGE,NR_HUGE)
+ * FIXME: for empty paths shouldn't this return (NR_HUGE,NR_HUGE)
  */
 NR::Point
 SPCurve::second_point() const
 {
-    g_return_val_if_fail(this != NULL, NR::Point(0, 0));
-
-    if (_end < 1) {
-        return _movePos;
-    }
-
-    NArtBpath *bpath = NULL;
-    if (_end < 2) {
-        bpath = _bpath;
-    } else {
-        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() );
-
     if (is_empty()) {
         return NR::Point(0,0);
     }
@@ -1040,8 +888,6 @@ SPCurve::second_point() const
 NR::Point
 SPCurve::penultimate_point() const
 {
-    g_return_val_if_fail(this != NULL, NR::Point(0, 0));
-
     if (_end < 2) {
         return _movePos;
     }
@@ -1052,24 +898,19 @@ SPCurve::penultimate_point() const
 
     Geom::Curve const& back = _pathv.back().back_default();
     Geom::Point p = back.initialPoint();
-
-    debug_check("SPCurve::penultimate_point", bpath->c(3) == from_2geom(p) );
     return from_2geom(p);
 }
 
 /**
  * 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) ?
+ * If the last path is only a moveto, then return that point.
  */
 NR::Point
 SPCurve::last_point() const
 {
-    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() );
 }
 
@@ -1128,8 +969,6 @@ SPCurve::create_reverse() const
     }
 
     new_curve->_pathv = Geom::reverse_paths_and_order(_pathv);
-
-    debug_check("SPCurve::create_reverse", new_curve);
 }
 
 /**
@@ -1142,7 +981,6 @@ void
 SPCurve::append(SPCurve const *curve2,
                 bool use_lineto)
 {
-    g_return_if_fail(this != NULL);
     g_return_if_fail(curve2 != NULL);
 
     if (curve2->is_empty())
@@ -1195,8 +1033,6 @@ SPCurve::append(SPCurve const *curve2,
         closepath();
     }
 
-    debug_check("SPCurve::append", this);
-
     /* 2GEOM code when code above is removed:
     if (use_lineto) {
         Geom::PathVector::const_iterator it = curve2->_pathv.begin();
@@ -1226,7 +1062,6 @@ SPCurve::append(SPCurve const *curve2,
 SPCurve *
 SPCurve::append_continuous(SPCurve const *c1, gdouble tolerance)
 {
-    g_return_val_if_fail(this != NULL, NULL);
     g_return_val_if_fail(c1 != NULL, NULL);
     g_return_val_if_fail(!_closed, NULL);
     g_return_val_if_fail(!c1->_closed, NULL);
@@ -1235,8 +1070,6 @@ SPCurve::append_continuous(SPCurve const *c1, gdouble tolerance)
         return this;
     }
 
-    debug_check("SPCurve::append_continuous 11", this);
-
     NArtBpath const *be = last_bpath();
     if (be) {
         NArtBpath const *bs = c1->get_bpath();
@@ -1278,8 +1111,6 @@ SPCurve::append_continuous(SPCurve const *c1, gdouble tolerance)
         append(c1, TRUE);
     }
 
-    debug_check("SPCurve::append_continuous", this);
-
     return this;
 }
 
@@ -1291,8 +1122,6 @@ SPCurve::append_continuous(SPCurve const *c1, gdouble tolerance)
 void
 SPCurve::backspace()
 {
-    g_return_if_fail(this != NULL);
-
     if ( is_empty() )
         return;
 
@@ -1317,8 +1146,6 @@ SPCurve::backspace()
         _pathv.back().erase_last();
         _pathv.back().close(false);
     }
-
-    debug_check("SPCurve::backspace", this);
 }
 
 /* Private methods */
@@ -1517,8 +1344,6 @@ SPCurve::stretch_endpoints(NR::Point const &new_p0, NR::Point const &new_p1)
     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);
 }
 
 /**
@@ -1539,8 +1364,6 @@ SPCurve::move_endpoints(NR::Point const &new_p0, NR::Point const &new_p1)
 
     _pathv.front().setInitial(to_2geom(new_p0));
     _pathv.front().setFinal(to_2geom(new_p1));
-
-    debug_check("SPCurve::move_endpoints", this);
 }
 
 /**
@@ -1564,8 +1387,6 @@ SPCurve::nodes_in_path() const
         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;
 }
 
@@ -1600,8 +1421,6 @@ SPCurve::last_point_additive_move(Geom::Point const & p)
         newcube.setPoint(2, newcube[2] + p);
         _pathv.back().replace( --_pathv.back().end(), newcube );
     }
-
-    debug_check("SPCurve::last_point_additive_move", this);
 }
 
 /*