static void svgParsePoly(struct SVGParser* p, const char** attr, int closeFlag) { int i; const char* s; float args[2]; int nargs; char item[64]; svgResetPath(p); for (i = 0; attr[i]; i += 2) { if (!svgParseAttr(p, attr[i], attr[i + 1])) { if (strcmp(attr[i], "points") == 0) { s = attr[i + 1]; nargs = 0; while (*s) { s = getNextPathItem(s, item); args[nargs++] = (float)atof(item); if (nargs >= 2) { svgPathPoint(p, args[0], args[1]); nargs = 0; } } } } } svgCreatePath(p, closeFlag); }
static void svgParseLine(struct SVGParser* p, const char** attr) { float x1 = 0.0; float y1 = 0.0; float x2 = 0.0; float y2 = 0.0; int i; for (i = 0; attr[i]; i += 2) { if (!svgParseAttr(p, attr[i], attr[i + 1])) { if (strcmp(attr[i], "x1") == 0) x1 = parseFloat(attr[i + 1]); if (strcmp(attr[i], "y1") == 0) y1 = parseFloat(attr[i + 1]); if (strcmp(attr[i], "x2") == 0) x2 = parseFloat(attr[i + 1]); if (strcmp(attr[i], "y2") == 0) y2 = parseFloat(attr[i + 1]); } } svgResetPath(p); svgPathPoint(p, x1, y1); svgPathPoint(p, x2, y2); svgCreatePath(p, 0); }
static void svgParseRect(struct SVGParser* p, const char** attr) { float x = 0.0f; float y = 0.0f; float w = 0.0f; float h = 0.0f; int i; for (i = 0; attr[i]; i += 2) { if (!svgParseAttr(p, attr[i], attr[i + 1])) { if (strcmp(attr[i], "x") == 0) x = parseFloat(attr[i+1]); if (strcmp(attr[i], "y") == 0) y = parseFloat(attr[i+1]); if (strcmp(attr[i], "width") == 0) w = parseFloat(attr[i+1]); if (strcmp(attr[i], "height") == 0) h = parseFloat(attr[i+1]); } } if (w != 0.0f && h != 0.0f) { svgResetPath(p); svgPathPoint(p, x, y); svgPathPoint(p, x+w, y); svgPathPoint(p, x+w, y+h); svgPathPoint(p, x, y+h); svgCreatePath(p, 1); } }
static void svgParseCircle(struct SVGParser* p, const char** attr) { float cx = 0.0f; float cy = 0.0f; float r = 0.0f; float da; int i,n; float x,y,u; for (i = 0; attr[i]; i += 2) { if (!svgParseAttr(p, attr[i], attr[i + 1])) { if (strcmp(attr[i], "cx") == 0) cx = parseFloat(attr[i+1]); if (strcmp(attr[i], "cy") == 0) cy = parseFloat(attr[i+1]); if (strcmp(attr[i], "r") == 0) r = fabsf(parseFloat(attr[i+1])); } } if (r != 0.0f) { svgResetPath(p); da = acosf(r/(r+p->tol))*2; n = (int)ceilf(M_PI*2/da); da = (float)(M_PI*2)/n; for (i = 0; i < n; ++i) { u = i*da; x = cx + cosf(u)*r; y = cy + sinf(u)*r; svgPathPoint(p, x, y); } svgCreatePath(p, 1); } }
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(const char** attr) { nbuf = 0; 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]; s = attr[0]; svgResetPath(); 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(&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<ofxVec2f*>(); // Start new subpath. //svgResetPath(); closedFlag = 0; nargs = 0; cpx = 0; cpy = 0; } else if (cmd == 'Z' || cmd == 'z') { closedFlag = 1; // Commit path. //path = new vector<ofxVec2f*>(); // Start new subpath. svgResetPath(); closedFlag = 0; nargs = 0; } } } /* // Commit path. path = new vector<ofxVec2f*>(); */ }