summaryrefslogtreecommitdiffstats
path: root/src/svg/svg-affine-parser.rl
diff options
context:
space:
mode:
Diffstat (limited to 'src/svg/svg-affine-parser.rl')
-rw-r--r--src/svg/svg-affine-parser.rl132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/svg/svg-affine-parser.rl b/src/svg/svg-affine-parser.rl
new file mode 100644
index 0000000..616ff44
--- /dev/null
+++ b/src/svg/svg-affine-parser.rl
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * SVG data parser
+ *
+ * Authors:
+ * Marc Jeanmougin <marc.jeanmougin@telecom-paris.fr>
+ *
+ * Copyright (C) 2019 Marc Jeanmougin (.rl parser, CSS-transform spec)
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ *
+ * THE CPP FILE IS GENERATED FROM THE RL FILE, DO NOT EDIT THE CPP
+ *
+ * To generate it, run
+ * ragel svg-affine-parser.rl -o svg-affine-parser.cpp
+ * sed -Ei 's/\(1\)/(true)/' svg-affine-parser.cpp
+ */
+
+#include <string>
+#include <glib.h>
+#include <2geom/transforms.h>
+#include "svg.h"
+#include "preferences.h"
+
+%%{
+ machine svg_transform;
+ write data noerror;
+}%%
+
+// https://www.w3.org/TR/css-transforms-1/#svg-syntax
+bool sp_svg_transform_read(gchar const *str, Geom::Affine *transform)
+{
+ if (str == nullptr)
+ return false;
+
+ std::vector<double> params;
+ Geom::Affine final_transform (Geom::identity());
+ *transform = final_transform;
+ Geom::Affine tmp_transform (Geom::identity());
+ int cs;
+ const char *p = str;
+ const char *pe = p + strlen(p) + 1;
+ const char *eof = pe;
+ char const *start_num = 0;
+ char const *ts = p;
+ char const *te = pe;
+ int act = 0;
+ if (pe == p+1) return true; // ""
+
+%%{
+ write init;
+
+ action number {
+ std::string buf(start_num, p);
+ params.push_back(g_ascii_strtod(buf.c_str(), NULL));
+ }
+
+ action translate { tmp_transform = Geom::Translate(params[0], params.size() == 1 ? 0 : params[1]); }
+ action scale { tmp_transform = Geom::Scale(params[0], params.size() == 1 ? params[0] : params[1]); }
+ action rotate {
+ if (params.size() == 1)
+ tmp_transform = Geom::Rotate(Geom::rad_from_deg(params[0]));
+ else {
+ tmp_transform = Geom::Translate(-params[1], -params[2]) *
+ Geom::Rotate(Geom::rad_from_deg(params[0])) *
+ Geom::Translate(params[1], params[2]);
+ }
+ }
+ action skewX { tmp_transform = Geom::Affine(1, 0, tan(params[0] * M_PI / 180.0), 1, 0, 0); }
+ action skewY { tmp_transform = Geom::Affine(1, tan(params[0] * M_PI / 180.0), 0, 1, 0, 0); }
+ action matrix { tmp_transform = Geom::Affine(params[0], params[1], params[2], params[3], params[4], params[5]);}
+ action transform {params.clear(); final_transform = tmp_transform * final_transform ;}
+ action transformlist { *transform = final_transform; /*printf("%p %p %p %p
+%d\n",p, pe, ts, te, cs);*/ return (te+1 == pe);}
+
+ comma = ',';
+ wsp = ( 10 | 13 | 9 | ' ');
+ sign = ('+' | '-');
+ digit_sequence = digit+;
+ exponent = ('e' | 'E') sign? digit_sequence;
+ fractional_constant = digit_sequence? '.' digit_sequence
+ | digit_sequence '.';
+ floating_point_constant = fractional_constant exponent?
+ | digit_sequence exponent;
+ integer_constant = digit_sequence;
+ number = ( sign? integer_constant | sign? floating_point_constant )
+ > {start_num = p;}
+ %number;
+
+ commawsp = (wsp+ comma? wsp*) | (comma wsp*);
+ translate = "translate" wsp* "(" wsp* number <: ( commawsp? number )? wsp* ")"
+ %translate;
+ scale = "scale" wsp* "(" wsp* number <: ( commawsp? number )? wsp* ")"
+ %scale;
+ rotate = "rotate" wsp* "(" wsp* number <: ( commawsp? number <: commawsp? number )? wsp* ")"
+ %rotate;
+ skewX = "skewX" wsp* "(" wsp* number wsp* ")"
+ %skewX;
+ skewY = "skewY" wsp* "(" wsp* number wsp* ")"
+ %skewY;
+ matrix = "matrix" wsp* "(" wsp*
+ number <: commawsp?
+ number <: commawsp?
+ number <: commawsp?
+ number <: commawsp?
+ number <: commawsp?
+ number wsp* ")"
+ %matrix;
+ transform = (matrix | translate | scale | rotate | skewX | skewY)
+ %transform;
+ transforms = transform ( commawsp? transform )**;
+ transformlist = wsp* transforms? wsp*;
+ main := |*
+ transformlist => transformlist;
+ *|;
+ write exec;
+}%%
+ g_warning("could not parse transform attribute");
+
+ return false;
+}
+
+/*
+ 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=ragel:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :