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>
----------------------------------------------------------------------------