Skip to content

Commit 92c23d7

Browse files
committed
Take svg files from tk trunk: fix svgnano bugs 184, 185
Signed-off-by: Harald Oehlmann <[email protected]>
1 parent 881edbe commit 92c23d7

File tree

1 file changed

+51
-17
lines changed

1 file changed

+51
-17
lines changed

generic/nanosvg.h

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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-
263258
static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
264259
static 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

796791
static 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

803800
static NSVGattrib* nsvg__getAttr(NSVGparser* p)
@@ -867,7 +864,9 @@ static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig,
867864
static 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+
15341553
static 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

19802002
static 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

Comments
 (0)