Code

NR:: to Geom:: for most of src/extension/
[inkscape.git] / src / extension / internal / odf.cpp
index 33242b09e0c405cffba7d1655c9adac9d5d77377..01690628964480c352f800d5e9c811d49831bd6a 100644 (file)
 #include "inkscape.h"
 #include <style.h>
 #include "display/curve.h"
-#include "libnr/n-art-bpath.h"
+#include <2geom/pathvector.h>
+#include <2geom/bezier-curve.h>
+#include <2geom/hvlinesegment.h>
+#include <2geom/transforms.h>
+#include <helper/geom.h>
+#include "helper/geom-curves.h"
 #include "extension/system.h"
 
 #include "xml/repr.h"
@@ -253,7 +258,7 @@ private:
  * NOTE:
  * This class is ported almost verbatim from the public domain
  * JAMA Matrix package.  It is modified to handle only 3x3 matrices
- * and our NR::Matrix affine transform class.  We give full
+ * and our Geom::Matrix affine transform class.  We give full
  * attribution to them, along with many thanks.  JAMA can be found at:
  *     http://math.nist.gov/javanumerics/jama
  *
@@ -915,10 +920,10 @@ static Glib::ustring getExtension(const Glib::ustring &fname)
 }
 
 
-static Glib::ustring formatTransform(NR::Matrix &tf)
+static Glib::ustring formatTransform(Geom::Matrix &tf)
 {
     Glib::ustring str;
-    if (!tf.test_identity())
+    if (!tf.isIdentity())
         {
         StringOutputStream outs;
         OutputStreamWriter out(outs);
@@ -937,16 +942,16 @@ static Glib::ustring formatTransform(NR::Matrix &tf)
  * Get the general transform from SVG pixels to
  * ODF cm
  */
-static NR::Matrix getODFTransform(const SPItem *item)
+static Geom::Matrix getODFTransform(const SPItem *item)
 {
     //### Get SVG-to-ODF transform
-    NR::Matrix tf = from_2geom(sp_item_i2d_affine(item));
+    Geom::Matrix tf (sp_item_i2d_affine(item));
     //Flip Y into document coordinates
     double doc_height    = sp_document_height(SP_ACTIVE_DOCUMENT);
-    NR::Matrix doc2dt_tf = NR::Matrix(NR::scale(1.0, -1.0));
-    doc2dt_tf            = doc2dt_tf * NR::Matrix(NR::translate(0, doc_height));
+    Geom::Matrix doc2dt_tf = Geom::Matrix(Geom::Scale(1.0, -1.0));
+    doc2dt_tf            = doc2dt_tf * Geom::Matrix(Geom::Translate(0, doc_height));
     tf                   = tf * doc2dt_tf;
-    tf                   = tf * NR::Matrix(NR::scale(pxToCm));
+    tf                   = tf * Geom::Matrix(Geom::Scale(pxToCm));
     return tf;
 }
 
@@ -957,15 +962,17 @@ static NR::Matrix getODFTransform(const SPItem *item)
  * Get the bounding box of an item, as mapped onto
  * an ODF document, in cm.
  */
-static NR::Maybe<NR::Rect> getODFBoundingBox(const SPItem *item)
+static boost::optional<Geom::Rect> getODFBoundingBox(const SPItem *item)
 {
-    NR::Maybe<NR::Rect> bbox = sp_item_bbox_desktop((SPItem *)item);
-    if (bbox) {
+    boost::optional<NR::Rect> bbox_temp = sp_item_bbox_desktop((SPItem *)item);
+    boost::optional<Geom::Rect> bbox;
+    if (bbox_temp) {
+        bbox = to_2geom(*bbox_temp);
         double doc_height    = sp_document_height(SP_ACTIVE_DOCUMENT);
-        NR::Matrix doc2dt_tf = NR::Matrix(NR::scale(1.0, -1.0));
-        doc2dt_tf            = doc2dt_tf * NR::Matrix(NR::translate(0, doc_height));
+        Geom::Matrix doc2dt_tf = Geom::Matrix(Geom::Scale(1.0, -1.0));
+        doc2dt_tf            = doc2dt_tf * Geom::Matrix(Geom::Translate(0, doc_height));
         bbox                 = *bbox * doc2dt_tf;
-        bbox                 = *bbox * NR::Matrix(NR::scale(pxToCm));
+        bbox                 = *bbox * Geom::Matrix(Geom::Scale(pxToCm));
     }
     return bbox;
 }
@@ -976,11 +983,11 @@ static NR::Maybe<NR::Rect> getODFBoundingBox(const SPItem *item)
  * Get the transform for an item, correcting for
  * handedness reversal
  */
-static NR::Matrix getODFItemTransform(const SPItem *item)
+static Geom::Matrix getODFItemTransform(const SPItem *item)
 {
-    NR::Matrix itemTransform = NR::Matrix(NR::scale(1, -1));
-    itemTransform = itemTransform * item->transform;
-    itemTransform = itemTransform * NR::Matrix(NR::scale(1, -1));
+    Geom::Matrix itemTransform (Geom::Scale(1, -1));
+    itemTransform = itemTransform * (Geom::Matrix)item->transform;
+    itemTransform = itemTransform * Geom::Scale(1, -1);
     return itemTransform;
 }
 
@@ -989,7 +996,7 @@ static NR::Matrix getODFItemTransform(const SPItem *item)
 /**
  * Get some fun facts from the transform
  */
-static void analyzeTransform(NR::Matrix &tf,
+static void analyzeTransform(Geom::Matrix &tf,
                              double &rotate, double &/*xskew*/, double &/*yskew*/,
                              double &xscale, double &yscale)
 {
@@ -1079,7 +1086,7 @@ OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node)
         }
     SPItem *item  = SP_ITEM(reprobj);
     //### Get SVG-to-ODF transform
-    NR::Matrix tf = getODFTransform(item);
+    Geom::Matrix tf = getODFTransform(item);
 
     if (nodeName == "image" || nodeName == "svg:image")
         {
@@ -1095,7 +1102,7 @@ OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node)
                 {
                 char buf[64];
                 snprintf(buf, sizeof(buf), "Pictures/image%u%s",
-                         imageTable.size(), ext.c_str());
+                         static_cast<unsigned int>(imageTable.size()), ext.c_str());
                 Glib::ustring newName = buf;
                 imageTable[oldName] = newName;
                 Glib::ustring comment = "old name was: ";
@@ -1475,72 +1482,57 @@ bool OdfOutput::writeStyle(ZipFile &zf)
 
 
 /**
- * Writes an SVG path as an ODF <draw:path>
+ * Writes an SVG path as an ODF <draw:path> and returns the number of points written
  */
 static int
-writePath(Writer &outs, NArtBpath const *bpath,
-          NR::Matrix &tf, double xoff, double yoff)
+writePath(Writer &outs, Geom::PathVector const &pathv,
+          Geom::Matrix const &tf, double xoff, double yoff)
 {
-    bool closed   = false;
+    using Geom::X;
+    using Geom::Y;
+
     int nrPoints  = 0;
-    NArtBpath *bp = (NArtBpath *)bpath;
 
-    double destx = 0.0;
-    double desty = 0.0;
-    int code = -1;
+    // convert the path to only lineto's and cubic curveto's:
+    Geom::PathVector pv = pathv_to_linear_and_cubic_beziers(pathv * tf * Geom::Translate(xoff, yoff) * Geom::Scale(1000.));
 
-    for (  ; bp->code != NR_END; bp++)
-        {
-        code = bp->code;
-
-        NR::Point const p1(bp->c(1) * tf);
-        NR::Point const p2(bp->c(2) * tf);
-        NR::Point const p3(bp->c(3) * tf);
-        double x1 = (p1[NR::X] - xoff) * 1000.0;
-        if (fabs(x1)<1.0) x1=0.0;
-        double y1 = (p1[NR::Y] - yoff) * 1000.0;
-        if (fabs(y1)<1.0) y1=0.0;
-        double x2 = (p2[NR::X] - xoff) * 1000.0;
-        if (fabs(x2)<1.0) x2=0.0;
-        double y2 = (p2[NR::Y] - yoff) * 1000.0;
-        if (fabs(y2)<1.0) y2=0.0;
-        double x3 = (p3[NR::X] - xoff) * 1000.0;
-        if (fabs(x3)<1.0) x3=0.0;
-        double y3 = (p3[NR::Y] - yoff) * 1000.0;
-        if (fabs(y3)<1.0) y3=0.0;
-        destx = x3;
-        desty = y3;
-
-        switch (code)
-            {
-            case NR_LINETO:
-                outs.printf("L %.3f %.3f ",  destx, desty);
-                break;
-
-            case NR_CURVETO:
-                outs.printf("C %.3f %.3f %.3f %.3f %.3f %.3f ",
-                              x1, y1, x2, y2, destx, desty);
-                break;
-
-            case NR_MOVETO_OPEN:
-            case NR_MOVETO:
-                if (closed)
-                    outs.printf("Z ");
-                closed = ( code == NR_MOVETO );
-                outs.printf("M %.3f %.3f ",  destx, desty);
-                break;
-
-            default:
-                break;
+        for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit) {
 
-            }
+            double destx = pit->initialPoint()[X];
+            double desty = pit->initialPoint()[Y];
+            if (fabs(destx)<1.0) destx = 0.0;   // Why is this needed? Shouldn't we just round all numbers then?
+            if (fabs(desty)<1.0) desty = 0.0;
+            outs.printf("M %.3f %.3f ", destx, desty);
+            nrPoints++;
 
-        nrPoints++;
-        }
+            for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_closed(); ++cit) {
 
-    if (closed)
-        {
-        outs.printf("Z");
+                if( is_straight_curve(*cit) )
+                {
+                    double destx = cit->finalPoint()[X];
+                    double desty = cit->finalPoint()[Y];
+                    if (fabs(destx)<1.0) destx = 0.0;   // Why is this needed? Shouldn't we just round all numbers then?
+                    if (fabs(desty)<1.0) desty = 0.0;
+                    outs.printf("L %.3f %.3f ",  destx, desty);
+                }
+                else if(Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const*>(&*cit)) {
+                    std::vector<Geom::Point> points = cubic->points();
+                    for (unsigned i = 1; i <= 3; i++) {
+                        if (fabs(points[i][X])<1.0) points[i][X] = 0.0;   // Why is this needed? Shouldn't we just round all numbers then?
+                        if (fabs(points[i][Y])<1.0) points[i][Y] = 0.0;
+                    }
+                    outs.printf("C %.3f %.3f %.3f %.3f %.3f %.3f ", points[1][X],points[1][Y], points[2][X],points[2][Y], points[3][X],points[3][Y]);
+                }
+                else {
+                    g_error ("logical error, because pathv_to_linear_and_cubic_beziers was used");
+                }
+
+                nrPoints++;
+            }
+
+            if (pit->closed()) {
+                outs.printf("Z");
+            }
         }
 
     return nrPoints;
@@ -1645,7 +1637,7 @@ bool OdfOutput::processStyle(Writer &outs, SPItem *item,
 
 
 bool OdfOutput::processGradient(Writer &outs, SPItem *item,
-                                const Glib::ustring &id, NR::Matrix &/*tf*/)
+                                const Glib::ustring &id, Geom::Matrix &/*tf*/)
 {
     if (!item)
         return false;
@@ -1683,14 +1675,14 @@ bool OdfOutput::processGradient(Writer &outs, SPItem *item,
         gi.style = "linear";
         SPLinearGradient *linGrad = SP_LINEARGRADIENT(gradient);
         /*
-        NR::Point p1(linGrad->x1.value, linGrad->y1.value);
+        Geom::Point p1(linGrad->x1.value, linGrad->y1.value);
         p1 = p1 * tf;
-        gi.x1 = p1[NR::X];
-        gi.y1 = p1[NR::Y];
-        NR::Point p2(linGrad->x2.value, linGrad->y2.value);
+        gi.x1 = p1[Geom::X];
+        gi.y1 = p1[Geom::Y];
+        Geom::Point p2(linGrad->x2.value, linGrad->y2.value);
         p2 = p2 * tf;
-        gi.x2 = p2[NR::X];
-        gi.y2 = p2[NR::Y];
+        gi.x2 = p2[Geom::X];
+        gi.y2 = p2[Geom::Y];
         */
         gi.x1 = linGrad->x1.value;
         gi.y1 = linGrad->y1.value;
@@ -1871,18 +1863,18 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts,
     Glib::ustring id       = getAttribute(node, "id");
 
     //### Get SVG-to-ODF transform
-    NR::Matrix tf        = getODFTransform(item);
+    Geom::Matrix tf        = getODFTransform(item);
 
     //### Get ODF bounding box params for item
-    NR::Maybe<NR::Rect> bbox = getODFBoundingBox(item);
+    boost::optional<Geom::Rect> bbox = getODFBoundingBox(item);
     if (!bbox) {
         return true;
     }
 
-    double bbox_x        = bbox->min()[NR::X];
-    double bbox_y        = bbox->min()[NR::Y];
-    double bbox_width    = bbox->extent(NR::X);
-    double bbox_height   = bbox->extent(NR::Y);
+    double bbox_x        = bbox->min()[Geom::X];
+    double bbox_y        = bbox->min()[Geom::Y];
+    double bbox_width    = (*bbox)[Geom::X].extent();
+    double bbox_height   = (*bbox)[Geom::Y].extent();
 
     double rotate;
     double xskew;
@@ -1958,16 +1950,16 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts,
         double iwidth  = img->width.value;
         double iheight = img->height.value;
 
-        NR::Rect ibbox(NR::Point(ix, iy), NR::Point(ix+iwidth, iy+iheight));
+        Geom::Rect ibbox(Geom::Point(ix, iy), Geom::Point(ix+iwidth, iy+iheight));
         ibbox = ibbox * tf;
-        ix      = ibbox.min()[NR::X];
-        iy      = ibbox.min()[NR::Y];
-        //iwidth  = ibbox.max()[NR::X] - ibbox.min()[NR::X];
-        //iheight = ibbox.max()[NR::Y] - ibbox.min()[NR::Y];
+        ix      = ibbox.min()[Geom::X];
+        iy      = ibbox.min()[Geom::Y];
+        //iwidth  = ibbox.max()[Geom::X] - ibbox.min()[Geom::X];
+        //iheight = ibbox.max()[Geom::Y] - ibbox.min()[Geom::Y];
         iwidth  = xscale * iwidth;
         iheight = yscale * iheight;
 
-        NR::Matrix itemTransform = getODFItemTransform(item);
+        Geom::Matrix itemTransform = getODFItemTransform(item);
 
         Glib::ustring itemTransformString = formatTransform(itemTransform);
 
@@ -2050,7 +2042,7 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts,
                        bbox_width * 1000.0, bbox_height * 1000.0);
 
         couts.printf("    svg:d=\"");
-        int nrPoints = writePath(couts, SP_CURVE_BPATH(curve),
+        int nrPoints = writePath(couts, curve->get_pathvector(),
                              tf, bbox_x, bbox_y);
         couts.printf("\"");