From a64f3a1b503cb060bbf27c741cd0473cd585080d Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 3 Jul 2024 00:11:04 +0100 Subject: [PATCH] Reimplement parsing of viewbox fixup tests that used non existant viewport attribute --- src/svgtiny.c | 18 ++++--------- src/svgtiny_internal.h | 3 +++ src/svgtiny_parse.c | 57 ++++++++++++++++++++++++++++++++++++++++ test/data/colors.svg | 2 +- test/data/polyline.mvg | 2 ++ test/data/polyline.svg | 2 +- test/data/polypoints.svg | 3 +-- test/data/transform.svg | 2 +- 8 files changed, 71 insertions(+), 18 deletions(-) create mode 100644 test/data/polyline.mvg diff --git a/src/svgtiny.c b/src/svgtiny.c index dacf2c8..3813d7c 100644 --- a/src/svgtiny.c +++ b/src/svgtiny.c @@ -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); } diff --git a/src/svgtiny_internal.h b/src/svgtiny_internal.h index 4e58002..519f65f 100644 --- a/src/svgtiny_internal.h +++ b/src/svgtiny_internal.h @@ -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, diff --git a/src/svgtiny_parse.c b/src/svgtiny_parse.c index 4ecc811..b459d1d 100644 --- a/src/svgtiny_parse.c +++ b/src/svgtiny_parse.c @@ -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 + * + * ,? ,? ,? + */ +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, ¶mend, ¶mv[paramidx]); + if (res != svgtiny_OK) { + /* failed to parse number */ + return res; + } + cursor = paramend; + advance_comma_whitespace(&cursor, textend); + } + paramend = textend; + res = parse_number(cursor, ¶mend, ¶mv[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; +} diff --git a/test/data/colors.svg b/test/data/colors.svg index 8ddbe07..2b51869 100644 --- a/test/data/colors.svg +++ b/test/data/colors.svg @@ -1,5 +1,5 @@ - + diff --git a/test/data/polyline.mvg b/test/data/polyline.mvg new file mode 100644 index 0000000..573d3f1 --- /dev/null +++ b/test/data/polyline.mvg @@ -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 ' diff --git a/test/data/polyline.svg b/test/data/polyline.svg index 2f37e44..6a5216a 100644 --- a/test/data/polyline.svg +++ b/test/data/polyline.svg @@ -1,6 +1,6 @@ - + diff --git a/test/data/transform.svg b/test/data/transform.svg index da05c42..476d006 100644 --- a/test/data/transform.svg +++ b/test/data/transform.svg @@ -1,5 +1,5 @@ - -- 2.49.0