X-Git-Url: https://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2Fsvgtiny.c;h=18884a11f45012ab3ca2940971b2da829d736691;hb=9275ab308;hp=9b2af327307b0c32acf2140cfeb3cd1499b8bf81;hpb=7edb291dd90bfac6736abca08f5549ad0961d3f8;p=libsvgtiny.git diff --git a/src/svgtiny.c b/src/svgtiny.c index 9b2af32..18884a1 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); /** @@ -160,20 +162,21 @@ svgtiny_code svgtiny_parse(struct svgtiny_diagram *diagram, dom_string_unref(svg_name); /* get graphic dimensions */ + memset(&state, 0, sizeof(state)); state.diagram = diagram; state.document = document; 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 +205,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; } @@ -870,26 +873,37 @@ svgtiny_code svgtiny_parse_line(dom_element *line, svgtiny_code svgtiny_parse_poly(dom_element *poly, struct svgtiny_parse_state state, bool polygon) { + dom_string *points_str; + dom_exception exc; char *s, *points; float *p; unsigned int i; svgtiny_parse_paint_attributes(poly, &state); svgtiny_parse_transform_attributes(poly, &state); - - /* read points attribute */ - s = points = (char *) xmlGetProp(poly, (const xmlChar *) "points"); - if (!s) { - state.diagram->error_line = poly->line; + + exc = dom_element_get_attribute(poly, state.interned_points, + &points_str); + if (exc != DOM_NO_ERR) + return svgtiny_LIBDOM_ERROR; + + if (points_str == NULL) { + state.diagram->error_line = -1; /* poly->line; */ state.diagram->error_message = "polyline/polygon: missing points attribute"; return svgtiny_SVG_ERROR; } + s = points = strndup(dom_string_data(points_str), + dom_string_length(points_str)); + dom_string_unref(points_str); + /* read points attribute */ + if (s == NULL) + return svgtiny_OUT_OF_MEMORY; /* allocate space for path: it will never have more elements than s */ p = malloc(sizeof p[0] * strlen(s)); if (!p) { - xmlFree(points); + free(points); return svgtiny_OUT_OF_MEMORY; } @@ -917,7 +931,7 @@ svgtiny_code svgtiny_parse_poly(dom_element *poly, if (polygon) p[i++] = svgtiny_PATH_CLOSE; - xmlFree(points); + free(points); return svgtiny_add_path(p, i, &state); } @@ -932,7 +946,8 @@ svgtiny_code svgtiny_parse_text(dom_element *text, { float x, y, width, height; float px, py; - dom_element *child; + dom_node *child; + dom_exception exc; svgtiny_parse_position_attributes(text, state, &x, &y, &width, &height); @@ -946,27 +961,61 @@ svgtiny_code svgtiny_parse_text(dom_element *text, /*struct css_style style = state.style; style.font_size.value.length.value *= state.ctm.a;*/ - - for (child = text->children; child; child = child->next) { + + exc = dom_node_get_first_child(text, &child); + if (exc != DOM_NO_ERR) + return svgtiny_LIBDOM_ERROR; + while (child != NULL) { + dom_node *next; + dom_node_type nodetype; svgtiny_code code = svgtiny_OK; - if (child->type == XML_TEXT_NODE) { + exc = dom_node_get_node_type(child, &nodetype); + if (exc != DOM_NO_ERR) { + dom_node_unref(child); + return svgtiny_LIBDOM_ERROR; + } + if (nodetype == DOM_ELEMENT_NODE) { + dom_string *nodename; + exc = dom_node_get_node_name(child, &nodename); + if (exc != DOM_NO_ERR) { + dom_node_unref(child); + return svgtiny_LIBDOM_ERROR; + } + if (dom_string_caseless_isequal(nodename, + state.interned_tspan)) + code = svgtiny_parse_text((dom_element *)child, + state); + dom_string_unref(nodename); + } else if (nodetype == DOM_TEXT_NODE) { struct svgtiny_shape *shape = svgtiny_add_shape(&state); - if (!shape) + dom_string *content; + if (shape == NULL) { + dom_node_unref(child); return svgtiny_OUT_OF_MEMORY; - shape->text = strdup((const char *) child->content); + } + exc = dom_text_get_whole_text(child, &content); + if (exc != DOM_NO_ERR) { + dom_node_unref(child); + return svgtiny_LIBDOM_ERROR; + } + shape->text = strndup(dom_string_data(content), + dom_string_length(content)); + dom_string_unref(content); shape->text_x = px; shape->text_y = py; state.diagram->shape_count++; - - } else if (child->type == XML_ELEMENT_NODE && - strcmp((const char *) child->name, - "tspan") == 0) { - code = svgtiny_parse_text(child, state); } - if (!code != svgtiny_OK) + if (code != svgtiny_OK) { + dom_node_unref(child); return code; + } + exc = dom_node_get_next_sibling(child, &next); + dom_node_unref(child); + if (exc != DOM_NO_ERR) + return svgtiny_LIBDOM_ERROR; + child = next; } return svgtiny_OK; @@ -981,28 +1030,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); } } @@ -1049,7 +1108,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; @@ -1062,49 +1121,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); } } @@ -1113,7 +1184,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; @@ -1172,6 +1243,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. @@ -1180,6 +1258,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); @@ -1195,6 +1277,7 @@ void svgtiny_parse_font_attributes(const dom_element *node, }*/ } } +#endif } @@ -1208,14 +1291,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); } }