svgtiny_code svgtiny_parse_svg(svgInfo &info,Poco::XML::Element *svg, struct svgtiny_parse_state state, ofPtr<svgNode> currnode){ float x, y, width, height; Poco::XML::Attr *view_box; Poco::XML::Element *child; svgtiny_parse_position_attributes(svg, state, &x, &y, &width, &height); svgtiny_parse_paint_attributes(svg, &state); svgtiny_parse_font_attributes(svg, &state); view_box = svg->getAttributeNode("viewBox"); if (view_box) { //const char *s = (const char *) view_box->children->content; const char *s = (const char *) view_box->getValue().c_str(); 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; } } svgtiny_parse_transform_attributes(svg, &state); // this is how this should work, but it doesn't //Poco::XML::NodeIterator it(svg, Poco::XML::NodeFilter::SHOW_ELEMENT | Poco::XML::NodeFilter::SHOW_TEXT); //Poco::XML::Node* pNode = it.nextNode(); //while (pNode) // Note: this should be using the NodeIterator, but it doesn't seem to work as advertised when using // a Node as the root for the iterator constructor. Really weird. Poco::XML::ChildNodesList *cnl = ( Poco::XML::ChildNodesList *) svg->childNodes(); svgtiny_code code = processChildren(info,currnode,cnl,state); if (code != svgtiny_OK){ return code; } return svgtiny_OK; }
svgtiny_code svgtiny_parse_text(xmlNode *text, struct svgtiny_parse_state state) { float x, y, width, height; float px, py; xmlNode *child; svgtiny_parse_position_attributes(text, state, &x, &y, &width, &height); svgtiny_parse_font_attributes(text, &state); svgtiny_parse_transform_attributes(text, &state); px = state.ctm.a * x + state.ctm.c * y + state.ctm.e; py = state.ctm.b * x + state.ctm.d * y + state.ctm.f; /* state.ctm.e = px - state.origin_x; */ /* state.ctm.f = py - state.origin_y; */ /*struct css_style style = state.style; style.font_size.value.length.value *= state.ctm.a;*/ for (child = text->children; child; child = child->next) { svgtiny_code code = svgtiny_OK; if (child->type == XML_TEXT_NODE) { struct svgtiny_shape *shape = svgtiny_add_shape(&state); if (!shape) return svgtiny_OUT_OF_MEMORY; shape->text = strdup((const char *) child->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) return code; } return svgtiny_OK; }
svgtiny_code svgtiny_parse_svg(dom_element *svg, struct svgtiny_parse_state state) { float x, y, width, height; dom_string *view_box; dom_element *child; dom_exception exc; svgtiny_setup_state_local(&state); svgtiny_parse_position_attributes(svg, state, &x, &y, &width, &height); svgtiny_parse_paint_attributes(svg, &state); svgtiny_parse_font_attributes(svg, &state); exc = dom_element_get_attribute(svg, state.interned_viewBox, &view_box); if (exc != DOM_NO_ERR) { svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } 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); dom_string_unref(view_box); } svgtiny_parse_transform_attributes(svg, &state); exc = dom_node_get_first_child(svg, (dom_node **) (void *) &child); if (exc != DOM_NO_ERR) { svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } while (child != NULL) { dom_element *next; dom_node_type nodetype; svgtiny_code code = svgtiny_OK; 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); svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } if (dom_string_caseless_isequal(state.interned_svg, nodename)) code = svgtiny_parse_svg(child, state); else if (dom_string_caseless_isequal(state.interned_g, nodename)) code = svgtiny_parse_svg(child, state); else if (dom_string_caseless_isequal(state.interned_a, nodename)) code = svgtiny_parse_svg(child, state); else if (dom_string_caseless_isequal(state.interned_path, nodename)) code = svgtiny_parse_path(child, state); else if (dom_string_caseless_isequal(state.interned_rect, nodename)) code = svgtiny_parse_rect(child, state); else if (dom_string_caseless_isequal(state.interned_circle, nodename)) code = svgtiny_parse_circle(child, state); else if (dom_string_caseless_isequal(state.interned_ellipse, nodename)) code = svgtiny_parse_ellipse(child, state); else if (dom_string_caseless_isequal(state.interned_line, nodename)) code = svgtiny_parse_line(child, state); else if (dom_string_caseless_isequal(state.interned_polyline, nodename)) code = svgtiny_parse_poly(child, state, false); else if (dom_string_caseless_isequal(state.interned_polygon, nodename)) code = svgtiny_parse_poly(child, state, true); else if (dom_string_caseless_isequal(state.interned_text, nodename)) code = svgtiny_parse_text(child, state); dom_string_unref(nodename); } if (code != svgtiny_OK) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return code; } exc = dom_node_get_next_sibling(child, (dom_node **) (void *) &next); dom_node_unref(child); if (exc != DOM_NO_ERR) { svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } child = next; } svgtiny_cleanup_state_local(&state); return svgtiny_OK; }
svgtiny_code svgtiny_parse_text(dom_element *text, struct svgtiny_parse_state state) { float x, y, width, height; float px, py; dom_node *child; dom_exception exc; svgtiny_setup_state_local(&state); svgtiny_parse_position_attributes(text, state, &x, &y, &width, &height); svgtiny_parse_font_attributes(text, &state); svgtiny_parse_transform_attributes(text, &state); px = state.ctm.a * x + state.ctm.c * y + state.ctm.e; py = state.ctm.b * x + state.ctm.d * y + state.ctm.f; /* state.ctm.e = px - state.origin_x; */ /* state.ctm.f = py - state.origin_y; */ /*struct css_style style = state.style; style.font_size.value.length.value *= state.ctm.a;*/ exc = dom_node_get_first_child(text, &child); if (exc != DOM_NO_ERR) { return svgtiny_LIBDOM_ERROR; svgtiny_cleanup_state_local(&state); } while (child != NULL) { dom_node *next; dom_node_type nodetype; svgtiny_code code = svgtiny_OK; exc = dom_node_get_node_type(child, &nodetype); if (exc != DOM_NO_ERR) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); 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); svgtiny_cleanup_state_local(&state); 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); dom_string *content; if (shape == NULL) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return svgtiny_OUT_OF_MEMORY; } exc = dom_text_get_whole_text(child, &content); if (exc != DOM_NO_ERR) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } if (content != NULL) { shape->text = strndup(dom_string_data(content), dom_string_byte_length(content)); dom_string_unref(content); } else { shape->text = strdup(""); } shape->text_x = px; shape->text_y = py; state.diagram->shape_count++; } if (code != svgtiny_OK) { dom_node_unref(child); svgtiny_cleanup_state_local(&state); return code; } exc = dom_node_get_next_sibling(child, &next); dom_node_unref(child); if (exc != DOM_NO_ERR) { svgtiny_cleanup_state_local(&state); return svgtiny_LIBDOM_ERROR; } child = next; } svgtiny_cleanup_state_local(&state); return svgtiny_OK; }
svgtiny_code svgtiny_parse_svg(xmlNode *svg, struct svgtiny_parse_state state) { float x, y, width, height; xmlAttr *view_box; xmlNode *child; svgtiny_parse_position_attributes(svg, state, &x, &y, &width, &height); svgtiny_parse_paint_attributes(svg, &state); svgtiny_parse_font_attributes(svg, &state); /* parse viewBox */ view_box = xmlHasProp(svg, (const xmlChar *) "viewBox"); if (view_box) { const char *s = (const char *) view_box->children->content; 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; } } svgtiny_parse_transform_attributes(svg, &state); for (child = svg->children; child; child = child->next) { svgtiny_code code = svgtiny_OK; if (child->type == XML_ELEMENT_NODE) { const char *name = (const char *) child->name; if (strcmp(name, "svg") == 0) code = svgtiny_parse_svg(child, state); else if (strcmp(name, "g") == 0) code = svgtiny_parse_svg(child, state); else if (strcmp(name, "a") == 0) code = svgtiny_parse_svg(child, state); else if (strcmp(name, "path") == 0) code = svgtiny_parse_path(child, state); else if (strcmp(name, "rect") == 0) code = svgtiny_parse_rect(child, state); else if (strcmp(name, "circle") == 0) code = svgtiny_parse_circle(child, state); else if (strcmp(name, "ellipse") == 0) code = svgtiny_parse_ellipse(child, state); else if (strcmp(name, "line") == 0) code = svgtiny_parse_line(child, state); else if (strcmp(name, "polyline") == 0) code = svgtiny_parse_poly(child, state, false); else if (strcmp(name, "polygon") == 0) code = svgtiny_parse_poly(child, state, true); else if (strcmp(name, "text") == 0) code = svgtiny_parse_text(child, state); } if (code != svgtiny_OK) return code; } return svgtiny_OK; }
svgtiny_code svgtiny_parse_text(Poco::XML::Element *text, struct svgtiny_parse_state state) { float x, y, width, height; float px, py; Poco::XML::Element *child; svgtiny_parse_position_attributes(text, state, &x, &y, &width, &height); svgtiny_parse_font_attributes(text, &state); svgtiny_parse_transform_attributes(text, &state); px = state.ctm.a * x + state.ctm.c * y + state.ctm.e; py = state.ctm.b * x + state.ctm.d * y + state.ctm.f; /* state.ctm.e = px - state.origin_x; */ /* state.ctm.f = py - state.origin_y; */ /*struct css_style style = state.style; style.font_size.value.length.value *= state.ctm.a;*/ //for (child = text->children; child; child = child->next) { //for( child = (Poco::XML::Element*) text->FirstChild( false ); child; child = (Poco::XML::Element*) child->NextSibling( false ) ) { Poco::XML::NodeIterator it(text, Poco::XML::NodeFilter::SHOW_ELEMENT | Poco::XML::NodeFilter::SHOW_TEXT); Poco::XML::Node* pNode = it.nextNode(); while (pNode) { svgtiny_code code = svgtiny_OK; if (pNode->getNodeValue().compare("text") == 0) { struct svgtiny_shape *shape = svgtiny_add_shape(&state); if (!shape) return svgtiny_OUT_OF_MEMORY; //shape->text = strdup((const char *) child->content); shape->text = strdup((const char *) pNode->getNodeValue().c_str()); shape->text_x = px; shape->text_y = py; state.diagram->shape_count++; } //else if (strcmp((const char *) child->Value(), "tspan") == 0) else if (pNode->getNodeValue().compare("tspan") == 0) { code = svgtiny_parse_text(child, state); } pNode = it.nextNode(); if (!code != svgtiny_OK) return code; } return svgtiny_OK; }