[haiku-commits] haiku: hrev54246 - src/apps/icon-o-matic/import_export/svg

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 22 May 2020 10:08:22 -0400 (EDT)

hrev54246 adds 2 changesets to branch 'master'
old head: c419919252f9076761900fd4e7575407a554255e
new head: 17626df948e1d384072e6a2f8eab4f7fc6a18d0a
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=17626df948e1+%5Ec419919252f9

----------------------------------------------------------------------------

2a3b385efba2: Icon-O-Matic: replace SVG parser with nanosvg
  
  The parser was based on an old example from agg. NanoSVG is originally
  based on the same code, but has lots of bugfixes. So it makes sense
  to use it.
  
  Nanosvg revision 25241c5a8f8451d41ab1b02ab2d865b01600d949
  
  Fixes #5955, #8586, #13021.
  
  Change-Id: I38ff9aa4e1d403c41979ebe42f7b45d4500a870c
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/2661
  Reviewed-by: waddlesplash <waddlesplash@xxxxxxxxx>

17626df948e1: Icon-O-Matic: use the MIME sniffer to recognize SVG files
  
  Our sniffing rule is not perfect, but it is already a lot better than
  what was done here.
  
  Partially fixes #14437 (the icons also fails parsing for other reasons,
  but with an error message, at least)
  
  Change-Id: I25475b419b5fbe863c71f553a336757d7950bf48
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/2662
  Reviewed-by: waddlesplash <waddlesplash@xxxxxxxxx>

                             [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

14 files changed, 3170 insertions(+), 2703 deletions(-)
src/apps/icon-o-matic/Jamfile                    |    3 -
.../import_export/svg/DocumentBuilder.cpp        |  830 +----
.../import_export/svg/DocumentBuilder.h          |  208 +-
.../import_export/svg/PathTokenizer.cpp          |  157 -
.../import_export/svg/PathTokenizer.h            |  106 -
.../import_export/svg/SVGGradients.cpp           |  199 --
.../import_export/svg/SVGGradients.h             |   81 -
.../import_export/svg/SVGImporter.cpp            |   44 +-
.../icon-o-matic/import_export/svg/SVGParser.cpp | 1152 -------
.../icon-o-matic/import_export/svg/SVGParser.h   |  105 -
.../icon-o-matic/import_export/svg/nanosvg.h     | 2975 ++++++++++++++++++
src/libs/icon/style/GradientTransformable.cpp    |    2 +
src/libs/icon/transformable/Transformable.cpp    |    9 +
src/libs/icon/transformable/Transformable.h      |    2 +

############################################################################

Commit:      2a3b385efba22655c4d6ff61ed59203283392ad7
URL:         https://git.haiku-os.org/haiku/commit/?id=2a3b385efba2
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sun May 10 15:14:39 2020 UTC
Committer:   waddlesplash <waddlesplash@xxxxxxxxx>
Commit-Date: Fri May 22 14:08:17 2020 UTC

Ticket:      https://dev.haiku-os.org/ticket/5955
Ticket:      https://dev.haiku-os.org/ticket/8586
Ticket:      https://dev.haiku-os.org/ticket/13021

Icon-O-Matic: replace SVG parser with nanosvg

The parser was based on an old example from agg. NanoSVG is originally
based on the same code, but has lots of bugfixes. So it makes sense
to use it.

Nanosvg revision 25241c5a8f8451d41ab1b02ab2d865b01600d949

Fixes #5955, #8586, #13021.

Change-Id: I38ff9aa4e1d403c41979ebe42f7b45d4500a870c
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2661
Reviewed-by: waddlesplash <waddlesplash@xxxxxxxxx>

----------------------------------------------------------------------------

diff --git a/src/apps/icon-o-matic/Jamfile b/src/apps/icon-o-matic/Jamfile
index 14a10e08b0..b2d19f473f 100644
--- a/src/apps/icon-o-matic/Jamfile
+++ b/src/apps/icon-o-matic/Jamfile
@@ -233,11 +233,8 @@ Application Icon-O-Matic :
 
        # import_export/svg
        DocumentBuilder.cpp
-       PathTokenizer.cpp
        SVGExporter.cpp
-       SVGGradients.cpp
        SVGImporter.cpp
-       SVGParser.cpp
 
        # shape
        PathManipulator.cpp
diff --git a/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp 
b/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp
index 39fd6d5aab..186eeb265e 100644
--- a/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp
+++ b/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp
@@ -6,21 +6,8 @@
  *             Stephan Aßmus <superstippi@xxxxxx>
  */
 
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.2
-// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@xxxxxxxxxxxxx
-//               mcseemagg@xxxxxxxxx
-//               http://www.antigrain.com
-//----------------------------------------------------------------------------
 
+#define NANOSVG_IMPLEMENTATION
 #include "DocumentBuilder.h"
 
 #include <new>
@@ -28,8 +15,6 @@
 
 #include <Bitmap.h>
 
-#include <agg_bounding_rect.h>
-
 #include "AutoDeleter.h"
 #include "GradientTransformable.h"
 #include "Icon.h"
@@ -39,166 +24,24 @@
 #include "StrokeTransformer.h"
 #include "Style.h"
 #include "StyleContainer.h"
-#include "SVGGradients.h"
 #include "SVGImporter.h"
 #include "VectorPath.h"
 
-using std::nothrow;
+#include <agg_math_stroke.h>
+#include <agg_trans_affine.h>
 
-namespace agg {
-namespace svg {
+using std::nothrow;
 
 // constructor
-DocumentBuilder::DocumentBuilder()
-       : fGradients(20),
-         fCurrentGradient(NULL),
-         fWidth(0),
+DocumentBuilder::DocumentBuilder(NSVGimage* source)
+       : fWidth(0),
          fHeight(0),
          fViewBox(0.0, 0.0, -1.0, -1.0),
-         fTitle("")
-{
-}
-
-
-// remove_all
-void
-DocumentBuilder::remove_all()
-{
-       fPathStorage.remove_all();
-       fAttributesStorage.remove_all();
-       fAttributesStack.remove_all();
-       fTransform.reset();
-}
-
-// begin_path
-void
-DocumentBuilder::begin_path()
-{
-       push_attr();
-       unsigned idx = fPathStorage.start_new_path();
-       fAttributesStorage.add(path_attributes(cur_attr(), idx));
-}
-
-// end_path
-void
-DocumentBuilder::end_path()
-{
-       if (fAttributesStorage.size() == 0) {
-               throw exception("end_path: The path was not begun");
-       }
-       path_attributes attr = cur_attr();
-       unsigned idx = fAttributesStorage[fAttributesStorage.size() - 1].index;
-       attr.index = idx;
-       fAttributesStorage[fAttributesStorage.size() - 1] = attr;
-       pop_attr();
-}
-
-// move_to
-void
-DocumentBuilder::move_to(double x, double y, bool rel)           // M, m
-{
-       if (rel)
-               fPathStorage.move_rel(x, y);
-       else
-               fPathStorage.move_to(x, y);
-}
-
-// line_to
-void
-DocumentBuilder::line_to(double x,  double y, bool rel)                 // L, l
-{
-       if (rel)
-               fPathStorage.line_rel(x, y);
-       else
-               fPathStorage.line_to(x, y);
-}
-
-// hline_to
-void
-DocumentBuilder::hline_to(double x, bool rel)                             // 
H, h
+         fTitle(""),
+         fSource(source)
 {
-       if (rel)
-               fPathStorage.hline_rel(x);
-       else
-               fPathStorage.hline_to(x);
-}
-
-// vline_to
-void
-DocumentBuilder::vline_to(double y, bool rel)                             // 
V, v
-{
-       if (rel)
-               fPathStorage.vline_rel(y);
-       else
-               fPathStorage.vline_to(y);
-}
-
-// curve3
-void
-DocumentBuilder::curve3(double x1, double y1,                             // 
Q, q
-                                               double x,  double y, bool rel)
-{
-       if (rel)
-               fPathStorage.curve3_rel(x1, y1, x, y);
-       else
-               fPathStorage.curve3(x1, y1, x, y);
-}
-
-// curve3
-void
-DocumentBuilder::curve3(double x, double y, bool rel)             // T, t
-{
-       if (rel)
-               fPathStorage.curve3_rel(x, y);
-       else
-               fPathStorage.curve3(x, y);
-}
-
-// curve4
-void
-DocumentBuilder::curve4(double x1, double y1,                             // 
C, c
-                                               double x2, double y2,
-                                               double x,  double y, bool rel)
-{
-       if (rel) {
-               fPathStorage.curve4_rel(x1, y1, x2, y2, x, y);
-       } else {
-               fPathStorage.curve4(x1, y1, x2, y2, x, y);
-       }
-}
-
-// curve4
-void
-DocumentBuilder::curve4(double x2, double y2,                             // 
S, s
-                                               double x,  double y, bool rel)
-{
-       if (rel) {
-               fPathStorage.curve4_rel(x2, y2, x, y);
-       } else {
-               fPathStorage.curve4(x2, y2, x, y);
-       }
-}
-
-// elliptical_arc
-void
-DocumentBuilder::elliptical_arc(double rx, double ry, double angle,
-                                                           bool 
large_arc_flag, bool sweep_flag,
-                                                           double x, double y, 
bool rel)
-{
-       angle = angle / 180.0 * pi;
-       if (rel) {
-               fPathStorage.arc_rel(rx, ry, angle, large_arc_flag, sweep_flag, 
x, y);
-       } else {
-               fPathStorage.arc_to(rx, ry, angle, large_arc_flag, sweep_flag, 
x, y);
-       }
 }
 
-// close_subpath
-void
-DocumentBuilder::close_subpath()
-{
-       fPathStorage.end_poly(path_flags_close);
-}
 
 // SetTitle
 void
@@ -216,244 +59,6 @@ DocumentBuilder::SetDimensions(uint32 width, uint32 
height, BRect viewBox)
        fViewBox = viewBox;
 }
 
-// cur_attr
-path_attributes&
-DocumentBuilder::cur_attr()
-{
-       if (fAttributesStack.size() == 0) {
-               throw exception("cur_attr: Attribute stack is empty");
-       }
-       return fAttributesStack[fAttributesStack.size() - 1];
-}
-
-// push_attr
-void
-DocumentBuilder::push_attr()
-{
-//printf("DocumentBuilder::push_attr() (size: %d)\n", fAttributesStack.size());
-       fAttributesStack.add(fAttributesStack.size() ? 
fAttributesStack[fAttributesStack.size() - 1]
-                                                                               
                 : path_attributes());
-}
-
-// pop_attr
-void
-DocumentBuilder::pop_attr()
-{
-//printf("DocumentBuilder::pop_attr() (size: %d)\n", fAttributesStack.size());
-       if (fAttributesStack.size() == 0) {
-               throw exception("pop_attr: Attribute stack is empty");
-       }
-       fAttributesStack.remove_last();
-}
-
-// fill
-void
-DocumentBuilder::fill(const rgba8& f)
-{
-       path_attributes& attr = cur_attr();
-       attr.fill_color = f;
-       attr.fill_flag = true;
-}
-
-// stroke
-void
-DocumentBuilder::stroke(const rgba8& s)
-{
-       path_attributes& attr = cur_attr();
-       attr.stroke_color = s;
-       attr.stroke_flag = true;
-}
-
-// even_odd
-void
-DocumentBuilder::even_odd(bool flag)
-{
-       cur_attr().even_odd_flag = flag;
-}
-
-// stroke_width
-void
-DocumentBuilder::stroke_width(double w)
-{
-       path_attributes& attr = cur_attr();
-       attr.stroke_width = w;
-       attr.stroke_flag = true;
-}
-
-// fill_none
-void
-DocumentBuilder::fill_none()
-{
-       cur_attr().fill_flag = false;
-}
-
-// fill_url
-void
-DocumentBuilder::fill_url(const char* url)
-{
-       sprintf(cur_attr().fill_url, "%s", url);
-}
-
-// stroke_none
-void
-DocumentBuilder::stroke_none()
-{
-       cur_attr().stroke_flag = false;
-}
-
-// stroke_url
-void
-DocumentBuilder::stroke_url(const char* url)
-{
-       sprintf(cur_attr().stroke_url, "%s", url);
-}
-
-// opacity
-void
-DocumentBuilder::opacity(double op)
-{
-       cur_attr().opacity *= op;
-//printf("opacity: %.1f\n", cur_attr().opacity);
-}
-
-// fill_opacity
-void
-DocumentBuilder::fill_opacity(double op)
-{
-       cur_attr().fill_color.opacity(op);
-//     cur_attr().opacity *= op;
-}
-
-// stroke_opacity
-void
-DocumentBuilder::stroke_opacity(double op)
-{
-       cur_attr().stroke_color.opacity(op);
-//     cur_attr().opacity *= op;
-}
-
-// line_join
-void
-DocumentBuilder::line_join(line_join_e join)
-{
-       cur_attr().line_join = join;
-}
-
-// line_cap
-void
-DocumentBuilder::line_cap(line_cap_e cap)
-{
-       cur_attr().line_cap = cap;
-}
-
-// miter_limit
-void
-DocumentBuilder::miter_limit(double ml)
-{
-       cur_attr().miter_limit = ml;
-}
-
-// transform
-trans_affine&
-DocumentBuilder::transform()
-{
-       return cur_attr().transform;
-}
-
-// parse_path
-void
-DocumentBuilder::parse_path(PathTokenizer& tok)
-{
-       char lastCmd = 0;
-       while(tok.next()) {
-               double arg[10];
-               char cmd = tok.last_command();
-               unsigned i;
-               switch(cmd) {
-                       case 'M': case 'm':
-                               arg[0] = tok.last_number();
-                               arg[1] = tok.next(cmd);
-                               if (lastCmd != cmd)
-                                       move_to(arg[0], arg[1], cmd == 'm');
-                               else
-                                       line_to(arg[0], arg[1], lastCmd == 'm');
-                               break;
-
-                       case 'L': case 'l':
-                               arg[0] = tok.last_number();
-                               arg[1] = tok.next(cmd);
-                               line_to(arg[0], arg[1], cmd == 'l');
-                               break;
-
-                       case 'V': case 'v':
-                               vline_to(tok.last_number(), cmd == 'v');
-                               break;
-
-                       case 'H': case 'h':
-                               hline_to(tok.last_number(), cmd == 'h');
-                               break;
-
-                       case 'Q': case 'q':
-                               arg[0] = tok.last_number();
-                               for(i = 1; i < 4; i++) {
-                                       arg[i] = tok.next(cmd);
-                               }
-                               curve3(arg[0], arg[1], arg[2], arg[3], cmd == 
'q');
-                               break;
-
-                       case 'T': case 't':
-                               arg[0] = tok.last_number();
-                               arg[1] = tok.next(cmd);
-                               curve3(arg[0], arg[1], cmd == 't');
-                               break;
-
-                       case 'C': case 'c':
-                               arg[0] = tok.last_number();
-                               for(i = 1; i < 6; i++) {
-                                       arg[i] = tok.next(cmd);
-                               }
-                               curve4(arg[0], arg[1], arg[2], arg[3], arg[4], 
arg[5], cmd == 'c');
-                               break;
-
-                       case 'S': case 's':
-                               arg[0] = tok.last_number();
-                               for(i = 1; i < 4; i++) {
-                                       arg[i] = tok.next(cmd);
-                               }
-                               curve4(arg[0], arg[1], arg[2], arg[3], cmd == 
's');
-                               break;
-
-                       case 'A': case 'a': {
-                               arg[0] = tok.last_number();
-                               for(i = 1; i < 3; i++) {
-                                       arg[i] = tok.next(cmd);
-                               }
-                               bool large_arc_flag = (bool)tok.next(cmd);
-                               bool sweep_flag = (bool)tok.next(cmd);
-                               for(i = 3; i < 5; i++) {
-                                       arg[i] = tok.next(cmd);
-                               }
-                               elliptical_arc(arg[0], arg[1], arg[2],
-                                                          large_arc_flag, 
sweep_flag,
-                                                          arg[3], arg[4], cmd 
== 'a');
-                               break;
-                       }
-
-                       case 'Z': case 'z':
-                               close_subpath();
-                               break;
-
-                       default:
-                       {
-                               char buf[100];
-                               sprintf(buf, "parse_path: Invalid path command 
'%c'", cmd);
-                               throw exception(buf);
-                       }
-               }
-               lastCmd = cmd;
-       }
-}
-
 // #pragma mark -
 
 // GetIcon
@@ -461,22 +66,10 @@ status_t
 DocumentBuilder::GetIcon(Icon* icon, SVGImporter* importer,
                                                 const char* fallbackName)
 {
-       double xMin;
-       double yMin;
-       double xMax;
-       double yMax;
-
-       int32 pathCount = fAttributesStorage.size();
-
-       agg::conv_transform<agg::path_storage> transformedPaths(
-               fPathStorage, fTransform);
-       agg::bounding_rect(transformedPaths, *this, 0, pathCount,
-                                          &xMin, &yMin, &xMax, &yMax);
-
-       xMin = floor(xMin);
-       yMin = floor(yMin);
-       xMax = ceil(xMax);
-       yMax = ceil(yMax);
+       double xMin = 0;
+       double yMin = 0;
+       double xMax = ceil(fSource->width);
+       double yMax = ceil(fSource->height);
 
        BRect bounds;
        if (fViewBox.IsValid()) {
@@ -497,7 +90,7 @@ printf("using bounding box: ");
 bounds.PrintToStream();
        }
 
-       float size = min_c(bounds.Width() + 1.0, bounds.Height() + 1.0);
+       float size = max_c(bounds.Width(), bounds.Height());
        double scale = 64.0 / size;
 printf("scale: %f\n", scale);
 
@@ -510,15 +103,11 @@ printf("scale: %f\n", scale);
 //     else
 //             icon->SetName(fallbackName);
 
-       for (int32 i = 0; i < pathCount; i++) {
-
-               path_attributes& attributes = fAttributesStorage[i];
-
-               if (attributes.fill_flag)
-                       _AddShape(attributes, false, transform, icon);
-
-               if (attributes.stroke_flag)
-                       _AddShape(attributes, true, transform, icon);
+       for (NSVGshape* shape = fSource->shapes; shape != NULL; shape = 
shape->next) {
+               if (shape->fill.type != NSVG_PAINT_NONE)
+                       _AddShape(shape, false, transform, icon);
+               if (shape->stroke.type != NSVG_PAINT_NONE)
+                       _AddShape(shape, true, transform, icon);
        }
 
        // clean up styles and paths (remove duplicates)
@@ -543,218 +132,67 @@ printf("scale: %f\n", scale);
        return B_OK;
 }
 
-// StartGradient
-void
-DocumentBuilder::StartGradient(bool radial)
-{
-       if (fCurrentGradient) {
-               fprintf(stderr, "DocumentBuilder::StartGradient() - ERROR: "
-                                               "previous gradient (%s) not 
finished!\n",
-                                               fCurrentGradient->ID());
-       }
-
-       if (radial)
-               fCurrentGradient = new SVGRadialGradient();
-       else
-               fCurrentGradient = new SVGLinearGradient();
-
-       _AddGradient(fCurrentGradient);
-}
-
-// EndGradient
-void
-DocumentBuilder::EndGradient()
-{
-       if (fCurrentGradient) {
-//             fCurrentGradient->PrintToStream();
-       } else {
-               fprintf(stderr, "DocumentBuilder::EndGradient() - "
-                               "ERROR: no gradient started!\n");
-       }
-       fCurrentGradient = NULL;
-}
-
-// #pragma mark -
-
-// _AddGradient
-void
-DocumentBuilder::_AddGradient(SVGGradient* gradient)
-{
-       if (gradient) {
-               fGradients.AddItem((void*)gradient);
-       }
-}
-
-// _GradientAt
-SVGGradient*
-DocumentBuilder::_GradientAt(int32 index) const
-{
-       return (SVGGradient*)fGradients.ItemAt(index);
-}
-
-// _FindGradient
-SVGGradient*
-DocumentBuilder::_FindGradient(const char* name) const
-{
-       for (int32 i = 0; SVGGradient* g = _GradientAt(i); i++) {
-               if (strcmp(g->ID(), name) == 0)
-                       return g;
-       }
-       return NULL;
-}
-
 
 // AddVertexSource
-template<class VertexSource>
 status_t
-AddPathsFromVertexSource(Icon* icon, Shape* shape,
-                                                VertexSource& source, int32 
index)
+AddPathsFromVertexSource(Icon* icon, Shape* shape, NSVGshape* svgShape)
 {
 //printf("AddPathsFromVertexSource(pathID = %ld)\n", index);
 
-       // start with the first path
-       VectorPath* path = new (nothrow) VectorPath();
-       if (!path || !icon->Paths()->AddPath(path)) {
-               delete path;
-               return B_NO_MEMORY;
-       }
-
-       if (!shape->Paths()->AddPath(path))
-               return B_NO_MEMORY;
-
-       source.rewind(index);
-       double x1 = 0, y1 = 0;
-       unsigned cmd = source.vertex(&x1, &y1);
-       bool keepGoing = true;
-       int32 subPath = 0;
-       while (keepGoing) {
-               if (agg::is_next_poly(cmd)) {
-//printf("next polygon\n");
-                       if (agg::is_end_poly(cmd)) {
-//printf("  end polygon\n");
-                               path->SetClosed(true);
-                               subPath++;
-                       } else {
-//printf("  not end polygon\n");
-                       }
-
-                       if (agg::is_stop(cmd)) {
-//printf("  stop = true\n");
-                               keepGoing = false;
-                       } else {
-                               if (subPath > 0) {
-//printf("  new subpath\n");
-                                       path->CleanUp();
-                                       if (path->CountPoints() == 0) {
-//printf("  path with no points!\n");
-                                               icon->Paths()->RemovePath(path);
-                                               
shape->Paths()->RemovePath(path);
-                                               path->ReleaseReference();
-                                       }
-                                       path = new (nothrow) VectorPath();
-                                       if (!path || 
!icon->Paths()->AddPath(path)) {
-                                               delete path;
-                                               return B_NO_MEMORY;
-                                       }
-                                       if (!shape->Paths()->AddPath(path))
-                                               return B_NO_MEMORY;
-                               }
-                       }
+       for (NSVGpath* svgPath = svgShape->paths; svgPath != NULL;
+               svgPath = svgPath->next) {
+               VectorPath* path = new (nothrow) VectorPath();
+               if (!path || !icon->Paths()->AddPath(path)) {
+                       delete path;
+                       return B_NO_MEMORY;
                }
-               switch (cmd) {
-                       case agg::path_cmd_move_to:
-//printf("move to (%.2f, %.2f) (subPath: %ld)\n", x1, y1, subPath);
-                               if (path->CountPoints() > 0) {
-                                       // cannot MoveTo on a path that has 
already points!
-                                       path->CleanUp();
-                                       path = new (nothrow) VectorPath();
-                                       if (!path || 
!icon->Paths()->AddPath(path)) {
-                                               delete path;
-                                               return B_NO_MEMORY;
-                                       }
-                                       if (!shape->Paths()->AddPath(path))
-                                               return B_NO_MEMORY;
-                               }
-                               if (!path->AddPoint(BPoint(x1, y1)))
-                                       return B_NO_MEMORY;
-                               path->SetInOutConnected(path->CountPoints() - 
1, false);
-                               break;
-
-                       case agg::path_cmd_line_to:
-//printf("line to (%.2f, %.2f) (subPath: %ld)\n", x1, y1, subPath);
-                               if (!path->AddPoint(BPoint(x1, y1)))
-                                       return B_NO_MEMORY;
-                               path->SetInOutConnected(path->CountPoints() - 
1, false);
-                               break;
 
-                       case agg::path_cmd_curve3: {
-                               double x2 = 0, y2 = 0;
-                               cmd = source.vertex(&x2, &y2);
-//printf("curve3 (%.2f, %.2f)\n", x1, y1);
-//printf("        (%.2f, %.2f)\n", x2, y2);
+               if (!shape->Paths()->AddPath(path))
+                       return B_NO_MEMORY;
 
-                               // convert to curve4 for easier editing
-                               int32 start = path->CountPoints() - 1;
-                               BPoint from;
-                               path->GetPointAt(start, from);
+               path->SetClosed(svgPath->closed);
 
-                               double cx2 = (1.0/3.0) * from.x + (2.0/3.0) * 
x1;
-                               double cy2 = (1.0/3.0) * from.y + (2.0/3.0) * 
y1;
-                               double cx3 = (2.0/3.0) * x1 + (1.0/3.0) * x2;
-                               double cy3 = (2.0/3.0) * y1 + (1.0/3.0) * y2;
+               int pointCount = svgPath->npts;
+               float* points = svgPath->pts;
 
-                               path->SetPointOut(start, BPoint(cx2, cy2));
+               // First entry in the points list is always a "move" to the path
+               // starting point
+               if (!path->AddPoint(BPoint(points[0], points[1])))
+                       return B_NO_MEMORY;
+               path->SetInOutConnected(path->CountPoints() - 1, false);
 
-                               if (!path->AddPoint(BPoint(x2, y2)))
-                                       return B_NO_MEMORY;
+               pointCount--;
+               points += 2;
 
-                               int32 end = path->CountPoints() - 1;
-                               path->SetInOutConnected(end, false);
-                               path->SetPointIn(end, BPoint(cx3, cy3));
-                               break;
-                       }
+               while (pointCount > 0) {
+                       BPoint vector1(points[0], points[1]);
+                       BPoint vector2(points[2], points[3]);
+                       BPoint endPoint(points[4], points[5]);
 
-                       case agg::path_cmd_curve4: {
-                               double x2 = 0, y2 = 0;
-                               double x3 = 0, y3 = 0;
-                               cmd = source.vertex(&x2, &y2);
-                               cmd = source.vertex(&x3, &y3);
+                       if (!path->AddPoint(endPoint))
+                               return B_NO_MEMORY;
 
-                               if (!path->AddPoint(BPoint(x3, y3)))
-                                       return B_NO_MEMORY;
+                       int32 start = path->CountPoints() - 2;
+                       int32 end = path->CountPoints() - 1;
 
-                               int32 start = path->CountPoints() - 2;
-                               int32 end = path->CountPoints() - 1;
+                       path->SetInOutConnected(end, false);
+                       path->SetPointOut(start, vector1);
+                       path->SetPointIn(end, vector2);
 
-//printf("curve4 [%ld] (%.2f, %.2f) -> [%ld] (%.2f, %.2f) -> (%.2f, %.2f)\n", 
start, x1, y1, end, x2, y2, x3, y3);
-
-                               path->SetInOutConnected(end, false);
-                               path->SetPointOut(start, BPoint(x1, y1));
-                               path->SetPointIn(end, BPoint(x2, y2));
-                               break;
-                       }
-                       default:
-//printf("unkown command\n");
-                               break;
+                       pointCount -= 3;
+                       points += 6;
                }
-               cmd = source.vertex(&x1, &y1);
-       }
-//path->PrintToStream();
-       path->CleanUp();
-       if (path->CountPoints() == 0) {
-//printf("path with no points!\n");
-               icon->Paths()->RemovePath(path);
-               shape->Paths()->RemovePath(path);
-               path->ReleaseReference();
        }
 
+       // FIXME handle closed vs open paths
+
        return B_OK;
 }
 
 
 // _AddShape
 status_t
-DocumentBuilder::_AddShape(path_attributes& attributes, bool outline,
+DocumentBuilder::_AddShape(NSVGshape* svgShape, bool outline,
                                                   const Transformable& 
transform, Icon* icon)
 {
        Shape* shape = new (nothrow) Shape(NULL);
@@ -763,20 +201,43 @@ DocumentBuilder::_AddShape(path_attributes& attributes, 
bool outline,
                return B_NO_MEMORY;
        }
 
-       if (AddPathsFromVertexSource(icon, shape, fPathStorage, 
attributes.index) < B_OK)
+       if (AddPathsFromVertexSource(icon, shape, svgShape) < B_OK)
                printf("failed to convert from vertex source\n");
 
-       shape->multiply(attributes.transform);
+       shape->SetName(svgShape->id);
        shape->Multiply(transform);
 
        StrokeTransformer* stroke = NULL;
+       NSVGpaint* paint = NULL;
        if (outline) {
                stroke = new (nothrow) StrokeTransformer(shape->VertexSource());
+               paint = &svgShape->stroke;
 
                if (stroke) {
-                       stroke->width(attributes.stroke_width);
-                       stroke->line_cap(attributes.line_cap);
-                       stroke->line_join(attributes.line_join);
+                       stroke->width(svgShape->strokeWidth);
+                       switch(svgShape->strokeLineCap) {
+                               case NSVG_CAP_BUTT:
+                                       stroke->line_cap(agg::butt_cap);
+                                       break;
+                               case NSVG_CAP_ROUND:
+                                       stroke->line_cap(agg::round_cap);
+                                       break;
+                               case NSVG_CAP_SQUARE:
+                                       stroke->line_cap(agg::square_cap);
+                                       break;
+                       }
+
+                       switch(svgShape->strokeLineJoin) {
+                               case NSVG_JOIN_MITER:
+                                       stroke->line_join(agg::miter_join);
+                                       break;
+                               case NSVG_JOIN_ROUND:
+                                       stroke->line_join(agg::round_join);
+                                       break;
+                               case NSVG_JOIN_BEVEL:
+                                       stroke->line_join(agg::bevel_join);
+                                       break;
+                       }
                }
 
                if (!shape->AddTransformer(stroke)) {
@@ -784,45 +245,83 @@ DocumentBuilder::_AddShape(path_attributes& attributes, 
bool outline,
                        stroke = NULL;
                }
        } else {
-//             if (attributes.even_odd_flag)
-//                     shape->SetFillingRule(FILL_MODE_EVEN_ODD);
-//             else
-//                     shape->SetFillingRule(FILL_MODE_NON_ZERO);
+               paint = &svgShape->fill;
+#if 0 // FIXME filling rule are missing from Shape class
+               if (svgShape->fillRule == NSVG_FILLRULE_EVENODD)
+                       shape->SetFillingRule(FILL_MODE_EVEN_ODD);
+               else
+                       shape->SetFillingRule(FILL_MODE_NON_ZERO);
+#endif
        }
 
-
-       Gradient* gradient = NULL;
-       SVGGradient* g = NULL;
-       const char* url = outline ? attributes.stroke_url : attributes.fill_url;
-       if (url[0] != 0) {
-               g = _FindGradient(url);
-               if (g != NULL)
-                       gradient = g->GetGradient(shape->Bounds());
+       Gradient gradient(true);
+       rgb_color color;
+       switch(paint->type) {
+               case NSVG_PAINT_COLOR:
+                       color.red = paint->color & 0xFF;
+                       color.green = (paint->color >> 8) & 0xFF;
+                       color.blue = (paint->color >> 16) & 0xFF;
+                       color.alpha = (paint->color >> 24) & 0xFF;
+                       break;
+               case NSVG_PAINT_LINEAR_GRADIENT:
+               {
+                       gradient.SetType(GRADIENT_LINEAR);
+                       // The base gradient axis in Icon-O-Matic is a 
horizontal line from
+                       // (-64, 0) to (64, 0). The base gradient axis used by 
nanosvg is
+                       // a vertical line from (0, 0) to (0, 1). This initial 
transform
+                       // converts from one space to the other.
+                       agg::trans_affine baseTransform(0, 1.0/128.0, 
-1.0/128.0, 0,
+                               -0.5, 0.5);
+                       gradient.multiply(baseTransform);
+                       break;
+               }
+               case NSVG_PAINT_RADIAL_GRADIENT:
+               {
+                       gradient.SetType(GRADIENT_CIRCULAR);
+                       agg::trans_affine baseTransform(0, 1.0/64.0, -1.0/64.0, 
0,
+                               0, 0);
+                       gradient.multiply(baseTransform);
+                       break;
+               }
        }
 
-       ObjectDeleter<Gradient> gradientDeleter(gradient);
-
-       rgb_color color;
+       if (paint->type != NSVG_PAINT_COLOR) {
+               gradient.SetInterpolation(INTERPOLATION_LINEAR);
+               agg::trans_affine gradientTransform(
+                       paint->gradient->xform[0], paint->gradient->xform[1],
+                       paint->gradient->xform[2], paint->gradient->xform[3],
+                       paint->gradient->xform[4], paint->gradient->xform[5]
+               );
+
+               // The transform from nanosvg converts a screen space 
coordinate into
+               // a gradient offset. It is the inverse of what we need at this 
stage,
+               // so we just invert it and multiply our base transform with it.
+               gradient.multiply_inv(gradientTransform);
+
+               // Finally, scale the gradient according to the global scaling 
to fit
+               // the 64x64 box we work in.
+               gradient.Multiply(*shape);
+
+               for (int i = 0; i < paint->gradient->nstops; i++) {
+                       rgb_color stopColor;
+                       stopColor.red = paint->gradient->stops[i].color & 0xFF;
+                       stopColor.green = (paint->gradient->stops[i].color >> 
8) & 0xFF;
+                       stopColor.blue = (paint->gradient->stops[i].color >> 
16) & 0xFF;
+                       stopColor.alpha = (paint->gradient->stops[i].color >> 
24) & 0xFF;
+                       gradient.AddColor(stopColor, 
paint->gradient->stops[i].offset);
+               }
 
-       BGradient::ColorStop* step;
-       if (gradient && (step = gradient->ColorAt(0))) {
-               color.red               = step->color.red;
-               color.green             = step->color.green;
-               color.blue              = step->color.blue;
-       } else {
-               if (outline) {
-                       color.red       = attributes.stroke_color.r;
-                       color.green     = attributes.stroke_color.g;
-                       color.blue      = attributes.stroke_color.b;
-                       color.alpha = (uint8)(attributes.stroke_color.a * 
attributes.opacity);
-               } else {
-                       color.red       = attributes.fill_color.r;
-                       color.green     = attributes.fill_color.g;
-                       color.blue      = attributes.fill_color.b;
-                       color.alpha = (uint8)(attributes.fill_color.a * 
attributes.opacity);
+               BGradient::ColorStop* step = gradient.ColorAt(0);
+               if (step) {
+                       color.red               = step->color.red;
+                       color.green             = step->color.green;
+                       color.blue              = step->color.blue;
+                       color.alpha             = step->color.alpha;
                }
        }
 
+       color.alpha = (uint8)(color.alpha * svgShape->opacity);
+
        Style* style = new (nothrow) Style(color);
        if (!style || !icon->Styles()->AddStyle(style)) {
                delete style;
@@ -831,31 +330,22 @@ DocumentBuilder::_AddShape(path_attributes& attributes, 
bool outline,
 
        // NOTE: quick hack to freeze all transformations (only works because
        // paths and styles are not used by multiple shapes!!)
-//     if (modifiers() & B_COMMAND_KEY) {
-               int32 pathCount = shape->Paths()->CountPaths();
-               for (int32 i = 0; i < pathCount; i++) {
-                       VectorPath* path = shape->Paths()->PathAtFast(i);
-                       path->ApplyTransform(*shape);
-               }
-               if (gradient)
-                       gradient->Multiply(*shape);
+       int32 pathCount = shape->Paths()->CountPaths();
+       for (int32 i = 0; i < pathCount; i++) {
+               VectorPath* path = shape->Paths()->PathAtFast(i);
+               path->ApplyTransform(*shape);
+       }
 
-               if (stroke)
-                       stroke->width(stroke->width() * shape->scale());
+       if (stroke)
+               stroke->width(stroke->width() * shape->scale());
 
-               shape->Reset();
-//     }
+       if (paint->type != NSVG_PAINT_COLOR)
+               style->SetGradient(&gradient);
 
-       if (gradient) {
-               style->SetGradient(gradient);
-               style->SetName(g->ID());
-       }
+       shape->Reset();
 
        shape->SetStyle(style);
 
        return B_OK;
 }
 
-} // namespace svg
-} // namespace agg
-
diff --git a/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.h 
b/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.h
index 6874f611e1..55760e6897 100644
--- a/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.h
+++ b/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.h
@@ -6,41 +6,17 @@
  *             Stephan Aßmus <superstippi@xxxxxx>
  */
 
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.2
-// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@xxxxxxxxxxxxx
-//               mcseemagg@xxxxxxxxx
-//               http://www.antigrain.com
-//----------------------------------------------------------------------------
 
 #ifndef DOCUMENT_BUILD_H
 #define DOCUMENT_BUILD_H
 
 #include <stdio.h>
 
-#include <List.h>
 #include <Rect.h>
 #include <String.h>
 
-#include <agg_array.h>
-#include <agg_color_rgba.h>
-#include <agg_conv_transform.h>
-#include <agg_conv_stroke.h>
-#include <agg_conv_contour.h>
-#include <agg_conv_curve.h>
-#include <agg_path_storage.h>
-#include <agg_rasterizer_scanline_aa.h>
-
 #include "IconBuild.h"
-#include "PathTokenizer.h"
+#include "nanosvg.h"
 
 
 class SVGImporter;
@@ -52,207 +28,33 @@ _END_ICON_NAMESPACE
 
 _USING_ICON_NAMESPACE
 
-namespace agg {
-namespace svg {
-
-class SVGGradient;
-
-// Basic path attributes
-struct path_attributes {
-
-       unsigned                index;
-       rgba8                   fill_color;
-       rgba8                   stroke_color;
-       double                  opacity;
-       bool                    fill_flag;
-       bool                    stroke_flag;
-       bool                    even_odd_flag;
-       line_join_e             line_join;
-       line_cap_e              line_cap;
-       double                  miter_limit;
-       double                  stroke_width;
-       trans_affine    transform;
-
-       char                    stroke_url[64];
-       char                    fill_url[64];
-
-       // Empty constructor
-       path_attributes() :
-               index                   (0),
-               fill_color              (rgba(0,0,0)),
-               stroke_color    (rgba(0,0,0)),
-               opacity                 (1.0),
-               fill_flag               (true),
-               stroke_flag             (false),
-               even_odd_flag   (false),
-               line_join               (miter_join),
-               line_cap                (butt_cap),
-               miter_limit             (4.0),
-               stroke_width    (1.0),
-               transform               ()
-       {
-               stroke_url[0] = 0;
-               fill_url[0] = 0;
-       }
-
-       // Copy constructor
-       path_attributes(const path_attributes& attr) :
-               index                   (attr.index),
-               fill_color              (attr.fill_color),
-               stroke_color    (attr.stroke_color),
-               opacity                 (attr.opacity),
-               fill_flag               (attr.fill_flag),
-               stroke_flag             (attr.stroke_flag),
-               even_odd_flag   (attr.even_odd_flag),
-               line_join               (attr.line_join),
-               line_cap                (attr.line_cap),
-               miter_limit             (attr.miter_limit),
-               stroke_width    (attr.stroke_width),
-               transform               (attr.transform)
-       {
-               sprintf(stroke_url, "%s", attr.stroke_url);
-               sprintf(fill_url, "%s", attr.fill_url);
-       }
-
-       // Copy constructor with new index value
-       path_attributes(const path_attributes& attr, unsigned idx) :
-               index                   (idx),
-               fill_color              (attr.fill_color),
-               stroke_color    (attr.stroke_color),
-               fill_flag               (attr.fill_flag),
-               stroke_flag             (attr.stroke_flag),
-               even_odd_flag   (attr.even_odd_flag),
-               line_join               (attr.line_join),
-               line_cap                (attr.line_cap),
-               miter_limit             (attr.miter_limit),
-               stroke_width    (attr.stroke_width),
-               transform               (attr.transform)
-       {
-               sprintf(stroke_url, "%s", attr.stroke_url);
-               sprintf(fill_url, "%s", attr.fill_url);
-       }
-};
 
 class DocumentBuilder {
  public:
 
-       typedef pod_bvector<path_attributes>            attr_storage;
-
-                                                               
DocumentBuilder();
-
-                       void                            remove_all();
-
-       // Use these functions as follows:
-       // begin_path() when the XML tag <path> comes ("start_element" handler)
-       // parse_path() on "d=" tag attribute
-       // end_path() when parsing of the entire tag is done.
-                       void                            begin_path();
-                       void                            
parse_path(PathTokenizer& tok);
-                       void                            end_path();
-
-       // The following functions are essentially a "reflection" of
-       // the respective SVG path commands.
-                       void                            move_to(double x, 
double y, bool rel = false);  // M, m
-                       void                            line_to(double x,  
double y, bool rel = false); // L, l
-                       void                            hline_to(double x, bool 
rel = false);                   // H, h
-                       void                            vline_to(double y, bool 
rel = false);                   // V, v
-                       void                            curve3(double x1, 
double y1,                                    // Q, q
-                                                                          
double x,  double y, bool rel = false);
-                       void                            curve3(double x, double 
y, bool rel = false);   // T, t
-                       void                            curve4(double x1, 
double y1,                                    // C, c
-                                                                          
double x2, double y2,
-                                                                          
double x,  double y, bool rel = false);
-                       void                            curve4(double x2, 
double y2,                                    // S, s
-                                                                          
double x,  double y, bool rel = false);
-                       void                            elliptical_arc(double 
rx, double ry,
-                                                                               
           double angle,
-                                                                               
           bool large_arc_flag,
-                                                                               
           bool sweep_flag,
-                                                                               
           double x, double y,
-                                                                               
           bool rel = false);                           // A, a
-                       void                            close_subpath();        
                                                        // Z, z
-
-/*                     template<class VertexSource>
-                       void                            add_path(VertexSource& 
vs,
-                                                                               
 unsigned path_id = 0,
-                                                                               
 bool solid_path = true)
-                                                               {
-                                                                       
fPathStorage.add_path(vs, path_id, solid_path);
-                                                               }*/
+                                                               
DocumentBuilder(NSVGimage* image);
 
                        void                            SetTitle(const char* 
title);
                        void                            SetDimensions(uint32 
width, uint32 height, BRect viewBox);
 
 
-                       // Call these functions on <g> tag (start_element, 
end_element respectively)
-                       void                            push_attr();
-                       void                            pop_attr();
-
-                       // Attribute setting functions.
-                       void                            fill(const rgba8& f);
-                       void                            stroke(const rgba8& s);
-                       void                            even_odd(bool flag);
-                       void                            stroke_width(double w);
-                       void                            fill_none();
-                       void                            fill_url(const char* 
url);
-                       void                            stroke_none();
-                       void                            stroke_url(const char* 
url);
-                       void                            opacity(double op);
-                       void                            fill_opacity(double op);
-                       void                            stroke_opacity(double 
op);
-                       void                            line_join(line_join_e 
join);
-                       void                            line_cap(line_cap_e 
cap);
-                       void                            miter_limit(double ml);
-                       trans_affine&           transform();
-
-/*                     // Make all polygons CCW-oriented
-                       void                            arrange_orientations()
-                       {
-                               
fPathStorage.arrange_orientations_all_paths(path_flags_ccw);
-                       }*/
-
-                       unsigned                        operator [](unsigned 
idx)
-               {
-                   fTransform = fAttributesStorage[idx].transform;
-                   return fAttributesStorage[idx].index;
-               }
-
                        status_t                        GetIcon(Icon* icon,
                                                                                
SVGImporter* importer,
                                                                                
const char* fallbackName);
 
-                       void                            StartGradient(bool 
radial = false);
-                       void                            EndGradient();
-                       SVGGradient*            CurrentGradient() const
-                                                                       { 
return fCurrentGradient; }
-
  private:
-                       void                            
_AddGradient(SVGGradient* gradient);
-                       SVGGradient*            _GradientAt(int32 index) const;
-                       SVGGradient*            _FindGradient(const char* name) 
const;
-                       status_t                        
_AddShape(path_attributes& attributes,
+                       status_t                        _AddShape(NSVGshape* 
svgShape,
                                                                                
  bool outline,
                                                                                
  const Transformable& transform,
                                                                                
  Icon* icon);
 
-                       path_attributes&        cur_attr();
-
-                       path_storage            fPathStorage;
-                       attr_storage            fAttributesStorage;
-                       attr_storage            fAttributesStack;
-
-                       trans_affine            fTransform;
-
-                       BList                           fGradients;
-                       SVGGradient*            fCurrentGradient;
 
                        uint32                          fWidth;
                        uint32                          fHeight;
                        BRect                           fViewBox;
                        BString                         fTitle;
-};
 
-} // namespace svg
-} // namespace agg
+                       NSVGimage*                      fSource;
+};
 
 #endif // DOCUMENT_BUILD_H
diff --git a/src/apps/icon-o-matic/import_export/svg/PathTokenizer.cpp 
b/src/apps/icon-o-matic/import_export/svg/PathTokenizer.cpp
deleted file mode 100644
index 38999ad933..0000000000
--- a/src/apps/icon-o-matic/import_export/svg/PathTokenizer.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright 2006, Haiku. All rights reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *             Stephan Aßmus <superstippi@xxxxxx>
- */
-
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.2
-// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Permission to copy, use, modify, sell and distribute this software 
-// is granted provided this copyright notice appears in all copies. 
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@xxxxxxxxxxxxx
-//               mcseemagg@xxxxxxxxx
-//               http://www.antigrain.com
-
-#include "PathTokenizer.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-
-namespace agg {        
-namespace svg {
-
-// globals
-const char PathTokenizer::sCommands[]   = "+-MmZzLlHhVvCcSsQqTtAaFfPp";
-const char PathTokenizer::sNumeric[]   = ".Ee0123456789";
-const char PathTokenizer::sSeparators[] = " ,\t\n\r";
-
-// constructor
-PathTokenizer::PathTokenizer()
-       : fPath(0),
-         fLastNumber(0.0),
-         fLastCommand(0)
-{
-       init_char_mask(fCommandsMask,   sCommands);
-       init_char_mask(fNumericMask,    sNumeric);
-       init_char_mask(fSeparatorsMask, sSeparators);
-}
-
-// set_path_str
-void
-PathTokenizer::set_path_str(const char* str)
-{
-       fPath = str;
-       fLastCommand = 0;
-       fLastNumber = 0.0;
-}
-
-// next
-bool
-PathTokenizer::next()
-{
-       if(fPath == 0) return false;
-
-       // Skip all white spaces and other garbage
-       while (*fPath && !is_command(*fPath) && !isNumeric(*fPath))  {
-               if (!is_separator(*fPath)) {
-                       char buf[100];
-                       sprintf(buf, "PathTokenizer::next : Invalid Character 
%c", *fPath);
-                       throw exception(buf);
-               }
-               fPath++;
-       }
-
-       if (*fPath == 0) return false;
-
-       if (is_command(*fPath)) {
-               // Check if the command is a numeric sign character
-               if(*fPath == '-' || *fPath == '+')
-               {
-                       return parse_number();
-               }
-               fLastCommand = *fPath++;
-               while(*fPath && is_separator(*fPath)) fPath++;
-               if(*fPath == 0) return true;
-       }
-       return parse_number();
-}
-
-// next
-double
-PathTokenizer::next(char cmd)
-{
-       if (!next()) throw exception("parse_path: Unexpected end of path");
-       if (last_command() != cmd) {
-               char buf[100];
-               sprintf(buf, "parse_path: Command %c: bad or missing 
parameters", cmd);
-               throw exception(buf);
-       }
-       return last_number();
-}
-
-// init_char_mask
-void
-PathTokenizer::init_char_mask(char* mask, const char* char_set)
-{
-       memset(mask, 0, 256/8);
-       while (*char_set) {
-               unsigned c = unsigned(*char_set++) & 0xFF;
-               mask[c >> 3] |= 1 << (c & 7);
-       }
-}
-
-// contains
-inline bool
-PathTokenizer::contains(const char* mask, unsigned c) const
-{
-       return (mask[(c >> 3) & (256 / 8 - 1)] & (1 << (c & 7))) != 0;
-}
-
-// is_command
-inline bool
-PathTokenizer::is_command(unsigned c) const
-{
-       return contains(fCommandsMask, c);
-}
-
-// isNumeric
-inline bool
-PathTokenizer::isNumeric(unsigned c) const
-{
-       return contains(fNumericMask, c);
-}
-
-// is_separator
-inline bool
-PathTokenizer::is_separator(unsigned c) const
-{
-       return contains(fSeparatorsMask, c);
-}
-
-// parse_number
-bool
-PathTokenizer::parse_number()
-{
-       char* end;
-       fLastNumber = strtod(fPath, &end);
-       fPath = end;
-       return true;
-}
-
-
-} //namespace svg
-} //namespace agg
-
-
-
-
diff --git a/src/apps/icon-o-matic/import_export/svg/PathTokenizer.h 
b/src/apps/icon-o-matic/import_export/svg/PathTokenizer.h
deleted file mode 100644
index 4cde3b87ae..0000000000
--- a/src/apps/icon-o-matic/import_export/svg/PathTokenizer.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2006, Haiku. All rights reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *             Stephan Aßmus <superstippi@xxxxxx>
- */
-
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.2
-// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Permission to copy, use, modify, sell and distribute this software 
-// is granted provided this copyright notice appears in all copies. 
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@xxxxxxxxxxxxx
-//               mcseemagg@xxxxxxxxx
-//               http://www.antigrain.com
-//----------------------------------------------------------------------------
-
-#ifndef PATH_TOKENIZER_H
-#define PATH_TOKENIZER_H
-
-#include "SVGException.h"
-
-namespace agg { 
-namespace svg {
-       // SVG path tokenizer. 
-       // Example:
-       //
-       // agg::svg::PathTokenizer tok;
-       //
-       // tok.set_str("M-122.304 84.285L-122.304 84.285 122.203 86.179 ");
-       // while(tok.next())
-       // {
-       //       printf("command='%c' number=%f\n", 
-       //                       tok.last_command(), 
-       //                       tok.last_number());
-       // }
-       //
-       // The tokenizer does all the routine job of parsing the SVG paths.
-       // It doesn't recognize any graphical primitives, it even doesn't know
-       // anything about pairs of coordinates (X,Y). The purpose of this class 
-       // is to tokenize the numeric values and commands. SVG paths can 
-       // have single numeric values for Horizontal or Vertical line_to 
commands 
-       // as well as more than two coordinates (4 or 6) for Bezier curves 
-       // depending on the semantics of the command.
-       // The behaviour is as follows:
-       //
-       // Each call to next() returns true if there's new command or new 
numeric
-       // value or false when the path ends. How to interpret the result
-       // depends on the sematics of the command. For example, command "C" 
-       // (cubic Bezier curve) implies 6 floating point numbers preceded by 
this 
-       // command. If the command assumes no arguments (like z or Z) the 
-       // the last_number() values won't change, that is, last_number() always
-       // returns the last recognized numeric value, so does last_command().
-
-class PathTokenizer {
- public:
-                                                               PathTokenizer();
-
-                       void                            set_path_str(const 
char* str);
-                       bool                            next();
-
-                       double                          next(char cmd);
-               
-                       char                            last_command() const
-                                                                       { 
return fLastCommand; }
-                       double                          last_number() const
-                                                                       { 
return fLastNumber; }
-
-
- private:
-       static  void                            init_char_mask(char* mask,
-                                                                               
           const char* char_set);
-
-       inline  bool                            contains(const char* mask, 
unsigned c) const;
-       inline  bool                            is_command(unsigned c) const;
-       inline  bool                            isNumeric(unsigned c) const;
-       inline  bool                            is_separator(unsigned c) const;
-
-                       bool                            parse_number();
-
-                       char                            fSeparatorsMask[256 / 
8];
-                       char                            fCommandsMask[256 / 8];
-                       char                            fNumericMask[256 / 8];
-               
-                       const char*                     fPath;
-                       double                          fLastNumber;
-                       char                            fLastCommand;
-               
-       static  const char                      sCommands[];
-       static  const char                      sNumeric[];
-       static  const char                      sSeparators[];
-};
-
-
-
-} //namespace svg
-} //namespace agg
-
-
-#endif // PATH_TOKENIZER_H
diff --git a/src/apps/icon-o-matic/import_export/svg/SVGGradients.cpp 
b/src/apps/icon-o-matic/import_export/svg/SVGGradients.cpp
deleted file mode 100644
index 43a9509480..0000000000
--- a/src/apps/icon-o-matic/import_export/svg/SVGGradients.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2006, Haiku. All rights reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *             Stephan Aßmus <superstippi@xxxxxx>
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "GradientTransformable.h"
-
-#include "SVGGradients.h"
-
-namespace agg {
-namespace svg {
-
-// constructor
-SVGGradient::SVGGradient()
-       : BMessage(),
-         fGradient(NULL),
-         fID(""),
-         fGradientUnits(UNSPECIFIED)
-{
-}
-
-// destructor
-SVGGradient::~SVGGradient()
-{
-}
-
-// SetID
-void
-SVGGradient::SetID(const char* id)
-{
-       fID = id;
-}
-
-// ID
-const char*
-SVGGradient::ID() const
-{
-       return fID.String();
-}
-
-// AddStop
-void
-SVGGradient::AddStop(float offset, rgba8 color)
-{
-       if (!fGradient)
-               fGradient = MakeGradient();
-
-       rgb_color c = { color.r, color.g, color.b, color.a };
-       fGradient->AddColor(c, offset);
-}
-
-// SetTransformation
-void
-SVGGradient::SetTransformation(const trans_affine& transform)
-{
-//printf("SVGGradient::SetTransformation()\n");
-       if (!fGradient)
-               fGradient = MakeGradient();
-
-       fGradient->multiply(transform);
-}
-
-// GetGradient
-Gradient*
-SVGGradient::GetGradient(BRect objectBounds)
-{
-       if (fGradient) {
-               Gradient* gradient = new Gradient(*fGradient);
-
-               IdentifyGradientUnits();
-               if (fGradientUnits == OBJECT_BOUNDING_BOX) {
-                       gradient->FitToBounds(objectBounds);
-               }
-
-               return gradient;
-       }
-       return NULL;
-}
-
-// IdentifyGradientUnits
-void
-SVGGradient::IdentifyGradientUnits()
-{
-       if (fGradientUnits == UNSPECIFIED) {
-               const char* units;
-               if (FindString("gradientUnits", &units) >= B_OK) {
-                       if (strcmp(units, "objectBoundingBox") == 0)
-                               fGradientUnits = OBJECT_BOUNDING_BOX;
-               }
-       }
-}
-
-// constructor
-SVGLinearGradient::SVGLinearGradient()
-       : SVGGradient()
-{
-}
-
-// destructor
-SVGLinearGradient::~SVGLinearGradient()
-{
-}
-
-// MakeGradient
-Gradient*
-SVGLinearGradient::MakeGradient() const
-{
-//printf("SVGLinearGradient::MakeGradient()\n");
-//PrintToStream();
-
-       Gradient* gradient = new Gradient(true);
-       gradient->SetType(GRADIENT_LINEAR);
-       gradient->SetInterpolation(INTERPOLATION_LINEAR);
-       // setup the gradient transform 
-       BPoint start(-64.0, -64.0);
-       BPoint end(64.0, -64.0);
-       BString coordinate;
-       if (FindString("x1", &coordinate) >= B_OK)
-               start.x = atof(coordinate.String());
-       if (FindString("y1", &coordinate) >= B_OK)
-               start.y = atof(coordinate.String());
-       if (FindString("x2", &coordinate) >= B_OK)
-               end.x = atof(coordinate.String());
-       if (FindString("y2", &coordinate) >= B_OK)
-               end.y = atof(coordinate.String());
-
-       // the transformed parallelogram
-       double parl[6];
-       parl[0] = start.x;
-       parl[1] = start.y;
-       parl[2] = end.x;
-       parl[3] = end.y;
-       parl[4] = end.x - (end.y - start.y);
-       parl[5] = end.y + (end.x - start.x);
-
-       trans_affine transform(-64.0, -64.0, 64.0, 64.0, parl);
-       gradient->multiply(transform);
-
-       return gradient;
-}
-
-// constructor
-SVGRadialGradient::SVGRadialGradient()
-       : SVGGradient()
-{
-}
-
-// destructor
-SVGRadialGradient::~SVGRadialGradient()
-{
-}
-
-// MakeGradient
-Gradient*
-SVGRadialGradient::MakeGradient() const
-{
-//printf("SVGRadialGradient::MakeGradient()\n");
-       // TODO: handle userSpaceOnUse/objectBoundingBox
-       Gradient* gradient = new Gradient(true);
-       gradient->SetType(GRADIENT_CIRCULAR);
-       gradient->SetInterpolation(INTERPOLATION_LINEAR);
-
-       double cx = 0.0;
-       double cy = 0.0;
-       double r = 100.0;
-
-       BString value;
-       if (FindString("cx", &value) >= B_OK)
-               cx = atof(value.String());
-       if (FindString("cy", &value) >= B_OK)
-               cy = atof(value.String());
-       if (FindString("r", &value) >= B_OK)
-               r = atof(value.String());
-
-       // the transformed parallelogram
-       double parl[6];
-       parl[0] = cx - r;
-       parl[1] = cy - r;
-       parl[2] = cx + r;
-       parl[3] = cy - r;
-       parl[4] = cx + r;
-       parl[5] = cy + r;
-
-       trans_affine transform(-64.0, -64.0, 64.0, 64.0, parl);
-       gradient->multiply(transform);
-
-       return gradient;
-}
-
-} // namespace svg
-} // namespace agg
-
diff --git a/src/apps/icon-o-matic/import_export/svg/SVGGradients.h 
b/src/apps/icon-o-matic/import_export/svg/SVGGradients.h
deleted file mode 100644
index c510ecbec1..0000000000
--- a/src/apps/icon-o-matic/import_export/svg/SVGGradients.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2006-2007, Haiku. All rights reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *             Stephan Aßmus <superstippi@xxxxxx>
- */
-#ifndef SVG_GRADIENTS_H
-#define SVG_GRADIENTS_H
-
-
-#include <agg_color_rgba.h>
-#include <agg_trans_affine.h>
-
-#include <Message.h>
-#include <String.h>
-
-#include "IconBuild.h"
-
-
-_BEGIN_ICON_NAMESPACE
-       class Gradient;
-_END_ICON_NAMESPACE
-
-namespace agg {
-namespace svg {
-
-class SVGGradient : public BMessage {
- public:
-                                                       SVGGradient();
-       virtual                                 ~SVGGradient();
-
-                       void                    SetID(const char* id);
-                       const char*             ID() const;
-
-       virtual void                    AddStop(float offset, rgba8 color);
-                       void                    SetTransformation(const 
trans_affine& transform);
-
-                       Gradient*               GetGradient(BRect objectBounds);
-
- protected:
-       virtual Gradient*               MakeGradient() const = 0;
-                       void                    IdentifyGradientUnits();
-
- private:
-
-       enum {
-               UNSPECIFIED = 0,
-               USER_SPACE_ON_USE,
-               OBJECT_BOUNDING_BOX,
-       };
-
-                       Gradient*               fGradient;
-                       BString                 fID;
-                       uint32                  fGradientUnits;
-};
-
-class SVGLinearGradient : public SVGGradient {
- public:
-                                                       SVGLinearGradient();
-       virtual                                 ~SVGLinearGradient();
-
- protected:
-       virtual Gradient*               MakeGradient() const;
-
-};
-
-class SVGRadialGradient : public SVGGradient {
- public:
-                                                       SVGRadialGradient();
-       virtual                                 ~SVGRadialGradient();
-
- protected:
-       virtual Gradient*               MakeGradient() const;
-
-};
-
-} // namespace svg
-} // namespace agg
-
-#endif // SVG_GRADIENTS_H
diff --git a/src/apps/icon-o-matic/import_export/svg/SVGImporter.cpp 
b/src/apps/icon-o-matic/import_export/svg/SVGImporter.cpp
index 280ac80c61..534b36c4b3 100644
--- a/src/apps/icon-o-matic/import_export/svg/SVGImporter.cpp
+++ b/src/apps/icon-o-matic/import_export/svg/SVGImporter.cpp
@@ -18,7 +18,7 @@
 #include <Path.h>
 
 #include "DocumentBuilder.h"
-#include "SVGParser.h"
+#include "nanosvg.h"
 
 
 #undef B_TRANSLATION_CONTEXT
@@ -69,23 +69,22 @@ SVGImporter::Import(Icon* icon, const entry_ref* ref)
                return B_ERROR;
        }
 
-       try {
-               agg::svg::DocumentBuilder builder;
-               agg::svg::Parser parser(builder);
-               parser.parse(path.Path());
-               ret = builder.GetIcon(icon, this, ref->name);
-       } catch(agg::svg::exception& e) {
+       NSVGimage* svg = nsvgParseFromFile(path.Path(), "px", 96);
+       if (svg == NULL) {
                char error[1024];
                sprintf(error, B_TRANSLATE("Failed to open the file '%s' as "
-                                          "an SVG document.\n\n"
-                                          "Error: %s"), ref->name, e.msg());
+                       "an SVG document.\n\n"), ref->name);
                BAlert* alert = new BAlert(B_TRANSLATE("load error"),
-                                                                  error, 
B_TRANSLATE("OK"), NULL, NULL,
-                                                                  
B_WIDTH_AS_USUAL, B_WARNING_ALERT);
+                       error, B_TRANSLATE("OK"), NULL, NULL,
+                       B_WIDTH_AS_USUAL, B_WARNING_ALERT);
                alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
                alert->Go(NULL);
-               ret = B_ERROR;
+               return B_ERROR;
        }
 
+       DocumentBuilder builder(svg);
+       ret = builder.GetIcon(icon, this, ref->name);
+       nsvgDelete(svg);
+
        return ret;
 }
diff --git a/src/apps/icon-o-matic/import_export/svg/SVGParser.cpp 
b/src/apps/icon-o-matic/import_export/svg/SVGParser.cpp
deleted file mode 100644
index fcd182d472..0000000000
--- a/src/apps/icon-o-matic/import_export/svg/SVGParser.cpp
+++ /dev/null
@@ -1,1152 +0,0 @@
-/*
- * Copyright 2006, Haiku. All rights reserved.
- * Distributed under the terms of the MIT License.
- *
- * Authors:
- *             Stephan Aßmus <superstippi@xxxxxx>
- */
-
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.2
-// Copyright (C) 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Permission to copy, use, modify, sell and distribute this software 
-// is granted provided this copyright notice appears in all copies. 
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@xxxxxxxxxxxxx
-//               mcseemagg@xxxxxxxxx
-//               http://www.antigrain.com
-//----------------------------------------------------------------------------
-
-#include "SVGParser.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <expat.h>
-
-#include "SVGGradients.h"
-
-namespace agg {
-namespace svg {
-
-struct named_color
-{
-       char  name[22];
-       int8u r, g, b, a;
-};
-
-named_color colors[] = 
-{
-       { "aliceblue",240,248,255, 255 },
-       { "antiquewhite",250,235,215, 255 },
-       { "aqua",0,255,255, 255 },
-       { "aquamarine",127,255,212, 255 },
-       { "azure",240,255,255, 255 },
-       { "beige",245,245,220, 255 },
-       { "bisque",255,228,196, 255 },
-       { "black",0,0,0, 255 },
-       { "blanchedalmond",255,235,205, 255 },
-       { "blue",0,0,255, 255 },
-       { "blueviolet",138,43,226, 255 },
-       { "brown",165,42,42, 255 },
-       { "burlywood",222,184,135, 255 },
-       { "cadetblue",95,158,160, 255 },
-       { "chartreuse",127,255,0, 255 },
-       { "chocolate",210,105,30, 255 },
-       { "coral",255,127,80, 255 },
-       { "cornflowerblue",100,149,237, 255 },
-       { "cornsilk",255,248,220, 255 },
-       { "crimson",220,20,60, 255 },
-       { "cyan",0,255,255, 255 },
-       { "darkblue",0,0,139, 255 },
-       { "darkcyan",0,139,139, 255 },
-       { "darkgoldenrod",184,134,11, 255 },
-       { "darkgray",169,169,169, 255 },
-       { "darkgreen",0,100,0, 255 },
-       { "darkgrey",169,169,169, 255 },
-       { "darkkhaki",189,183,107, 255 },
-       { "darkmagenta",139,0,139, 255 },
-       { "darkolivegreen",85,107,47, 255 },
-       { "darkorange",255,140,0, 255 },
-       { "darkorchid",153,50,204, 255 },
-       { "darkred",139,0,0, 255 },
-       { "darksalmon",233,150,122, 255 },
-       { "darkseagreen",143,188,143, 255 },
-       { "darkslateblue",72,61,139, 255 },
-       { "darkslategray",47,79,79, 255 },
-       { "darkslategrey",47,79,79, 255 },
-       { "darkturquoise",0,206,209, 255 },
-       { "darkviolet",148,0,211, 255 },
-       { "deeppink",255,20,147, 255 },
-       { "deepskyblue",0,191,255, 255 },
-       { "dimgray",105,105,105, 255 },
-       { "dimgrey",105,105,105, 255 },
-       { "dodgerblue",30,144,255, 255 },
-       { "firebrick",178,34,34, 255 },
-       { "floralwhite",255,250,240, 255 },
-       { "forestgreen",34,139,34, 255 },
-       { "fuchsia",255,0,255, 255 },
-       { "gainsboro",220,220,220, 255 },
-       { "ghostwhite",248,248,255, 255 },
-       { "gold",255,215,0, 255 },
-       { "goldenrod",218,165,32, 255 },
-       { "gray",128,128,128, 255 },
-       { "green",0,128,0, 255 },
-       { "greenyellow",173,255,47, 255 },
-       { "grey",128,128,128, 255 },
-       { "honeydew",240,255,240, 255 },
-       { "hotpink",255,105,180, 255 },
-       { "indianred",205,92,92, 255 },
-       { "indigo",75,0,130, 255 },
-       { "ivory",255,255,240, 255 },
-       { "khaki",240,230,140, 255 },
-       { "lavender",230,230,250, 255 },
-       { "lavenderblush",255,240,245, 255 },
-       { "lawngreen",124,252,0, 255 },
-       { "lemonchiffon",255,250,205, 255 },
-       { "lightblue",173,216,230, 255 },
-       { "lightcoral",240,128,128, 255 },
-       { "lightcyan",224,255,255, 255 },
-       { "lightgoldenrodyellow",250,250,210, 255 },
-       { "lightgray",211,211,211, 255 },
-       { "lightgreen",144,238,144, 255 },
-       { "lightgrey",211,211,211, 255 },
-       { "lightpink",255,182,193, 255 },
-       { "lightsalmon",255,160,122, 255 },
-       { "lightseagreen",32,178,170, 255 },
-       { "lightskyblue",135,206,250, 255 },
-       { "lightslategray",119,136,153, 255 },
-       { "lightslategrey",119,136,153, 255 },
-       { "lightsteelblue",176,196,222, 255 },
-       { "lightyellow",255,255,224, 255 },
-       { "lime",0,255,0, 255 },
-       { "limegreen",50,205,50, 255 },
-       { "linen",250,240,230, 255 },
-       { "magenta",255,0,255, 255 },
-       { "maroon",128,0,0, 255 },
-       { "mediumaquamarine",102,205,170, 255 },
-       { "mediumblue",0,0,205, 255 },
-       { "mediumorchid",186,85,211, 255 },
-       { "mediumpurple",147,112,219, 255 },
-       { "mediumseagreen",60,179,113, 255 },
-       { "mediumslateblue",123,104,238, 255 },
-       { "mediumspringgreen",0,250,154, 255 },
-       { "mediumturquoise",72,209,204, 255 },
-       { "mediumvioletred",199,21,133, 255 },
-       { "midnightblue",25,25,112, 255 },
-       { "mintcream",245,255,250, 255 },
-       { "mistyrose",255,228,225, 255 },
-       { "moccasin",255,228,181, 255 },
-       { "navajowhite",255,222,173, 255 },
-       { "navy",0,0,128, 255 },
-       { "oldlace",253,245,230, 255 },
-       { "olive",128,128,0, 255 },
-       { "olivedrab",107,142,35, 255 },
-       { "orange",255,165,0, 255 },
-       { "orangered",255,69,0, 255 },
-       { "orchid",218,112,214, 255 },
-       { "palegoldenrod",238,232,170, 255 },
-       { "palegreen",152,251,152, 255 },
-       { "paleturquoise",175,238,238, 255 },
-       { "palevioletred",219,112,147, 255 },
-       { "papayawhip",255,239,213, 255 },
-       { "peachpuff",255,218,185, 255 },
-       { "peru",205,133,63, 255 },
-       { "pink",255,192,203, 255 },
-       { "plum",221,160,221, 255 },
-       { "powderblue",176,224,230, 255 },
-       { "purple",128,0,128, 255 },
-       { "red",255,0,0, 255 },
-       { "rosybrown",188,143,143, 255 },
-       { "royalblue",65,105,225, 255 },
-       { "saddlebrown",139,69,19, 255 },
-       { "salmon",250,128,114, 255 },
-       { "sandybrown",244,164,96, 255 },
-       { "seagreen",46,139,87, 255 },
-       { "seashell",255,245,238, 255 },
-       { "sienna",160,82,45, 255 },
-       { "silver",192,192,192, 255 },
-       { "skyblue",135,206,235, 255 },
-       { "slateblue",106,90,205, 255 },
-       { "slategray",112,128,144, 255 },
-       { "slategrey",112,128,144, 255 },
-       { "snow",255,250,250, 255 },
-       { "springgreen",0,255,127, 255 },
-       { "steelblue",70,130,180, 255 },
-       { "tan",210,180,140, 255 },
-       { "teal",0,128,128, 255 },
-       { "thistle",216,191,216, 255 },
-       { "tomato",255,99,71, 255 },
-       { "turquoise",64,224,208, 255 },
-       { "violet",238,130,238, 255 },
-       { "wheat",245,222,179, 255 },
-       { "white",255,255,255, 255 },
-       { "whitesmoke",245,245,245, 255 },
-       { "yellow",255,255,0, 255 },
-       { "yellowgreen",154,205,50, 255 },
-       { "zzzzzzzzzzz",0,0,0, 0 }
-}; 
-
-
-
-// cmp_color
-int
-cmp_color(const void* p1, const void* p2)
-{
-       return strcmp(((named_color*)p1)->name, ((named_color*)p2)->name);
-}
-
-// parse_color
-rgba8
-parse_color(const char* str)
-{
-       while(*str == ' ') ++str;
-       if (*str == '#') {
-               str++;
-               int32 length = strlen(str);
-               unsigned c = 0;
-               if (length == 3) {
-                       // if there are only 3 byte, than it means that we
-                       // need to expand the color (#f60 -> #ff6600)
-                       // TODO: There must be an easier way...
-                       char expanded[7];
-                       expanded[0] = *str;
-                       expanded[1] = *str++;
-                       expanded[2] = *str;
-                       expanded[3] = *str++;
-                       expanded[4] = *str;
-                       expanded[5] = *str++;
-                       expanded[6] = 0;
-                       sscanf(expanded, "%x", &c);
-               } else {
-                       sscanf(str, "%x", &c);
-               }
-               return rgb8_packed(c);
-       } else {
-               named_color c;
-               unsigned len = strlen(str);
-               if(len > sizeof(c.name) - 1)
-               {
-                       throw exception("parse_color: Invalid color name '%s'", 
str);
-               }
-               strcpy(c.name, str);
-               const void* p = bsearch(&c, 
-                                                               colors, 
-                                                               sizeof(colors) 
/ sizeof(colors[0]), 
-                                                               
sizeof(colors[0]), 
-                                                               cmp_color);
-               if(p == 0)
-               {
-                       throw exception("parse_color: Invalid color name '%s'", 
str);
-               }
-               const named_color* pc = (const named_color*)p;
-               return rgba8(pc->r, pc->g, pc->b, pc->a);
-       }
-}
-
-// parse_double
-double
-parse_double(const char* str)
-{
-       while(*str == ' ') ++str;
-       double value = atof(str);
-       // handle percent
-       int32 length = strlen(str);
-       if (str[length - 1] == '%')
-               value /= 100.0;
-       return value;
-}
-
-// parse_url
-char*
-parse_url(const char* str)
-{
-       const char* begin = str;
-       while (*begin != '#')
-               begin++;
-
-       begin++;
-       const char* end = begin;
-       while (*end != ')')
-               end++;
-
-       end--;
-
-       int32 length = end - begin + 2;
-       char* result = new char[length];
-       memcpy(result, begin, length - 1);
-       result[length - 1] = 0;
-
-       return result;
-}
-
-
-// #pragma mark -
-
-// constructor
-Parser::Parser(DocumentBuilder& builder)
-       : fBuilder(builder),
-         fPathTokenizer(),
-         fBuffer(new char[buf_size]),
-         fTitle(new char[256]),
-         fTitleLength(0),
-
-         fTitleFlag(false),
-         fPathFlag(false),
-
-         fAttrName(new char[128]),
-         fAttrValue(new char[1024]),
-         fAttrNameLength(127),
-         fAttrValueLength(1023),
-
-         fTagsIgnored(false)
-{
-       fTitle[0] = 0;
-}
-
-// destructor
-Parser::~Parser()
-{
-       delete[] fAttrValue;
-       delete[] fAttrName;
-       delete[] fBuffer;
-       delete[] fTitle;
-}
-
-// parse
-void
-Parser::parse(const char* pathToFile)
-{
-       char msg[1024];
-       XML_Parser p = XML_ParserCreate(NULL);
-       if (p == 0) {
-               throw exception("Couldn't allocate memory for Parser");
-       }
-
-       XML_SetUserData(p, this);
-       XML_SetElementHandler(p, start_element, end_element);
-       XML_SetCharacterDataHandler(p, content);
-
-       FILE* fd = fopen(pathToFile, "r");
-       if (fd == 0) {
-               sprintf(msg, "Couldn't open file %s", pathToFile);
-               XML_ParserFree(p);
-               throw exception(msg);
-       }
-
-       bool done = false;
-       do {
-               size_t len = fread(fBuffer, 1, buf_size, fd);
-               done = len < buf_size;
-               if (!XML_Parse(p, fBuffer, len, done)) {
-                       sprintf(msg, "%s at line %ld\n",
-                                       XML_ErrorString(XML_GetErrorCode(p)),
-                                       XML_GetCurrentLineNumber(p));
-                       fclose(fd);
-                       XML_ParserFree(p);
-                       throw exception(msg);
-               }
-       } while (!done);
-
-       fclose(fd);
-       XML_ParserFree(p);
-
-       char* ts = fTitle;
-       while (*ts) {
-               if (*ts < ' ') *ts = ' ';
-               ++ts;
-       }
-}
-
-// start_element
-void
-Parser::start_element(void* data, const char* el, const char** attr)
-{
-// printf("Parser::start_element(%s)\n", el);
-       Parser& self = *(Parser*)data;
-
-       if (strcmp(el, "svg") == 0)
-       {
-               self.parse_svg(attr);
-       }
-       else
-       if (strcmp(el, "title") == 0)
-       {
-               self.fTitleFlag = true;
-       }
-       else
-       if (strcmp(el, "g") == 0)
-       {
-               self.fBuilder.push_attr();
-               self.parse_attr(attr);
-       }
-       else
-       if (strcmp(el, "path") == 0)
-       {
-               if (self.fPathFlag) {
-                       throw exception("start_element: Nested path");
-               }
-               self.fBuilder.begin_path();
-               self.parse_path(attr);
-               self.fBuilder.end_path();
-               self.fPathFlag = true;
-       }
-       else
-       if (strcmp(el, "circle") == 0)
-       {
-               self.parse_circle(attr);
-       }
-       else
-       if (strcmp(el, "ellipse") == 0)
-       {
-               self.parse_ellipse(attr);
-       }
-       else
-       if (strcmp(el, "rect") == 0)
-       {
-               self.parse_rect(attr);
-       }
-       else
-       if (strcmp(el, "line") == 0)
-       {
-               self.parse_line(attr);
-       }
-       else
-       if (strcmp(el, "polyline") == 0)
-       {
-               self.parse_poly(attr, false);
-       }
-       else
-       if (strcmp(el, "polygon") == 0)
-       {
-               self.parse_poly(attr, true);
-       }
-       else
-       if (strcmp(el, "linearGradient") == 0 || strcmp(el, "radialGradient") 
== 0)
-       {
-               self.parse_gradient(attr, strcmp(el, "radialGradient") == 0);
-       }
-       else
-       if (strcmp(el, "stop") == 0)
-       {
-               self.parse_gradient_stop(attr);
-       }
-       //else
-       //if(strcmp(el, "<OTHER_ELEMENTS>") == 0) 
-       //{
-       //}
-       // . . .
-       else
-       {
-               fprintf(stderr, "SVGParser igoring tag: \"%s\"\n", el);
-               self.fTagsIgnored = true;
-       }
-} 
-
-// end_element
-void
-Parser::end_element(void* data, const char* el)
-{
-       Parser& self = *(Parser*)data;
-
-       if (strcmp(el, "title") == 0)
-       {
-               self.fTitleFlag = false;
-               self.fBuilder.SetTitle(self.fTitle);
-       }
-       else
-       if (strcmp(el, "g") == 0)
-       {
-               self.fBuilder.pop_attr();
-       }
-       else
-       if (strcmp(el, "path") == 0)
-       {
-               self.fPathFlag = false;
-       }
-       else
-       if (strcmp(el, "linearGradient") == 0 || strcmp(el, "radialGradient") 
== 0)
-       {
-               self.fBuilder.EndGradient();
-       }
-       //else
-       //if(strcmp(el, "<OTHER_ELEMENTS>") == 0) 
-       //{
-       //}
-       // . . .
-}
-
-// content
-void
-Parser::content(void* data, const char* s, int len)
-{
-       Parser& self = *(Parser*)data;
-
-       // fTitleFlag signals that the <title> tag is being parsed now.
-       // The following code concatenates the pieces of content of the <title> 
tag.
-       if(self.fTitleFlag)
-       {
-               if(len + self.fTitleLength > 255) len = 255 - self.fTitleLength;
-               if(len > 0) 
-               {
-                       memcpy(self.fTitle + self.fTitleLength, s, len);
-                       self.fTitleLength += len;
-                       self.fTitle[self.fTitleLength] = 0;
-               }
-       }
-}
-
-// parse_svg
-void Parser::parse_svg(const char** attr)
-{
-       double width = 0.0;
-       double height = 0.0;
-       BRect viewBox(0.0, 0.0, -1.0, -1.0);
-
-       for (int i = 0; attr[i]; i += 2) {
-               if (strcmp(attr[i], "width") == 0)
-               {
-                       width = parse_double(attr[i + 1]);
-               }
-               else
-               if (strcmp(attr[i], "height") == 0)
-               {
-                       height = parse_double(attr[i + 1]);
-               }
-               else
-               if (strcmp(attr[i], "viewBox") == 0)
-               {
-                       fPathTokenizer.set_path_str(attr[i + 1]);
-                       if(!fPathTokenizer.next())
-                       {
-                               throw exception("parse_svg (viewBox): Too few 
coordinates");
-                       }
-                       viewBox.left = fPathTokenizer.last_number();
-                       if(!fPathTokenizer.next())
-                       {
-                               throw exception("parse_svg (viewBox): Too few 
coordinates");
-                       }
-                       viewBox.top = fPathTokenizer.last_number();
-                       if(!fPathTokenizer.next())
-                       {
-                               throw exception("parse_svg (viewBox): Too few 
coordinates");
-                       }
-                       viewBox.right = fPathTokenizer.last_number();
-                       if(!fPathTokenizer.next())
-                       {
-                               throw exception("parse_svg (viewBox): Too few 
coordinates");
-                       }
-                       viewBox.bottom = fPathTokenizer.last_number();
-               }
-       }
-       if (width >= 0.0 && height >= 0.0) {
-               fBuilder.SetDimensions((uint32)ceil(width), 
(uint32)ceil(height), viewBox);
-       } else {
-               throw exception("parse_svg: Invalid width or height\n");
-       }
-}
-
-// parse_attr
-void Parser::parse_attr(const char** attr)
-{
-       for (int i = 0; attr[i]; i += 2) {
-               if (strcmp(attr[i], "style") == 0) {
-                       parse_style(attr[i + 1]);
-               } else {
-                       parse_attr(attr[i], attr[i + 1]);
-               }
-       }
-}
-
-// parse_path
-void Parser::parse_path(const char** attr)
-{
-       int i;
-
-       for(i = 0; attr[i]; i += 2)
-       {
-               // The <path> tag can consist of the path itself ("d=") 
-               // as well as of other parameters like "style=", "transform=", 
etc.
-               // In the last case we simply rely on the function of parsing 
-               // attributes (see 'else' branch).
-               if(strcmp(attr[i], "d") == 0)
-               {
-                       fPathTokenizer.set_path_str(attr[i + 1]);
-                       fBuilder.parse_path(fPathTokenizer);
-               }
-               else
-               {
-                       // Create a temporary single pair "name-value" in order
-                       // to avoid multiple calls for the same attribute.
-                       const char* tmp[4];
-                       tmp[0] = attr[i];
-                       tmp[1] = attr[i + 1];
-                       tmp[2] = 0;
-                       tmp[3] = 0;
-                       parse_attr(tmp);
-               }
-       }
-}
-
-// parse_attr
-bool
-Parser::parse_attr(const char* name, const char* value)
-{
-       if(strcmp(name, "style") == 0) {
-               parse_style(value);
-       } else
-       if(strcmp(name, "opacity") == 0) {
-               fBuilder.opacity(parse_double(value));
-       } else
-       if(strcmp(name, "fill") == 0) {
-               if(strcmp(value, "none") == 0) {
-                       fBuilder.fill_none();
-               } else if (strncmp(value, "url", 3) == 0) {
-                       char* url = parse_url(value);
-                       fBuilder.fill_url(url);
-                       delete[] url;
-               } else {
-                       fBuilder.fill(parse_color(value));
-               }
-       } else
-       if(strcmp(name, "fill-opacity") == 0) {
-               fBuilder.fill_opacity(parse_double(value));
-       } else
-       if(strcmp(name, "fill-rule") == 0) {
-               fBuilder.even_odd(strcmp(value, "evenodd") == 0);
-       } else
-       if(strcmp(name, "stroke") == 0) {
-               if(strcmp(value, "none") == 0) {
-                       fBuilder.stroke_none();
-               } else if (strncmp(value, "url", 3) == 0) {
-                       char* url = parse_url(value);
-                       fBuilder.stroke_url(url);
-                       delete[] url;
-               } else {
-                       fBuilder.stroke(parse_color(value));
-               }
-       } else

[ *** diff truncated: 3654 lines dropped *** ]


############################################################################

Revision:    hrev54246
Commit:      17626df948e1d384072e6a2f8eab4f7fc6a18d0a
URL:         https://git.haiku-os.org/haiku/commit/?id=17626df948e1
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Sun May 10 15:25:39 2020 UTC
Committer:   waddlesplash <waddlesplash@xxxxxxxxx>
Commit-Date: Fri May 22 14:08:17 2020 UTC

Ticket:      https://dev.haiku-os.org/ticket/14437

Icon-O-Matic: use the MIME sniffer to recognize SVG files

Our sniffing rule is not perfect, but it is already a lot better than
what was done here.

Partially fixes #14437 (the icons also fails parsing for other reasons,
but with an error message, at least)

Change-Id: I25475b419b5fbe863c71f553a336757d7950bf48
Reviewed-on: https://review.haiku-os.org/c/haiku/+/2662
Reviewed-by: waddlesplash <waddlesplash@xxxxxxxxx>

----------------------------------------------------------------------------


Other related posts:

  • » [haiku-commits] haiku: hrev54246 - src/apps/icon-o-matic/import_export/svg - waddlesplash