Code

Node tool: snap while scaling a selection of nodes. Consider this as experimental...
[inkscape.git] / src / sp-offset.cpp
index 5c79eb3342e8581624bae6c04f2302eb8515b0d8..51bb1e1ccc190c845e808588b3f47b2a26a99114 100644 (file)
@@ -1,5 +1,3 @@
-#define __SP_OFFSET_C__
-
 /** \file
  * Implementation of <path sodipodi:type="inkscape:offset">.
  */
@@ -8,6 +6,7 @@
  * Authors: (of the sp-spiral.c upon which this file was constructed):
  *   Mitsuru Oka <oka326@parkcity.ne.jp>
  *   Lauris Kaplinski <lauris@kaplinski.com>
+ *   Abhishek Sharma
  *
  * Copyright (C) 1999-2002 Lauris Kaplinski
  * Copyright (C) 2000-2001 Ximian, Inc.
@@ -19,6 +18,8 @@
 # include "config.h"
 #endif
 
+#include <cstring>
+#include <string>
 
 #include "svg/svg.h"
 #include "attributes.h"
 #include "livarot/Shape.h"
 
 #include "enums.h"
-#include "prefs-utils.h"
+#include "preferences.h"
 #include "sp-text.h"
 #include "sp-offset.h"
 #include "sp-use-reference.h"
 #include "uri.h"
 
-#include "libnr/n-art-bpath.h"
 #include <libnr/nr-matrix-fns.h>
+#include <2geom/pathvector.h>
 
 #include "xml/repr.h"
 
@@ -46,24 +47,24 @@ class SPDocument;
 
 /** \note
  * SPOffset is a derivative of SPShape, much like the SPSpiral or SPRect.
- * The goal is to have a source shape (= originalPath), an offset (= radius) 
- * and compute the offset of the source by the radius. To get it to work, 
- * one needs to know what the source is and what the radius is, and how it's 
- * stored in the xml representation. The object itself is a "path" element, 
- * to get lots of shape functionality for free. The source is the easy part: 
- * it's stored in a "inkscape:original" attribute in the path. In case of 
+ * The goal is to have a source shape (= originalPath), an offset (= radius)
+ * and compute the offset of the source by the radius. To get it to work,
+ * one needs to know what the source is and what the radius is, and how it's
+ * stored in the xml representation. The object itself is a "path" element,
+ * to get lots of shape functionality for free. The source is the easy part:
+ * it's stored in a "inkscape:original" attribute in the path. In case of
  * "linked" offset, as they've been dubbed, there is an additional
- * "inkscape:href" that contains the id of an element of the svg. 
- * When built, the object will attach a listener vector to that object and 
- * rebuild the "inkscape:original" whenever the href'd object changes. This 
- * is of course grossly inefficient, and also does not react to changes 
- * to the href'd during context stuff (like changing the shape of a star by 
- * dragging control points) unless the path of that object is changed during 
- * the context (seems to be the case for SPEllipse). The computation of the 
- * offset is done in sp_offset_set_shape(), a function that is called whenever 
+ * "inkscape:href" that contains the id of an element of the svg.
+ * When built, the object will attach a listener vector to that object and
+ * rebuild the "inkscape:original" whenever the href'd object changes. This
+ * is of course grossly inefficient, and also does not react to changes
+ * to the href'd during context stuff (like changing the shape of a star by
+ * dragging control points) unless the path of that object is changed during
+ * the context (seems to be the case for SPEllipse). The computation of the
+ * offset is done in sp_offset_set_shape(), a function that is called whenever
  * a change occurs to the offset (change of source or change of radius).
- * just like the sp-star and other, this path derivative can make control 
- * points, or more precisely one control point, that's enough to define the 
+ * just like the sp-star and other, this path derivative can make control
+ * points, or more precisely one control point, that's enough to define the
  * radius (look in object-edit).
  */
 
@@ -73,7 +74,7 @@ static void sp_offset_finalize(GObject *obj);
 
 static void sp_offset_build (SPObject * object, SPDocument * document,
                              Inkscape::XML::Node * repr);
-static Inkscape::XML::Node *sp_offset_write (SPObject * object, Inkscape::XML::Node * repr,
+static Inkscape::XML::Node *sp_offset_write (SPObject * object, Inkscape::XML::Document *doc, Inkscape::XML::Node * repr,
                                 guint flags);
 static void sp_offset_set (SPObject * object, unsigned int key,
                            const gchar * value);
@@ -81,17 +82,15 @@ static void sp_offset_update (SPObject * object, SPCtx * ctx, guint flags);
 static void sp_offset_release (SPObject * object);
 
 static gchar *sp_offset_description (SPItem * item);
-static void sp_offset_snappoints(SPItem const *item, SnapPointsIter p);
+static void sp_offset_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
 static void sp_offset_set_shape (SPShape * shape);
 
-Path *bpath_to_liv_path (NArtBpath * bpath);
-
 static void refresh_offset_source(SPOffset* offset);
 
 static void sp_offset_start_listening(SPOffset *offset,SPObject* to);
 static void sp_offset_quit_listening(SPOffset *offset);
 static void sp_offset_href_changed(SPObject *old_ref, SPObject *ref, SPOffset *offset);
-static void sp_offset_move_compensate(NR::Matrix const *mp, SPItem *original, SPOffset *self);
+static void sp_offset_move_compensate(Geom::Matrix const *mp, SPItem *original, SPOffset *self);
 static void sp_offset_delete_self(SPObject *deleted, SPOffset *self);
 static void sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *item);
 
@@ -99,7 +98,7 @@ static void sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *i
 // slow= source path->polygon->offset of polygon->polygon->path
 // fast= source path->offset of source path->polygon->path
 // fast is not mathematically correct, because computing the offset of a single
-// cubic bezier patch is not trivial; in particular, there are problems with holes 
+// cubic bezier patch is not trivial; in particular, there are problems with holes
 // reappearing in offset when the radius becomes too large
 static bool   use_slow_but_correct_offset_method=false;
 
@@ -114,7 +113,7 @@ GType
 sp_offset_get_type (void)
 {
     static GType offset_type = 0;
-  
+
     if (!offset_type)
     {
         GTypeInfo offset_info = {
@@ -146,9 +145,9 @@ sp_offset_class_init(SPOffsetClass *klass)
     SPObjectClass *sp_object_class = (SPObjectClass *) klass;
     SPItemClass   *item_class = (SPItemClass *) klass;
     SPShapeClass  *shape_class = (SPShapeClass *) klass;
-  
+
     parent_class = (SPShapeClass *) g_type_class_ref (SP_TYPE_SHAPE);
-  
+
     gobject_class->finalize = sp_offset_finalize;
 
     sp_object_class->build = sp_offset_build;
@@ -156,10 +155,10 @@ sp_offset_class_init(SPOffsetClass *klass)
     sp_object_class->set = sp_offset_set;
     sp_object_class->update = sp_offset_update;
     sp_object_class->release = sp_offset_release;
-  
+
     item_class->description = sp_offset_description;
     item_class->snappoints = sp_offset_snappoints;
-  
+
     shape_class->set_shape = sp_offset_set_shape;
 }
 
@@ -179,6 +178,7 @@ sp_offset_init(SPOffset *offset)
     offset->sourceHref = NULL;
     offset->sourceRepr = NULL;
     offset->sourceObject = NULL;
+    new (&offset->_modified_connection) sigc::connection();
     new (&offset->_delete_connection) sigc::connection();
     new (&offset->_changed_connection) sigc::connection();
     new (&offset->_transformed_connection) sigc::connection();
@@ -194,10 +194,16 @@ static void
 sp_offset_finalize(GObject *obj)
 {
     SPOffset *offset = (SPOffset *) obj;
-       
+
     delete offset->sourceRef;
+
+    offset->_modified_connection.disconnect();
+    offset->_modified_connection.~connection();
+    offset->_delete_connection.disconnect();
     offset->_delete_connection.~connection();
+    offset->_changed_connection.disconnect();
     offset->_changed_connection.~connection();
+    offset->_transformed_connection.disconnect();
     offset->_transformed_connection.~connection();
 }
 
@@ -209,40 +215,43 @@ sp_offset_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *rep
 {
     if (((SPObjectClass *) parent_class)->build)
         ((SPObjectClass *) parent_class)->build (object, document, repr);
-  
-    if (object->repr->attribute("inkscape:radius")) {
-        sp_object_read_attr (object, "inkscape:radius");
+
+    //XML Tree being used directly here while it shouldn't be.
+    if (object->getRepr()->attribute("inkscape:radius")) {
+        object->readAttr( "inkscape:radius" );
     } else {
-        gchar const *oldA = object->repr->attribute("sodipodi:radius");
-        object->repr->setAttribute("inkscape:radius",oldA);
-        object->repr->setAttribute("sodipodi:radius",NULL);
-    
-        sp_object_read_attr (object, "inkscape:radius");
+        //XML Tree being used directly here (as object->getRepr) 
+        //in all the below lines in the block while it shouldn't be.
+        gchar const *oldA = object->getRepr()->attribute("sodipodi:radius");
+        object->getRepr()->setAttribute("inkscape:radius",oldA);
+        object->getRepr()->setAttribute("sodipodi:radius",NULL);
+
+        object->readAttr( "inkscape:radius" );
     }
-    if (object->repr->attribute("inkscape:original")) {
-        sp_object_read_attr (object, "inkscape:original");
-    } else {    
-        gchar const *oldA = object->repr->attribute("sodipodi:original");
-        object->repr->setAttribute("inkscape:original",oldA);
-        object->repr->setAttribute("sodipodi:original",NULL);
-
-        sp_object_read_attr (object, "inkscape:original");
+    if (object->getRepr()->attribute("inkscape:original")) {
+        object->readAttr( "inkscape:original" );
+    } else {
+        gchar const *oldA = object->getRepr()->attribute("sodipodi:original");
+        object->getRepr()->setAttribute("inkscape:original",oldA);
+        object->getRepr()->setAttribute("sodipodi:original",NULL);
+
+        object->readAttr( "inkscape:original" );
     }
-    if (object->repr->attribute("xlink:href")) {
-        sp_object_read_attr(object, "xlink:href");
+    if (object->getRepr()->attribute("xlink:href")) {
+        object->readAttr( "xlink:href" );
     } else {
-        gchar const *oldA = object->repr->attribute("inkscape:href");
+        gchar const *oldA = object->getRepr()->attribute("inkscape:href");
         if (oldA) {
             size_t lA = strlen(oldA);
-            char *nA=(char*)malloc((lA+1)*sizeof(char));
+            char *nA=(char*)malloc((1+lA+1)*sizeof(char));
             memcpy(nA+1,oldA,lA*sizeof(char));
             nA[0]='#';
             nA[lA+1]=0;
-            object->repr->setAttribute("xlink:href",nA);
+            object->getRepr()->setAttribute("xlink:href",nA);
             free(nA);
-            object->repr->setAttribute("inkscape:href",NULL);
+            object->getRepr()->setAttribute("inkscape:href",NULL);
         }
-        sp_object_read_attr (object, "xlink:href");
+        object->readAttr( "xlink:href" );
     }
 }
 
@@ -250,14 +259,14 @@ sp_offset_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *rep
  * Virtual write: write offset attributes to corresponding repr.
  */
 static Inkscape::XML::Node *
-sp_offset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
+sp_offset_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
 {
     SPOffset *offset = SP_OFFSET (object);
-  
+
     if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
-        repr = sp_repr_new ("svg:path");
+        repr = xml_doc->createElement("svg:path");
     }
-  
+
     if (flags & SP_OBJECT_WRITE_EXT) {
         /** \todo
          * Fixme: we may replace these attributes by
@@ -270,21 +279,21 @@ sp_offset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
     }
 
 
-    // Make sure the object has curve 
-    SPCurve *curve = sp_shape_get_curve (SP_SHAPE (offset));
+    // Make sure the object has curve
+    SPCurve *curve = SP_SHAPE (offset)->getCurve();
     if (curve == NULL) {
         sp_offset_set_shape (SP_SHAPE (offset));
     }
 
     // write that curve to "d"
-    char *d = sp_svg_write_path (((SPShape *) offset)->curve->bpath);
+    char *d = sp_svg_write_path (((SPShape *) offset)->curve->get_pathvector());
     repr->setAttribute("d", d);
     g_free (d);
-  
+
     if (((SPObjectClass *) (parent_class))->write)
-        ((SPObjectClass *) (parent_class))->write (object, repr,
+        ((SPObjectClass *) (parent_class))->write (object, xml_doc, repr,
                                                    flags | SP_SHAPE_WRITE_PATH);
-  
+
     return repr;
 }
 
@@ -295,36 +304,36 @@ static void
 sp_offset_release(SPObject *object)
 {
     SPOffset *offset = (SPOffset *) object;
-  
+
     if (offset->original) free (offset->original);
     if (offset->originalPath) delete ((Path *) offset->originalPath);
     offset->original = NULL;
     offset->originalPath = NULL;
-  
+
     sp_offset_quit_listening(offset);
-       
+
     offset->_changed_connection.disconnect();
     g_free(offset->sourceHref);
     offset->sourceHref = NULL;
     offset->sourceRef->detach();
-    
+
     if (((SPObjectClass *) parent_class)->release) {
         ((SPObjectClass *) parent_class)->release (object);
     }
-  
+
 }
 
 /**
- * Set callback: the function that is called whenever a change is made to 
+ * Set callback: the function that is called whenever a change is made to
  * the description of the object.
  */
 static void
 sp_offset_set(SPObject *object, unsigned key, gchar const *value)
 {
     SPOffset *offset = SP_OFFSET (object);
-  
+
     if ( offset->sourceDirty ) refresh_offset_source(offset);
-  
+
     /* fixme: we should really collect updates */
     switch (key)
     {
@@ -338,17 +347,13 @@ sp_offset_set(SPObject *object, unsigned key, gchar const *value)
                     offset->original = NULL;
                     offset->originalPath = NULL;
                 }
-                NArtBpath *bpath;
-                SPCurve *curve;
-        
+
                 offset->original = strdup (value);
-        
-                bpath = sp_svg_read_path (offset->original);
-                curve = sp_curve_new_from_bpath (bpath);       // curve se chargera de detruire bpath
-                g_assert (curve != NULL);
-                offset->originalPath = bpath_to_liv_path (curve->bpath);
-                sp_curve_unref (curve);
-        
+
+                Geom::PathVector pv = sp_svg_read_pathv(offset->original);
+                offset->originalPath = new Path;
+                reinterpret_cast<Path *>(offset->originalPath)->LoadPathVector(pv);
+
                 offset->knotSet = false;
                 if ( offset->isUpdating == false ) object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
             }
@@ -402,10 +407,10 @@ sp_offset_update(SPObject *object, SPCtx *ctx, guint flags)
     if (flags &
         (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
          SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
-        sp_shape_set_shape ((SPShape *) object);
+        ((SPShape *) object)->setShape ();
     }
     offset->isUpdating=false;
-  
+
     if (((SPObjectClass *) parent_class)->update)
         ((SPObjectClass *) parent_class)->update (object, ctx, flags);
 }
@@ -429,75 +434,6 @@ sp_offset_description(SPItem *item)
     }
 }
 
-/**
- * Converts an NArtBpath (like the one stored in a SPCurve) into a 
- * livarot Path. Duplicate of splivarot.
- */
-Path *
-bpath_to_liv_path(NArtBpath *bpath)
-{
-    if (bpath == NULL)
-        return NULL;
-  
-    Path *dest = new Path;
-    dest->SetBackData (false);
-    {
-        int i;
-        bool closed = false;
-        float lastX = 0.0;
-        float lastY = 0.0;
-    
-        for (i = 0; bpath[i].code != NR_END; i++)
-        {
-            switch (bpath[i].code)
-            {
-                case NR_LINETO:
-                    lastX = bpath[i].x3;
-                    lastY = bpath[i].y3;
-                    {
-                        NR::Point  tmp(lastX,lastY);
-                        dest->LineTo (tmp);
-                    }
-                    break;
-          
-                case NR_CURVETO:
-                {
-                    NR::Point  tmp(bpath[i].x3, bpath[i].y3);
-                    NR::Point  tms;
-                    tms[0]=3 * (bpath[i].x1 - lastX);
-                    tms[1]=3 * (bpath[i].y1 - lastY);
-                    NR::Point  tme;
-                    tme[0]=3 * (bpath[i].x3 - bpath[i].x2);
-                    tme[1]= 3 * (bpath[i].y3 - bpath[i].y2);
-                    dest->CubicTo (tmp,tms,tme);
-                }
-                lastX = bpath[i].x3;
-                lastY = bpath[i].y3;
-                break;
-          
-                case NR_MOVETO_OPEN:
-                case NR_MOVETO:
-                    if (closed)
-                        dest->Close ();
-                    closed = (bpath[i].code == NR_MOVETO);
-                    lastX = bpath[i].x3;
-                    lastY = bpath[i].y3;
-                    {
-                        NR::Point tmp(lastX,lastY);
-                        dest->MoveTo(tmp);
-                    }
-                    break;
-                default:
-                    break;
-            }
-        }
-        if (closed)
-            dest->Close ();
-    }
-  
-    return dest;
-}
-
 /**
  * Compute and set shape's offset.
  */
@@ -505,7 +441,7 @@ static void
 sp_offset_set_shape(SPShape *shape)
 {
     SPOffset *offset = SP_OFFSET (shape);
-  
+
     if ( offset->originalPath == NULL ) {
         // oops : no path?! (the offset object should do harakiri)
         return;
@@ -514,30 +450,31 @@ sp_offset_set_shape(SPShape *shape)
     g_print ("rad=%g\n", offset->rad);
 #endif
     // au boulot
-  
+
     if ( fabs(offset->rad) < 0.01 ) {
         // grosso modo: 0
         // just put the source shape as the offseted one, no one will notice
         // it's also useless to compute the offset with a 0 radius
-    
-        const char *res_d = SP_OBJECT(shape)->repr->attribute("inkscape:original");
+
+        //XML Tree being used directly here while it shouldn't be.
+        const char *res_d = SP_OBJECT(shape)->getRepr()->attribute("inkscape:original");
         if ( res_d ) {
-            NArtBpath *bpath = sp_svg_read_path (res_d);
-            SPCurve *c = sp_curve_new_from_bpath (bpath);
+            Geom::PathVector pv = sp_svg_read_pathv(res_d);
+            SPCurve *c = new SPCurve(pv);
             g_assert(c != NULL);
-            sp_shape_set_curve_insync ((SPShape *) offset, c, TRUE);
-            sp_curve_unref (c);
+            ((SPShape *) offset)->setCurveInsync (c, TRUE);
+            c->unref();
         }
         return;
     }
-  
+
     // extra paraniac careful check. the preceding if () should take care of this case
     if (fabs (offset->rad) < 0.01)
         offset->rad = (offset->rad < 0) ? -0.01 : 0.01;
-  
+
     Path *orig = new Path;
     orig->Copy ((Path *) offset->originalPath);
-  
+
     if ( use_slow_but_correct_offset_method == false ) {
         // version par outline
         Shape *theShape = new Shape;
@@ -545,7 +482,7 @@ sp_offset_set_shape(SPShape *shape)
         Path *originaux[1];
         Path *res = new Path;
         res->SetBackData (false);
-  
+
         // and now: offset
         float o_width;
         if (offset->rad >= 0)
@@ -558,7 +495,7 @@ sp_offset_set_shape(SPShape *shape)
             o_width = -offset->rad;
             orig->OutsideOutline (res, -o_width, join_round, butt_straight, 20.0);
         }
-  
+
         if (o_width >= 1.0)
         {
             //      res->ConvertForOffset (1.0, orig, offset->rad);
@@ -572,21 +509,21 @@ sp_offset_set_shape(SPShape *shape)
         res->Fill (theShape, 0);
         theRes->ConvertToShape (theShape, fill_positive);
         originaux[0] = res;
-  
+
         theRes->ConvertToForme (orig, 1, originaux);
 
         SPItem *item = shape;
-        NR::Rect bbox = sp_item_bbox_desktop (item);
-        if (!bbox.isEmpty()) {
-            gdouble size = L2(bbox.dimensions());
-            gdouble const exp = NR::expansion(item->transform);
-            if (exp != 0) 
+        Geom::OptRect bbox = item->getBboxDesktop ();
+        if ( bbox ) {
+            gdouble size = L2(bbox->dimensions());
+            gdouble const exp = item->transform.descrim();
+            if (exp != 0)
                 size /= exp;
             orig->Coalesce (size * 0.001);
             //g_print ("coa %g    exp %g    item %p\n", size * 0.001, exp, item);
         }
 
-  
+
         //  if (o_width >= 1.0)
         //  {
         //    orig->Coalesce (0.1);  // small treshhold, since we only want to get rid of small segments
@@ -600,7 +537,7 @@ sp_offset_set_shape(SPShape *shape)
         //   orig->ConvertEvenLines (o_width);
         //   orig->Simplify (0.5 * o_width);
         //  }
-  
+
         delete theShape;
         delete theRes;
         delete res;
@@ -608,8 +545,8 @@ sp_offset_set_shape(SPShape *shape)
         // version par makeoffset
         Shape *theShape = new Shape;
         Shape *theRes = new Shape;
-    
-    
+
+
         // and now: offset
         float o_width;
         if (offset->rad >= 0)
@@ -620,7 +557,7 @@ sp_offset_set_shape(SPShape *shape)
         {
             o_width = -offset->rad;
         }
-    
+
         // one has to have a measure of the details
         if (o_width >= 1.0)
         {
@@ -664,7 +601,7 @@ sp_offset_set_shape(SPShape *shape)
                     onePart->ConvertToShape(oneCleanPart,fill_positive); // there aren't intersections in that one, but maybe duplicate points and null edges
                     oneCleanPart->MakeOffset(onePart,offset->rad,join_round,20.0);
                     onePart->ConvertToShape(oneCleanPart,fill_positive);
-          
+
                     onePart->CalcBBox();
                     double  typicalSize=0.5*((onePart->rightX-onePart->leftX)+(onePart->bottomY-onePart->topY));
                     if ( typicalSize < 0.05 ) typicalSize=0.05;
@@ -691,7 +628,7 @@ sp_offset_set_shape(SPShape *shape)
                     oneCleanPart->MakeOffset(onePart,-offset->rad,join_round,20.0);
                     onePart->ConvertToShape(oneCleanPart,fill_positive);
 //          for (int j=0;j<onePart->nbAr;j++) onePart->Inverse(j); // pas oublier de reinverser
-          
+
                     onePart->CalcBBox();
                     double  typicalSize=0.5*((onePart->rightX-onePart->leftX)+(onePart->bottomY-onePart->topY));
                     if ( typicalSize < 0.05 ) typicalSize=0.05;
@@ -707,7 +644,7 @@ sp_offset_set_shape(SPShape *shape)
                         parts[i]=NULL;
                     } else {
                     }
-          
+
                     /*         int  firstP=theShape->nbPt;
                                for (int j=0;j<onePart->nbPt;j++) theShape->AddPoint(onePart->pts[j].x);
                                for (int j=0;j<onePart->nbAr;j++) theShape->AddEdge(firstP+onePart->aretes[j].en,firstP+onePart->aretes[j].st);*/
@@ -724,9 +661,9 @@ sp_offset_set_shape(SPShape *shape)
                 if ( parts[i] ) {
                     parts[i]->ConvertWithBackData(1.0);
                     if ( holes[i] ) {
-                        parts[i]->Fill(theShape,i,true,true,true);        
+                        parts[i]->Fill(theShape,i,true,true,true);
                     } else {
-                        parts[i]->Fill(theShape,i,true,true,false);        
+                        parts[i]->Fill(theShape,i,true,true,false);
                     }
                 }
             }
@@ -741,7 +678,7 @@ sp_offset_set_shape(SPShape *shape)
         }
 //    theRes->ConvertToShape (theShape, fill_positive);
 //    theRes->ConvertToForme (orig);
-    
+
 /*    if (o_width >= 1.0) {
       orig->ConvertEvenLines (1.0);
       orig->Simplify (1.0);
@@ -749,13 +686,13 @@ sp_offset_set_shape(SPShape *shape)
       orig->ConvertEvenLines (1.0*o_width);
       orig->Simplify (1.0 * o_width);
       }*/
-    
+
         if ( parts ) free(parts);
         if ( holes ) free(holes);
         delete res;
         delete theShape;
         delete theRes;
-    } 
+    }
     {
         char *res_d = NULL;
         if (orig->descr_cmd.size() <= 1)
@@ -766,17 +703,17 @@ sp_offset_set_shape(SPShape *shape)
         }
         else
         {
-      
+
             res_d = orig->svg_dump_path ();
-        } 
+        }
         delete orig;
-    
-        NArtBpath *bpath = sp_svg_read_path (res_d);
-        SPCurve *c = sp_curve_new_from_bpath (bpath);
+
+        Geom::PathVector pv = sp_svg_read_pathv(res_d);
+        SPCurve *c = new SPCurve(pv);
         g_assert(c != NULL);
-        sp_shape_set_curve_insync ((SPShape *) offset, c, TRUE);
-        sp_curve_unref (c);
-    
+        ((SPShape *) offset)->setCurveInsync (c, TRUE);
+        c->unref();
+
         free (res_d);
     }
 }
@@ -784,10 +721,10 @@ sp_offset_set_shape(SPShape *shape)
 /**
  * Virtual snappoints function.
  */
-static void sp_offset_snappoints(SPItem const *item, SnapPointsIter p)
+static void sp_offset_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs)
 {
     if (((SPItemClass *) parent_class)->snappoints) {
-        ((SPItemClass *) parent_class)->snappoints (item, p);
+        ((SPItemClass *) parent_class)->snappoints (item, p, snapprefs);
     }
 }
 
@@ -795,33 +732,33 @@ static void sp_offset_snappoints(SPItem const *item, SnapPointsIter p)
 // utilitaires pour les poignees
 // used to get the distance to the shape: distance to polygon give the fabs(radius), we still need
 // the sign. for edges, it's easy to determine which side the point is on, for points of the polygon
-// it's trickier: we need to identify which angle the point is in; to that effect, we take each 
+// it's trickier: we need to identify which angle the point is in; to that effect, we take each
 // successive clockwise angle (A,C) and check if the vector B given by the point is in the angle or
 // outside.
-// another method would be to use the Winding() function to test whether the point is inside or outside 
+// another method would be to use the Winding() function to test whether the point is inside or outside
 // the polygon (it would be wiser to do so, in fact, but i like being stupid)
 
-/** 
+/**
  *
  * \todo
  * FIXME: This can be done using linear operations, more stably and
  *  faster.  method: transform A and C into B's space, A should be
  *  negative and B should be positive in the orthogonal component.  I
- *  think this is equivalent to 
- *  dot(A, rot90(B))*dot(C, rot90(B)) == -1.  
- *    -- njh 
+ *  think this is equivalent to
+ *  dot(A, rot90(B))*dot(C, rot90(B)) == -1.
+ *    -- njh
  */
 bool
-vectors_are_clockwise (NR::Point A, NR::Point B, NR::Point C)
+vectors_are_clockwise (Geom::Point A, Geom::Point B, Geom::Point C)
 {
-    using NR::rot90;
+    using Geom::rot90;
     double ab_s = dot(A, rot90(B));
     double ab_c = dot(A, B);
     double bc_s = dot(B, rot90(C));
     double bc_c = dot(B, C);
     double ca_s = dot(C, rot90(A));
     double ca_c = dot(C, A);
-  
+
     double ab_a = acos (ab_c);
     if (ab_c <= -1.0)
         ab_a = M_PI;
@@ -843,24 +780,24 @@ vectors_are_clockwise (NR::Point A, NR::Point B, NR::Point C)
         ca_a = 0;
     if (ca_s < 0)
         ca_a = 2 * M_PI - ca_a;
-  
+
     double lim = 2 * M_PI - ca_a;
-  
+
     if (ab_a < lim)
         return true;
     return false;
 }
 
-/** 
- * Distance to the original path; that function is called from object-edit 
+/**
+ * Distance to the original path; that function is called from object-edit
  * to set the radius when the control knot moves.
  *
- * The sign of the result is the radius we're going to offset the shape with, 
- * so result > 0 ==outset and result < 0 ==inset. thus result<0 means 
+ * The sign of the result is the radius we're going to offset the shape with,
+ * so result > 0 ==outset and result < 0 ==inset. thus result<0 means
  * 'px inside source'.
  */
 double
-sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
+sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
 {
     if (offset == NULL || offset->originalPath == NULL
         || ((Path *) offset->originalPath)->descr_cmd.size() <= 1)
@@ -868,24 +805,24 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
     double dist = 1.0;
     Shape *theShape = new Shape;
     Shape *theRes = new Shape;
-  
-    /** \todo 
-     * Awfully damn stupid method: uncross the source path EACH TIME you 
-     * need to compute the distance. The good way to do this would be to 
+
+    /** \todo
+     * Awfully damn stupid method: uncross the source path EACH TIME you
+     * need to compute the distance. The good way to do this would be to
      * store the uncrossed source path somewhere, and delete it when the
-     * context is finished. Hopefully this part is much faster than actually 
-     * computing the offset (which happen just after), so the time spent in 
-     * this function should end up being negligible with respect to the 
+     * context is finished. Hopefully this part is much faster than actually
+     * computing the offset (which happen just after), so the time spent in
+     * this function should end up being negligible with respect to the
      * delay of one context.
      */
     // move
     ((Path *) offset->originalPath)->Convert (1.0);
     ((Path *) offset->originalPath)->Fill (theShape, 0);
     theRes->ConvertToShape (theShape, fill_oddEven);
-  
+
     if (theRes->numberOfEdges() <= 1)
     {
-    
+
     }
     else
     {
@@ -898,14 +835,14 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
         {
             if (theRes->getPoint(i).totalDegree() > 0)
            {
-                NR::Point nx = theRes->getPoint(i).x;
-                NR::Point nxpx = px-nx;
+                Geom::Point nx = theRes->getPoint(i).x;
+                Geom::Point nxpx = px-nx;
                 double ndist = sqrt (dot(nxpx,nxpx));
                 if (ptSet == false || fabs (ndist) < fabs (ptDist))
                 {
                     // we have a new minimum distance
                     // now we need to wheck if px is inside or outside (for the sign)
-                    nx = px - theRes->getPoint(i).x;
+                    nx = px - to_2geom(theRes->getPoint(i).x);
                     double nlen = sqrt (dot(nx , nx));
                     nx /= nlen;
                     int pb, cb, fb;
@@ -915,7 +852,7 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
                     do
                     {
                         // one angle
-                        NR::Point prx, nex;
+                        Geom::Point prx, nex;
                         prx = theRes->getEdge(pb).dx;
                         nlen = sqrt (dot(prx, prx));
                         prx /= nlen;
@@ -930,7 +867,7 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
                         {
                             nex = -nex;
                         }
-            
+
                         if (vectors_are_clockwise (nex, nx, prx))
                         {
                             // we're in that angle. set the sign, and exit that loop
@@ -951,18 +888,18 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
                     }
                     while (cb >= 0 && pb >= 0 && pb != fb);
                 }
-           }
+            }
         }
         // loop over the edges to try to improve the distance
         for (int i = 0; i < theRes->numberOfEdges(); i++)
         {
-            NR::Point sx = theRes->getPoint(theRes->getEdge(i).st).x;
-            NR::Point ex = theRes->getPoint(theRes->getEdge(i).en).x;
-            NR::Point nx = ex - sx;
+            Geom::Point sx = theRes->getPoint(theRes->getEdge(i).st).x;
+            Geom::Point ex = theRes->getPoint(theRes->getEdge(i).en).x;
+            Geom::Point nx = ex - sx;
             double len = sqrt (dot(nx,nx));
             if (len > 0.0001)
-           {
-                NR::Point   pxsx=px-sx;
+            {
+                Geom::Point   pxsx=px-sx;
                 double ab = dot(nx,pxsx);
                 if (ab > 0 && ab < len * len)
                 {
@@ -974,7 +911,7 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
                         arSet = true;
                     }
                 }
-           }
+            }
         }
         if (arSet || ptSet)
         {
@@ -988,68 +925,69 @@ sp_offset_distance_to_original (SPOffset * offset, NR::Point px)
                 dist = arDist;
         }
     }
-  
+
     delete theShape;
     delete theRes;
-  
+
     return dist;
 }
 
-/** 
- * Computes a point on the offset;  used to set a "seed" position for 
+/**
+ * Computes a point on the offset;  used to set a "seed" position for
  * the control knot.
  *
  * \return the topmost point on the offset.
  */
 void
-sp_offset_top_point (SPOffset * offset, NR::Point *px)
+sp_offset_top_point (SPOffset * offset, Geom::Point *px)
 {
-    (*px) = NR::Point(0, 0);
+    (*px) = Geom::Point(0, 0);
     if (offset == NULL)
         return;
-  
+
     if (offset->knotSet)
     {
         (*px) = offset->knot;
         return;
     }
-  
-    SPCurve *curve = sp_shape_get_curve (SP_SHAPE (offset));
+
+    SPCurve *curve = SP_SHAPE (offset)->getCurve();
     if (curve == NULL)
     {
         sp_offset_set_shape (SP_SHAPE (offset));
-        curve = sp_shape_get_curve (SP_SHAPE (offset));
+        curve = SP_SHAPE (offset)->getCurve();
         if (curve == NULL)
             return;
     }
-  
-    Path *finalPath = bpath_to_liv_path (curve->bpath);
-    if (finalPath == NULL)
+    if (curve->is_empty())
     {
-        sp_curve_unref (curve);
+        curve->unref();
         return;
     }
-  
+
+    Path *finalPath = new Path;
+    finalPath->LoadPathVector(curve->get_pathvector());
+
     Shape *theShape = new Shape;
-  
+
     finalPath->Convert (1.0);
     finalPath->Fill (theShape, 0);
-  
+
     if (theShape->hasPoints())
     {
         theShape->SortPoints ();
         *px = theShape->getPoint(0).x;
     }
-  
+
     delete theShape;
     delete finalPath;
-    sp_curve_unref (curve);
+    curve->unref();
 }
 
 // the listening functions
 static void sp_offset_start_listening(SPOffset *offset,SPObject* to)
 {
-    if ( to == NULL ) 
+    if ( to == NULL )
         return;
 
     offset->sourceObject = to;
@@ -1057,15 +995,15 @@ static void sp_offset_start_listening(SPOffset *offset,SPObject* to)
 
     offset->_delete_connection = SP_OBJECT(to)->connectDelete(sigc::bind(sigc::ptr_fun(&sp_offset_delete_self), offset));
     offset->_transformed_connection = SP_ITEM(to)->connectTransformed(sigc::bind(sigc::ptr_fun(&sp_offset_move_compensate), offset));
-    offset->_modified_connection = g_signal_connect (G_OBJECT (to), "modified", G_CALLBACK (sp_offset_source_modified), offset);
+    offset->_modified_connection = SP_OBJECT(to)->connectModified(sigc::bind<2>(sigc::ptr_fun(&sp_offset_source_modified), offset));
 }
 
 static void sp_offset_quit_listening(SPOffset *offset)
 {
-    if ( offset->sourceObject == NULL )  
+    if ( offset->sourceObject == NULL )
         return;
 
-    g_signal_handler_disconnect (offset->sourceObject, offset->_modified_connection);
+    offset->_modified_connection.disconnect();
     offset->_delete_connection.disconnect();
     offset->_transformed_connection.disconnect();
 
@@ -1086,23 +1024,24 @@ sp_offset_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPOffset *offse
 }
 
 static void
-sp_offset_move_compensate(NR::Matrix const *mp, SPItem *original, SPOffset *self)
-{      
-    guint mode = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_PARALLEL);
+sp_offset_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPOffset *self)
+{
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL);
     if (mode == SP_CLONE_COMPENSATION_NONE) return;
 
-    NR::Matrix m(*mp);
-    if (!(m.is_translation())) return;
+    Geom::Matrix m(*mp);
+    if (!(m.isTranslation())) return;
 
     // calculate the compensation matrix and the advertized movement matrix
     SPItem *item = SP_ITEM(self);
 
-    NR::Matrix compensate;
-    NR::Matrix advertized_move;
+    Geom::Matrix compensate;
+    Geom::Matrix advertized_move;
 
     if (mode == SP_CLONE_COMPENSATION_UNMOVED) {
-        compensate = NR::identity();
-        advertized_move.set_identity();
+        compensate = Geom::identity();
+        advertized_move.setIdentity();
     } else if (mode == SP_CLONE_COMPENSATION_PARALLEL) {
         compensate = m;
         advertized_move = m;
@@ -1113,15 +1052,16 @@ sp_offset_move_compensate(NR::Matrix const *mp, SPItem *original, SPOffset *self
     item->transform *= compensate;
 
     // commit the compensation
-    sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform, &advertized_move);
+    item->doWriteTransform(SP_OBJECT_REPR(item), item->transform, &advertized_move);
     SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
 }
 
 static void
 sp_offset_delete_self(SPObject */*deleted*/, SPOffset *offset)
 {
-    guint const mode = prefs_get_int_attribute("options.cloneorphans", "value", SP_CLONE_ORPHANS_UNLINK);
-       
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    guint const mode = prefs->getInt("/options/cloneorphans/value", SP_CLONE_ORPHANS_UNLINK);
+
     if (mode == SP_CLONE_ORPHANS_UNLINK) {
         // leave it be. just forget about the source
         sp_offset_quit_listening(offset);
@@ -1134,53 +1074,53 @@ sp_offset_delete_self(SPObject */*deleted*/, SPOffset *offset)
 }
 
 static void
-sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *item)
+sp_offset_source_modified (SPObject */*iSource*/, guint /*flags*/, SPItem *item)
 {
     SPOffset *offset = SP_OFFSET(item);
     offset->sourceDirty=true;
     refresh_offset_source(offset);
-    sp_shape_set_shape ((SPShape *) offset);
+    ((SPShape *) offset)->setShape ();
 }
 
-static void 
+static void
 refresh_offset_source(SPOffset* offset)
 {
     if ( offset == NULL ) return;
     offset->sourceDirty=false;
-    Path *orig = NULL;
-  
+
     // le mauvais cas: pas d'attribut d => il faut verifier que c'est une SPShape puis prendre le contour
     // The bad case: no d attribute.  Must check that it's an SPShape and then take the outline.
     SPObject *refobj=offset->sourceObject;
     if ( refobj == NULL ) return;
     SPItem *item = SP_ITEM (refobj);
-  
+
     SPCurve *curve=NULL;
     if (!SP_IS_SHAPE (item) && !SP_IS_TEXT (item)) return;
     if (SP_IS_SHAPE (item)) {
-        curve = sp_shape_get_curve (SP_SHAPE (item));
+        curve = SP_SHAPE (item)->getCurve ();
         if (curve == NULL)
             return;
     }
     if (SP_IS_TEXT (item)) {
         curve = SP_TEXT (item)->getNormalizedBpath ();
         if (curve == NULL)
-           return;
+        return;
     }
-    orig = bpath_to_liv_path (curve->bpath);
-    sp_curve_unref (curve);
-  
-  
+    Path *orig = new Path;
+    orig->LoadPathVector(curve->get_pathvector());
+    curve->unref();
+
+
     // Finish up.
     {
         SPCSSAttr *css;
         const gchar *val;
         Shape *theShape = new Shape;
         Shape *theRes = new Shape;
-    
+
         orig->ConvertWithBackData (1.0);
         orig->Fill (theShape, 0);
-    
+
         css = sp_repr_css_attr (offset->sourceRepr , "style");
         val = sp_repr_css_property (css, "fill-rule", NULL);
         if (val && strcmp (val, "nonzero") == 0)
@@ -1195,21 +1135,22 @@ refresh_offset_source(SPOffset* offset)
         {
             theRes->ConvertToShape (theShape, fill_nonZero);
         }
-    
+
         Path *originaux[1];
         originaux[0] = orig;
         Path *res = new Path;
         theRes->ConvertToForme (res, 1, originaux);
-    
+
         delete theShape;
         delete theRes;
-    
+
         char *res_d = res->svg_dump_path ();
         delete res;
         delete orig;
-    
-        SP_OBJECT (offset)->repr->setAttribute("inkscape:original", res_d);
-    
+
+        //XML Tree being used diectly here while it shouldn't be.
+        SP_OBJECT (offset)->getRepr()->setAttribute("inkscape:original", res_d);
+
         free (res_d);
     }
 }
@@ -1235,4 +1176,4 @@ sp_offset_get_source (SPOffset *offset)
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :