diff --git a/src/nanosvg.h b/src/nanosvg.h index 82f46d3..576fc0c 100644 --- a/src/nanosvg.h +++ b/src/nanosvg.h @@ -225,11 +225,6 @@ static int nsvg__isdigit(char c) return c >= '0' && c <= '9'; } -static int nsvg__isnum(char c) -{ - return strchr("0123456789+-.eE", c) != 0; -} - static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; } static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; } @@ -736,9 +731,11 @@ static void nsvg__lineTo(NSVGparser* p, float x, float y) static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y) { - nsvg__addPoint(p, cpx1, cpy1); - nsvg__addPoint(p, cpx2, cpy2); - nsvg__addPoint(p, x, y); + if (p->npts > 0) { + nsvg__addPoint(p, cpx1, cpy1); + nsvg__addPoint(p, cpx2, cpy2); + nsvg__addPoint(p, x, y); + } } static NSVGattrib* nsvg__getAttr(NSVGparser* p) @@ -1040,6 +1037,10 @@ static void nsvg__addPath(NSVGparser* p, char closed) if (closed) nsvg__lineTo(p, p->pts[0], p->pts[1]); + // Expect 1 + N*3 points (N = number of cubic bezier segments). + if ((p->npts % 3) != 1) + return; + path = (NSVGpath*)malloc(sizeof(NSVGpath)); if (path == NULL) goto error; memset(path, 0, sizeof(NSVGpath)); @@ -1458,6 +1459,15 @@ static int nsvg__parseUnits(const char* units) return NSVG_UNITS_USER; } +static int nsvg__isCoordinate(const char* s) +{ + // optional sign + if (*s == '-' || *s == '+') + s++; + // must have at least one digit + return nsvg__isdigit(*s); +} + static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) { NSVGcoordinate coord = {0, NSVG_UNITS_USER}; @@ -1883,8 +1893,11 @@ static int nsvg__getArgsPerElement(char cmd) case 'a': case 'A': return 7; + case 'z': + case 'Z': + return 0; } - return 0; + return -1; } static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel) @@ -2194,6 +2207,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) float args[10]; int nargs; int rargs = 0; + char initPoint; float cpx, cpy, cpx2, cpy2; const char* tmp[4]; char closedFlag; @@ -2216,13 +2230,14 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) nsvg__resetPath(p); cpx = 0; cpy = 0; cpx2 = 0; cpy2 = 0; + initPoint = 0; closedFlag = 0; nargs = 0; while (*s) { s = nsvg__getNextPathItem(s, item); if (!*item) break; - if (nsvg__isnum(item[0])) { + if (cmd != '\0' && nsvg__isCoordinate(item)) { if (nargs < 10) args[nargs++] = (float)nsvg__atof(item); if (nargs >= rargs) { @@ -2235,6 +2250,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) cmd = (cmd == 'm') ? 'l' : 'L'; rargs = nsvg__getArgsPerElement(cmd); cpx2 = cpx; cpy2 = cpy; + initPoint = 1; break; case 'l': case 'L': @@ -2284,7 +2300,6 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) } } else { cmd = item[0]; - rargs = nsvg__getArgsPerElement(cmd); if (cmd == 'M' || cmd == 'm') { // Commit path. if (p->npts > 0) @@ -2293,7 +2308,11 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) nsvg__resetPath(p); closedFlag = 0; nargs = 0; - } else if (cmd == 'Z' || cmd == 'z') { + } else if (initPoint == 0) { + // Do not allow other commands until initial point has been set (moveTo called once). + cmd = '\0'; + } + if (cmd == 'Z' || cmd == 'z') { closedFlag = 1; // Commit path. if (p->npts > 0) { @@ -2309,6 +2328,12 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) closedFlag = 0; nargs = 0; } + rargs = nsvg__getArgsPerElement(cmd); + if (rargs == -1) { + // Command not recognized + cmd = '\0'; + rargs = 0; + } } } // Commit path.