static void svgParsePath(struct SVGParser* p, const char** attr) { const char* s; char cmd; float args[10]; int nargs; int rargs; float cpx, cpy, cpx2, cpy2; const char* tmp[4]; char closedFlag; int i; char item[64]; for (i = 0; attr[i]; i += 2) { if (strcmp(attr[i], "d") == 0) { s = attr[i + 1]; svgResetPath(p); closedFlag = 0; nargs = 0; while (*s) { s = getNextPathItem(s, item); if (!*item) break; if (isnum(item[0])) { if (nargs < 10) args[nargs++] = (float)atof(item); if (nargs >= rargs) { switch (cmd) { case 'm': case 'M': case 'l': case 'L': pathLineTo(p, &cpx, &cpy, args, (cmd == 'm' || cmd == 'l') ? 1 : 0); break; case 'H': case 'h': pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0); break; case 'V': case 'v': pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0); break; case 'C': case 'c': pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0); break; case 'S': case 's': pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); break; case 'Q': case 'q': pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0); break; case 'T': case 't': pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); break; default: if (nargs >= 2) { cpx = args[nargs-2]; cpy = args[nargs-1]; } break; } nargs = 0; } } else { cmd = item[0]; rargs = getArgsPerElement(cmd); if (cmd == 'M' || cmd == 'm') { // Commit path. if (p->nbuf) svgCreatePath(p, closedFlag); // Start new subpath. svgResetPath(p); closedFlag = 0; nargs = 0; cpx = 0; cpy = 0; } else if (cmd == 'Z' || cmd == 'z') { closedFlag = 1; // Commit path. if (p->nbuf) svgCreatePath(p, closedFlag); // Start new subpath. svgResetPath(p); closedFlag = 0; nargs = 0; } } } // Commit path. if (p->nbuf) svgCreatePath(p, closedFlag); } else { tmp[0] = attr[i]; tmp[1] = attr[i + 1]; tmp[2] = 0; tmp[3] = 0; svgParseAttribs(p, tmp); } } }
void ofxSVGPathParser::parse(string& path) { nbuf = 0; char cmd; float args[10]; int nargs; int rargs; float cpx, cpy, cpx2, cpy2; const char* tmp[4]; char closedFlag; int i; char item[64]; string::iterator s = path.begin(); pathInstance->newSubPath(); closedFlag = 0; nargs = 0; while (s != path.end()) { getNextPathItem(s, item); if (!*item) break; if (isnum(item[0])) { if (nargs < 10) { args[nargs++] = (float) atof(item); } if (nargs >= rargs) { cout << " command " << cmd << endl; switch (cmd) { case 'm': case 'M': case 'l': case 'L': pathLineTo(&cpx, &cpy, args, (cmd == 'm' || cmd == 'l') ? 1 : 0); break; case 'H': case 'h': pathHLineTo(&cpx, &cpy, args, cmd == 'h' ? 1 : 0); break; case 'V': case 'v': pathVLineTo(&cpx, &cpy, args, cmd == 'v' ? 1 : 0); break; case 'C': case 'c': pathCubicBezTo(&cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0); break; case 'S': case 's': pathCubicBezShortTo(&cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); break; case 'Q': case 'q': pathQuadBezTo(&cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0); break; case 'T': case 't': pathQuadBezShortTo(&cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0); break; default: if (nargs >= 2) { cpx = args[nargs-2]; cpy = args[nargs-1]; } break; } nargs = 0; } } else { cmd = item[0]; rargs = getArgsPerElement(cmd); if (cmd == 'M' || cmd == 'm') { // Commit path-> // TODO get all the transform/translate/etc data from the parent? // or just return out of this and handle in the parent? //path = new vector<ofVec2f*>(); // Start new subpath-> //svgResetPath(); pathInstance->close(); closedFlag = 0; nargs = 0; cpx = 0; cpy = 0; } else if (cmd == 'Z' || cmd == 'z') { closedFlag = 1; // Commit path-> //path = new vector<ofVec2f*>(); // Start new subpath-> pathInstance->close(); closedFlag = 0; nargs = 0; } } } pathInstance->close(); }