Code

remove many unnecessary to_2geom and from_2geom calls
[inkscape.git] / src / extension / internal / odf.cpp
index 48e217bd83cf7d56f3ea0fd45720eecd97146f4d..8ad9b5031e5067d6b04536f8b93ccd8e5677aa83 100644 (file)
@@ -15,7 +15,7 @@
  * Authors:
  *   Bob Jamison
  *
- * Copyright (C) 2006 Bob Jamison
+ * Copyright (C) 2006, 2007 Bob Jamison
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
 #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"
@@ -186,8 +191,8 @@ public:
          for (unsigned int i=0 ; i<rows ; i++)
              {
              for (unsigned int j=0 ; j<other.cols ; j++)
-                {
-                double sum = 0.0;
+             {
+                 double sum = 0.0;
                  for (unsigned int k=0 ; k<cols ; k++)
                      {
                      //sum += a[i][k] * b[k][j];
@@ -205,7 +210,7 @@ public:
          SVDMatrix result(cols, rows);
          for (unsigned int i=0 ; i<rows ; i++)
              for (unsigned int j=0 ; j<cols ; j++)
-                result(j, i) = d[i*cols + j];
+                 result(j, i) = d[i*cols + j];
          return result;
          }
 
@@ -884,12 +889,12 @@ int SingularValueDecomposition::rank()
 /**
  * Get the value of a node/attribute pair
  */
-static Glib::ustring getAttribute( Inkscape::XML::Node *node, char *attrName)
+static Glib::ustring getAttribute( Inkscape::XML::Node *node, char const *attrName)
 {
     Glib::ustring val;
-    char *valstr = (char *)node->attribute(attrName);
+    char const *valstr = node->attribute(attrName);
     if (valstr)
-        val = (const char *)valstr;
+        val = valstr;
     return val;
 }
 
@@ -902,7 +907,7 @@ static Glib::ustring getExtension(const Glib::ustring &fname)
 {
     Glib::ustring ext;
 
-    unsigned int pos = fname.rfind('.');
+    std::string::size_type pos = fname.rfind('.');
     if (pos == fname.npos)
         {
         ext = "";
@@ -940,8 +945,7 @@ static Glib::ustring formatTransform(NR::Matrix &tf)
 static NR::Matrix getODFTransform(const SPItem *item)
 {
     //### Get SVG-to-ODF transform
-    NR::Matrix tf;
-    tf                   = sp_item_i2d_affine(item);
+    NR::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));
@@ -958,14 +962,16 @@ static NR::Matrix getODFTransform(const SPItem *item)
  * Get the bounding box of an item, as mapped onto
  * an ODF document, in cm.
  */
-static NR::Rect getODFBoundingBox(const SPItem *item)
+static boost::optional<NR::Rect> getODFBoundingBox(const SPItem *item)
 {
-    NR::Rect bbox        = sp_item_bbox_desktop((SPItem *)item);
-    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));
-    bbox                 = bbox * doc2dt_tf;
-    bbox                 = bbox * NR::Matrix(NR::scale(pxToCm));
+    boost::optional<NR::Rect> bbox = sp_item_bbox_desktop((SPItem *)item);
+    if (bbox) {
+        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));
+        bbox                 = *bbox * doc2dt_tf;
+        bbox                 = *bbox * NR::Matrix(NR::scale(pxToCm));
+    }
     return bbox;
 }
 
@@ -989,8 +995,8 @@ static NR::Matrix getODFItemTransform(const SPItem *item)
  * Get some fun facts from the transform
  */
 static void analyzeTransform(NR::Matrix &tf,
-           double &rotate, double &xskew, double &yskew,
-           double &xscale, double &yscale)
+                             double &rotate, double &/*xskew*/, double &/*yskew*/,
+                             double &xscale, double &yscale)
 {
     SVDMatrix mat(2, 2);
     mat(0, 0) = tf[0];
@@ -1026,7 +1032,7 @@ static void gatherText(Inkscape::XML::Node *node, Glib::ustring &buf)
         if (s)
             buf.append(s);
         }
-    
+
     for (Inkscape::XML::Node *child = node->firstChild() ;
                 child != NULL; child = child->next())
         {
@@ -1093,8 +1099,8 @@ OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node)
             if (imageTable.find(oldName) == imageTable.end())
                 {
                 char buf[64];
-                snprintf(buf, 63, "Pictures/image%d%s",
-                    (int)imageTable.size(), ext.c_str());
+                snprintf(buf, sizeof(buf), "Pictures/image%u%s",
+                         static_cast<unsigned int>(imageTable.size()), ext.c_str());
                 Glib::ustring newName = buf;
                 imageTable[oldName] = newName;
                 Glib::ustring comment = "old name was: ";
@@ -1173,7 +1179,7 @@ bool OdfOutput::writeManifest(ZipFile &zf)
         else if (ext == ".jpg")
             outs.printf("image/jpeg");
         outs.printf("\" manifest:full-path=\"");
-        outs.printf((char *)newName.c_str());
+        outs.printf(newName.c_str());
         outs.printf("\"/>\n");
         }
     outs.printf("</manifest:manifest>\n");
@@ -1243,7 +1249,7 @@ bool OdfOutput::writeMeta(ZipFile &zf)
         Glib::ustring value = iter->second;
         if (name.size() > 0 && value.size()>0)
             {
-            outs.printf("    <%#s>%#s</%#s>\n", 
+            outs.printf("    <%#s>%#s</%#s>\n",
                       name.c_str(), value.c_str(), name.c_str());
             }
         }
@@ -1351,7 +1357,7 @@ bool OdfOutput::writeStyle(ZipFile &zf)
             outs.printf("<svg:linearGradient ");
             outs.printf("id=\"%#s_g\" ", gi.name.c_str());
             outs.printf("draw:name=\"%#s_g\"\n", gi.name.c_str());
-            outs.printf("    draw:display-name=\"imported linear %d\"\n",
+            outs.printf("    draw:display-name=\"imported linear %u\"\n",
                         gradientCount);
             outs.printf("    svg:x1=\"%05.3fcm\" svg:y1=\"%05.3fcm\"\n",
                         gi.x1, gi.y1);
@@ -1474,72 +1480,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;
@@ -1555,10 +1546,9 @@ bool OdfOutput::processStyle(Writer &outs, SPItem *item,
     StyleInfo si;
 
     //## FILL
-    if (style->fill.type == SP_PAINT_TYPE_COLOR)
+    if (style->fill.isColor())
         {
-        guint32 fillCol =
-            sp_color_get_rgba32_ualpha(&style->fill.value.color, 0);
+        guint32 fillCol = style->fill.value.color.toRGBA32( 0 );
         char buf[16];
         int r = (fillCol >> 24) & 0xff;
         int g = (fillCol >> 16) & 0xff;
@@ -1574,10 +1564,9 @@ bool OdfOutput::processStyle(Writer &outs, SPItem *item,
         }
 
     //## STROKE
-    if (style->stroke.type == SP_PAINT_TYPE_COLOR)
+    if (style->stroke.isColor())
         {
-        guint32 strokeCol =
-            sp_color_get_rgba32_ualpha(&style->stroke.value.color, 0);
+        guint32 strokeCol = style->stroke.value.color.toRGBA32( 0 );
         char buf[16];
         int r = (strokeCol >> 24) & 0xff;
         int g = (strokeCol >> 16) & 0xff;
@@ -1646,10 +1635,19 @@ 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, NR::Matrix &/*tf*/)
 {
+    if (!item)
+        return false;
+
     SPStyle *style = item->style;
 
+    if (!style)
+        return false;
+
+    if (!style->fill.isPaintserver())
+        return false;
+
     //## Gradient.  Look in writeStyle() below to see what info
     //   we need to read into GradientInfo.
     if (!SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)))
@@ -1832,7 +1830,7 @@ bool OdfOutput::processGradient(Writer &outs, SPItem *item,
     outs.printf("        draw:textarea-horizontal-align=\"center\" ");
     outs.printf("draw:textarea-vertical-align=\"middle\"/>\n");
     outs.printf("</style:style>\n\n");
+
     return true;
 }
 
@@ -1866,11 +1864,15 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts,
     NR::Matrix tf        = getODFTransform(item);
 
     //### Get ODF bounding box params for item
-    NR::Rect bbox        = getODFBoundingBox(item);
-    double bbox_x        = bbox.min()[NR::X];
-    double bbox_y        = bbox.min()[NR::Y];
-    double bbox_width    = bbox.max()[NR::X] - bbox.min()[NR::X];
-    double bbox_height   = bbox.max()[NR::Y] - bbox.min()[NR::Y];
+    boost::optional<NR::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 rotate;
     double xskew;
@@ -2032,22 +2034,22 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts,
 
         couts.printf("draw:layer=\"layout\" svg:x=\"%.3fcm\" svg:y=\"%.3fcm\" ",
                        bbox_x, bbox_y);
-       couts.printf("svg:width=\"%.3fcm\" svg:height=\"%.3fcm\" ",
-                      bbox_width, bbox_height);
-       couts.printf("svg:viewBox=\"0.0 0.0 %.3f %.3f\"\n",
-                      bbox_width * 1000.0, bbox_height * 1000.0);
+        couts.printf("svg:width=\"%.3fcm\" svg:height=\"%.3fcm\" ",
+                       bbox_width, bbox_height);
+        couts.printf("svg:viewBox=\"0.0 0.0 %.3f %.3f\"\n",
+                       bbox_width * 1000.0, bbox_height * 1000.0);
 
-       couts.printf("    svg:d=\"");
-       int nrPoints = writePath(couts, SP_CURVE_BPATH(curve),
+        couts.printf("    svg:d=\"");
+        int nrPoints = writePath(couts, curve->get_pathvector(),
                              tf, bbox_x, bbox_y);
-       couts.printf("\"");
+        couts.printf("\"");
 
-       couts.printf(">\n");
+        couts.printf(">\n");
         couts.printf("    <!-- %d nodes -->\n", nrPoints);
         couts.printf("</draw:path>\n\n");
 
 
-        sp_curve_unref(curve);
+        curve->unref();
         }
 
     return true;
@@ -2363,7 +2365,7 @@ OdfOutput::reset()
  * Descends into the SVG tree, mapping things to ODF when appropriate
  */
 void
-OdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *uri)
+OdfOutput::save(Inkscape::Extension::Output */*mod*/, SPDocument *doc, gchar const *uri)
 {
     reset();
 
@@ -2407,7 +2409,7 @@ void
 OdfOutput::init()
 {
     Inkscape::Extension::build_from_mem(
-        "<inkscape-extension>\n"
+        "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
             "<name>" N_("OpenDocument Drawing Output") "</name>\n"
             "<id>org.inkscape.output.odf</id>\n"
             "<output>\n"
@@ -2424,7 +2426,7 @@ OdfOutput::init()
  * Make sure that we are in the database
  */
 bool
-OdfOutput::check (Inkscape::Extension::Extension *module)
+OdfOutput::check (Inkscape::Extension::Extension */*module*/)
 {
     /* We don't need a Key
     if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_POV))