@@ -45,15 +45,15 @@ extern "C" {
4545// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose
4646// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.
4747//
48- // The units passed to NanoVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
48+ // The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
4949// DPI (dots-per-inch) controls how the unit conversion is done.
5050//
5151// If you don't know or care about the units stuff, "px" and 96 should get you going.
5252
5353
5454/* Example Usage:
55- // Load
56- NSVGImage * image;
55+ // Load SVG
56+ NSVGimage * image;
5757 image = nsvgParseFromFile("test.svg", "px", 96);
5858 printf("size: %f x %f\n", image->width, image->height);
5959 // Use...
@@ -255,11 +255,6 @@ static int nsvg__isdigit(char c)
255255 return c >= '0' && c <= '9' ;
256256}
257257
258- static int nsvg__isnum (char c )
259- {
260- return strchr ("0123456789+-.eE" , c ) != 0 ;
261- }
262-
263258static NSVG_INLINE float nsvg__minf (float a , float b ) { return a < b ? a : b ; }
264259static NSVG_INLINE float nsvg__maxf (float a , float b ) { return a > b ? a : b ; }
265260
@@ -795,9 +790,11 @@ static void nsvg__lineTo(NSVGparser* p, float x, float y)
795790
796791static void nsvg__cubicBezTo (NSVGparser * p , float cpx1 , float cpy1 , float cpx2 , float cpy2 , float x , float y )
797792{
798- nsvg__addPoint (p , cpx1 , cpy1 );
799- nsvg__addPoint (p , cpx2 , cpy2 );
800- nsvg__addPoint (p , x , y );
793+ if (p -> npts > 0 ) {
794+ nsvg__addPoint (p , cpx1 , cpy1 );
795+ nsvg__addPoint (p , cpx2 , cpy2 );
796+ nsvg__addPoint (p , x , y );
797+ }
801798}
802799
803800static NSVGattrib * nsvg__getAttr (NSVGparser * p )
@@ -867,7 +864,9 @@ static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig,
867864static NSVGgradientData * nsvg__findGradientData (NSVGparser * p , const char * id )
868865{
869866 NSVGgradientData * grad = p -> gradients ;
870- while (grad ) {
867+ if (id == NULL || * id == '\0' )
868+ return NULL ;
869+ while (grad != NULL ) {
871870 if (strcmp (grad -> id , id ) == 0 )
872871 return grad ;
873872 grad = grad -> next ;
@@ -884,19 +883,26 @@ static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const f
884883 NSVGgradient * grad ;
885884 float ox , oy , sw , sh , sl ;
886885 int nstops = 0 ;
886+ int refIter ;
887887
888888 data = nsvg__findGradientData (p , id );
889889 if (data == NULL ) return NULL ;
890890
891891 // TODO: use ref to fill in all unset values too.
892892 ref = data ;
893+ refIter = 0 ;
893894 while (ref != NULL ) {
895+ NSVGgradientData * nextRef = NULL ;
894896 if (stops == NULL && ref -> stops != NULL ) {
895897 stops = ref -> stops ;
896898 nstops = ref -> nstops ;
897899 break ;
898900 }
899- ref = nsvg__findGradientData (p , ref -> ref );
901+ nextRef = nsvg__findGradientData (p , ref -> ref );
902+ if (nextRef == ref ) break ; // prevent infite loops on malformed data
903+ ref = nextRef ;
904+ refIter ++ ;
905+ if (refIter > 32 ) break ; // prevent infite loops on malformed data
900906 }
901907 if (stops == NULL ) return NULL ;
902908
@@ -1099,6 +1105,10 @@ static void nsvg__addPath(NSVGparser* p, char closed)
10991105 if (closed )
11001106 nsvg__lineTo (p , p -> pts [0 ], p -> pts [1 ]);
11011107
1108+ // Expect 1 + N*3 points (N = number of cubic bezier segments).
1109+ if ((p -> npts % 3 ) != 1 )
1110+ return ;
1111+
11021112 path = (NSVGpath * )NANOSVG_malloc (sizeof (NSVGpath ));
11031113 if (path == NULL ) goto error ;
11041114 memset (path , 0 , sizeof (NSVGpath ));
@@ -1531,6 +1541,15 @@ static int nsvg__parseUnits(const char* units)
15311541 return NSVG_UNITS_USER ;
15321542}
15331543
1544+ static int nsvg__isCoordinate (const char * s )
1545+ {
1546+ // optional sign
1547+ if (* s == '-' || * s == '+' )
1548+ s ++ ;
1549+ // must have at least one digit
1550+ return nsvg__isdigit (* s );
1551+ }
1552+
15341553static NSVGcoordinate nsvg__parseCoordinateRaw (const char * str )
15351554{
15361555 NSVGcoordinate coord = {0 , NSVG_UNITS_USER };
@@ -1973,8 +1992,11 @@ static int nsvg__getArgsPerElement(char cmd)
19731992 case 'a' :
19741993 case 'A' :
19751994 return 7 ;
1995+ case 'z' :
1996+ case 'Z' :
1997+ return 0 ;
19761998 }
1977- return 0 ;
1999+ return -1 ;
19782000}
19792001
19802002static void nsvg__pathMoveTo (NSVGparser * p , float * cpx , float * cpy , float * args , int rel )
@@ -2284,6 +2306,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
22842306 float args [10 ];
22852307 int nargs ;
22862308 int rargs = 0 ;
2309+ char initPoint ;
22872310 float cpx , cpy , cpx2 , cpy2 ;
22882311 const char * tmp [4 ];
22892312 char closedFlag ;
@@ -2306,13 +2329,14 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
23062329 nsvg__resetPath (p );
23072330 cpx = 0 ; cpy = 0 ;
23082331 cpx2 = 0 ; cpy2 = 0 ;
2332+ initPoint = 0 ;
23092333 closedFlag = 0 ;
23102334 nargs = 0 ;
23112335
23122336 while (* s ) {
23132337 s = nsvg__getNextPathItem (s , item );
23142338 if (!* item ) break ;
2315- if (nsvg__isnum (item [ 0 ] )) {
2339+ if (cmd != '\0' && nsvg__isCoordinate (item )) {
23162340 if (nargs < 10 )
23172341 args [nargs ++ ] = (float )nsvg__atof (item );
23182342 if (nargs >= rargs ) {
@@ -2325,6 +2349,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
23252349 cmd = (cmd == 'm' ) ? 'l' : 'L' ;
23262350 rargs = nsvg__getArgsPerElement (cmd );
23272351 cpx2 = cpx ; cpy2 = cpy ;
2352+ initPoint = 1 ;
23282353 break ;
23292354 case 'l' :
23302355 case 'L' :
@@ -2374,7 +2399,6 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
23742399 }
23752400 } else {
23762401 cmd = item [0 ];
2377- rargs = nsvg__getArgsPerElement (cmd );
23782402 if (cmd == 'M' || cmd == 'm' ) {
23792403 // Commit path.
23802404 if (p -> npts > 0 )
@@ -2383,7 +2407,11 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
23832407 nsvg__resetPath (p );
23842408 closedFlag = 0 ;
23852409 nargs = 0 ;
2386- } else if (cmd == 'Z' || cmd == 'z' ) {
2410+ } else if (initPoint == 0 ) {
2411+ // Do not allow other commands until initial point has been set (moveTo called once).
2412+ cmd = '\0' ;
2413+ }
2414+ if (cmd == 'Z' || cmd == 'z' ) {
23872415 closedFlag = 1 ;
23882416 // Commit path.
23892417 if (p -> npts > 0 ) {
@@ -2399,6 +2427,12 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
23992427 closedFlag = 0 ;
24002428 nargs = 0 ;
24012429 }
2430+ rargs = nsvg__getArgsPerElement (cmd );
2431+ if (rargs == -1 ) {
2432+ // Command not recognized
2433+ cmd = '\0' ;
2434+ rargs = 0 ;
2435+ }
24022436 }
24032437 }
24042438 // Commit path.
0 commit comments