Beispiel #1
0
svgtiny_code svgtiny_parse_rect(xmlNode *rect,
		struct svgtiny_parse_state state)
{
	float x, y, width, height;
	float *p;

	svgtiny_parse_position_attributes(rect, state,
			&x, &y, &width, &height);
	svgtiny_parse_paint_attributes(rect, &state);
	svgtiny_parse_transform_attributes(rect, &state);

	p = malloc(13 * sizeof p[0]);
	if (!p)
		return svgtiny_OUT_OF_MEMORY;

	p[0] = svgtiny_PATH_MOVE;
	p[1] = x;
	p[2] = y;
	p[3] = svgtiny_PATH_LINE;
	p[4] = x + width;
	p[5] = y;
	p[6] = svgtiny_PATH_LINE;
	p[7] = x + width;
	p[8] = y + height;
	p[9] = svgtiny_PATH_LINE;
	p[10] = x;
	p[11] = y + height;
	p[12] = svgtiny_PATH_CLOSE;

	return svgtiny_add_path(p, 13, &state);
}
Beispiel #2
0
svgtiny_code svgtiny_parse_poly(Poco::XML::Element *poly,
		struct svgtiny_parse_state state, bool polygon)
{
	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");
    
    s = points = (char *) poly->getAttribute("points").c_str();
    
	if (!s) {
		//state.diagram->error_line = poly->line;
		state.diagram->error_message =
				"polyline/polygon: missing points attribute";
		return svgtiny_SVG_ERROR;
	}

	/* allocate space for path: it will never have more elements than s */
	p = (float*) malloc(sizeof p[0] * strlen(s));
	if (!p) {
        //xmlFree(points);
        free(points);
		return svgtiny_OUT_OF_MEMORY;
	}

	/* parse s and build path */
	for (i = 0; s[i]; i++)
		if (s[i] == ',')
			s[i] = ' ';
	i = 0;
	while (*s) {
		float x, y;
		int n;

		if (sscanf(s, "%f %f %n", &x, &y, &n) == 2) {
			if (i == 0)
				p[i++] = svgtiny_PATH_MOVE;
			else
				p[i++] = svgtiny_PATH_LINE;
			p[i++] = x;
			p[i++] = y;
			s += n;
                } else {
                	break;
                }
        }
        if (polygon)
		p[i++] = svgtiny_PATH_CLOSE;

	//xmlFree(points);
    free(points);

	return svgtiny_add_path(p, i, &state);
}
Beispiel #3
0
svgtiny_code svgtiny_parse_line(Poco::XML::Element *line,
		struct svgtiny_parse_state state)
{
	float x1 = 0, y1 = 0, x2 = 0, y2 = 0;
	float *p;
	//xmlAttr *attr;
    Poco::XML::Attr *attr;

	//for (attr = line->properties; attr; attr = attr->next) {
    //for( attr = line->FirstAttribute(); attr; attr = attr->Next() ) {
    
    Poco::XML::NamedNodeMap *map = line->attributes();
    for( int i = 0; i < map->length(); i++ ) {
    
		//const char *name = (const char *) attr->name;
		//const char *content = (const char *) attr->children->content;
        
        //const char *name = (const char *) attr->Name();
		//const char *content = (const char *) attr->Value();
        
        const char *name = (const char *) map->item(i)->localName().c_str();
		const char *content = (const char *) map->item(i)->getNodeValue().c_str();
        
		if (strcmp(name, "x1") == 0)
			x1 = svgtiny_parse_length(content,
					state.viewport_width, state);
		else if (strcmp(name, "y1") == 0)
			y1 = svgtiny_parse_length(content,
					state.viewport_height, state);
		else if (strcmp(name, "x2") == 0)
			x2 = svgtiny_parse_length(content,
					state.viewport_width, state);
		else if (strcmp(name, "y2") == 0)
			y2 = svgtiny_parse_length(content,
					state.viewport_height, state);
        }
	svgtiny_parse_paint_attributes(line, &state);
	svgtiny_parse_transform_attributes(line, &state);

	p = (float*) malloc(7 * sizeof p[0]);
	if (!p)
		return svgtiny_OUT_OF_MEMORY;

	p[0] = svgtiny_PATH_MOVE;
	p[1] = x1;
	p[2] = y1;
	p[3] = svgtiny_PATH_LINE;
	p[4] = x2;
	p[5] = y2;
	p[6] = svgtiny_PATH_CLOSE;

	return svgtiny_add_path(p, 7, &state);
}
Beispiel #4
0
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;
}
Beispiel #5
0
svgtiny_code svgtiny_parse_rect(dom_element *rect,
		struct svgtiny_parse_state state)
{
	svgtiny_code err;
	float x, y, width, height;
	float *p;

	svgtiny_setup_state_local(&state);

	svgtiny_parse_position_attributes(rect, state,
			&x, &y, &width, &height);
	svgtiny_parse_paint_attributes(rect, &state);
	svgtiny_parse_transform_attributes(rect, &state);

	p = malloc(13 * sizeof p[0]);
	if (!p) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}

	p[0] = svgtiny_PATH_MOVE;
	p[1] = x;
	p[2] = y;
	p[3] = svgtiny_PATH_LINE;
	p[4] = x + width;
	p[5] = y;
	p[6] = svgtiny_PATH_LINE;
	p[7] = x + width;
	p[8] = y + height;
	p[9] = svgtiny_PATH_LINE;
	p[10] = x;
	p[11] = y + height;
	p[12] = svgtiny_PATH_CLOSE;

	err = svgtiny_add_path(p, 13, &state);

	svgtiny_cleanup_state_local(&state);

	return err;
}
Beispiel #6
0
svgtiny_code svgtiny_parse_line(xmlNode *line,
		struct svgtiny_parse_state state)
{
	float x1 = 0, y1 = 0, x2 = 0, y2 = 0;
	float *p;
	xmlAttr *attr;

	for (attr = line->properties; attr; attr = attr->next) {
		const char *name = (const char *) attr->name;
		const char *content = (const char *) attr->children->content;
		if (strcmp(name, "x1") == 0)
			x1 = svgtiny_parse_length(content,
					state.viewport_width, state);
		else if (strcmp(name, "y1") == 0)
			y1 = svgtiny_parse_length(content,
					state.viewport_height, state);
		else if (strcmp(name, "x2") == 0)
			x2 = svgtiny_parse_length(content,
					state.viewport_width, state);
		else if (strcmp(name, "y2") == 0)
			y2 = svgtiny_parse_length(content,
					state.viewport_height, state);
        }
	svgtiny_parse_paint_attributes(line, &state);
	svgtiny_parse_transform_attributes(line, &state);

	p = malloc(7 * sizeof p[0]);
	if (!p)
		return svgtiny_OUT_OF_MEMORY;

	p[0] = svgtiny_PATH_MOVE;
	p[1] = x1;
	p[2] = y1;
	p[3] = svgtiny_PATH_LINE;
	p[4] = x2;
	p[5] = y2;
	p[6] = svgtiny_PATH_CLOSE;

	return svgtiny_add_path(p, 7, &state);
}
Beispiel #7
0
svgtiny_code svgtiny_parse_line(dom_element *line,
		struct svgtiny_parse_state state)
{
	svgtiny_code err;
	float x1 = 0, y1 = 0, x2 = 0, y2 = 0;
	float *p;
	dom_string *attr;
	dom_exception exc;

	svgtiny_setup_state_local(&state);

	exc = dom_element_get_attribute(line, state.interned_x1, &attr);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	if (attr != NULL) {
		x1 = svgtiny_parse_length(attr, state.viewport_width, state);
	}
	dom_string_unref(attr);

	exc = dom_element_get_attribute(line, state.interned_y1, &attr);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	if (attr != NULL) {
		y1 = svgtiny_parse_length(attr, state.viewport_height, state);
	}
	dom_string_unref(attr);

	exc = dom_element_get_attribute(line, state.interned_x2, &attr);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	if (attr != NULL) {
		x2 = svgtiny_parse_length(attr, state.viewport_width, state);
	}
	dom_string_unref(attr);

	exc = dom_element_get_attribute(line, state.interned_y2, &attr);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	if (attr != NULL) {
		y2 = svgtiny_parse_length(attr, state.viewport_height, state);
	}
	dom_string_unref(attr);

	svgtiny_parse_paint_attributes(line, &state);
	svgtiny_parse_transform_attributes(line, &state);

	p = malloc(7 * sizeof p[0]);
	if (!p) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}

	p[0] = svgtiny_PATH_MOVE;
	p[1] = x1;
	p[2] = y1;
	p[3] = svgtiny_PATH_LINE;
	p[4] = x2;
	p[5] = y2;
	p[6] = svgtiny_PATH_CLOSE;

	err = svgtiny_add_path(p, 7, &state);

	svgtiny_cleanup_state_local(&state);

	return err;
}
Beispiel #8
0
svgtiny_code svgtiny_parse_ellipse(dom_element *ellipse,
		struct svgtiny_parse_state state)
{
	svgtiny_code err;
	float x = 0, y = 0, rx = -1, ry = -1;
	float *p;
	dom_string *attr;
	dom_exception exc;

	svgtiny_setup_state_local(&state);

	exc = dom_element_get_attribute(ellipse, state.interned_cx, &attr);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	if (attr != NULL) {
		x = svgtiny_parse_length(attr, state.viewport_width, state);
	}
	dom_string_unref(attr);

	exc = dom_element_get_attribute(ellipse, state.interned_cy, &attr);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	if (attr != NULL) {
		y = svgtiny_parse_length(attr, state.viewport_height, state);
	}
	dom_string_unref(attr);

	exc = dom_element_get_attribute(ellipse, state.interned_rx, &attr);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	if (attr != NULL) {
		rx = svgtiny_parse_length(attr, state.viewport_width, state);
	}
	dom_string_unref(attr);

	exc = dom_element_get_attribute(ellipse, state.interned_ry, &attr);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	if (attr != NULL) {
		ry = svgtiny_parse_length(attr, state.viewport_width, state);
	}
	dom_string_unref(attr);

	svgtiny_parse_paint_attributes(ellipse, &state);
	svgtiny_parse_transform_attributes(ellipse, &state);

	if (rx < 0 || ry < 0) {
		state.diagram->error_line = -1; /* ellipse->line; */
		state.diagram->error_message = "ellipse: rx or ry missing "
				"or negative";
		svgtiny_cleanup_state_local(&state);
		return svgtiny_SVG_ERROR;
	}
	if (rx == 0 || ry == 0) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OK;
	}

	p = malloc(32 * sizeof p[0]);
	if (!p) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}

	p[0] = svgtiny_PATH_MOVE;
	p[1] = x + rx;
	p[2] = y;
	p[3] = svgtiny_PATH_BEZIER;
	p[4] = x + rx;
	p[5] = y + ry * KAPPA;
	p[6] = x + rx * KAPPA;
	p[7] = y + ry;
	p[8] = x;
	p[9] = y + ry;
	p[10] = svgtiny_PATH_BEZIER;
	p[11] = x - rx * KAPPA;
	p[12] = y + ry;
	p[13] = x - rx;
	p[14] = y + ry * KAPPA;
	p[15] = x - rx;
	p[16] = y;
	p[17] = svgtiny_PATH_BEZIER;
	p[18] = x - rx;
	p[19] = y - ry * KAPPA;
	p[20] = x - rx * KAPPA;
	p[21] = y - ry;
	p[22] = x;
	p[23] = y - ry;
	p[24] = svgtiny_PATH_BEZIER;
	p[25] = x + rx * KAPPA;
	p[26] = y - ry;
	p[27] = x + rx;
	p[28] = y - ry * KAPPA;
	p[29] = x + rx;
	p[30] = y;
	p[31] = svgtiny_PATH_CLOSE;
	
	err = svgtiny_add_path(p, 32, &state);

	svgtiny_cleanup_state_local(&state);

	return err;
}
Beispiel #9
0
svgtiny_code svgtiny_parse_path(dom_element *path,
		struct svgtiny_parse_state state)
{
	svgtiny_code err;
	dom_string *path_d_str;
	dom_exception exc;
	char *s, *path_d;
	float *p;
	unsigned int i;
	float last_x = 0, last_y = 0;
	float last_cubic_x = 0, last_cubic_y = 0;
	float last_quad_x = 0, last_quad_y = 0;

	svgtiny_setup_state_local(&state);

	svgtiny_parse_paint_attributes(path, &state);
	svgtiny_parse_transform_attributes(path, &state);

	/* read d attribute */
	exc = dom_element_get_attribute(path, state.interned_d, &path_d_str);
	if (exc != DOM_NO_ERR) {
		state.diagram->error_line = -1; /* path->line; */
		state.diagram->error_message = "path: error retrieving d attribute";
		svgtiny_cleanup_state_local(&state);
		return svgtiny_SVG_ERROR;
	}

	if (path_d_str == NULL) {
		state.diagram->error_line = -1; /* path->line; */
		state.diagram->error_message = "path: missing d attribute";
		svgtiny_cleanup_state_local(&state);
		return svgtiny_SVG_ERROR;
	}

	s = path_d = strndup(dom_string_data(path_d_str),
			     dom_string_byte_length(path_d_str));
	dom_string_unref(path_d_str);
	if (s == NULL) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}
	/* allocate space for path: it will never have more elements than d */
	p = malloc(sizeof p[0] * strlen(s));
	if (!p) {
		free(path_d);
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}

	/* parse d and build path */
	for (i = 0; s[i]; i++)
		if (s[i] == ',')
			s[i] = ' ';
	i = 0;
	while (*s) {
		char command[2];
		int plot_command;
		float x, y, x1, y1, x2, y2, rx, ry, rotation, large_arc, sweep;
		int n;

		/* moveto (M, m), lineto (L, l) (2 arguments) */
		if (sscanf(s, " %1[MmLl] %f %f %n", command, &x, &y, &n) == 3) {
			/*LOG(("moveto or lineto"));*/
			if (*command == 'M' || *command == 'm')
				plot_command = svgtiny_PATH_MOVE;
			else
				plot_command = svgtiny_PATH_LINE;
			do {
				p[i++] = plot_command;
				if ('a' <= *command) {
					x += last_x;
					y += last_y;
				}
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
				plot_command = svgtiny_PATH_LINE;
			} while (sscanf(s, "%f %f %n", &x, &y, &n) == 2);

		/* closepath (Z, z) (no arguments) */
		} else if (sscanf(s, " %1[Zz] %n", command, &n) == 1) {
			/*LOG(("closepath"));*/
			p[i++] = svgtiny_PATH_CLOSE;
			s += n;

		/* horizontal lineto (H, h) (1 argument) */
		} else if (sscanf(s, " %1[Hh] %f %n", command, &x, &n) == 2) {
			/*LOG(("horizontal lineto"));*/
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'h')
					x += last_x;
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y;
				s += n;
			} while (sscanf(s, "%f %n", &x, &n) == 1);

		/* vertical lineto (V, v) (1 argument) */
		} else if (sscanf(s, " %1[Vv] %f %n", command, &y, &n) == 2) {
			/*LOG(("vertical lineto"));*/
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'v')
					y += last_y;
				p[i++] = last_cubic_x = last_quad_x = last_x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
			} while (sscanf(s, "%f %n", &x, &n) == 1);

		/* curveto (C, c) (6 arguments) */
		} else if (sscanf(s, " %1[Cc] %f %f %f %f %f %f %n", command,
				&x1, &y1, &x2, &y2, &x, &y, &n) == 7) {
			/*LOG(("curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				if (*command == 'c') {
					x1 += last_x;
					y1 += last_y;
					x2 += last_x;
					y2 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = x1;
				p[i++] = y1;
				p[i++] = last_cubic_x = x2;
				p[i++] = last_cubic_y = y2;
				p[i++] = last_quad_x = last_x = x;
				p[i++] = last_quad_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %f %f %n",
					&x1, &y1, &x2, &y2, &x, &y, &n) == 6);

		/* shorthand/smooth curveto (S, s) (4 arguments) */
		} else if (sscanf(s, " %1[Ss] %f %f %f %f %n", command,
				&x2, &y2, &x, &y, &n) == 5) {
			/*LOG(("shorthand/smooth curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				x1 = last_x + (last_x - last_cubic_x);
				y1 = last_y + (last_y - last_cubic_y);
				if (*command == 's') {
					x2 += last_x;
					y2 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = x1;
				p[i++] = y1;
				p[i++] = last_cubic_x = x2;
				p[i++] = last_cubic_y = y2;
				p[i++] = last_quad_x = last_x = x;
				p[i++] = last_quad_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %n",
					&x2, &y2, &x, &y, &n) == 4);

		/* quadratic Bezier curveto (Q, q) (4 arguments) */
		} else if (sscanf(s, " %1[Qq] %f %f %f %f %n", command,
				&x1, &y1, &x, &y, &n) == 5) {
			/*LOG(("quadratic Bezier curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				last_quad_x = x1;
				last_quad_y = y1;
				if (*command == 'q') {
					x1 += last_x;
					y1 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = 1./3 * last_x + 2./3 * x1;
				p[i++] = 1./3 * last_y + 2./3 * y1;
				p[i++] = 2./3 * x1 + 1./3 * x;
				p[i++] = 2./3 * y1 + 1./3 * y;
				p[i++] = last_cubic_x = last_x = x;
				p[i++] = last_cubic_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %n",
					&x1, &y1, &x, &y, &n) == 4);

		/* shorthand/smooth quadratic Bezier curveto (T, t)
		   (2 arguments) */
		} else if (sscanf(s, " %1[Tt] %f %f %n", command,
				&x, &y, &n) == 3) {
			/*LOG(("shorthand/smooth quadratic Bezier curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				x1 = last_x + (last_x - last_quad_x);
				y1 = last_y + (last_y - last_quad_y);
				last_quad_x = x1;
				last_quad_y = y1;
				if (*command == 't') {
					x1 += last_x;
					y1 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = 1./3 * last_x + 2./3 * x1;
				p[i++] = 1./3 * last_y + 2./3 * y1;
				p[i++] = 2./3 * x1 + 1./3 * x;
				p[i++] = 2./3 * y1 + 1./3 * y;
				p[i++] = last_cubic_x = last_x = x;
				p[i++] = last_cubic_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %n",
					&x, &y, &n) == 2);

		/* elliptical arc (A, a) (7 arguments) */
		} else if (sscanf(s, " %1[Aa] %f %f %f %f %f %f %f %n", command,
				&rx, &ry, &rotation, &large_arc, &sweep,
				&x, &y, &n) == 8) {
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'a') {
					x += last_x;
					y += last_y;
				}
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %f %f %f %n",
				&rx, &ry, &rotation, &large_arc, &sweep,
				&x, &y, &n) == 7);

		} else {
			fprintf(stderr, "parse failed at \"%s\"\n", s);
			break;
		}
	}

	free(path_d);

	if (i <= 4) {
		/* no real segments in path */
		free(p);
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OK;
	}

	err = svgtiny_add_path(p, i, &state);

	svgtiny_cleanup_state_local(&state);

	return err;
}
Beispiel #10
0
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;
}
Beispiel #11
0
svgtiny_code svgtiny_parse_poly(dom_element *poly,
		struct svgtiny_parse_state state, bool polygon)
{
	svgtiny_code err;
	dom_string *points_str;
	dom_exception exc;
	char *s, *points;
	float *p;
	unsigned int i;

	svgtiny_setup_state_local(&state);

	svgtiny_parse_paint_attributes(poly, &state);
	svgtiny_parse_transform_attributes(poly, &state);
	
	exc = dom_element_get_attribute(poly, state.interned_points,
					&points_str);
	if (exc != DOM_NO_ERR) {
		svgtiny_cleanup_state_local(&state);
		return svgtiny_LIBDOM_ERROR;
	}
	
	if (points_str == NULL) {
		state.diagram->error_line = -1; /* poly->line; */
		state.diagram->error_message =
				"polyline/polygon: missing points attribute";
		svgtiny_cleanup_state_local(&state);
		return svgtiny_SVG_ERROR;
	}

	s = points = strndup(dom_string_data(points_str),
			     dom_string_byte_length(points_str));
	dom_string_unref(points_str);
	/* read points attribute */
	if (s == NULL) {
		svgtiny_cleanup_state_local(&state);
		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) {
		free(points);
		svgtiny_cleanup_state_local(&state);
		return svgtiny_OUT_OF_MEMORY;
	}

	/* parse s and build path */
	for (i = 0; s[i]; i++)
		if (s[i] == ',')
			s[i] = ' ';
	i = 0;
	while (*s) {
		float x, y;
		int n;

		if (sscanf(s, "%f %f %n", &x, &y, &n) == 2) {
			if (i == 0)
				p[i++] = svgtiny_PATH_MOVE;
			else
				p[i++] = svgtiny_PATH_LINE;
			p[i++] = x;
			p[i++] = y;
			s += n;
                } else {
                	break;
                }
        }
        if (polygon)
		p[i++] = svgtiny_PATH_CLOSE;

	free(points);

	err = svgtiny_add_path(p, i, &state);

	svgtiny_cleanup_state_local(&state);

	return err;
}
Beispiel #12
0
svgtiny_code svgtiny_parse_ellipse(xmlNode *ellipse,
		struct svgtiny_parse_state state)
{
	float x = 0, y = 0, rx = -1, ry = -1;
	float *p;
	xmlAttr *attr;

	for (attr = ellipse->properties; attr; attr = attr->next) {
		const char *name = (const char *) attr->name;
		const char *content = (const char *) attr->children->content;
		if (strcmp(name, "cx") == 0)
			x = svgtiny_parse_length(content,
					state.viewport_width, state);
		else if (strcmp(name, "cy") == 0)
			y = svgtiny_parse_length(content,
					state.viewport_height, state);
		else if (strcmp(name, "rx") == 0)
			rx = svgtiny_parse_length(content,
					state.viewport_width, state);
		else if (strcmp(name, "ry") == 0)
			ry = svgtiny_parse_length(content,
					state.viewport_width, state);
        }
	svgtiny_parse_paint_attributes(ellipse, &state);
	svgtiny_parse_transform_attributes(ellipse, &state);

	if (rx < 0 || ry < 0) {
		state.diagram->error_line = ellipse->line;
		state.diagram->error_message = "ellipse: rx or ry missing "
				"or negative";
		return svgtiny_SVG_ERROR;
	}
	if (rx == 0 || ry == 0)
		return svgtiny_OK;

	p = malloc(32 * sizeof p[0]);
	if (!p)
		return svgtiny_OUT_OF_MEMORY;

	p[0] = svgtiny_PATH_MOVE;
	p[1] = x + rx;
	p[2] = y;
	p[3] = svgtiny_PATH_BEZIER;
	p[4] = x + rx;
	p[5] = y + ry * KAPPA;
	p[6] = x + rx * KAPPA;
	p[7] = y + ry;
	p[8] = x;
	p[9] = y + ry;
	p[10] = svgtiny_PATH_BEZIER;
	p[11] = x - rx * KAPPA;
	p[12] = y + ry;
	p[13] = x - rx;
	p[14] = y + ry * KAPPA;
	p[15] = x - rx;
	p[16] = y;
	p[17] = svgtiny_PATH_BEZIER;
	p[18] = x - rx;
	p[19] = y - ry * KAPPA;
	p[20] = x - rx * KAPPA;
	p[21] = y - ry;
	p[22] = x;
	p[23] = y - ry;
	p[24] = svgtiny_PATH_BEZIER;
	p[25] = x + rx * KAPPA;
	p[26] = y - ry;
	p[27] = x + rx;
	p[28] = y - ry * KAPPA;
	p[29] = x + rx;
	p[30] = y;
	p[31] = svgtiny_PATH_CLOSE;
	
	return svgtiny_add_path(p, 32, &state);
}
Beispiel #13
0
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;
}
Beispiel #14
0
svgtiny_code svgtiny_parse_ellipse(Poco::XML::Element *ellipse,
		struct svgtiny_parse_state state)
{
	float x = 0, y = 0, rx = -1, ry = -1;
	float *p;
	Poco::XML::Attr *attr;

	//for (attr = ellipse->properties; attr; attr = attr->next) {
    //for( attr = ellipse->FirstAttribute(); attr; attr = attr->Next() ) {
    
    Poco::XML::NamedNodeMap *map = ellipse->attributes();
    for( int i = 0; i < map->length(); i++ ) {
    
		//const char *name = (const char *) attr->name;
		//const char *content = (const char *) attr->children->content;
        
        //const char *name = (const char *) attr->Name();
		//const char *content = (const char *) attr->Value();
        
        const char *name = (const char *) map->item(i)->localName().c_str();
		const char *content = (const char *) map->item(i)->getNodeValue().c_str();
        
		if (strcmp(name, "cx") == 0)
			x = svgtiny_parse_length(content,
					state.viewport_width, state);
		else if (strcmp(name, "cy") == 0)
			y = svgtiny_parse_length(content,
					state.viewport_height, state);
		else if (strcmp(name, "rx") == 0)
			rx = svgtiny_parse_length(content,
					state.viewport_width, state);
		else if (strcmp(name, "ry") == 0)
			ry = svgtiny_parse_length(content,
					state.viewport_width, state);
        }
	svgtiny_parse_paint_attributes(ellipse, &state);
	svgtiny_parse_transform_attributes(ellipse, &state);

	if (rx < 0 || ry < 0) {
		//state.diagram->error_line = ellipse->line;
		state.diagram->error_message = "ellipse: rx or ry missing "
				"or negative";
		return svgtiny_SVG_ERROR;
	}
	if (rx == 0 || ry == 0)
		return svgtiny_OK;

	p = (float*) malloc(32 * sizeof p[0]);
	if (!p)
		return svgtiny_OUT_OF_MEMORY;

	p[0] = svgtiny_PATH_MOVE;
	p[1] = x + rx;
	p[2] = y;
	p[3] = svgtiny_PATH_BEZIER;
	p[4] = x + rx;
	p[5] = y + ry * KAPPA;
	p[6] = x + rx * KAPPA;
	p[7] = y + ry;
	p[8] = x;
	p[9] = y + ry;
	p[10] = svgtiny_PATH_BEZIER;
	p[11] = x - rx * KAPPA;
	p[12] = y + ry;
	p[13] = x - rx;
	p[14] = y + ry * KAPPA;
	p[15] = x - rx;
	p[16] = y;
	p[17] = svgtiny_PATH_BEZIER;
	p[18] = x - rx;
	p[19] = y - ry * KAPPA;
	p[20] = x - rx * KAPPA;
	p[21] = y - ry;
	p[22] = x;
	p[23] = y - ry;
	p[24] = svgtiny_PATH_BEZIER;
	p[25] = x + rx * KAPPA;
	p[26] = y - ry;
	p[27] = x + rx;
	p[28] = y - ry * KAPPA;
	p[29] = x + rx;
	p[30] = y;
	p[31] = svgtiny_PATH_CLOSE;
	
	return svgtiny_add_path(p, 32, &state);
}
Beispiel #15
0
svgtiny_code svgtiny_parse_path(Poco::XML::Element *path,
		struct svgtiny_parse_state state)
{
	char *s, *path_d;
	float *p;
	unsigned int i;
	float last_x = 0, last_y = 0;
	float last_cubic_x = 0, last_cubic_y = 0;
	float last_quad_x = 0, last_quad_y = 0;

	svgtiny_parse_paint_attributes(path, &state);
	svgtiny_parse_transform_attributes(path, &state);

	/* read d attribute */
	//s = path_d = (char *) xmlGetProp(path, (const xmlChar *) "d");
    //s = path_d = (char *) path->Attribute("d");
    s = path_d = (char *) path->getAttribute("d").c_str();
    
    
	if (!s) {
		//state.diagram->error_line = path->line;
		state.diagram->error_message = "path: missing d attribute";
		return svgtiny_SVG_ERROR;
	}

    
    //ofLog()<<"path "<<s<<endl;
    
    
	/* allocate space for path: it will never have more elements than d */
	p = (float*) malloc(sizeof p[0] * strlen(s));
	if (!p)
		return svgtiny_OUT_OF_MEMORY;

	/* parse d and build path */
	for (i = 0; s[i]; i++)
		if (s[i] == ',')
			s[i] = ' ';
	i = 0;
	while (*s) {
		char command[2];
		int plot_command;
		float x, y, x1, y1, x2, y2, rx, ry, rotation, large_arc, sweep;
		int n;

		/* moveto (M, m), lineto (L, l) (2 arguments) */
		if (sscanf(s, " %1[MmLl] %f %f %n", command, &x, &y, &n) == 3) {
			/*LOG(("moveto or lineto"));*/
			if (*command == 'M' || *command == 'm')
				plot_command = svgtiny_PATH_MOVE;
			else
				plot_command = svgtiny_PATH_LINE;
			do {
				p[i++] = plot_command;
				if ('a' <= *command) {
					x += last_x;
					y += last_y;
				}
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
				plot_command = svgtiny_PATH_LINE;
			} while (sscanf(s, "%f %f %n", &x, &y, &n) == 2);

		/* closepath (Z, z) (no arguments) */
		} else if (sscanf(s, " %1[Zz] %n", command, &n) == 1) {
			/*LOG(("closepath"));*/
			p[i++] = svgtiny_PATH_CLOSE;
			s += n;

		/* horizontal lineto (H, h) (1 argument) */
		} else if (sscanf(s, " %1[Hh] %f %n", command, &x, &n) == 2) {
			/*LOG(("horizontal lineto"));*/
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'h')
					x += last_x;
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y;
				s += n;
			} while (sscanf(s, "%f %n", &x, &n) == 1);

		/* vertical lineto (V, v) (1 argument) */
		} else if (sscanf(s, " %1[Vv] %f %n", command, &y, &n) == 2) {
			/*LOG(("vertical lineto"));*/
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'v')
					y += last_y;
				p[i++] = last_cubic_x = last_quad_x = last_x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
			} while (sscanf(s, "%f %n", &x, &n) == 1);

		/* curveto (C, c) (6 arguments) */
		} else if (sscanf(s, " %1[Cc] %f %f %f %f %f %f %n", command,
				&x1, &y1, &x2, &y2, &x, &y, &n) == 7) {
			/*LOG(("curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				if (*command == 'c') {
					x1 += last_x;
					y1 += last_y;
					x2 += last_x;
					y2 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = x1;
				p[i++] = y1;
				p[i++] = last_cubic_x = x2;
				p[i++] = last_cubic_y = y2;
				p[i++] = last_quad_x = last_x = x;
				p[i++] = last_quad_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %f %f %n",
					&x1, &y1, &x2, &y2, &x, &y, &n) == 6);

		/* shorthand/smooth curveto (S, s) (4 arguments) */
		} else if (sscanf(s, " %1[Ss] %f %f %f %f %n", command,
				&x2, &y2, &x, &y, &n) == 5) {
			/*LOG(("shorthand/smooth curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				x1 = last_x + (last_x - last_cubic_x);
				y1 = last_y + (last_y - last_cubic_y);
				if (*command == 's') {
					x2 += last_x;
					y2 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = x1;
				p[i++] = y1;
				p[i++] = last_cubic_x = x2;
				p[i++] = last_cubic_y = y2;
				p[i++] = last_quad_x = last_x = x;
				p[i++] = last_quad_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %n",
					&x2, &y2, &x, &y, &n) == 4);

		/* quadratic Bezier curveto (Q, q) (4 arguments) */
		} else if (sscanf(s, " %1[Qq] %f %f %f %f %n", command,
				&x1, &y1, &x, &y, &n) == 5) {
			/*LOG(("quadratic Bezier curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				last_quad_x = x1;
				last_quad_y = y1;
				if (*command == 'q') {
					x1 += last_x;
					y1 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = 1./3 * last_x + 2./3 * x1;
				p[i++] = 1./3 * last_y + 2./3 * y1;
				p[i++] = 2./3 * x1 + 1./3 * x;
				p[i++] = 2./3 * y1 + 1./3 * y;
				p[i++] = last_cubic_x = last_x = x;
				p[i++] = last_cubic_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %n",
					&x1, &y1, &x, &y, &n) == 4);

		/* shorthand/smooth quadratic Bezier curveto (T, t)
		   (2 arguments) */
		} else if (sscanf(s, " %1[Tt] %f %f %n", command,
				&x, &y, &n) == 3) {
			/*LOG(("shorthand/smooth quadratic Bezier curveto"));*/
			do {
				p[i++] = svgtiny_PATH_BEZIER;
				x1 = last_x + (last_x - last_quad_x);
				y1 = last_y + (last_y - last_quad_y);
				last_quad_x = x1;
				last_quad_y = y1;
				if (*command == 't') {
					x1 += last_x;
					y1 += last_y;
					x += last_x;
					y += last_y;
				}
				p[i++] = 1./3 * last_x + 2./3 * x1;
				p[i++] = 1./3 * last_y + 2./3 * y1;
				p[i++] = 2./3 * x1 + 1./3 * x;
				p[i++] = 2./3 * y1 + 1./3 * y;
				p[i++] = last_cubic_x = last_x = x;
				p[i++] = last_cubic_y = last_y = y;
				s += n;
			} while (sscanf(s, "%f %f %n",
					&x, &y, &n) == 2);

		/* elliptical arc (A, a) (7 arguments) */
		} else if (sscanf(s, " %1[Aa] %f %f %f %f %f %f %f %n", command,
				&rx, &ry, &rotation, &large_arc, &sweep,
				&x, &y, &n) == 8) {
			do {
				p[i++] = svgtiny_PATH_LINE;
				if (*command == 'a') {
					x += last_x;
					y += last_y;
				}
				p[i++] = last_cubic_x = last_quad_x = last_x
						= x;
				p[i++] = last_cubic_y = last_quad_y = last_y
						= y;
				s += n;
			} while (sscanf(s, "%f %f %f %f %f %f %f %n",
				&rx, &ry, &rotation, &large_arc, &sweep,
				&x, &y, &n) == 7);

		} else {
			fprintf(stderr, "parse failed at \"%s\"\n", s);
			break;
		}
	}

	//xmlFree(path_d);
    if(path_d) {
        //delete path_d;
    }

	if (i <= 4) {
		/* no real segments in path */
		free(p);
		return svgtiny_OK;
	}

	return svgtiny_add_path(p, i, &state);
}