X-Git-Url: https://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Fsvgtiny.c;h=69cbcf7125b2f7ae540d5743e40be7d0edf3200f;hb=d5060009e934f2715a35601f7e4192702a473216;hp=76df69aa573dc0d6b938ab206b2d2fd0384beaf0;hpb=0f0342a4416a5b3bb03fe80d428d73a431f03a76;p=libsvgtiny.git diff --git a/src/svgtiny.c b/src/svgtiny.c index 76df69a..69cbcf7 100644 --- a/src/svgtiny.c +++ b/src/svgtiny.c @@ -20,6 +20,9 @@ #include "svgtiny.h" #include "svgtiny_internal.h" +/* Source file generated by `gperf`. */ +#include "autogenerated_colors.c" + #ifndef M_PI #define M_PI 3.14159265358979323846 #endif @@ -54,54 +57,74 @@ static void svgtiny_parse_transform_attributes(dom_element *node, static svgtiny_code svgtiny_add_path(float *p, unsigned int n, struct svgtiny_parse_state *state); static void _svgtiny_parse_color(const char *s, svgtiny_colour *c, + struct svgtiny_parse_state_gradient *grad, struct svgtiny_parse_state *state); /** - * Set the local externally-stored parts of a parse state. - * Call this in functions that made a new state on the stack. - * Doesn't make own copy of global state, such as the interned string list. + * Call this to ref the strings in a gradient state. */ -static void svgtiny_setup_state_local(struct svgtiny_parse_state *state) +static void svgtiny_grad_string_ref(struct svgtiny_parse_state_gradient *grad) { - if (state->gradient_x1 != NULL) { - dom_string_ref(state->gradient_x1); + if (grad->gradient_x1 != NULL) { + dom_string_ref(grad->gradient_x1); } - if (state->gradient_y1 != NULL) { - dom_string_ref(state->gradient_y1); + if (grad->gradient_y1 != NULL) { + dom_string_ref(grad->gradient_y1); } - if (state->gradient_x2 != NULL) { - dom_string_ref(state->gradient_x2); + if (grad->gradient_x2 != NULL) { + dom_string_ref(grad->gradient_x2); } - if (state->gradient_y2 != NULL) { - dom_string_ref(state->gradient_y2); + if (grad->gradient_y2 != NULL) { + dom_string_ref(grad->gradient_y2); } } /** - * Cleanup the local externally-stored parts of a parse state. - * Call this in functions that made a new state on the stack. - * Doesn't cleanup global state, such as the interned string list. + * Call this to clean up the strings in a gradient state. */ -static void svgtiny_cleanup_state_local(struct svgtiny_parse_state *state) +static void svgtiny_grad_string_cleanup( + struct svgtiny_parse_state_gradient *grad) { - if (state->gradient_x1 != NULL) { - dom_string_unref(state->gradient_x1); - state->gradient_x1 = NULL; + if (grad->gradient_x1 != NULL) { + dom_string_unref(grad->gradient_x1); + grad->gradient_x1 = NULL; } - if (state->gradient_y1 != NULL) { - dom_string_unref(state->gradient_y1); - state->gradient_y1 = NULL; + if (grad->gradient_y1 != NULL) { + dom_string_unref(grad->gradient_y1); + grad->gradient_y1 = NULL; } - if (state->gradient_x2 != NULL) { - dom_string_unref(state->gradient_x2); - state->gradient_x2 = NULL; + if (grad->gradient_x2 != NULL) { + dom_string_unref(grad->gradient_x2); + grad->gradient_x2 = NULL; } - if (state->gradient_y2 != NULL) { - dom_string_unref(state->gradient_y2); - state->gradient_y2 = NULL; + if (grad->gradient_y2 != NULL) { + dom_string_unref(grad->gradient_y2); + grad->gradient_y2 = NULL; } } +/** + * Set the local externally-stored parts of a parse state. + * Call this in functions that made a new state on the stack. + * Doesn't make own copy of global state, such as the interned string list. + */ +static void svgtiny_setup_state_local(struct svgtiny_parse_state *state) +{ + svgtiny_grad_string_ref(&(state->fill_grad)); + svgtiny_grad_string_ref(&(state->stroke_grad)); +} + +/** + * Cleanup the local externally-stored parts of a parse state. + * Call this in functions that made a new state on the stack. + * Doesn't cleanup global state, such as the interned string list. + */ +static void svgtiny_cleanup_state_local(struct svgtiny_parse_state *state) +{ + svgtiny_grad_string_cleanup(&(state->fill_grad)); + svgtiny_grad_string_cleanup(&(state->stroke_grad)); +} + /** * Create a new svgtiny_diagram structure. @@ -248,7 +271,6 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram, state.fill = 0x000000; state.stroke = svgtiny_TRANSPARENT; state.stroke_width = 1; - state.linear_gradient_stop_count = 0; /* parse tree */ code = svgtiny_parse_svg(svg, state); @@ -555,7 +577,7 @@ svgtiny_code svgtiny_parse_path(dom_element *path, p[i++] = last_cubic_y = last_quad_y = last_y = y; s += n; - } while (sscanf(s, "%f %n", &x, &n) == 1); + } while (sscanf(s, "%f %n", &y, &n) == 1); /* curveto (C, c) (6 arguments) */ } else if (sscanf(s, " %1[Cc] %f %f %f %f %f %f %n", command, @@ -1365,13 +1387,13 @@ void svgtiny_parse_paint_attributes(dom_element *node, exc = dom_element_get_attribute(node, state->interned_fill, &attr); if (exc == DOM_NO_ERR && attr != NULL) { - svgtiny_parse_color(attr, &state->fill, state); + svgtiny_parse_color(attr, &state->fill, &state->fill_grad, state); dom_string_unref(attr); } exc = dom_element_get_attribute(node, state->interned_stroke, &attr); if (exc == DOM_NO_ERR && attr != NULL) { - svgtiny_parse_color(attr, &state->stroke, state); + svgtiny_parse_color(attr, &state->stroke, &state->stroke_grad, state); dom_string_unref(attr); } @@ -1393,7 +1415,7 @@ void svgtiny_parse_paint_attributes(dom_element *node, while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); - _svgtiny_parse_color(value, &state->fill, state); + _svgtiny_parse_color(value, &state->fill, &state->fill_grad, state); free(value); } if ((s = strstr(style, "stroke:"))) { @@ -1401,7 +1423,7 @@ void svgtiny_parse_paint_attributes(dom_element *node, while (*s == ' ') s++; value = strndup(s, strcspn(s, "; ")); - _svgtiny_parse_color(value, &state->stroke, state); + _svgtiny_parse_color(value, &state->stroke, &state->stroke_grad, state); free(value); } if ((s = strstr(style, "stroke-width:"))) { @@ -1424,6 +1446,7 @@ void svgtiny_parse_paint_attributes(dom_element *node, */ static void _svgtiny_parse_color(const char *s, svgtiny_colour *c, + struct svgtiny_parse_state_gradient *grad, struct svgtiny_parse_state *state) { unsigned int r, g, b; @@ -1455,19 +1478,21 @@ static void _svgtiny_parse_color(const char *s, svgtiny_colour *c, } else if (5 < len && s[0] == 'u' && s[1] == 'r' && s[2] == 'l' && s[3] == '(') { - if (s[4] == '#') { + if (grad == NULL) { + *c = svgtiny_RGB(0, 0, 0); + } else if (s[4] == '#') { id = strdup(s + 5); if (!id) return; rparen = strchr(id, ')'); if (rparen) *rparen = 0; - svgtiny_find_gradient(id, state); + svgtiny_find_gradient(id, grad, state); free(id); - if (state->linear_gradient_stop_count == 0) + if (grad->linear_gradient_stop_count == 0) *c = svgtiny_TRANSPARENT; - else if (state->linear_gradient_stop_count == 1) - *c = state->gradient_stop[0].color; + else if (grad->linear_gradient_stop_count == 1) + *c = grad->gradient_stop[0].color; else *c = svgtiny_LINEAR_GRADIENT; } @@ -1481,10 +1506,11 @@ static void _svgtiny_parse_color(const char *s, svgtiny_colour *c, } void svgtiny_parse_color(dom_string *s, svgtiny_colour *c, + struct svgtiny_parse_state_gradient *grad, struct svgtiny_parse_state *state) { dom_string_ref(s); - _svgtiny_parse_color(dom_string_data(s), c, state); + _svgtiny_parse_color(dom_string_data(s), c, grad, state); dom_string_unref(s); } @@ -1566,6 +1592,7 @@ void svgtiny_parse_transform(char *s, float *ma, float *mb, a = d = 1; b = c = 0; e = f = 0; + n = 0; if ((sscanf(s, " matrix (%f %f %f %f %f %f ) %n", &a, &b, &c, &d, &e, &f, &n) == 6) && (n > 0)) ;