diff options
| author | Johan B. C. Engelen <jbc.engelen@swissonline.ch> | 2008-09-10 23:42:59 +0000 |
|---|---|---|
| committer | johanengelen <johanengelen@users.sourceforge.net> | 2008-09-10 23:42:59 +0000 |
| commit | 34dd43b53b90b8293b86da4a828d69f966aa51a4 (patch) | |
| tree | fb6a3810bcce412e6a1be5ed3e30a1c4a7501ed7 /src | |
| parent | 2geomify, remove warnings and other fixes (diff) | |
| download | inkscape-34dd43b53b90b8293b86da4a828d69f966aa51a4.tar.gz inkscape-34dd43b53b90b8293b86da4a828d69f966aa51a4.zip | |
LIBNR REMOVAL. remove nartbpath code!!!
remove nartbpath test code etc.
remove inkscape's path parsing, since it is now done by 2geom.
(bzr r6789)
Diffstat (limited to 'src')
| -rw-r--r-- | src/extension/internal/cairo-render-context.h | 1 | ||||
| -rw-r--r-- | src/extension/internal/emf-win32-print.cpp | 2 | ||||
| -rw-r--r-- | src/extension/internal/win32.h | 4 | ||||
| -rw-r--r-- | src/libnr/Makefile_insert | 3 | ||||
| -rw-r--r-- | src/libnr/n-art-bpath-2geom.cpp | 103 | ||||
| -rw-r--r-- | src/libnr/n-art-bpath-2geom.h | 31 | ||||
| -rw-r--r-- | src/libnr/n-art-bpath.h | 64 | ||||
| -rw-r--r-- | src/libnr/nr-forward.h | 3 | ||||
| -rw-r--r-- | src/object-snapper.cpp | 12 | ||||
| -rw-r--r-- | src/svg/Makefile_insert | 5 | ||||
| -rw-r--r-- | src/svg/gnome-canvas-bpath-util.cpp | 209 | ||||
| -rw-r--r-- | src/svg/gnome-canvas-bpath-util.h | 48 | ||||
| -rw-r--r-- | src/svg/svg-path-nr-test.h | 500 | ||||
| -rw-r--r-- | src/svg/svg-path.cpp | 680 | ||||
| -rw-r--r-- | src/svg/svg.h | 2 |
15 files changed, 5 insertions, 1662 deletions
diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h index 4c078f87f..72a1790cf 100644 --- a/src/extension/internal/cairo-render-context.h +++ b/src/extension/internal/cairo-render-context.h @@ -138,7 +138,6 @@ public: /* Rendering methods */ bool renderPathVector(Geom::PathVector const & pathv, SPStyle const *style, NRRect const *pbox); - bool renderPath(const_NRBPath const *bpath, SPStyle const *style, NRRect const *pbox); bool renderImage(unsigned char *px, unsigned int w, unsigned int h, unsigned int rs, Geom::Matrix const *image_transform, SPStyle const *style); bool renderGlyphtext(PangoFont *font, Geom::Matrix const *font_matrix, diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp index e53eda81c..d5bdcb6d3 100644 --- a/src/extension/internal/emf-win32-print.cpp +++ b/src/extension/internal/emf-win32-print.cpp @@ -31,7 +31,6 @@ //#include <signal.h> //#include <errno.h> -//#include "libnr/n-art-bpath.h" //#include "libnr/nr-point-matrix-ops.h" //#include "libnr/nr-rect.h" //#include "libnr/nr-matrix.h" @@ -42,7 +41,6 @@ //#include "libnr/nr-translate-scale-ops.h" //#include "libnr/nr-matrix-fns.h" //#include "libnr/nr-pixblock.h" -#include "libnr/n-art-bpath-2geom.h" #include <2geom/pathvector.h> #include <2geom/rect.h> #include <2geom/bezier-curve.h> diff --git a/src/extension/internal/win32.h b/src/extension/internal/win32.h index f32e354ee..4fb726fae 100644 --- a/src/extension/internal/win32.h +++ b/src/extension/internal/win32.h @@ -74,10 +74,6 @@ public: virtual unsigned int bind (Inkscape::Extension::Print * module, const Geom::Matrix *transform, float opacity); virtual unsigned int release (Inkscape::Extension::Print * module); virtual unsigned int comment (Inkscape::Extension::Print * module, const char * comment); - virtual unsigned int fill (Inkscape::Extension::Print * module, const const_NRBPath *bpath, const Geom::Matrix *ctm, const SPStyle *style, - const NRRect *pbox, const NRRect *dbox, const NRRect *bbox); - virtual unsigned int stroke (Inkscape::Extension::Print * module, const const_NRBPath *bpath, const Geom::Matrix *transform, const SPStyle *style, - const NRRect *pbox, const NRRect *dbox, const NRRect *bbox); virtual unsigned int image (Inkscape::Extension::Print * module, unsigned char *px, unsigned int w, unsigned int h, unsigned int rs, const Geom::Matrix *transform, const SPStyle *style); */ diff --git a/src/libnr/Makefile_insert b/src/libnr/Makefile_insert index c7f5fd28c..ef813a8be 100644 --- a/src/libnr/Makefile_insert +++ b/src/libnr/Makefile_insert @@ -16,9 +16,6 @@ endif libnr_libnr_a_SOURCES = \ libnr/in-svg-plane.h \ - libnr/n-art-bpath.h \ - libnr/n-art-bpath-2geom.cpp \ - libnr/n-art-bpath-2geom.h \ libnr/nr-blit.cpp \ libnr/nr-blit.h \ libnr/nr-compose-transform.cpp \ diff --git a/src/libnr/n-art-bpath-2geom.cpp b/src/libnr/n-art-bpath-2geom.cpp deleted file mode 100644 index 2bd76e623..000000000 --- a/src/libnr/n-art-bpath-2geom.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#define SEEN_LIBNR_N_ART_BPATH_2GEOM_CPP - -/** \file - * Contains functions to convert from NArtBpath to 2geom's Path - * - * Copyright (C) Johan Engelen 2007-2008 <j.b.c.engelen@utwente.nl> - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include "libnr/n-art-bpath-2geom.h" - -#include "svg/svg.h" -#include <glib.h> -#include <2geom/path.h> -#include <2geom/svg-path.h> -#include <2geom/svg-path-parser.h> -#include <typeinfo> - -std::vector<Geom::Path> -BPath_to_2GeomPath(NArtBpath const * bpath) -{ - std::vector<Geom::Path> pathv; - if (!bpath) { - return pathv; - } - - NArtBpath const *bp = bpath; // points to element within bpath - Geom::Path * current = NULL; // points to current path - while (bp->code != NR_END) { - if ( current && - ( (bp->code == NR_MOVETO) || (bp->code == NR_MOVETO_OPEN) ) - ) - { // about to start a new path, correct the current path: nartbpath manually adds the closing line segment so erase it for closed path. - if (current->closed() && !current->empty()) { - // but only remove this last segment if it is a *linesegment*: - if ( dynamic_cast<Geom::LineSegment const *>(¤t->back()) ) { - current->erase_last(); - } - } - } - - switch(bp->code) { - case NR_MOVETO: - pathv.push_back( Geom::Path() ); // for some reason Geom::Path(Point) does not work... - current = &pathv.back(); - current->start( Geom::Point(bp->x3, bp->y3) ); - current->close(true); - break; - - case NR_MOVETO_OPEN: - pathv.push_back( Geom::Path() ); // for some reason Geom::Path(Point) does not work... - current = &pathv.back(); - current->start( Geom::Point(bp->x3, bp->y3) ); - current->close(false); - break; - - case NR_LINETO: - current->appendNew<Geom::LineSegment>( Geom::Point(bp->x3, bp->y3) ); - break; - - case NR_CURVETO: - current->appendNew<Geom::CubicBezier> ( Geom::Point(bp->x1, bp->y1), Geom::Point(bp->x2, bp->y2), Geom::Point(bp->x3, bp->y3) ); - break; - - case NR_END: - g_error("BPath_to_2GeomPath: logical error"); - break; - } - ++bp; - } - if ( current && current->closed() && !current->empty() ) { - // correct the current path: nartbpath manually adds the closing line segment so erase it for closed path. - // but only remove this last segment if it is a *linesegment*: - if ( dynamic_cast<Geom::LineSegment const *>(¤t->back()) ) { - current->erase_last(); - } - } - - return pathv; -} - -NArtBpath * -BPath_from_2GeomPath(std::vector<Geom::Path> const & path) -{ - char * svgd = sp_svg_write_path(path); - NArtBpath *bpath = sp_svg_read_path(svgd); - g_free(svgd); - return bpath; -} - - - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/libnr/n-art-bpath-2geom.h b/src/libnr/n-art-bpath-2geom.h deleted file mode 100644 index bf1592e28..000000000 --- a/src/libnr/n-art-bpath-2geom.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef SEEN_LIBNR_N_ART_BPATH_2GEOM_H -#define SEEN_LIBNR_N_ART_BPATH_2GEOM_H - -/** \file - * Contains functions to convert from NArtBpath to 2geom's Path - * - * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl> - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#include <vector> -#include <2geom/path.h> -#include <libnr/n-art-bpath.h> - -std::vector<Geom::Path> BPath_to_2GeomPath (NArtBpath const *bpath); -NArtBpath * BPath_from_2GeomPath (std::vector<Geom::Path> const & path); - - -#endif /* !SEEN_LIBNR_N_ART_BPATH_2GEOM_H */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/libnr/n-art-bpath.h b/src/libnr/n-art-bpath.h deleted file mode 100644 index fdb9855be..000000000 --- a/src/libnr/n-art-bpath.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef SEEN_LIBNR_N_ART_BPATH_H -#define SEEN_LIBNR_N_ART_BPATH_H - -/** \file - * NArtBpath: old-style path segment. - */ - -#include <stdlib.h> - -#include "libnr/nr-point.h" -#include "libnr/nr-path-code.h" -#include <cstdlib> - -/** - * Old-style path segment. - * - * Arrays of paths segment start with a MOVETO or MOVETO_OPEN segment - * where the former indicates the beginning of a closed subpath. - * \see subpath_from_bpath() - */ -class NArtBpath { -public: - NRPathcode code; ///< Type of segment - double x1, y1; ///< Position of control point in case of NR_CURVETO - double x2, y2; ///< Position of control point in case of NR_CURVETO - double x3, y3; ///< Position of next point - - /// Convert i-th position data pair to Point object - /// \pre 1 <= i <= 3 - NR::Point c(unsigned const i) const { - switch (i) { - case 1: return NR::Point(x1, y1); - case 2: return NR::Point(x2, y2); - case 3: return NR::Point(x3, y3); - default: std::abort(); - } - } - - /// Set i-th position data pair from Point - /// \pre 1 <= i <= 3 - void setC(unsigned const i, NR::Point const &p) { - using NR::X; using NR::Y; - switch (i) { - case 1: x1 = p[X]; y1 = p[Y]; break; - case 2: x2 = p[X]; y2 = p[Y]; break; - case 3: x3 = p[X]; y3 = p[Y]; break; - default: std::abort(); - } - } -}; - - -#endif /* !SEEN_LIBNR_N_ART_BPATH_H */ - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/libnr/nr-forward.h b/src/libnr/nr-forward.h index 112313b24..da4fe99df 100644 --- a/src/libnr/nr-forward.h +++ b/src/libnr/nr-forward.h @@ -19,9 +19,6 @@ class scale; class translate; } -class NArtBpath; -struct NRBPath; -struct const_NRBPath; struct NRPixBlock; struct NRRect; struct NRRectL; diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 084fd1c36..41866b41c 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -293,18 +293,6 @@ void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &s * Returns index of first NR_END bpath in array. */ -/* Obsolete -static unsigned sp_bpath_length(NArtBpath const bpath[]) -{ - g_return_val_if_fail(bpath != NULL, FALSE); - unsigned ret = 0; - while ( bpath[ret].code != NR_END ) { - ++ret; - } - ++ret; - return ret; -}*/ - void Inkscape::ObjectSnapper::_collectPaths(Inkscape::Snapper::PointType const &t, bool const &first_point) const { diff --git a/src/svg/Makefile_insert b/src/svg/Makefile_insert index f7d2fcc5e..45a1a7db3 100644 --- a/src/svg/Makefile_insert +++ b/src/svg/Makefile_insert @@ -16,8 +16,6 @@ svg/clean: svg_libspsvg_a_SOURCES = \ svg/css-ostringstream.h \ svg/css-ostringstream.cpp \ - svg/gnome-canvas-bpath-util.cpp \ - svg/gnome-canvas-bpath-util.h \ svg/itos.cpp \ svg/path-string.h \ svg/path-string.cpp \ @@ -50,8 +48,7 @@ svg_test_svg_includes = \ $(srcdir)/svg/svg-affine-test.h \ $(srcdir)/svg/svg-color-test.h \ $(srcdir)/svg/svg-length-test.h \ - $(srcdir)/svg/svg-path-geom-test.h \ - $(srcdir)/svg/svg-path-nr-test.h + $(srcdir)/svg/svg-path-geom-test.h svg_libtest_svg_a_SOURCES = \ svg/test-svg.cpp \ diff --git a/src/svg/gnome-canvas-bpath-util.cpp b/src/svg/gnome-canvas-bpath-util.cpp deleted file mode 100644 index bd55bfb10..000000000 --- a/src/svg/gnome-canvas-bpath-util.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* GnomeCanvas Bezier polyline paths & segments - * - * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is - * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. - * - * Copyright (C) 1998,1999 The Free Software Foundation - * - * Authors: Federico Mena <federico@nuclecu.unam.mx> - * Lauris Kaplinski <lauris@ariman.ee> - * Raph Levien <raph@acm.org> - * Jasper van de Gronde <th.v.d.gronde@hccnet.nl> - */ - -#include <cstring> -#include <string> -#include <cstdlib> -#include <cstdio> -#include <glib/gmem.h> -#include <glib/gmessages.h> -#include <algorithm> - -#include "libnr/n-art-bpath.h" -#include "libnr/nr-point-ops.h" -#include "gnome-canvas-bpath-util.h" -#include "prefs-utils.h" - -static inline NR::Point distTo(GnomeCanvasBpathDef *bpd, size_t idx1, size_t idx2, unsigned int coord1=3, unsigned int coord2=3) { - NR::Point diff(bpd->bpath[idx1].c(coord1) - bpd->bpath[idx2].c(coord2)); - return NR::Point(std::abs(diff[NR::X]), std::abs(diff[NR::Y])); -} - -static bool isApproximatelyClosed(GnomeCanvasBpathDef *bpd) { - int const np = prefs_get_int_attribute("options.svgoutput", "numericprecision", 8); - double const precision = pow(10.0, -(np+1)); // This roughly corresponds to a difference below the last significant digit - int const initial = bpd->moveto_idx; - int const current = bpd->n_bpath - 1; - NR::Point distToInit(distTo(bpd, current, initial)); - // TODO check the double to int conversion in the abs() call: - return - distToInit[NR::X] <= abs(bpd->bpath[current].c(3)[NR::X])*precision && - distToInit[NR::Y] <= abs(bpd->bpath[current].c(3)[NR::Y])*precision; -} - -GnomeCanvasBpathDef * -gnome_canvas_bpath_def_new (void) -{ - GnomeCanvasBpathDef *bpd; - - bpd = g_new (GnomeCanvasBpathDef, 1); - bpd->n_bpath = 0; - bpd->n_bpath_max = 16; - bpd->moveto_idx = -1; - bpd->bpath = g_new (NArtBpath, bpd->n_bpath_max); - bpd->ref_count = 1; - - return bpd; -} - -GnomeCanvasBpathDef * -gnome_canvas_bpath_def_new_from (NArtBpath *path) -{ - GnomeCanvasBpathDef *bpd; - int i; - - g_return_val_if_fail (path != NULL, NULL); - - bpd = g_new (GnomeCanvasBpathDef, 1); - - for (i = 0; path [i].code != NR_END; i++) - ; - bpd->n_bpath = i; - bpd->n_bpath_max = i; - bpd->moveto_idx = -1; - bpd->ref_count = 1; - bpd->bpath = g_new (NArtBpath, i); - - memcpy (bpd->bpath, path, i * sizeof (NArtBpath)); - return bpd; -} - -GnomeCanvasBpathDef * -gnome_canvas_bpath_def_ref (GnomeCanvasBpathDef *bpd) -{ - g_return_val_if_fail (bpd != NULL, NULL); - - bpd->ref_count += 1; - return bpd; -} - -void -gnome_canvas_bpath_def_free (GnomeCanvasBpathDef *bpd) -{ - g_return_if_fail (bpd != NULL); - - bpd->ref_count -= 1; - if (bpd->ref_count == 0) { - g_free (bpd->bpath); - g_free (bpd); - } -} - -void -gnome_canvas_bpath_def_moveto (GnomeCanvasBpathDef *bpd, double x, double y) -{ - NArtBpath *bpath; - int n_bpath; - - g_return_if_fail (bpd != NULL); - - n_bpath = bpd->n_bpath++; - - if (n_bpath == bpd->n_bpath_max) - bpd->bpath = (NArtBpath*)g_realloc (bpd->bpath, - (bpd->n_bpath_max <<= 1) * sizeof (NArtBpath)); - bpath = bpd->bpath; - bpath[n_bpath].code = NR_MOVETO_OPEN; - bpath[n_bpath].x3 = x; - bpath[n_bpath].y3 = y; - bpd->moveto_idx = n_bpath; -} - -void -gnome_canvas_bpath_def_lineto (GnomeCanvasBpathDef *bpd, double x, double y) -{ - NArtBpath *bpath; - int n_bpath; - - g_return_if_fail (bpd != NULL); - g_return_if_fail (bpd->moveto_idx >= 0); - - n_bpath = bpd->n_bpath++; - - if (n_bpath == bpd->n_bpath_max) - bpd->bpath = (NArtBpath*)g_realloc (bpd->bpath, - (bpd->n_bpath_max <<= 1) * sizeof (NArtBpath)); - bpath = bpd->bpath; - bpath[n_bpath].code = NR_LINETO; - bpath[n_bpath].x3 = x; - bpath[n_bpath].y3 = y; -} - -void -gnome_canvas_bpath_def_curveto (GnomeCanvasBpathDef *bpd, double x1, double y1, double x2, double y2, double x3, double y3) -{ - NArtBpath *bpath; - int n_bpath; - - g_return_if_fail (bpd != NULL); - g_return_if_fail (bpd->moveto_idx >= 0); - - n_bpath = bpd->n_bpath++; - - if (n_bpath == bpd->n_bpath_max) - bpd->bpath = (NArtBpath*)g_realloc (bpd->bpath, - (bpd->n_bpath_max <<= 1) * sizeof (NArtBpath)); - bpath = bpd->bpath; - bpath[n_bpath].code = NR_CURVETO; - bpath[n_bpath].x1 = x1; - bpath[n_bpath].y1 = y1; - bpath[n_bpath].x2 = x2; - bpath[n_bpath].y2 = y2; - bpath[n_bpath].x3 = x3; - bpath[n_bpath].y3 = y3; -} - -void -gnome_canvas_bpath_def_closepath (GnomeCanvasBpathDef *bpd) -{ - NArtBpath *bpath; - int n_bpath; - - g_return_if_fail (bpd != NULL); - g_return_if_fail (bpd->moveto_idx >= 0); - g_return_if_fail (bpd->n_bpath > 0); - - bpath = bpd->bpath; - n_bpath = bpd->n_bpath; - - /* Add closing vector if we need it. */ - if (!isApproximatelyClosed(bpd)) { - gnome_canvas_bpath_def_lineto (bpd, bpath[bpd->moveto_idx].x3, - bpath[bpd->moveto_idx].y3); - bpath = bpd->bpath; - } else { - // If it is approximately closed we close it here to prevent internal logic to fail. - // In addition it is probably better to continue working with this end point, as it - // is probably more precise than the original. - bpath[n_bpath-1].x3 = bpath[bpd->moveto_idx].x3; - bpath[n_bpath-1].y3 = bpath[bpd->moveto_idx].y3; - } - bpath[bpd->moveto_idx].code = NR_MOVETO; - bpd->moveto_idx = -1; -} - -void -gnome_canvas_bpath_def_art_finish (GnomeCanvasBpathDef *bpd) -{ - int n_bpath; - - g_return_if_fail (bpd != NULL); - - n_bpath = bpd->n_bpath++; - - if (n_bpath == bpd->n_bpath_max) - bpd->bpath = (NArtBpath*)g_realloc (bpd->bpath, - (bpd->n_bpath_max <<= 1) * sizeof (NArtBpath)); - bpd->bpath [n_bpath].code = NR_END; -} - diff --git a/src/svg/gnome-canvas-bpath-util.h b/src/svg/gnome-canvas-bpath-util.h deleted file mode 100644 index 62d47c178..000000000 --- a/src/svg/gnome-canvas-bpath-util.h +++ /dev/null @@ -1,48 +0,0 @@ -/* GnomeCanvas Bezier polyline paths & segments - * - * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is - * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties. - * - * Copyright (C) 1998,1999 The Free Software Foundation - * - * Authors: Federico Mena <federico@nuclecu.unam.mx> - * Lauris Kaplinski <lauris@ariman.ee> - * Raph Levien <raph@acm.org> - */ - -#ifndef PATH_UTIL_H -#define PATH_UTIL_H - -struct NArtBpath; - -struct GnomeCanvasBpathDef { - int ref_count; - NArtBpath *bpath; - int n_bpath; - int n_bpath_max; - int moveto_idx; -}; - - -GnomeCanvasBpathDef *gnome_canvas_bpath_def_new (void); -GnomeCanvasBpathDef *gnome_canvas_bpath_def_new_from (NArtBpath *bpath); -GnomeCanvasBpathDef *gnome_canvas_bpath_def_ref (GnomeCanvasBpathDef *bpd); - -#define gnome_canvas_bpath_def_unref gnome_canvas_bpath_def_free -void gnome_canvas_bpath_def_free (GnomeCanvasBpathDef *bpd); - -void gnome_canvas_bpath_def_moveto (GnomeCanvasBpathDef *bpd, - double x, double y); -void gnome_canvas_bpath_def_lineto (GnomeCanvasBpathDef *bpd, - double x, double y); -void gnome_canvas_bpath_def_curveto (GnomeCanvasBpathDef *bpd, - double x1, double y1, - double x2, double y2, - double x3, double y3); -void gnome_canvas_bpath_def_closepath (GnomeCanvasBpathDef *bpd); - -void gnome_canvas_bpath_def_art_finish (GnomeCanvasBpathDef *bpd); - - - -#endif diff --git a/src/svg/svg-path-nr-test.h b/src/svg/svg-path-nr-test.h deleted file mode 100644 index 58f7cd0e7..000000000 --- a/src/svg/svg-path-nr-test.h +++ /dev/null @@ -1,500 +0,0 @@ -/* WARNING: These tests are not completely correct! - * Specifically, 'M 0,0 L 1,1 z' and 'M 0,0 L 1,1 L 0,0 z' are treated as equal, but aren't. - * This difference is (probably?) only relevant in the context of markers. - * However, since NArtBpath has no (valid) way to distinguish these two and is being retired, - * these tests have not been updated to reflect this. - */ - -#include <cxxtest/TestSuite.h> -#include "libnr/n-art-bpath.h" -#include "svg/svg.h" -#include "2geom/coord.h" -#include "prefs-utils.h" -#include "streq.h" -#include <string> -#include <vector> -#include <glib/gmem.h> - -class SvgPathNRTest : public CxxTest::TestSuite -{ -private: - std::vector<std::string> rectanglesAbsoluteClosed; - std::vector<std::string> rectanglesRelativeClosed; - std::vector<std::string> rectanglesAbsoluteOpen; - std::vector<std::string> rectanglesRelativeOpen; - NArtBpath rectangleBpath[5+1]; -public: - SvgPathNRTest() { - // Lots of ways to define the same rectangle - rectanglesAbsoluteClosed.push_back("M 1,2 L 4,2 L 4,8 L 1,8 L 1,2 Z"); - rectanglesAbsoluteClosed.push_back("M 1,2 L 4,2 L 4,8 L 1,8 z"); - rectanglesAbsoluteClosed.push_back("M 1,2 4,2 4,8 1,8 z"); - rectanglesAbsoluteClosed.push_back("M 1,2 H 4 V 8 H 1 z"); - rectanglesRelativeClosed.push_back("m 1,2 l 3,0 l 0,6 l -3,0 z"); - rectanglesRelativeClosed.push_back("m 1,2 3,0 0,6 -3,0 z"); - rectanglesRelativeClosed.push_back("m 1,2 h 3 v 6 h -3 z"); - rectanglesAbsoluteOpen.push_back("M 1,2 L 4,2 L 4,8 L 1,8 L 1,2"); - rectanglesAbsoluteOpen.push_back("M 1,2 4,2 4,8 1,8 1,2"); - rectanglesAbsoluteOpen.push_back("M 1,2 H 4 V 8 H 1 V 2"); - rectanglesRelativeOpen.push_back("m 1,2 l 3,0 l 0,6 l -3,0 l 0,-6"); - rectanglesRelativeOpen.push_back("m 1,2 3,0 0,6 -3,0 0,-6"); - rectanglesRelativeOpen.push_back("m 1,2 h 3 v 6 h -3 v -6"); - rectangleBpath[0].code = NR_MOVETO; - rectangleBpath[0].x3 = 1; - rectangleBpath[0].y3 = 2; - rectangleBpath[1].code = NR_LINETO; - rectangleBpath[1].x3 = 4; - rectangleBpath[1].y3 = 2; - rectangleBpath[2].code = NR_LINETO; - rectangleBpath[2].x3 = 4; - rectangleBpath[2].y3 = 8; - rectangleBpath[3].code = NR_LINETO; - rectangleBpath[3].x3 = 1; - rectangleBpath[3].y3 = 8; - rectangleBpath[4].code = NR_LINETO; - rectangleBpath[4].x3 = 1; - rectangleBpath[4].y3 = 2; - rectangleBpath[5].code = NR_END; - // TODO: Also test some (smooth) cubic/quadratic beziers and elliptical arcs - } - -// createSuite and destroySuite get us per-suite setup and teardown -// without us having to worry about static initialization order, etc. - static SvgPathNRTest *createSuite() { return new SvgPathNRTest(); } - static void destroySuite( SvgPathNRTest *suite ) { delete suite; } - - void testReadRectanglesAbsoluteClosed() - { - rectangleBpath[0].code = NR_MOVETO; - for(size_t i=0; i<rectanglesAbsoluteClosed.size(); i++) { - NArtBpath * bpath = sp_svg_read_path(rectanglesAbsoluteClosed[i].c_str()); - TS_ASSERT(bpathEqual(bpath,rectangleBpath)); - g_free(bpath); - } - } - - void testReadRectanglesRelativeClosed() - { - rectangleBpath[0].code = NR_MOVETO; - for(size_t i=0; i<rectanglesRelativeClosed.size(); i++) { - NArtBpath * bpath = sp_svg_read_path(rectanglesRelativeClosed[i].c_str()); - TS_ASSERT(bpathEqual(bpath,rectangleBpath)); - g_free(bpath); - } - } - - void testReadRectanglesAbsoluteOpen() - { - rectangleBpath[0].code = NR_MOVETO_OPEN; - for(size_t i=0; i<rectanglesAbsoluteOpen.size(); i++) { - NArtBpath * bpath = sp_svg_read_path(rectanglesAbsoluteOpen[i].c_str()); - TS_ASSERT(bpathEqual(bpath,rectangleBpath)); - g_free(bpath); - } - } - - void testReadRectanglesRelativeOpen() - { - rectangleBpath[0].code = NR_MOVETO_OPEN; - for(size_t i=0; i<rectanglesRelativeOpen.size(); i++) { - NArtBpath * bpath = sp_svg_read_path(rectanglesRelativeOpen[i].c_str()); - TS_ASSERT(bpathEqual(bpath,rectangleBpath)); - g_free(bpath); - } - } - - void testReadConcatenatedPaths() - { - NArtBpath bpath_good[4*5+1]; - for(size_t i=0; i<4; i++) { - memcpy(bpath_good+i*5,rectangleBpath,sizeof(rectangleBpath[0])*5); - } - bpath_good[0*5].code = NR_MOVETO; - bpath_good[1*5].code = NR_MOVETO_OPEN; - bpath_good[2*5].code = NR_MOVETO; - bpath_good[3*5].code = NR_MOVETO_OPEN; - bpath_good[4*5].code = NR_END; - for(size_t i=0; i<5; i++) { - bpath_good[1*5+i].x3 += bpath_good[0*5+4].x3; - bpath_good[1*5+i].y3 += bpath_good[0*5+4].y3; - } - for(size_t i=0; i<5; i++) { - bpath_good[2*5+i].x3 += bpath_good[1*5+4].x3; - bpath_good[2*5+i].y3 += bpath_good[1*5+4].y3; - } - std::string path_str = rectanglesAbsoluteClosed[0] + rectanglesRelativeOpen[0] + rectanglesRelativeClosed[0] + rectanglesAbsoluteOpen[0]; - NArtBpath * bpath = sp_svg_read_path(path_str.c_str()); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - - void testReadZeroLengthSubpaths() { - // Per the SVG 1.1 specification (section F5) zero-length subpaths are relevant - NArtBpath bpath_good[8+1]; - bpath_good[0].code = NR_MOVETO_OPEN; - bpath_good[0].x3 = bpath_good[0].y3 = 0; - bpath_good[1].code = NR_MOVETO_OPEN; - bpath_good[1].x3 = bpath_good[1].y3 = 1; - bpath_good[2].code = NR_LINETO; - bpath_good[2].x3 = bpath_good[2].y3 = 2; - bpath_good[3].code = NR_MOVETO; - bpath_good[3].x3 = bpath_good[3].y3 = 3; - bpath_good[4].code = NR_MOVETO; - bpath_good[4].x3 = bpath_good[4].y3 = 4; - bpath_good[5].code = NR_LINETO; - bpath_good[5].x3 = bpath_good[5].y3 = 5; - bpath_good[6].code = NR_LINETO; - bpath_good[6].x3 = bpath_good[6].y3 = 4; - bpath_good[7].code = NR_MOVETO_OPEN; - bpath_good[7].x3 = bpath_good[7].y3 = 6; - bpath_good[8].code = NR_END; - { // Test absolute version - char const * path_str = "M 0,0 M 1,1 L 2,2 M 3,3 z M 4,4 L 5,5 z M 6,6"; - NArtBpath * bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - { // Test relative version - char const * path_str = "m 0,0 m 1,1 l 1,1 m 1,1 z m 1,1 l 1,1 z m 2,2"; - NArtBpath * bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - } - - void testReadImplicitMoveto() { - NArtBpath bpath_good[6+1]; - bpath_good[0].code = NR_MOVETO; - bpath_good[0].x3 = bpath_good[0].y3 = 1; - bpath_good[1].code = NR_LINETO; - bpath_good[1].x3 = bpath_good[1].y3 = 2; - bpath_good[2].code = NR_LINETO; - bpath_good[2].x3 = bpath_good[2].y3 = 1; - bpath_good[3].code = NR_MOVETO; - bpath_good[3].x3 = bpath_good[3].y3 = 1; - bpath_good[4].code = NR_LINETO; - bpath_good[4].x3 = bpath_good[4].y3 = 3; - bpath_good[5].code = NR_LINETO; - bpath_good[5].x3 = bpath_good[5].y3 = 1; - bpath_good[6].code = NR_END; - { // Test absolute version - char const * path_str = "M 1,1 L 2,2 z L 3,3 z"; - NArtBpath * bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - { // Test relative version - char const * path_str = "M 1,1 L 2,2 z L 3,3 z"; - NArtBpath * bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - } - - void testReadFloatingPoint() { - NArtBpath bpath_good[5+1]; - bpath_good[0].code = NR_MOVETO; - bpath_good[0].x3 = .01; - bpath_good[0].y3 = .02; - bpath_good[1].code = NR_LINETO; - bpath_good[1].x3 = .04; - bpath_good[1].y3 = .02; - bpath_good[2].code = NR_LINETO; - bpath_good[2].x3 = 1.5; - bpath_good[2].y3 = 1.6; - bpath_good[3].code = NR_LINETO; - bpath_good[3].x3 = .01; - bpath_good[3].y3 = .08; - bpath_good[4].code = NR_LINETO; - bpath_good[4].x3 = .01; - bpath_good[4].y3 = .02; - bpath_good[5].code = NR_END; - { // Test decimals - char const * path_str = "M .01,.02 L.04.02 L1.5,1.6L0.01,0.08 .01.02 z"; - NArtBpath * bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - { // Test exponent - char const * path_str = "M 1e-2,.2e-1 L 0.004e1,0.0002e+2 L0150E-2,1.6e0L1.0e-2,80e-3 z"; - NArtBpath * bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - } - - void testReadImplicitSeparation() { - // Coordinates need not be separated by whitespace if they can still be read unambiguously - NArtBpath bpath_good[5+1]; - bpath_good[0].code = NR_MOVETO; - bpath_good[0].x3 = .1; - bpath_good[0].y3 = .2; - bpath_good[1].code = NR_LINETO; - bpath_good[1].x3 = .4; - bpath_good[1].y3 = .2; - bpath_good[2].code = NR_LINETO; - bpath_good[2].x3 = .4; - bpath_good[2].y3 = .8; - bpath_good[3].code = NR_LINETO; - bpath_good[3].x3 = .1; - bpath_good[3].y3 = .8; - bpath_good[4].code = NR_LINETO; - bpath_good[4].x3 = .1; - bpath_good[4].y3 = .2; - bpath_good[5].code = NR_END; - { // Test absolute - char const * path_str = "M .1.2+0.4.2e0.4e0+8e-1.1.8 z"; - NArtBpath * bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - { // Test relative - char const * path_str = "m .1.2+0.3.0e0.0e0+6e-1-.3.0 z"; - NArtBpath * bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - } - - void testReadErrorMisplacedCharacter() { - char const * path_str; - NArtBpath * bpath; - NArtBpath * bpath_good = rectangleBpath; - bpath_good[0].code = NR_MOVETO; - // Comma in the wrong place (commas may only appear between parameters) - path_str = "M 1,2 4,2 4,8 1,8 z , m 13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Comma in the wrong place (commas may only appear between parameters) - path_str = "M 1,2 4,2 4,8 1,8 z m,13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Period in the wrong place (no numbers after a 'z') - path_str = "M 1,2 4,2 4,8 1,8 z . m 13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Sign in the wrong place (no numbers after a 'z') - path_str = "M 1,2 4,2 4,8 1,8 z + - m 13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Digit in the wrong place (no numbers after a 'z') - path_str = "M 1,2 4,2 4,8 1,8 z 9809 m 13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Digit in the wrong place (no numbers after a 'z') - path_str = "M 1,2 4,2 4,8 1,8 z 9809 876 m 13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - - void testReadErrorUnrecognizedCharacter() { - char const * path_str; - NArtBpath * bpath; - NArtBpath * bpath_good = rectangleBpath; - bpath_good[0].code = NR_MOVETO; - // Unrecognized character - path_str = "M 1,2 4,2 4,8 1,8 z&m 13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Unrecognized character - path_str = "M 1,2 4,2 4,8 1,8 z m &13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - - void testReadErrorTypo() { - char const * path_str; - NArtBpath * bpath; - NArtBpath * bpath_good = rectangleBpath; - bpath_good[0].code = NR_MOVETO; - // Typo - path_str = "M 1,2 4,2 4,8 1,8 z j 13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - - bpath_good[0].code = NR_MOVETO_OPEN; - // Typo - path_str = "M 1,2 4,2 4,8 1,8 L 1,2 x m 13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - - void testReadErrorIllformedNumbers() { - char const * path_str; - NArtBpath * bpath; - NArtBpath * bpath_good = rectangleBpath; - bpath_good[0].code = NR_MOVETO; - // Double exponent - path_str = "M 1,2 4,2 4,8 1,8 z m 13e4e5,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Double sign - path_str = "M 1,2 4,2 4,8 1,8 z m +-13,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Double sign - path_str = "M 1,2 4,2 4,8 1,8 z m 13e+-12,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // No digit - path_str = "M 1,2 4,2 4,8 1,8 z m .e12,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // No digit - path_str = "M 1,2 4,2 4,8 1,8 z m .,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // No digit - path_str = "M 1,2 4,2 4,8 1,8 z m +,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // No digit - path_str = "M 1,2 4,2 4,8 1,8 z m +.e+,15"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - - void testReadErrorJunk() { - char const * path_str; - NArtBpath * bpath; - NArtBpath * bpath_good = rectangleBpath; - bpath_good[0].code = NR_MOVETO; - // Junk - path_str = "M 1,2 4,2 4,8 1,8 z j 357 hkjh.,34e34 90ih6kj4 h5k6vlh4N.,6,45wikuyi3yere..3487 m 13,23"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - - void testReadErrorStopReading() { - char const * path_str; - NArtBpath * bpath; - NArtBpath * bpath_good = rectangleBpath; - bpath_good[0].code = NR_MOVETO; - // Unrecognized parameter - path_str = "M 1,2 4,2 4,8 1,8 z m #$%,23,34"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Invalid parameter - path_str = "M 1,2 4,2 4,8 1,8 z m #$%,23,34"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - // Illformed parameter - path_str = "M 1,2 4,2 4,8 1,8 z m +-12,23,34"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - - bpath_good[0].code = NR_MOVETO_OPEN; - // "Third" parameter - path_str = "M 1,2 4,2 4,8 1,8 1,2,3 M 12,23"; - bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,bpath_good)); - g_free(bpath); - } - - void testRoundTrip() { - // This is the easiest way to (also) test writing path data, as a path can be written in more than one way. - NArtBpath * bpath; - NArtBpath * new_bpath; - char * path_str; - // Rectangle (closed) - bpath = sp_svg_read_path(rectanglesAbsoluteClosed[0].c_str()); - path_str = sp_svg_write_path(bpath); - new_bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,new_bpath)); - g_free(bpath); g_free(path_str); g_free(new_bpath); - // Rectangle (open) - bpath = sp_svg_read_path(rectanglesAbsoluteOpen[0].c_str()); - path_str = sp_svg_write_path(bpath); - new_bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,new_bpath)); - g_free(bpath); g_free(path_str); g_free(new_bpath); - // Concatenated rectangles - bpath = sp_svg_read_path((rectanglesAbsoluteClosed[0] + rectanglesRelativeOpen[0] + rectanglesRelativeClosed[0] + rectanglesAbsoluteOpen[0]).c_str()); - path_str = sp_svg_write_path(bpath); - new_bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,new_bpath)); - g_free(bpath); g_free(path_str); g_free(new_bpath); - // Zero-length subpaths - bpath = sp_svg_read_path("M 0,0 M 1,1 L 2,2 M 3,3 z M 4,4 L 5,5 z M 6,6"); - path_str = sp_svg_write_path(bpath); - new_bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath,new_bpath)); - g_free(bpath); g_free(path_str); g_free(new_bpath); - // Floating-point - bpath = sp_svg_read_path("M .01,.02 L 0.04,0.02 L.04,.08L0.01,0.08 z""M 1e-2,.2e-1 L 0.004e1,0.0002e+2 L04E-2,.08e0L1.0e-2,80e-3 z"); - path_str = sp_svg_write_path(bpath); - new_bpath = sp_svg_read_path(path_str); - TS_ASSERT(bpathEqual(bpath, new_bpath, 1e-17)); - g_free(bpath); g_free(path_str); g_free(new_bpath); - } - - void testMinexpPrecision() { - NArtBpath * bpath; - char * path_str; - // Default values - prefs_set_int_attribute("options.svgoutput", "allowrelativecoordinates", 1); - prefs_set_int_attribute("options.svgoutput", "forcerepeatcommands", 0); - prefs_set_int_attribute("options.svgoutput", "numericprecision", 8); - prefs_set_int_attribute("options.svgoutput", "minimumexponent", -8); - bpath = sp_svg_read_path("M 123456781,1.23456781e-8 L 123456782,1.23456782e-8 L 123456785,1.23456785e-8 L 10123456400,1.23456785e-8 L 123456789,1.23456789e-8 L 123456789,101.234564e-8 L 123456789,1.23456789e-8"); - path_str = sp_svg_write_path(bpath); - TS_ASSERT_RELATION( streq_rel , "m 123456780,1.2345678e-8 0,0 10,1e-15 9999999210,0 -9999999210,0 0,9.99999921e-7 0,-9.99999921e-7" , path_str ); - g_free(bpath); g_free(path_str); - } - -private: - bool bpathEqual(NArtBpath const * a, NArtBpath const * b, double eps = 1e-16) { - while(a->code != NR_END && b->code == a->code) { - switch(a->code) { - case NR_MOVETO: - case NR_MOVETO_OPEN: - case NR_LINETO: - if (!Geom::are_near(a->x3,b->x3, eps) || !Geom::are_near(a->y3,b->y3, eps)) return false; - break; - case NR_CURVETO: - if (!Geom::are_near(a->x1,b->x1, eps) || !Geom::are_near(a->y1,b->y1, eps)) return false; - if (!Geom::are_near(a->x2,b->x2, eps) || !Geom::are_near(a->y2,b->y2, eps)) return false; - if (!Geom::are_near(a->x3,b->x3, eps) || !Geom::are_near(a->y3,b->y3, eps)) return false; - break; - default: - TS_FAIL("Unknown path code!"); - } - a++; - b++; - } - return a->code == b->code; - } -}; - - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/svg/svg-path.cpp b/src/svg/svg-path.cpp index 81eb7da59..334ba0c1a 100644 --- a/src/svg/svg-path.cpp +++ b/src/svg/svg-path.cpp @@ -5,6 +5,7 @@ Copyright (C) 2000 Eazel, Inc. Copyright (C) 2000 Lauris Kaplinski Copyright (C) 2001 Ximian, Inc. + Copyright (C) 2008 Johan Engelen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -22,8 +23,9 @@ Boston, MA 02111-1307, USA. Authors: - Raph Levien <raph@artofcode.com> - Lauris Kaplinski <lauris@ximian.com> + Johan Engelen + (old nartbpath code that has been deleted: Raph Levien <raph@artofcode.com>) + (old nartbpath code that has been deleted: Lauris Kaplinski <lauris@ximian.com>) */ #include <cstring> @@ -34,8 +36,6 @@ #include <glib/gstrfuncs.h> #include <glib.h> // g_assert() -#include "libnr/n-art-bpath.h" -#include "gnome-canvas-bpath-util.h" #include "svg/svg.h" #include "svg/path-string.h" @@ -47,636 +47,6 @@ #include <2geom/svg-path-parser.h> #include <2geom/exception.h> - -/* This module parses an SVG path element into an RsvgBpathDef. - - At present, there is no support for <marker> or any other contextual - information from the SVG file. The API will need to change rather - significantly to support these. - - Reference: SVG working draft 3 March 2000, section 8. -*/ - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif /* M_PI */ - -/* We are lazy ;-) (Lauris) */ -#define rsvg_bpath_def_new gnome_canvas_bpath_def_new -#define rsvg_bpath_def_moveto gnome_canvas_bpath_def_moveto -#define rsvg_bpath_def_lineto gnome_canvas_bpath_def_lineto -#define rsvg_bpath_def_curveto gnome_canvas_bpath_def_curveto -#define rsvg_bpath_def_closepath gnome_canvas_bpath_def_closepath - -struct RSVGParsePathCtx { - GnomeCanvasBpathDef *bpath; - double cpx, cpy; /* current point */ - double rpx, rpy; /* reflection point (for 's' and 't' commands) */ - double spx, spy; /* beginning of current subpath point */ - char cmd; /* current command (lowercase) */ - int param; /* parameter number */ - bool rel; /* true if relative coords */ - double params[7]; /* parameters that have been parsed */ -}; - -static void rsvg_path_arc_segment(RSVGParsePathCtx *ctx, - double xc, double yc, - double th0, double th1, - double rx, double ry, double x_axis_rotation) -{ - double sin_th, cos_th; - double a00, a01, a10, a11; - double x1, y1, x2, y2, x3, y3; - double t; - double th_half; - - sin_th = sin (x_axis_rotation * (M_PI / 180.0)); - cos_th = cos (x_axis_rotation * (M_PI / 180.0)); - /* inverse transform compared with rsvg_path_arc */ - a00 = cos_th * rx; - a01 = -sin_th * ry; - a10 = sin_th * rx; - a11 = cos_th * ry; - - th_half = 0.5 * (th1 - th0); - t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half); - x1 = xc + cos (th0) - t * sin (th0); - y1 = yc + sin (th0) + t * cos (th0); - x3 = xc + cos (th1); - y3 = yc + sin (th1); - x2 = x3 + t * sin (th1); - y2 = y3 - t * cos (th1); - rsvg_bpath_def_curveto(ctx->bpath, - a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, - a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, - a00 * x3 + a01 * y3, a10 * x3 + a11 * y3); -} - -/** - * rsvg_path_arc: Add an RSVG arc to the path context. - * @ctx: Path context. - * @rx: Radius in x direction (before rotation). - * @ry: Radius in y direction (before rotation). - * @x_axis_rotation: Rotation angle for axes. - * @large_arc_flag: 0 for arc length <= 180, 1 for arc >= 180. - * @sweep: 0 for "negative angle", 1 for "positive angle". - * @x: New x coordinate. - * @y: New y coordinate. - * - **/ -static void rsvg_path_arc (RSVGParsePathCtx *ctx, - double rx, double ry, double x_axis_rotation, - int large_arc_flag, int sweep_flag, - double x, double y) -{ - double sin_th, cos_th; - double a00, a01, a10, a11; - double x0, y0, x1, y1, xc, yc; - double d, sfactor, sfactor_sq; - double th0, th1, th_arc; - double px, py, pl; - int i, n_segs; - - sin_th = sin (x_axis_rotation * (M_PI / 180.0)); - cos_th = cos (x_axis_rotation * (M_PI / 180.0)); - - /* - Correction of out-of-range radii as described in Appendix F.6.6: - - 1. Ensure radii are non-zero (Done?). - 2. Ensure that radii are positive. - 3. Ensure that radii are large enough. - */ - - if(rx < 0.0) rx = -rx; - if(ry < 0.0) ry = -ry; - - px = cos_th * (ctx->cpx - x) * 0.5 + sin_th * (ctx->cpy - y) * 0.5; - py = cos_th * (ctx->cpy - y) * 0.5 - sin_th * (ctx->cpx - x) * 0.5; - pl = (px * px) / (rx * rx) + (py * py) / (ry * ry); - - if(pl > 1.0) - { - pl = sqrt(pl); - rx *= pl; - ry *= pl; - } - - /* Proceed with computations as described in Appendix F.6.5 */ - - a00 = cos_th / rx; - a01 = sin_th / rx; - a10 = -sin_th / ry; - a11 = cos_th / ry; - x0 = a00 * ctx->cpx + a01 * ctx->cpy; - y0 = a10 * ctx->cpx + a11 * ctx->cpy; - x1 = a00 * x + a01 * y; - y1 = a10 * x + a11 * y; - /* (x0, y0) is current point in transformed coordinate space. - (x1, y1) is new point in transformed coordinate space. - - The arc fits a unit-radius circle in this space. - */ - d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0); - sfactor_sq = 1.0 / d - 0.25; - if (sfactor_sq < 0) sfactor_sq = 0; - sfactor = sqrt (sfactor_sq); - if (sweep_flag == large_arc_flag) sfactor = -sfactor; - xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0); - yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0); - /* (xc, yc) is center of the circle. */ - - th0 = atan2 (y0 - yc, x0 - xc); - th1 = atan2 (y1 - yc, x1 - xc); - - th_arc = th1 - th0; - if (th_arc < 0 && sweep_flag) - th_arc += 2 * M_PI; - else if (th_arc > 0 && !sweep_flag) - th_arc -= 2 * M_PI; - - n_segs = (int) ceil (fabs (th_arc / (M_PI * 0.5 + 0.001))); - - for (i = 0; i < n_segs; i++) { - rsvg_path_arc_segment(ctx, xc, yc, - th0 + i * th_arc / n_segs, - th0 + (i + 1) * th_arc / n_segs, - rx, ry, x_axis_rotation); - } - - ctx->cpx = x; - ctx->cpy = y; -} - -static void rsvg_parse_path_do_cmd(RSVGParsePathCtx *ctx) -{ - double x1, y1, x2, y2, x3, y3; - - switch (ctx->cmd) { - case 'm': - /* moveto */ - if (ctx->param == 2) - { -#ifdef VERBOSE - g_print ("'m' moveto %g,%g\n", - ctx->params[0], ctx->params[1]); -#endif - rsvg_bpath_def_moveto (ctx->bpath, - ctx->params[0], ctx->params[1]); - ctx->cpx = ctx->rpx = ctx->spx = ctx->params[0]; - ctx->cpy = ctx->rpy = ctx->spy = ctx->params[1]; - ctx->param = 0; - ctx->cmd = 'l'; - /* Ref: http://www.w3.org/TR/SVG11/paths.html#PathDataMovetoCommands: "If a moveto is - * followed by multiple pairs of coordinates, the subsequent pairs are treated as - * implicit lineto commands." */ - } - break; - - case 'l': - /* lineto */ - if (ctx->param == 2) - { -#ifdef VERBOSE - g_print ("'l' lineto %g,%g\n", - ctx->params[0], ctx->params[1]); -#endif - rsvg_bpath_def_lineto (ctx->bpath, - ctx->params[0], ctx->params[1]); - ctx->cpx = ctx->rpx = ctx->params[0]; - ctx->cpy = ctx->rpy = ctx->params[1]; - ctx->param = 0; - } - break; - - case 'c': - /* curveto */ - if (ctx->param == 6) - { - x1 = ctx->params[0]; - y1 = ctx->params[1]; - x2 = ctx->params[2]; - y2 = ctx->params[3]; - x3 = ctx->params[4]; - y3 = ctx->params[5]; -#ifdef VERBOSE - g_print ("'c' curveto %g,%g %g,%g, %g,%g\n", - x1, y1, x2, y2, x3, y3); -#endif - rsvg_bpath_def_curveto (ctx->bpath, - x1, y1, x2, y2, x3, y3); - ctx->rpx = x2; - ctx->rpy = y2; - ctx->cpx = x3; - ctx->cpy = y3; - ctx->param = 0; - } - break; - - case 's': - /* smooth curveto */ - if (ctx->param == 4) - { - x1 = 2 * ctx->cpx - ctx->rpx; - y1 = 2 * ctx->cpy - ctx->rpy; - x2 = ctx->params[0]; - y2 = ctx->params[1]; - x3 = ctx->params[2]; - y3 = ctx->params[3]; -#ifdef VERBOSE - g_print ("'s' curveto %g,%g %g,%g, %g,%g\n", - x1, y1, x2, y2, x3, y3); -#endif - rsvg_bpath_def_curveto (ctx->bpath, - x1, y1, x2, y2, x3, y3); - ctx->rpx = x2; - ctx->rpy = y2; - ctx->cpx = x3; - ctx->cpy = y3; - ctx->param = 0; - } - break; - - case 'h': - /* horizontal lineto */ - if (ctx->param == 1) { -#ifdef VERBOSE - g_print ("'h' lineto %g,%g\n", - ctx->params[0], ctx->cpy); -#endif - rsvg_bpath_def_lineto (ctx->bpath, - ctx->params[0], ctx->cpy); - ctx->cpx = ctx->rpx = ctx->params[0]; - ctx->param = 0; - } - break; - - case 'v': - /* vertical lineto */ - if (ctx->param == 1) { -#ifdef VERBOSE - g_print ("'v' lineto %g,%g\n", - ctx->cpx, ctx->params[0]); -#endif - rsvg_bpath_def_lineto (ctx->bpath, - ctx->cpx, ctx->params[0]); - ctx->cpy = ctx->rpy = ctx->params[0]; - ctx->param = 0; - } - break; - - case 'q': - /* quadratic bezier curveto */ - - /* non-normative reference: - http://www.icce.rug.nl/erikjan/bluefuzz/beziers/beziers/beziers.html - */ - if (ctx->param == 4) - { - /* raise quadratic bezier to cubic */ - x1 = (ctx->cpx + 2 * ctx->params[0]) * (1.0 / 3.0); - y1 = (ctx->cpy + 2 * ctx->params[1]) * (1.0 / 3.0); - x3 = ctx->params[2]; - y3 = ctx->params[3]; - x2 = (x3 + 2 * ctx->params[0]) * (1.0 / 3.0); - y2 = (y3 + 2 * ctx->params[1]) * (1.0 / 3.0); -#ifdef VERBOSE - g_print("'q' curveto %g,%g %g,%g, %g,%g\n", - x1, y1, x2, y2, x3, y3); -#endif - rsvg_bpath_def_curveto(ctx->bpath, - x1, y1, x2, y2, x3, y3); - ctx->rpx = ctx->params[0]; - ctx->rpy = ctx->params[1]; - ctx->cpx = x3; - ctx->cpy = y3; - ctx->param = 0; - } - break; - - case 't': - /* Truetype quadratic bezier curveto */ - if (ctx->param == 2) { - double xc, yc; /* quadratic control point */ - - xc = 2 * ctx->cpx - ctx->rpx; - yc = 2 * ctx->cpy - ctx->rpy; - /* generate a quadratic bezier with control point = xc, yc */ - x1 = (ctx->cpx + 2 * xc) * (1.0 / 3.0); - y1 = (ctx->cpy + 2 * yc) * (1.0 / 3.0); - x3 = ctx->params[0]; - y3 = ctx->params[1]; - x2 = (x3 + 2 * xc) * (1.0 / 3.0); - y2 = (y3 + 2 * yc) * (1.0 / 3.0); -#ifdef VERBOSE - g_print ("'t' curveto %g,%g %g,%g, %g,%g\n", - x1, y1, x2, y2, x3, y3); -#endif - rsvg_bpath_def_curveto (ctx->bpath, - x1, y1, x2, y2, x3, y3); - ctx->rpx = xc; - ctx->rpy = yc; - ctx->cpx = x3; - ctx->cpy = y3; - ctx->param = 0; - } - break; - - case 'a': - if (ctx->param == 7) - { - rsvg_path_arc(ctx, - ctx->params[0], ctx->params[1], ctx->params[2], - (int) ctx->params[3], (int) ctx->params[4], - ctx->params[5], ctx->params[6]); - ctx->param = 0; - } - break; - - default: - g_assert_not_reached(); - } -} - -static void rsvg_parse_path_do_closepath(RSVGParsePathCtx *const ctx, const char next_cmd) -{ - g_assert(ctx->param == 0); - - rsvg_bpath_def_closepath (ctx->bpath); - ctx->cpx = ctx->rpx = ctx->spx; - ctx->cpy = ctx->rpy = ctx->spy; - - if (next_cmd != 0 && next_cmd != 'm') { - // This makes sure we do the right moveto if the closepath is followed by anything other than a moveto. - /* Ref: http://www.w3.org/TR/SVG11/paths.html#PathDataClosePathCommand: "If a - * "closepath" is followed immediately by a "moveto", then the "moveto" identifies - * the start point of the next subpath. If a "closepath" is followed immediately by - * any other command, then the next subpath starts at the same initial point as the - * current subpath." */ - - ctx->cmd = 'm'; - ctx->params[0] = ctx->cpx; - ctx->params[1] = ctx->cpy; - ctx->param = 2; - rsvg_parse_path_do_cmd(ctx); - - /* Any token after a closepath must be a command, not a parameter. We enforce this - * by clearing cmd rather than leaving as 'm'. */ - ctx->cmd = '\0'; - } -} - -static char const* rsvg_parse_unsigned_int(guint64 *val, char const *begin, bool zeroVal = true) { - if (zeroVal) *val = 0; - while('0' <= *begin && *begin <= '9') { - *val *= 10; - *val += *begin - '0'; - begin++; - } - return begin; -} - -static char const* rsvg_parse_sign(bool *neg, char const *begin) { - *neg = false; - if (*begin == '+') { - begin++; - } else if (*begin == '-') { - *neg = true; - begin++; - } - return begin; -} - -static char const* rsvg_parse_int(gint64 *val, char const *begin) { - bool neg; - char const *begin_of_int = rsvg_parse_sign(&neg, begin); - char const *end_of_int = rsvg_parse_unsigned_int((guint64*)val, begin_of_int); - if (neg) *val = -(*val); - return end_of_int==begin_of_int ? begin : end_of_int; -} - -static char const* rsvg_parse_unsigned_float(double *val, char const *begin) { - // A number is either one or more digits, optionally followed by a period and zero or more digits (and an exponent), - // or zero or more digits, followed by a period and one or more digits (and an exponent) - // See http://www.w3.org/TR/SVG/paths.html#PathDataBNF - guint64 intval; - int exp=0; - char const *begin_of_num = begin; - char const *end_of_num = rsvg_parse_unsigned_int(&intval, begin_of_num); - if (*end_of_num == '.') { - char const *begin_of_frac = end_of_num+1; - char const *end_of_frac = rsvg_parse_unsigned_int(&intval, begin_of_frac, false); - if (end_of_num != begin_of_num || end_of_frac != begin_of_frac) { - end_of_num = end_of_frac; - exp = -(int)(end_of_frac-begin_of_frac); - } - } - if (end_of_num != begin_of_num && (*end_of_num == 'e' || *end_of_num == 'E')) { - gint64 exponent; - char const *begin_of_exp = end_of_num+1; - char const *end_of_exp = rsvg_parse_int(&exponent, begin_of_exp); - if (end_of_exp != begin_of_exp) { - end_of_num = end_of_exp; - exp += (int)exponent; - } - } - - *val = ( exp < 0 - ? intval / pow(10, -exp) - : intval * pow(10, exp) ); - return end_of_num; -} - -static char const* rsvg_parse_float(double *val, char const *begin) { - bool neg; - char const *begin_of_num = rsvg_parse_sign(&neg, begin); - char const *end_of_num = rsvg_parse_unsigned_float(val, begin_of_num); - if (neg) *val = -(*val); - return end_of_num == begin_of_num ? begin : end_of_num; -} - -static void rsvg_parse_path_data(RSVGParsePathCtx *ctx, char const *const begin) { - /* fixme: Do better error processing: e.g. at least stop parsing as soon as we find an error. - * At some point we'll need to do all of - * http://www.w3.org/TR/SVG11/implnote.html#ErrorProcessing. - */ - - /* Comma is always allowed after a number token (so long as it's followed by another number: - * see require_number), and never allowed anywhere else. Only one comma is allowed between - * neighbouring number tokens. */ - bool comma_allowed = false; - - /* After a command other than closepath, and after a comma, we require a number. */ - bool require_number = false; - - for (char const *cur = begin;; ++cur) { - int const c = *cur; - if (c <= ' ') { - switch (c) { - case ' ': - case '\t': - case '\n': - case '\r': - /* wsp */ - break; - - case '\0': - if (require_number || ctx->param) { - goto error; - } - goto done; - - default: - goto error; - } - } else if (c == ',') { - if (!comma_allowed) { - goto error; - } - comma_allowed = false; - require_number = true; - } else if (c <= '9') { - if (!ctx->cmd || ctx->cmd == 'z') { - goto error; - } - - double val; - char const *const end = rsvg_parse_float(&val, cur); - if (cur == end) { - goto error; - } - - /* Special requirements for elliptical-arc arguments. */ - if (ctx->cmd == 'a') { - if (ctx->param < 2) { - if (c <= '-') { - /* Error: sign not allowed for first two params. */ - goto error; - } - } else if (ctx->param <= 4 && ctx->param >= 3) { - if (end - cur != 1 || c < '0' || c > '1') { - /* Error: flag must be either literally "0" or literally "1". */ - goto error; - } - } - } - - if (ctx->rel) { - /* Handle relative coordinates. */ - switch (ctx->cmd) { - case 'l': - case 'm': - case 'c': - case 's': - case 'q': - case 't': - if ( ctx->param & 1 ) { - val += ctx->cpy; /* odd param, y */ - } else { - val += ctx->cpx; /* even param, x */ - } - break; - case 'a': - /* rule: sixth and seventh are x and y, rest are not - relative */ - if (ctx->param == 5) - val += ctx->cpx; - else if (ctx->param == 6) - val += ctx->cpy; - break; - case 'h': - /* rule: x-relative */ - val += ctx->cpx; - break; - case 'v': - /* rule: y-relative */ - val += ctx->cpy; - break; - } - } - ctx->params[ctx->param++] = val; - rsvg_parse_path_do_cmd(ctx); - comma_allowed = true; - require_number = false; - cur = end - 1; - } else { - /* Command. */ - if (require_number || ctx->param) { - goto error; - } - char next_cmd; - if (c <= 'Z') { - next_cmd = c + ('a' - 'A'); - ctx->rel = false; - } else { - next_cmd = c; - ctx->rel = true; - } - - comma_allowed = false; - require_number = true; - switch (next_cmd) { - case 'z': - require_number = false; - case 'm': - case 'l': - case 'h': - case 'v': - case 'c': - case 's': - case 'q': - case 't': - case 'a': - /* valid command */ - break; - - default: - goto error; - } - - if (ctx->cmd == 'z') { - /* Closepath is the only command that allows no arguments. */ - rsvg_parse_path_do_closepath(ctx, next_cmd); - } - ctx->cmd = next_cmd; - } - } - -done: - if (ctx->cmd == 'z') { - rsvg_parse_path_do_closepath(ctx, 0); - } - return; - -error: - /* todo: set an error indicator. */ - goto done; -} - - -NArtBpath *sp_svg_read_path(gchar const *str) -{ - RSVGParsePathCtx ctx; - NArtBpath *bpath; - - ctx.bpath = gnome_canvas_bpath_def_new (); - ctx.cpx = 0.0; - ctx.cpy = 0.0; - ctx.cmd = 0; - ctx.param = 0; - - rsvg_parse_path_data (&ctx, str); - - gnome_canvas_bpath_def_art_finish (ctx.bpath); - - bpath = g_new (NArtBpath, ctx.bpath->n_bpath); - memcpy (bpath, ctx.bpath->bpath, ctx.bpath->n_bpath * sizeof (NArtBpath)); - g_assert ((bpath + ctx.bpath->n_bpath - 1)->code == NR_END); - gnome_canvas_bpath_def_unref (ctx.bpath); - - return bpath; -} - /* * Parses the path in str. When an error is found in the pathstring, this method * returns a truncated path up to where the error was found in the pathstring. @@ -704,48 +74,6 @@ Geom::PathVector sp_svg_read_pathv(char const * str) return pathv; } -gchar *sp_svg_write_path(NArtBpath const *bpath) -{ - bool closed=false; - - g_return_val_if_fail (bpath != NULL, NULL); - - Inkscape::SVG::PathString str; - - for (int i = 0; bpath[i].code != NR_END; i++){ - switch (bpath [i].code){ - case NR_LINETO: - if (!closed || bpath[i+1].code == NR_LINETO || bpath[i+1].code == NR_CURVETO) { - str.lineTo(bpath[i].x3, bpath[i].y3); - } - break; - - case NR_CURVETO: - str.curveTo(bpath[i].x1, bpath[i].y1, - bpath[i].x2, bpath[i].y2, - bpath[i].x3, bpath[i].y3); - break; - - case NR_MOVETO_OPEN: - case NR_MOVETO: - if (closed) { - str.closePath(); - } - closed = ( bpath[i].code == NR_MOVETO ); - str.moveTo(bpath[i].x3, bpath[i].y3); - break; - - default: - g_assert_not_reached (); - } - } - if (closed) { - str.closePath(); - } - - return g_strdup(str.c_str()); -} - static void sp_svg_write_curve(Inkscape::SVG::PathString & str, Geom::Curve const * c) { if(Geom::LineSegment const *line_segment = dynamic_cast<Geom::LineSegment const *>(c)) { // don't serialize stitch segments diff --git a/src/svg/svg.h b/src/svg/svg.h index 8617d4865..0e9939bec 100644 --- a/src/svg/svg.h +++ b/src/svg/svg.h @@ -66,9 +66,7 @@ double sp_svg_read_percentage (const char * str, double def); /* NB! As paths can be long, we use here dynamic string */ -NArtBpath * sp_svg_read_path (const char * str); Geom::PathVector sp_svg_read_pathv (char const * str); -gchar * sp_svg_write_path (const NArtBpath * bpath); gchar * sp_svg_write_path (Geom::PathVector const &p); gchar * sp_svg_write_path (Geom::Path const &p); |
