예제 #1
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;
}
예제 #2
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;
}
예제 #3
0
/*
 Traverse the whole DOM and process each node in three ways
 1. Save XML doc as a nested object tree to be saved out
 2. Parse graphics into ofPaths
 3. Save reference to current processed path node in a lookup flatlist
 
 
 info belongs to ofxSVG
 node is the current object in the tree being parsed, preserving nesting
 cnl is the childlist from original DOM
 state is tinysvg control parse value
 */
svgtiny_code processChildren(svgInfo &info, ofPtr<svgNode> node, Poco::XML::ChildNodesList *cnl,
                             struct svgtiny_parse_state state){

    
        
    svgtiny_code code = svgtiny_OK;
    int i  = 0, l = cnl->length();
    
    while( i < l ){

    Element *child = (Poco::XML::Element *) cnl->item(i);
        ofPtr<svgNode> childnode(new svgNode());
        
    
    // I think this can't happen?
    if (child->nodeType() == Poco::XML::Element::ELEMENT_NODE) {
        const char *name = (const char *) child->localName().c_str();
        
        if (strcmp(name, "svg") == 0){
            
            ofLog()<<"processing a nested svg (not root)"<<endl;
            
            
                        
            //this svg is within root svg
 
            svgDef svgDef;
            svgDef.width = ofToString(child->getAttribute("width").c_str());
            svgDef.height = ofToString(child->getAttribute("height").c_str());
            svgDef.x = ofToString(child->getAttribute("x").c_str());
            svgDef.y = ofToString(child->getAttribute("y").c_str());
            svgDef.viewbox = ofToString(child->getAttribute("viewbox").c_str());
            
            
                
            
            
            
            /*recursive call for any nodes inside svg
            Poco::XML::ChildNodesList *cnl = ( Poco::XML::ChildNodesList *) child->childNodes();
            int ii  = 0, ll = cnl->length();
            while( ii < ll ) {
                 ofLog()<<"recursive svg call"<<ii<<endl;
                Poco::XML::Element * grandchild = (Poco::XML::Element *) cnl->item(ii);
                svgNode childnode;
                svgtiny_code code = processChildren(info,childnode,grandchild,state);
                svgDef.nodes.push_back(childnode);
                if (code != svgtiny_OK)
                    return code;
                 ii++;
                
            }*/
            
            childnode->svg = svgDef;
            childnode->type =SVG_TAG_TYPE_SVG;
            node->children.push_back(childnode);
            
            //recursive call...it seeems svg and groups are treated the same
            code = svgtiny_parse_svg(info,child, state,childnode);
        }else if (strcmp(name, "g") == 0){
           /// ofLog()<<"processing group"<<endl;
            
            svgGroupDef gDef;
            gDef.transform = ofToString(child->getAttribute("transform").c_str());
            
            gDef.fill = ofToString(child->getAttribute("fill").c_str());
            gDef.stroke = ofToString(child->getAttribute("stroke").c_str());
            gDef.stroke_width = ofToString(child->getAttribute("stroke-width").c_str());
            gDef.stroke_miterlimit = ofToString(child->getAttribute("stroke-miterlimit").c_str());
            gDef.fill_opacity = ofToString(child->getAttribute("fill-opacity").c_str());
            gDef.stroke_opacity = ofToString(child->getAttribute("stroke-opacity").c_str());
            
            
            
            
            //recursive call for any nodes inside svg
            /*Poco::XML::ChildNodesList *cnl = ( Poco::XML::ChildNodesList *) child->childNodes();
            int ii  = 0, ll = cnl->length();
            while( ii < ll ) {
                 ofLog()<<"recursive grop call"<<ii<<endl;
                Poco::XML::Element * grandchild = (Poco::XML::Element *) cnl->item(ii);
                svgNode childnode;
                svgtiny_code code = processChildren(info,childnode,grandchild,state);
                gDef.nodes.push_back(childnode);
                if (code != svgtiny_OK)
                    return code;
                ii++;
                
            }
            */
            childnode->group = gDef;  
            childnode->type =SVG_TAG_TYPE_GROUP;
            node->children.push_back(childnode);
            
            
            //recursive call...it seeems svg and groups are treated the same
            code = svgtiny_parse_svg(info,child, state,childnode);
        }else if (strcmp(name, "a") == 0){
            //a node?! who cares

            code = svgtiny_parse_svg(info,child, state,childnode);
        }else if (strcmp(name, "path") == 0){
            //ofLog()<<"--------  "<<child->getAttribute("d").c_str()<<endl;
            //<path fill="#D14E8F" stroke="#0C0404" stroke-miterlimit="10" d="M2802.998,4477.002c-2.002-30-2.002-31.001,7.998-8.003c5,13.999,6.006,28.003,1.006,33.003                C2807.998,4506.001,2802.998,4495,2802.998,4477.002z"/>
            //info.paths.push_back(child->getAttribute("d").c_str());
            //info.paths.push_back("<"+ofToString(child->nodeName().c_str())+"/>");
            //"<path fill='#000000' stroke='#000000' stroke-width='1' stroke-miterlimit='10' d='M590 35 c0 -19 5 -35 11 -35 7 0 9 10 4 28 -4 17 -3 24 3 17 6 -5 12 -19 15 -30 4 -16 5 -16 6 5 1 15 -7 30 -19 38 -19 11 -20 10 -20 -23z' />"

            svgPathDef pDef;
            pDef.d = ofToString(child->getAttribute("d").c_str());
            pDef.fill = ofToString(child->getAttribute("fill").c_str());
            pDef.stroke = ofToString(child->getAttribute("stroke").c_str());
            pDef.stroke_width = ofToString(child->getAttribute("stroke-width").c_str());
            pDef.stroke_miterlimit = ofToString(child->getAttribute("stroke-miterlimit").c_str());
            //info.paths.push_back(pDef);
            pDef.fill_opacity = ofToString(child->getAttribute("fill-opacity").c_str());
            pDef.stroke_opacity = ofToString(child->getAttribute("stroke-opacity").c_str());
            
            childnode->path = pDef;         
            childnode->type = SVG_TAG_TYPE_PATH;
            node->children.push_back(childnode);
            
           // ofLog()<<"defining currNode"<<endl;
            state.currNode = childnode;
            
            /*
             if(info.svgs.size()>0){
             //this path is within a nested svg
             info.svgs[info.svgs.size()-1]->groups[info.svgs[info.svgs.size()-1]->groups.size()-1]->paths.push_back(pDef);
             }else{
             //this path belongs within group in root svg
             info.groups[info.groups.size()-1]->paths.push_back(pDef);                  
             }
             */
            
            
            code = svgtiny_parse_path(child, state);
            
            
        } else if (strcmp(name, "rect") == 0){
            
            
            svgRectDef pDef;
 
            pDef.fill = ofToString(child->getAttribute("fill").c_str());
            pDef.stroke = ofToString(child->getAttribute("stroke").c_str());
            pDef.stroke_width = ofToString(child->getAttribute("stroke-width").c_str());
            pDef.stroke_miterlimit = ofToString(child->getAttribute("stroke-miterlimit").c_str());
            //info.paths.push_back(pDef);
            pDef.fill_opacity = ofToString(child->getAttribute("fill-opacity").c_str());
            pDef.stroke_opacity = ofToString(child->getAttribute("stroke-opacity").c_str());
            
            pDef.x = ofToString(child->getAttribute("x").c_str());
            pDef.y = ofToString(child->getAttribute("y").c_str());
            pDef.width = ofToString(child->getAttribute("width").c_str());
            pDef.height = ofToString(child->getAttribute("height").c_str());
            
            
            childnode->rect = pDef;         
            childnode->type = SVG_TAG_TYPE_RECT;
            node->children.push_back(childnode);
            
           // ofLog()<<"defining currNode"<<endl;
            state.currNode = childnode;

            
            
            
            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);
        }
        // not sure about this
    } else if (child->nodeType() == Poco::XML::Element::TEXT_NODE) {
        
        const char *name = (const char *) child->localName().c_str();
        
        if (strcmp(name, "text") == 0)
            code = svgtiny_parse_text(child, state);
    }
    
    
    
    
   
    

    
    //pNode = it.nextNode();
   
    
        if (code != svgtiny_OK){
            return code;
        }

        
        i++;
        
	}

    return code;
};