Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
svg-path.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * svg-path.cpp: Parse SVG path element data into bezier path.
4 * Authors:
5 * Johan Engelen
6 * (old nartbpath code that has been deleted: Raph Levien <raph@artofcode.com>)
7 * (old nartbpath code that has been deleted: Lauris Kaplinski <lauris@ximian.com>)
8 *
9 * Copyright (C) 2000 Eazel, Inc.
10 * Copyright (C) 2000 Lauris Kaplinski
11 * Copyright (C) 2001 Ximian, Inc.
12 * Copyright (C) 2008 Johan Engelen
13 *
14 * Copyright (C) 2000-2008 authors
15 *
16 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
17 */
18
19#include <cstring>
20#include <string>
21#include <glib.h> // g_assert()
22
23#include <2geom/pathvector.h>
24#include <2geom/curves.h>
26#include <2geom/path-sink.h>
28
29#include "svg/svg.h"
30#include "svg/path-string.h"
31
32/*
33 * Parses the path in str. When an error is found in the pathstring, this method
34 * returns a truncated path up to where the error was found in the pathstring.
35 * Returns an empty PathVector when str==NULL
36 */
38{
39 Geom::PathVector pathv;
40 if (!str)
41 return pathv; // return empty pathvector when str == NULL
42
46
47 try {
48 parser.parse(str);
49 }
50 catch (Geom::SVGPathParseError &e) {
51 builder.flush();
52 // This warning is extremely annoying when testing
53 g_warning(
54 "Malformed SVG path, truncated path up to where error was found.\n Input path=\"%s\"\n Parsed path=\"%s\"",
55 str, sp_svg_write_path(pathv).c_str());
56 }
57
58 return pathv;
59}
60
61static void sp_svg_write_curve(Inkscape::SVG::PathString & str, Geom::Curve const * c, bool normalize = false) {
62 // TODO: this code needs to removed and replaced by appropriate path sink
63 if(Geom::LineSegment const *line_segment = dynamic_cast<Geom::LineSegment const *>(c)) {
64 // don't serialize stitch segments
65 if (!dynamic_cast<Geom::Path::StitchSegment const *>(c)) {
66 if (!normalize && line_segment->initialPoint()[Geom::X] == line_segment->finalPoint()[Geom::X]) {
67 str.verticalLineTo( line_segment->finalPoint()[Geom::Y] );
68 } else if (!normalize && line_segment->initialPoint()[Geom::Y] == line_segment->finalPoint()[Geom::Y]) {
69 str.horizontalLineTo( line_segment->finalPoint()[Geom::X] );
70 } else {
71 str.lineTo( (*line_segment)[1][0], (*line_segment)[1][1] );
72 }
73 }
74 }
75 else if(Geom::QuadraticBezier const *quadratic_bezier = dynamic_cast<Geom::QuadraticBezier const *>(c)) {
76 if (normalize) {
77 // Convert to bezier curve
78 double x1 = 1.0 / 3 * quadratic_bezier->initialPoint()[0] + 2.0 / 3 * (*quadratic_bezier)[1][0];
79 double x2 = 2.0 / 3 * (*quadratic_bezier)[1][0] + 1.0 / 3 * (*quadratic_bezier)[2][0];
80 double y1 = 1.0 / 3 * quadratic_bezier->initialPoint()[1] + 2.0 / 3 * (*quadratic_bezier)[1][1];
81 double y2 = 2.0 / 3 * (*quadratic_bezier)[1][1] + 1.0 / 3 * (*quadratic_bezier)[2][1];
82 str.curveTo(x1, y1, x2, y2, (*quadratic_bezier)[2][0], (*quadratic_bezier)[2][1]);
83 } else {
84 str.quadTo( (*quadratic_bezier)[1][0], (*quadratic_bezier)[1][1],
85 (*quadratic_bezier)[2][0], (*quadratic_bezier)[2][1] );
86 }
87 }
88 else if(Geom::CubicBezier const *cubic_bezier = dynamic_cast<Geom::CubicBezier const *>(c)) {
89 str.curveTo( (*cubic_bezier)[1][0], (*cubic_bezier)[1][1],
90 (*cubic_bezier)[2][0], (*cubic_bezier)[2][1],
91 (*cubic_bezier)[3][0], (*cubic_bezier)[3][1] );
92 }
93 else if(Geom::EllipticalArc const *elliptical_arc = dynamic_cast<Geom::EllipticalArc const *>(c)) {
94 str.arcTo( elliptical_arc->ray(Geom::X), elliptical_arc->ray(Geom::Y),
95 Geom::deg_from_rad(elliptical_arc->rotationAngle()),
96 elliptical_arc->largeArc(), elliptical_arc->sweep(),
97 elliptical_arc->finalPoint() );
98 } else {
99 //this case handles sbasis as well as all other curve types
100 Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c->toSBasis(), 0.1);
101
102 //recurse to convert the new path resulting from the sbasis to svgd
103 for(const auto & iter : sbasis_path) {
104 sp_svg_write_curve(str, &iter, normalize);
105 }
106 }
107}
108
109static void sp_svg_write_path(Inkscape::SVG::PathString & str, Geom::Path const & p, bool normalize = false) {
110 str.moveTo( p.initialPoint()[0], p.initialPoint()[1] );
111
112 for(Geom::Path::const_iterator cit = p.begin(); cit != p.end_open(); ++cit) {
113 sp_svg_write_curve(str, &(*cit), normalize);
114 }
115
116 if (p.closed()) {
117 str.closePath();
118 }
119}
120
121std::string sp_svg_write_path(Geom::PathVector const &p, bool normalize) {
123 if (normalize) {
125 }
126
127 for(const auto & pit : p) {
128 sp_svg_write_path(str, pit, normalize);
129 }
130
131 return str;
132}
133
134std::string sp_svg_write_path(Geom::Path const &p) {
136
137 sp_svg_write_path(str, p);
138
139 return str;
140}
141
142/*
143 Local Variables:
144 mode:c++
145 c-file-style:"stroustrup"
146 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
147 indent-tabs-mode:nil
148 fill-column:99
149 End:
150*/
151// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
vector_type normalize(const vector_type)
Abstract continuous curve on a plane defined on [0,1].
Definition curve.h:78
Elliptical arc curve.
Store paths to a PathVector.
Definition path-sink.h:226
Sequence of subpaths.
Definition pathvector.h:122
Sequence of contiguous curves, aka spline.
Definition path.h:353
bool closed() const
Check whether the path is closed.
Definition path.h:503
const_iterator end_open() const
Definition path.h:467
Point initialPoint() const
Get the first point in the path.
Definition path.h:705
const_iterator begin() const
Definition path.h:464
Read SVG path data and feed it to a PathSink.
void setZSnapThreshold(Coord threshold)
Set the threshold for considering the closing segment degenerate.
void parse(char const *str, int len=-1)
Parse a C-style string.
Builder for SVG path strings.
Definition path-string.h:38
PathString & curveTo(Geom::Coord x0, Geom::Coord y0, Geom::Coord x1, Geom::Coord y1, Geom::Coord x, Geom::Coord y)
PathString & moveTo(Geom::Coord x, Geom::Coord y)
Definition path-string.h:67
PathString & verticalLineTo(Geom::Coord y)
Definition path-string.h:95
PathString & arcTo(Geom::Coord rx, Geom::Coord ry, Geom::Coord rot, bool large_arc, bool sweep, Geom::Point p)
PathString & lineTo(Geom::Coord x, Geom::Coord y)
Definition path-string.h:79
PathString & quadTo(Geom::Coord cx, Geom::Coord cy, Geom::Coord x, Geom::Coord y)
PathString & horizontalLineTo(Geom::Coord x)
Definition path-string.h:89
Include all curve types.
double c[8][4]
constexpr Coord EPSILON
Default "acceptably small" value.
Definition coord.h:84
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
Path cubicbezierpath_from_sbasis(D2< SBasis > const &B, double tol)
callback interface for SVG path data
Inkscape::SVG::PathString - builder for SVG path strings.
PathVector - a sequence of subpaths.
Conversion between SBasis and Bezier basis polynomials.
parse SVG path specifications
Geom::PathVector sp_svg_read_pathv(char const *str)
Definition svg-path.cpp:37
static void sp_svg_write_curve(Inkscape::SVG::PathString &str, Geom::Curve const *c, bool normalize=false)
Definition svg-path.cpp:61
static void sp_svg_write_path(Inkscape::SVG::PathString &str, Geom::Path const &p, bool normalize=false)
Definition svg-path.cpp:109
Glib::RefPtr< Gtk::Builder > builder