From 60ce406e8b18627c6aab42c434830cc3dfbd67f3 Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 3 Nov 2012 16:46:39 +0000 Subject: [PATCH] More work towards libdom conversion --- src/svgtiny.c | 179 +++++++++++++++++++++++++---------------- src/svgtiny_gradient.c | 89 ++++++++++---------- src/svgtiny_internal.h | 7 +- src/svgtiny_strings.h | 16 +++- 4 files changed, 173 insertions(+), 118 deletions(-) diff --git a/src/svgtiny.c b/src/svgtiny.c index 79a87d7..635974f 100644 --- a/src/svgtiny.c +++ b/src/svgtiny.c @@ -53,6 +53,8 @@ static void svgtiny_parse_transform_attributes(dom_element *node, struct svgtiny_parse_state *state); 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 *state); /** @@ -165,15 +167,15 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram, state.viewport_width = viewport_width; state.viewport_height = viewport_height; -#define SVGTINY_STRING_ACTION(s) \ - if (dom_string_create_interned((const uint8_t *) #s, \ - strlen(#s), &state.interned_##s) \ +#define SVGTINY_STRING_ACTION2(s,n) \ + if (dom_string_create_interned((const uint8_t *) #n, \ + strlen(#n), &state.interned_##s) \ != DOM_NO_ERR) { \ code = svgtiny_LIBDOM_ERROR; \ goto cleanup; \ } #include "svgtiny_strings.h" -#undef SVGTINY_STRING_ACTION +#undef SVGTINY_STRING_ACTION2 svgtiny_parse_position_attributes(svg, state, &x, &y, &width, &height); diagram->width = width; @@ -202,11 +204,11 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram, dom_node_unref(document); cleanup: -#define SVGTINY_STRING_ACTION(s) \ +#define SVGTINY_STRING_ACTION2(s,n) \ if (state.interned_##s != NULL) \ dom_string_unref(state.interned_##s); //#include "svgtiny_strings.h" -#undef SVGTINY_STRING_ACTION +#undef SVGTINY_STRING_ACTION2 return code; } @@ -1027,28 +1029,38 @@ void svgtiny_parse_position_attributes(const dom_element *node, const struct svgtiny_parse_state state, float *x, float *y, float *width, float *height) { - xmlAttr *attr; + dom_string *attr; + dom_exception exc; *x = 0; *y = 0; *width = state.viewport_width; *height = state.viewport_height; - for (attr = node->properties; attr; attr = attr->next) { - const char *name = (const char *) attr->name; - const char *content = (const char *) attr->children->content; - if (strcmp(name, "x") == 0) - *x = svgtiny_parse_length(content, - state.viewport_width, state); - else if (strcmp(name, "y") == 0) - *y = svgtiny_parse_length(content, - state.viewport_height, state); - else if (strcmp(name, "width") == 0) - *width = svgtiny_parse_length(content, - state.viewport_width, state); - else if (strcmp(name, "height") == 0) - *height = svgtiny_parse_length(content, - state.viewport_height, state); + exc = dom_element_get_attribute(node, state.interned_x, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + *x = svgtiny_parse_length(attr, state.viewport_width, state); + dom_string_unref(attr); + } + + exc = dom_element_get_attribute(node, state.interned_y, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + *y = svgtiny_parse_length(attr, state.viewport_height, state); + dom_string_unref(attr); + } + + exc = dom_element_get_attribute(node, state.interned_width, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + *width = svgtiny_parse_length(attr, state.viewport_width, + state); + dom_string_unref(attr); + } + + exc = dom_element_get_attribute(node, state.interned_height, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + *height = svgtiny_parse_length(attr, state.viewport_height, + state); + dom_string_unref(attr); } } @@ -1095,7 +1107,7 @@ static float _svgtiny_parse_length(const char *s, int viewport_size, float svgtiny_parse_length(dom_string *s, int viewport_size, const struct svgtiny_parse_state state) { - const char *ss = strndup(dom_string_data(s), dom_string_length(s)); + char *ss = strndup(dom_string_data(s), dom_string_length(s)); float ret = _svgtiny_parse_length(ss, viewport_size, state); free(ss); return ret; @@ -1108,49 +1120,61 @@ float svgtiny_parse_length(dom_string *s, int viewport_size, void svgtiny_parse_paint_attributes(const dom_element *node, struct svgtiny_parse_state *state) { - const xmlAttr *attr; + dom_string *attr; + dom_exception exc; + + exc = dom_element_get_attribute(node, state->interned_fill, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + svgtiny_parse_color(attr, &state->fill, state); + dom_string_unref(attr); + } - for (attr = node->properties; attr; attr = attr->next) { - const char *name = (const char *) attr->name; - const char *content = (const char *) attr->children->content; - if (strcmp(name, "fill") == 0) - svgtiny_parse_color(content, &state->fill, state); - else if (strcmp(name, "stroke") == 0) - svgtiny_parse_color(content, &state->stroke, state); - else if (strcmp(name, "stroke-width") == 0) - state->stroke_width = svgtiny_parse_length(content, - state->viewport_width, *state); - else if (strcmp(name, "style") == 0) { - const char *style = (const char *) - attr->children->content; - const char *s; - char *value; - if ((s = strstr(style, "fill:"))) { - s += 5; - while (*s == ' ') - s++; - value = strndup(s, strcspn(s, "; ")); - svgtiny_parse_color(value, &state->fill, state); - free(value); - } - if ((s = strstr(style, "stroke:"))) { - s += 7; - while (*s == ' ') - s++; - value = strndup(s, strcspn(s, "; ")); - svgtiny_parse_color(value, &state->stroke, state); - free(value); - } - if ((s = strstr(style, "stroke-width:"))) { - s += 13; - while (*s == ' ') - s++; - value = strndup(s, strcspn(s, "; ")); - state->stroke_width = svgtiny_parse_length(value, + exc = dom_element_get_attribute(node, state->interned_stroke, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + svgtiny_parse_color(attr, &state->stroke, state); + dom_string_unref(attr); + } + + exc = dom_element_get_attribute(node, state->interned_stroke_width, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + state->stroke_width = svgtiny_parse_length(attr, state->viewport_width, *state); - free(value); - } + dom_string_unref(attr); + } + + exc = dom_element_get_attribute(node, state->interned_style, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + char *style = strndup(dom_string_data(attr), + dom_string_length(attr)); + const char *s; + char *value; + if ((s = strstr(style, "fill:"))) { + s += 5; + while (*s == ' ') + s++; + value = strndup(s, strcspn(s, "; ")); + _svgtiny_parse_color(value, &state->fill, state); + free(value); } + if ((s = strstr(style, "stroke:"))) { + s += 7; + while (*s == ' ') + s++; + value = strndup(s, strcspn(s, "; ")); + _svgtiny_parse_color(value, &state->stroke, state); + free(value); + } + if ((s = strstr(style, "stroke-width:"))) { + s += 13; + while (*s == ' ') + s++; + value = strndup(s, strcspn(s, "; ")); + state->stroke_width = _svgtiny_parse_length(value, + state->viewport_width, *state); + free(value); + } + free(style); + dom_string_unref(attr); } } @@ -1159,7 +1183,7 @@ void svgtiny_parse_paint_attributes(const dom_element *node, * Parse a colour. */ -void svgtiny_parse_color(const char *s, svgtiny_colour *c, +static void _svgtiny_parse_color(const char *s, svgtiny_colour *c, struct svgtiny_parse_state *state) { unsigned int r, g, b; @@ -1218,6 +1242,13 @@ void svgtiny_parse_color(const char *s, svgtiny_colour *c, } } +void svgtiny_parse_color(dom_string *s, svgtiny_colour *c, + struct svgtiny_parse_state *state) +{ + char *ss = strndup(dom_string_data(s), dom_string_length(s)); + _svgtiny_parse_color(ss, c, state); + free(ss); +} /** * Parse font attributes, if present. @@ -1226,6 +1257,10 @@ void svgtiny_parse_color(const char *s, svgtiny_colour *c, void svgtiny_parse_font_attributes(const dom_element *node, struct svgtiny_parse_state *state) { + /* TODO: Implement this, it never used to be */ + UNUSED(node); + UNUSED(state); +#ifdef WRITTEN_THIS_PROPERLY const xmlAttr *attr; UNUSED(state); @@ -1241,6 +1276,7 @@ void svgtiny_parse_font_attributes(const dom_element *node, }*/ } } +#endif } @@ -1254,14 +1290,19 @@ void svgtiny_parse_transform_attributes(dom_element *node, struct svgtiny_parse_state *state) { char *transform; - - /* parse transform */ - transform = (char *) xmlGetProp(node, (const xmlChar *) "transform"); - if (transform) { + dom_string *attr; + dom_exception exc; + + exc = dom_element_get_attribute(node, state->interned_transform, + &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + transform = strndup(dom_string_data(attr), + dom_string_length(attr)); svgtiny_parse_transform(transform, &state->ctm.a, &state->ctm.b, &state->ctm.c, &state->ctm.d, &state->ctm.e, &state->ctm.f); - xmlFree(transform); + free(transform); + dom_string_unref(attr); } } diff --git a/src/svgtiny_gradient.c b/src/svgtiny_gradient.c index 3a8db73..3544f1d 100644 --- a/src/svgtiny_gradient.c +++ b/src/svgtiny_gradient.c @@ -8,12 +8,14 @@ #include #include #include +#include + #include "svgtiny.h" #include "svgtiny_internal.h" #undef GRADIENT_DEBUG -static svgtiny_code svgtiny_parse_linear_gradient(xmlNode *linear, +static svgtiny_code svgtiny_parse_linear_gradient(dom_element *linear, struct svgtiny_parse_state *state); static float svgtiny_parse_gradient_offset(const char *s); static void svgtiny_path_bbox(float *p, unsigned int n, @@ -27,7 +29,9 @@ static void svgtiny_invert_matrix(float *m, float *inv); void svgtiny_find_gradient(const char *id, struct svgtiny_parse_state *state) { - xmlNode *gradient; + dom_element *gradient; + dom_string *id_str; + dom_exception exc; fprintf(stderr, "svgtiny_find_gradient: id \"%s\"\n", id); @@ -43,19 +47,34 @@ void svgtiny_find_gradient(const char *id, struct svgtiny_parse_state *state) state->gradient_transform.d = 1; state->gradient_transform.e = 0; state->gradient_transform.f = 0; + + exc = dom_string_create_interned((const uint8_t *) id, strlen(id), + &id_str); + if (exc != DOM_NO_ERR) + return; + + exc = dom_document_get_element_by_id(state->document, id_str, + &gradient); + dom_string_unref(id_str); + if (exc != DOM_NO_ERR) + return; - gradient = svgtiny_find_element_by_id( - (xmlNode *) state->document, id); - fprintf(stderr, "gradient %p\n", (void *) gradient); - if (!gradient) { + if (gradient == NULL) { fprintf(stderr, "gradient \"%s\" not found\n", id); return; } - - fprintf(stderr, "gradient name \"%s\"\n", gradient->name); - if (strcmp((const char *) gradient->name, "linearGradient") == 0) { - svgtiny_parse_linear_gradient(gradient, state); + + exc = dom_node_get_node_name(gradient, &id_str); + if (exc != DOM_NO_ERR) { + dom_node_unref(gradient); + return; } + + if (dom_string_isequal(id_str, state->interned_linearGradient)) + svgtiny_parse_linear_gradient(gradient, state); + + dom_string_unref(id_str); + dom_node_unref(gradient); } @@ -65,17 +84,25 @@ void svgtiny_find_gradient(const char *id, struct svgtiny_parse_state *state) * http://www.w3.org/TR/SVG11/pservers#LinearGradients */ -svgtiny_code svgtiny_parse_linear_gradient(xmlNode *linear, +svgtiny_code svgtiny_parse_linear_gradient(dom_element *linear, struct svgtiny_parse_state *state) { unsigned int i = 0; - xmlNode *stop; - xmlAttr *attr; - xmlAttr *href = xmlHasProp(linear, (const xmlChar *) "href"); - if (href && href->children->content[0] == '#') - svgtiny_find_gradient((const char *) href->children->content - + 1, state); - + dom_element *stop; + dom_string *attr; + dom_exception exc; + + exc = dom_element_get_attribute(linear, state->interned_href, &attr); + if (exc == DOM_NO_ERR && attr != NULL) { + if (dom_string_data(attr)[0] == (uint8_t) '#') { + char *s = strndup(dom_string_data(attr) + 1, + dom_string_length(attr) - 1); + svgtiny_find_gradient(s, state); + free(s); + } + dom_string_unref(attr); + } + for (attr = linear->properties; attr; attr = attr->next) { const char *name = (const char *) attr->name; const char *content = (const char *) attr->children->content; @@ -642,29 +669,3 @@ void svgtiny_invert_matrix(float *m, float *inv) inv[5] = (m[1]*m[4] - m[0]*m[5]) / determinant; } - -/** - * Find an element in the document by id. - */ - -xmlNode *svgtiny_find_element_by_id(xmlNode *node, const char *id) -{ - xmlNode *child; - xmlNode *found; - - for (child = node->children; child; child = child->next) { - xmlAttr *attr; - if (child->type != XML_ELEMENT_NODE) - continue; - attr = xmlHasProp(child, (const xmlChar *) "id"); - if (attr && strcmp(id, (const char *) attr->children->content) - == 0) - return child; - found = svgtiny_find_element_by_id(child, id); - if (found) - return found; - } - - return 0; -} - diff --git a/src/svgtiny_internal.h b/src/svgtiny_internal.h index 403805a..5ff1370 100644 --- a/src/svgtiny_internal.h +++ b/src/svgtiny_internal.h @@ -53,9 +53,9 @@ struct svgtiny_parse_state { } gradient_transform; /* Interned strings */ -#define SVGTINY_STRING_ACTION(n) dom_string *interned_##n; +#define SVGTINY_STRING_ACTION2(n,nn) dom_string *interned_##n; #include "svgtiny_strings.h" -#undef SVGTINY_STRING_ACTION +#undef SVGTINY_STRING_ACTION2 }; @@ -64,7 +64,7 @@ struct svgtiny_list; /* svgtiny.c */ float svgtiny_parse_length(dom_string *s, int viewport_size, const struct svgtiny_parse_state state); -void svgtiny_parse_color(const char *s, svgtiny_colour *c, +void svgtiny_parse_color(dom_string *s, svgtiny_colour *c, struct svgtiny_parse_state *state); void svgtiny_parse_transform(char *s, float *ma, float *mb, float *mc, float *md, float *me, float *mf); @@ -83,7 +83,6 @@ char *svgtiny_strndup(const char *s, size_t n); void svgtiny_find_gradient(const char *id, struct svgtiny_parse_state *state); svgtiny_code svgtiny_add_path_linear_gradient(float *p, unsigned int n, struct svgtiny_parse_state *state); -dom_node *svgtiny_find_element_by_id(dom_node *node, const char *id); /* svgtiny_list.c */ struct svgtiny_list *svgtiny_list_create(size_t item_size); diff --git a/src/svgtiny_strings.h b/src/svgtiny_strings.h index 69026ae..019bb14 100644 --- a/src/svgtiny_strings.h +++ b/src/svgtiny_strings.h @@ -4,16 +4,20 @@ * Copyright 2012 Daniel Silverstone */ -#ifndef SVGTINY_STRING_ACTION +#ifndef SVGTINY_STRING_ACTION2 #error No action defined #endif +#define SVGTINY_STRING_ACTION(s) SVGTINY_STRING_ACTION2(s,s) + SVGTINY_STRING_ACTION(svg) SVGTINY_STRING_ACTION(viewBox) SVGTINY_STRING_ACTION(a) SVGTINY_STRING_ACTION(d) SVGTINY_STRING_ACTION(g) SVGTINY_STRING_ACTION(r) +SVGTINY_STRING_ACTION(x) +SVGTINY_STRING_ACTION(y) SVGTINY_STRING_ACTION(cx) SVGTINY_STRING_ACTION(cy) SVGTINY_STRING_ACTION(rx) @@ -24,6 +28,8 @@ SVGTINY_STRING_ACTION(x2) SVGTINY_STRING_ACTION(y2) SVGTINY_STRING_ACTION(path) SVGTINY_STRING_ACTION(points) +SVGTINY_STRING_ACTION(width) +SVGTINY_STRING_ACTION(height) SVGTINY_STRING_ACTION(rect) SVGTINY_STRING_ACTION(circle) SVGTINY_STRING_ACTION(ellipse) @@ -32,3 +38,11 @@ SVGTINY_STRING_ACTION(polyline) SVGTINY_STRING_ACTION(polygon) SVGTINY_STRING_ACTION(text) SVGTINY_STRING_ACTION(tspan) +SVGTINY_STRING_ACTION(fill) +SVGTINY_STRING_ACTION(stroke) +SVGTINY_STRING_ACTION(style) +SVGTINY_STRING_ACTION(transform) +SVGTINY_STRING_ACTION(linearGradient) +SVGTINY_STRING_ACTION2(stroke_width,stroke-width) + +#undef SVGTINY_STRING_ACTION -- 2.44.2