summaryrefslogtreecommitdiff
path: root/src/svgtiny.c
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2016-10-26 16:10:49 +0100
committerMichael Drake <tlsa@netsurf-browser.org>2016-10-26 16:10:49 +0100
commit4d485643c1a8a36f3127593e992bae197e70048f (patch)
treecfb7ecaeba8b4c4a8d01a5f565223f3927216883 /src/svgtiny.c
parent28ef4f0a47dcb9e257ce3b6f088d3ae09d65c2b5 (diff)
parent2ec1f74153c4a53252bdeee55e0fde14706ca598 (diff)
downloadlibsvgtiny-4d485643c1a8a36f3127593e992bae197e70048f.tar.gz
libsvgtiny-4d485643c1a8a36f3127593e992bae197e70048f.tar.bz2
Merge branch 'tlsa/fix-gradients'
Diffstat (limited to 'src/svgtiny.c')
-rw-r--r--src/svgtiny.c111
1 files changed, 65 insertions, 46 deletions
diff --git a/src/svgtiny.c b/src/svgtiny.c
index bd9aeaa..4661a58 100644
--- a/src/svgtiny.c
+++ b/src/svgtiny.c
@@ -54,54 +54,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.
@@ -152,11 +172,6 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram,
UNUSED(url);
- state.gradient_x1 = NULL;
- state.gradient_y1 = NULL;
- state.gradient_x2 = NULL;
- state.gradient_y2 = NULL;
-
parser = dom_xml_parser_create(NULL, NULL,
ignore_msg, NULL, &document);
@@ -253,7 +268,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);
@@ -1370,13 +1384,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);
}
@@ -1398,7 +1412,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:"))) {
@@ -1406,7 +1420,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:"))) {
@@ -1429,6 +1443,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;
@@ -1460,19 +1475,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;
}
@@ -1486,11 +1503,12 @@ 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)
{
- char *ss = strndup(dom_string_data(s), dom_string_byte_length(s));
- _svgtiny_parse_color(ss, c, state);
- free(ss);
+ dom_string_ref(s);
+ _svgtiny_parse_color(dom_string_data(s), c, grad, state);
+ dom_string_unref(s);
}
/**
@@ -1571,6 +1589,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))
;