Code

Filters. New custom predefined filters (all ABCs, Neon draw, Color shilf, Silhouette...
[inkscape.git] / src / extension / internal / odf.cpp
index 58d19be325fa79740dee78654349ec22e983febf..b5c842a40c6dbf6b3857b1874f893ae54d89e522 100644 (file)
@@ -14,6 +14,7 @@
  *
  * Authors:
  *   Bob Jamison
+ *   Abhishek Sharma
  *
  * Copyright (C) 2006, 2007 Bob Jamison
  *
 #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 +192,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 +211,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;
          }
 
@@ -253,7 +259,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
  *
@@ -790,8 +796,8 @@ void SingularValueDecomposition::calculate()
          }
       }
 
-    delete e;
-    delete work;
+    delete [] e;
+    delete [] work;
 
 }
 
@@ -915,10 +921,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,17 +943,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;
-    tf                   = sp_item_i2d_affine(item);
+    Geom::Matrix tf (item->i2d_affine());
     //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));
+    double doc_height    = SP_ACTIVE_DOCUMENT->getHeight();
+    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;
 }
 
@@ -958,15 +963,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 Geom::OptRect getODFBoundingBox(const SPItem *item)
 {
-    NR::Maybe<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));
+    Geom::OptRect bbox_temp = ((SPItem *)item)->getBboxDesktop();
+    Geom::OptRect bbox;
+    if (bbox_temp) {
+        bbox = *bbox_temp;
+        double doc_height    = SP_ACTIVE_DOCUMENT->getHeight();
+        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;
 }
@@ -977,11 +984,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;
 }
 
@@ -990,9 +997,9 @@ 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)
+static void analyzeTransform(Geom::Matrix &tf,
+                             double &rotate, double &/*xskew*/, double &/*yskew*/,
+                             double &xscale, double &yscale)
 {
     SVDMatrix mat(2, 2);
     mat(0, 0) = tf[0];
@@ -1028,7 +1035,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())
         {
@@ -1080,7 +1087,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,8 +1102,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: ";
@@ -1245,7 +1252,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());
             }
         }
@@ -1353,7 +1360,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);
@@ -1476,72 +1483,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 = pv.begin(); pit != pv.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;
@@ -1646,7 +1638,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;
@@ -1668,9 +1660,9 @@ bool OdfOutput::processGradient(Writer &outs, SPItem *item,
 
     GradientInfo gi;
 
-    SPGradient *grvec = sp_gradient_get_vector(gradient, FALSE);
-    for (SPStop *stop = sp_first_stop(grvec) ;
-          stop ; stop = sp_next_stop(stop))
+    SPGradient *grvec = gradient->getVector(FALSE);
+    for (SPStop *stop = grvec->getFirstStop() ;
+         stop ; stop = stop->getNextStop())
         {
         unsigned long rgba = sp_stop_get_rgba32(stop);
         unsigned long rgb  = (rgba >> 8) & 0xffffff;
@@ -1684,14 +1676,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;
@@ -1841,7 +1833,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;
 }
 
@@ -1872,18 +1864,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);
+    Geom::OptRect 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;
@@ -1959,16 +1951,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);
 
@@ -2011,7 +2003,7 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts,
     else if (SP_IS_SHAPE(item))
         {
         //g_message("### %s is a shape", nodeName.c_str());
-        curve = sp_shape_get_curve(SP_SHAPE(item));
+        curve = SP_SHAPE(item)->getCurve();
         }
     else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item))
         {
@@ -2045,22 +2037,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;
@@ -2376,12 +2368,14 @@ 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 *filename)
 {
     reset();
 
-    //g_message("native file:%s\n", uri);
-    documentUri = URI(uri);
+    //g_message("native file:%s\n", filename);
+    documentUri = URI(filename);
+    /* fixme: It looks like we really are using documentUri as a URI, so we ought to call
+     * g_filename_to_uri for the URI constructor. */
 
     ZipFile zf;
     preprocess(zf, doc->rroot);
@@ -2404,7 +2398,7 @@ OdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *
         return;
         }
 
-    if (!zf.writeFile(uri))
+    if (!zf.writeFile(filename))
         {
         return;
         }
@@ -2420,7 +2414,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"
@@ -2437,7 +2431,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))
@@ -2489,4 +2483,4 @@ OdfOutput::check (Inkscape::Extension::Extension *module)
   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 :