]> gitweb.michael.orlitzky.com - libsvgtiny.git/commitdiff
Reimplement parsing of viewbox
authorVincent Sanders <vince@kyllikki.org>
Tue, 2 Jul 2024 23:11:04 +0000 (00:11 +0100)
committerVincent Sanders <vince@kyllikki.org>
Thu, 4 Jul 2024 13:15:31 +0000 (14:15 +0100)
fixup tests that used non existant viewport attribute

src/svgtiny.c
src/svgtiny_internal.h
src/svgtiny_parse.c
test/data/colors.svg
test/data/polyline.mvg [new file with mode: 0644]
test/data/polyline.svg
test/data/polypoints.svg
test/data/transform.svg

index dacf2c854a5132de6a124b17b403a633aa0444a7..3813d7c2ce155a359488d0af83f5d83b56561ab0 100644 (file)
@@ -766,19 +766,11 @@ svgtiny_code svgtiny_parse_svg(dom_element *svg,
        }
 
        if (view_box) {
-               char *s = strndup(dom_string_data(view_box),
-                                 dom_string_byte_length(view_box));
-               float min_x, min_y, vwidth, vheight;
-               if (sscanf(s, "%f,%f,%f,%f",
-                               &min_x, &min_y, &vwidth, &vheight) == 4 ||
-                               sscanf(s, "%f %f %f %f",
-                               &min_x, &min_y, &vwidth, &vheight) == 4) {
-                       state.ctm.a = (float) state.viewport_width / vwidth;
-                       state.ctm.d = (float) state.viewport_height / vheight;
-                       state.ctm.e += -min_x * state.ctm.a;
-                       state.ctm.f += -min_y * state.ctm.d;
-               }
-               free(s);
+               svgtiny_parse_viewbox(dom_string_data(view_box),
+                                     dom_string_byte_length(view_box),
+                                     state.viewport_width,
+                                     state.viewport_height,
+                                     &state.ctm);
                dom_string_unref(view_box);
        }
 
index 4e58002907658b175ccbad16f89262b71af8de52..519f65fd275e70656cc5e40cc9c65f2b4f8fc4c1 100644 (file)
@@ -98,6 +98,9 @@ svgtiny_code svgtiny_parse_paint(const char *text, size_t textlen,
                svgtiny_colour *c);
 svgtiny_code svgtiny_parse_color(const char *text, size_t textlen,
                svgtiny_colour *c);
+svgtiny_code svgtiny_parse_viewbox(const char *text, size_t textlen,
+               float viewport_width, float viewport_height,
+               struct svgtiny_transformation_matrix *tm);
 
 /* svgtiny_gradient.c */
 svgtiny_code svgtiny_find_gradient(const char *id,
index 4ecc811044ef14f046ddbd9c0ea68d39ad579a7b..b459d1d2ea593feb08a5a429a416bac7ecf6e4ff 100644 (file)
@@ -1208,3 +1208,60 @@ svgtiny_parse_color(const char *text, size_t textlen, svgtiny_colour *c)
        *c = svgtiny_RGB(0, 0, 0);
        return svgtiny_SVG_ERROR;
 }
+
+/**
+ * parse a viewbox attribute
+ *
+ * https://www.w3.org/TR/SVG11/coords.html#ViewBoxAttribute
+ * https://www.w3.org/TR/SVG2/coords.html#ViewBoxAttribute
+ *
+ * <min-x>,? <min-y>,? <width>,? <height>
+ */
+svgtiny_code
+svgtiny_parse_viewbox(const char *text,
+                     size_t textlen,
+                     float viewport_width,
+                     float viewport_height,
+                     struct svgtiny_transformation_matrix *tm)
+{
+       const char *cursor = text; /* text cursor */
+       const char *textend = text + textlen;
+       const char *paramend;
+       float paramv[4];
+       int paramidx = 0;
+       svgtiny_code res;
+
+       /* advance cursor past optional whitespace */
+       advance_whitespace(&cursor, textend);
+
+       for (paramidx = 0; paramidx < 3; paramidx++) {
+               paramend = textend;
+               res = parse_number(cursor, &paramend, &paramv[paramidx]);
+               if (res != svgtiny_OK) {
+                       /* failed to parse number */
+                       return res;
+               }
+               cursor = paramend;
+               advance_comma_whitespace(&cursor, textend);
+       }
+       paramend = textend;
+       res = parse_number(cursor, &paramend, &paramv[paramidx]);
+       if (res != svgtiny_OK) {
+               /* failed to parse number */
+               return res;
+       }
+       cursor = paramend;
+       advance_whitespace(&cursor, textend);
+
+       if (cursor != textend) {
+               /* syntax error */
+               return svgtiny_SVG_ERROR;
+       }
+
+       tm->a = (float)viewport_width / paramv[2];
+       tm->d = (float)viewport_height / paramv[3];
+       tm->e += -paramv[0] * tm->a;
+       tm->f += -paramv[1] * tm->d;
+
+       return svgtiny_OK;
+}
index 8ddbe0766e539ce4bd2d9dd05983bdf2a6d86f20..2b518694262408c4dd3b8b7c69288fb7270397a6 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<svg width="1200" height="1200" viewPort="0 0 1200 1200" version="1.1" xmlns="http://www.w3.org/2000/svg">
+<svg width="1200" height="1200" viewBox="0 0 1200 1200" version="1.1" xmlns="http://www.w3.org/2000/svg">
     <rect fill="#01234567"      stroke=" #89ABCD"         x="100" y="100" width="1000" height="100" stroke-width="10" />
     <rect fill="#EFab "         stroke=" #cde "           x="100" y="200" width="1000" height="100" stroke-width="10" />
     <rect fill="#f67 "          stroke="#bB6677 "         x="100" y="300" width="1000" height="100" stroke-width="10" />
diff --git a/test/data/polyline.mvg b/test/data/polyline.mvg
new file mode 100644 (file)
index 0000000..573d3f1
--- /dev/null
@@ -0,0 +1,2 @@
+viewbox 0 0 120 120
+fill none stroke #801bff stroke-width 1 path 'M 20 100 L 40 60 L 70 80 L 100 20 ' 
index 2f37e4456fc0c891713fc8ac77fbbd01cbf14616..6a5216afa802969007998b188a2f7167940f45fe 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <svg width="120" height="120" 
-     viewPort="0 0 120 120" version="1.1"
+     viewBox=" 0,0 , 120  , 120 " version="1.1"
      xmlns="http://www.w3.org/2000/svg">
 
     <polyline fill="none" stroke="rgb(50.5%,10.8%,100.0%)"
index 9c8378194474dccae3c26f136a054d80a88aa986..1977638de396dabbc62ef4533b3509efbfdc2120 100644 (file)
@@ -1,6 +1,5 @@
 <?xml version="1.0"?>
-<svg width="200" height="200"  viewPort="0 0 200 200" version="1.1"
-     xmlns="http://www.w3.org/2000/svg">
+<svg width="200" height="200" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg">
 
     <g transform="translate(100,100)">
         <!-- smallest minimal point set is line from top left to bottom right -->
index da05c42c88db3b14ec54f992c484fa29df482da3..476d006dee675c0ff191037cf013ec1108a665d7 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<svg width="400" height="400"  viewPort="0 0 400 400" version="1.1"
+<svg width="400" height="400" viewBox="0 0 400 400" version="1.1"
      xmlns="http://www.w3.org/2000/svg">
 
     <!-- transforms with a simple triangle -->