}
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);
}
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,
*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, ¶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;
+}
<?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" />
--- /dev/null
+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 '
<?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%)"
<?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 -->
<?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 -->