/* 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; };
size_t Parser::parseString(const std::string& text, size_t start, size_t len, PTextNode node) { size_t pos = node->content; size_t last = start + len; std::string debug1 = text.substr(pos, len); while(pos < last) { size_t view = pos; PTextView chunk(new TextView()); chunk->col = m_color; chunk->font = m_font; applyFormatting(chunk, node.get()); chunk->start = view; pos = text.find_first_of("[", pos); if(pos != std::string::npos && pos < last) { size_t close = text.find_first_of("]", pos); if(close == std::string::npos || close > last) { pos = last; chunk->len = pos - view; if(chunk->len || node->type == ImgTag) { chunk->isNewLine = m_paragraph; chunk->isList = m_list; m_paragraph = false; m_formatting.push_back(chunk); } m_list = false; break; // newline symbol inside a tag! } chunk->len = pos - view; if(chunk->len || node->type == ImgTag) { chunk->isNewLine = m_paragraph; chunk->isList = m_list; m_paragraph = false; m_formatting.push_back(chunk); } std::string param; std::string tag = text.substr(pos + 1, close - (pos + 1)); bool closed = false; TagType type = parseNodeTag(tag, closed, param); if(!closed) { if(type == ListTag) { m_list = true; if(!m_paragraph) { m_paragraph = true; pos = close; break; } } // New tag found PTextNode childnode(new TextNode()); childnode->start = pos; childnode->content = close + 1; childnode->parent = node.get(); childnode->type = type; childnode->param = param; node->children.push_back(childnode); pos = parseString(text, pos, last - pos, childnode); } else { pos = close; if(type == node->type) { break; } } } else { pos = last; chunk->len = pos - view; if(chunk->len || node->type == ImgTag) { chunk->isNewLine = m_paragraph; chunk->isList = m_list; m_paragraph = false; m_formatting.push_back(chunk); } break; } } pos++; node->len = pos - node->start; return pos; }