From bbd21c005c2fb0bcb6d189a74f5268fb9b411222 Mon Sep 17 00:00:00 2001 From: John Rassa Date: Tue, 27 Aug 2019 20:06:31 -0400 Subject: [PATCH] update nanosvg to latest version --- external/nanosvg/nanosvg.h | 282 ++++++++++++++++++++++++--------- external/nanosvg/nanosvgrast.h | 57 ++++--- 2 files changed, 238 insertions(+), 101 deletions(-) diff --git a/external/nanosvg/nanosvg.h b/external/nanosvg/nanosvg.h index a6c60155e..0cb1e902d 100644 --- a/external/nanosvg/nanosvg.h +++ b/external/nanosvg/nanosvg.h @@ -29,9 +29,11 @@ #ifndef NANOSVG_H #define NANOSVG_H +#ifndef NANOSVG_CPLUSPLUS #ifdef __cplusplus extern "C" { #endif +#endif // NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes. // @@ -45,15 +47,15 @@ extern "C" { // NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose // to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters. // -// The units passed to NanoVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. +// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'. // DPI (dots-per-inch) controls how the unit conversion is done. // // If you don't know or care about the units stuff, "px" and 96 should get you going. /* Example Usage: - // Load - NSVGImage* image; + // Load SVG + NSVGimage* image; image = nsvgParseFromFile("test.svg", "px", 96); printf("size: %f x %f\n", image->width, image->height); // Use... @@ -73,30 +75,30 @@ enum NSVGpaintType { NSVG_PAINT_NONE = 0, NSVG_PAINT_COLOR = 1, NSVG_PAINT_LINEAR_GRADIENT = 2, - NSVG_PAINT_RADIAL_GRADIENT = 3, + NSVG_PAINT_RADIAL_GRADIENT = 3 }; enum NSVGspreadType { NSVG_SPREAD_PAD = 0, NSVG_SPREAD_REFLECT = 1, - NSVG_SPREAD_REPEAT = 2, + NSVG_SPREAD_REPEAT = 2 }; enum NSVGlineJoin { NSVG_JOIN_MITER = 0, NSVG_JOIN_ROUND = 1, - NSVG_JOIN_BEVEL = 2, + NSVG_JOIN_BEVEL = 2 }; enum NSVGlineCap { NSVG_CAP_BUTT = 0, NSVG_CAP_ROUND = 1, - NSVG_CAP_SQUARE = 2, + NSVG_CAP_SQUARE = 2 }; enum NSVGfillRule { NSVG_FILLRULE_NONZERO = 0, - NSVG_FILLRULE_EVENODD = 1, + NSVG_FILLRULE_EVENODD = 1 }; enum NSVGflags { @@ -145,6 +147,7 @@ typedef struct NSVGshape char strokeDashCount; // Number of dash values in dash array. char strokeLineJoin; // Stroke join type. char strokeLineCap; // Stroke cap type. + float miterLimit; // Miter limit char fillRule; // Fill rule, see NSVGfillRule. unsigned char flags; // Logical or of NSVG_FLAGS_* flags float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. @@ -166,11 +169,16 @@ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) // Important note: changes the string. NSVGimage* nsvgParse(char* input, const char* units, float dpi); -// Deletes list of paths. +// Duplicates a path. +NSVGpath* nsvgDuplicatePath(NSVGpath* p); + +// Deletes an image. void nsvgDelete(NSVGimage* image); +#ifndef NANOSVG_CPLUSPLUS #ifdef __cplusplus -}; +} +#endif #endif #endif // NANOSVG_H @@ -182,7 +190,7 @@ void nsvgDelete(NSVGimage* image); #include #define NSVG_PI (3.14159265358979323846264338327f) -#define NSVG_KAPPA90 (0.5522847493f) // Lenght proportional to radius of a cubic bezier handle for 90deg arcs. +#define NSVG_KAPPA90 (0.5522847493f) // Length proportional to radius of a cubic bezier handle for 90deg arcs. #define NSVG_ALIGN_MIN 0 #define NSVG_ALIGN_MID 1 @@ -195,7 +203,7 @@ void nsvgDelete(NSVGimage* image); #define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16)) #ifdef _MSC_VER - #pragma warning (disable: 4996) // Switch off security warnings +#pragma warning (disable: 4996) // Switch off security warnings #pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings #ifdef __cplusplus #define NSVG_INLINE inline @@ -203,7 +211,7 @@ void nsvgDelete(NSVGimage* image); #define NSVG_INLINE #endif #else - #define NSVG_INLINE inline +#define NSVG_INLINE inline #endif @@ -214,7 +222,7 @@ static int nsvg__isspace(char c) static int nsvg__isdigit(char c) { - return strchr("0123456789", c) != 0; + return c >= '0' && c <= '9'; } static int nsvg__isnum(char c) @@ -278,6 +286,9 @@ static void nsvg__parseElement(char* s, // Get attribs while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) { + char* name = NULL; + char* value = NULL; + // Skip white space before the attrib name while (*s && nsvg__isspace(*s)) s++; if (!*s) break; @@ -285,7 +296,7 @@ static void nsvg__parseElement(char* s, end = 1; break; } - attr[nattr++] = s; + name = s; // Find end of the attrib name. while (*s && !nsvg__isspace(*s) && *s != '=') s++; if (*s) { *s++ = '\0'; } @@ -295,9 +306,15 @@ static void nsvg__parseElement(char* s, quote = *s; s++; // Store value and find the end of it. - attr[nattr++] = s; + value = s; while (*s && *s != quote) s++; if (*s) { *s++ = '\0'; } + + // Store only well formed attributes + if (name && value) { + attr[nattr++] = name; + attr[nattr++] = value; + } } // List terminator @@ -348,7 +365,7 @@ int nsvg__parseXML(char* input, enum NSVGgradientUnits { NSVG_USER_SPACE = 0, - NSVG_OBJECT_SPACE = 1, + NSVG_OBJECT_SPACE = 1 }; #define NSVG_MAX_DASHES 8 @@ -363,7 +380,7 @@ enum NSVGunits { NSVG_UNITS_IN, NSVG_UNITS_PERCENT, NSVG_UNITS_EM, - NSVG_UNITS_EX, + NSVG_UNITS_EX }; typedef struct NSVGcoordinate { @@ -413,6 +430,7 @@ typedef struct NSVGattrib int strokeDashCount; char strokeLineJoin; char strokeLineCap; + float miterLimit; char fillRule; float fontSize; unsigned int stopColor; @@ -433,6 +451,7 @@ typedef struct NSVGparser NSVGpath* plist; NSVGimage* image; NSVGgradientData* gradients; + NSVGshape* shapesTail; float viewMinx, viewMiny, viewWidth, viewHeight; int alignX, alignY, alignType; float dpi; @@ -620,13 +639,14 @@ static NSVGparser* nsvg__createParser() p->attr[0].strokeWidth = 1; p->attr[0].strokeLineJoin = NSVG_JOIN_MITER; p->attr[0].strokeLineCap = NSVG_CAP_BUTT; + p->attr[0].miterLimit = 4; p->attr[0].fillRule = NSVG_FILLRULE_NONZERO; p->attr[0].hasFill = 1; p->attr[0].visible = 1; return p; -error: + error: if (p) { if (p->image) free(p->image); free(p); @@ -918,7 +938,7 @@ static void nsvg__addShape(NSVGparser* p) { NSVGattrib* attr = nsvg__getAttr(p); float scale = 1.0f; - NSVGshape *shape, *cur, *prev; + NSVGshape* shape; NSVGpath* path; int i; @@ -933,11 +953,12 @@ static void nsvg__addShape(NSVGparser* p) scale = nsvg__getAverageScale(attr->xform); shape->strokeWidth = attr->strokeWidth * scale; shape->strokeDashOffset = attr->strokeDashOffset * scale; - shape->strokeDashCount = attr->strokeDashCount; + shape->strokeDashCount = (char)attr->strokeDashCount; for (i = 0; i < attr->strokeDashCount; i++) shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale; shape->strokeLineJoin = attr->strokeLineJoin; shape->strokeLineCap = attr->strokeLineCap; + shape->miterLimit = attr->miterLimit; shape->fillRule = attr->fillRule; shape->opacity = attr->opacity; @@ -993,20 +1014,15 @@ static void nsvg__addShape(NSVGparser* p) shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00); // Add to tail - prev = NULL; - cur = p->image->shapes; - while (cur != NULL) { - prev = cur; - cur = cur->next; - } - if (prev == NULL) + if (p->image->shapes == NULL) p->image->shapes = shape; else - prev->next = shape; + p->shapesTail->next = shape; + p->shapesTail = shape; return; -error: + error: if (shape) free(shape); } @@ -1059,13 +1075,73 @@ static void nsvg__addPath(NSVGparser* p, char closed) return; -error: + error: if (path != NULL) { if (path->pts != NULL) free(path->pts); free(path); } } +// We roll our own string to float because the std library one uses locale and messes things up. +static double nsvg__atof(const char* s) +{ + char* cur = (char*)s; + char* end = NULL; + double res = 0.0, sign = 1.0; + long long intPart = 0, fracPart = 0; + char hasIntPart = 0, hasFracPart = 0; + + // Parse optional sign + if (*cur == '+') { + cur++; + } else if (*cur == '-') { + sign = -1; + cur++; + } + + // Parse integer part + if (nsvg__isdigit(*cur)) { + // Parse digit sequence + intPart = strtoll(cur, &end, 10); + if (cur != end) { + res = (double)intPart; + hasIntPart = 1; + cur = end; + } + } + + // Parse fractional part. + if (*cur == '.') { + cur++; // Skip '.' + if (nsvg__isdigit(*cur)) { + // Parse digit sequence + fracPart = strtoll(cur, &end, 10); + if (cur != end) { + res += (double)fracPart / pow(10.0, (double)(end - cur)); + hasFracPart = 1; + cur = end; + } + } + } + + // A valid number should have integer or fractional part. + if (!hasIntPart && !hasFracPart) + return 0.0; + + // Parse optional exponent + if (*cur == 'e' || *cur == 'E') { + long expPart = 0; + cur++; // skip 'E' + expPart = strtol(cur, &end, 10); // Parse digit sequence with sign + if (cur != end) { + res *= pow(10.0, (double)expPart); + } + } + + return res * sign; +} + + static const char* nsvg__parseNumber(const char* s, char* it, const int size) { const int last = size-1; @@ -1092,7 +1168,7 @@ static const char* nsvg__parseNumber(const char* s, char* it, const int size) } } // exponent - if (*s == 'e' || *s == 'E') { + if ((*s == 'e' || *s == 'E') && (s[1] != 'm' && s[1] != 'x')) { if (i < last) it[i++] = *s; s++; if (*s == '-' || *s == '+') { @@ -1167,19 +1243,19 @@ typedef struct NSVGNamedColor { NSVGNamedColor nsvg__colors[] = { - { "red", NSVG_RGB(255, 0, 0) }, - { "green", NSVG_RGB( 0, 128, 0) }, - { "blue", NSVG_RGB( 0, 0, 255) }, - { "yellow", NSVG_RGB(255, 255, 0) }, - { "cyan", NSVG_RGB( 0, 255, 255) }, - { "magenta", NSVG_RGB(255, 0, 255) }, - { "black", NSVG_RGB( 0, 0, 0) }, - { "grey", NSVG_RGB(128, 128, 128) }, - { "gray", NSVG_RGB(128, 128, 128) }, - { "white", NSVG_RGB(255, 255, 255) }, + { "red", NSVG_RGB(255, 0, 0) }, + { "green", NSVG_RGB( 0, 128, 0) }, + { "blue", NSVG_RGB( 0, 0, 255) }, + { "yellow", NSVG_RGB(255, 255, 0) }, + { "cyan", NSVG_RGB( 0, 255, 255) }, + { "magenta", NSVG_RGB(255, 0, 255) }, + { "black", NSVG_RGB( 0, 0, 0) }, + { "grey", NSVG_RGB(128, 128, 128) }, + { "gray", NSVG_RGB(128, 128, 128) }, + { "white", NSVG_RGB(255, 255, 255) }, #ifdef NANOSVG_ALL_COLOR_KEYWORDS - { "aliceblue", NSVG_RGB(240, 248, 255) }, +{ "aliceblue", NSVG_RGB(240, 248, 255) }, { "antiquewhite", NSVG_RGB(250, 235, 215) }, { "aqua", NSVG_RGB( 0, 255, 255) }, { "aquamarine", NSVG_RGB(127, 255, 212) }, @@ -1346,13 +1422,19 @@ static unsigned int nsvg__parseColor(const char* str) static float nsvg__parseOpacity(const char* str) { - float val = 0; - sscanf(str, "%f", &val); + float val = nsvg__atof(str); if (val < 0.0f) val = 0.0f; if (val > 1.0f) val = 1.0f; return val; } +static float nsvg__parseMiterLimit(const char* str) +{ + float val = nsvg__atof(str); + if (val < 0.0f) val = 0.0f; + return val; +} + static int nsvg__parseUnits(const char* units) { if (units[0] == 'p' && units[1] == 'x') @@ -1379,9 +1461,9 @@ static int nsvg__parseUnits(const char* units) static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str) { NSVGcoordinate coord = {0, NSVG_UNITS_USER}; - char units[32]=""; - sscanf(str, "%f%s", &coord.value, units); - coord.units = nsvg__parseUnits(units); + char buf[64]; + coord.units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64)); + coord.value = nsvg__atof(buf); return coord; } @@ -1417,7 +1499,7 @@ static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) { if (*na >= maxNa) return 0; ptr = nsvg__parseNumber(ptr, it, 64); - args[(*na)++] = (float)atof(it); + args[(*na)++] = (float)nsvg__atof(it); } else { ++ptr; } @@ -1573,7 +1655,7 @@ static char nsvg__parseLineJoin(const char* str) else if (strcmp(str, "bevel") == 0) return NSVG_JOIN_BEVEL; // TODO: handle inherit. - return NSVG_CAP_BUTT; + return NSVG_JOIN_MITER; } static char nsvg__parseFillRule(const char* str) @@ -1679,6 +1761,8 @@ static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value) attr->strokeLineCap = nsvg__parseLineCap(value); } else if (strcmp(name, "stroke-linejoin") == 0) { attr->strokeLineJoin = nsvg__parseLineJoin(value); + } else if (strcmp(name, "stroke-miterlimit") == 0) { + attr->miterLimit = nsvg__parseMiterLimit(value); } else if (strcmp(name, "fill-rule") == 0) { attr->fillRule = nsvg__parseFillRule(value); } else if (strcmp(name, "font-size") == 0) { @@ -1995,7 +2079,7 @@ static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, rx = fabsf(args[0]); // y radius ry = fabsf(args[1]); // x radius - rotx = args[2] / 180.0f * NSVG_PI; // x rotation engle + rotx = args[2] / 180.0f * NSVG_PI; // x rotation angle fa = fabsf(args[3]) > 1e-6 ? 1 : 0; // Large arc fs = fabsf(args[4]) > 1e-6 ? 1 : 0; // Sweep direction x1 = *cpx; // start point @@ -2060,13 +2144,10 @@ static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, // if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI; // if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0; - if (fa) { - // Choose large arc - if (da > 0.0f) - da = da - 2*NSVG_PI; - else - da = 2*NSVG_PI + da; - } + if (fs == 0 && da > 0) + da -= 2 * NSVG_PI; + else if (fs == 1 && da < 0) + da += 2 * NSVG_PI; // Approximate the arc using cubic spline segments. t[0] = cosrx; t[1] = sinrx; @@ -2082,7 +2163,7 @@ static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, kappa = -kappa; for (i = 0; i <= ndivs; i++) { - a = a1 + da * (i/(float)ndivs); + a = a1 + da * ((float)i/(float)ndivs); dx = cosf(a); dy = sinf(a); nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position @@ -2136,7 +2217,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) if (!*item) break; if (nsvg__isnum(item[0])) { if (nargs < 10) - args[nargs++] = (float)atof(item); + args[nargs++] = (float)nsvg__atof(item); if (nargs >= rargs) { switch (cmd) { case 'm': @@ -2145,23 +2226,23 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) // Moveto can be followed by multiple coordinate pairs, // which should be treated as linetos. cmd = (cmd == 'm') ? 'l' : 'L'; - rargs = nsvg__getArgsPerElement(cmd); - cpx2 = cpx; cpy2 = cpy; + rargs = nsvg__getArgsPerElement(cmd); + cpx2 = cpx; cpy2 = cpy; break; case 'l': case 'L': nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0); - cpx2 = cpx; cpy2 = cpy; + cpx2 = cpx; cpy2 = cpy; break; case 'H': case 'h': nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0); - cpx2 = cpx; cpy2 = cpy; + cpx2 = cpx; cpy2 = cpy; break; case 'V': case 'v': nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0); - cpx2 = cpx; cpy2 = cpy; + cpx2 = cpx; cpy2 = cpy; break; case 'C': case 'c': @@ -2182,13 +2263,13 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr) case 'A': case 'a': nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0); - cpx2 = cpx; cpy2 = cpy; + cpx2 = cpx; cpy2 = cpy; break; default: if (nargs >= 2) { cpx = args[nargs-2]; cpy = args[nargs-1]; - cpx2 = cpx; cpy2 = cpy; + cpx2 = cpx; cpy2 = cpy; } break; } @@ -2393,7 +2474,7 @@ static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag) nargs = 0; while (*s) { s = nsvg__getNextPathItem(s, item); - args[nargs++] = (float)atof(item); + args[nargs++] = (float)nsvg__atof(item); if (nargs >= 2) { if (npts == 0) nsvg__moveTo(p, args[0], args[1]); @@ -2418,11 +2499,26 @@ static void nsvg__parseSVG(NSVGparser* p, const char** attr) for (i = 0; attr[i]; i += 2) { if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) { if (strcmp(attr[i], "width") == 0) { - p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 1.0f); + p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); } else if (strcmp(attr[i], "height") == 0) { - p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 1.0f); + p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f); } else if (strcmp(attr[i], "viewBox") == 0) { - sscanf(attr[i + 1], "%f%*[%%, \t]%f%*[%%, \t]%f%*[%%, \t]%f", &p->viewMinx, &p->viewMiny, &p->viewWidth, &p->viewHeight); + const char *s = attr[i + 1]; + char buf[64]; + s = nsvg__parseNumber(s, buf, 64); + p->viewMinx = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; + if (!*s) return; + s = nsvg__parseNumber(s, buf, 64); + p->viewMiny = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; + if (!*s) return; + s = nsvg__parseNumber(s, buf, 64); + p->viewWidth = nsvg__atof(buf); + while (*s && (nsvg__isspace(*s) || *s == '%' || *s == ',')) s++; + if (!*s) return; + s = nsvg__parseNumber(s, buf, 64); + p->viewHeight = nsvg__atof(buf); } else if (strcmp(attr[i], "preserveAspectRatio") == 0) { if (strstr(attr[i + 1], "none") != 0) { // No uniform scaling @@ -2678,12 +2774,12 @@ static float nsvg__viewAlign(float content, float container, int type) static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy) { - grad->xform[0] *= sx; - grad->xform[1] *= sx; - grad->xform[2] *= sy; - grad->xform[3] *= sy; - grad->xform[4] += tx*sx; - grad->xform[5] += ty*sx; + float t[6]; + nsvg__xformSetTranslation(t, tx, ty); + nsvg__xformMultiply (grad->xform, t); + + nsvg__xformSetScale(t, sx, sy); + nsvg__xformMultiply (grad->xform, t); } static void nsvg__scaleToViewbox(NSVGparser* p, const char* units) @@ -2823,13 +2919,43 @@ NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi) return image; -error: + error: if (fp) fclose(fp); if (data) free(data); if (image) nsvgDelete(image); return NULL; } +NSVGpath* nsvgDuplicatePath(NSVGpath* p) +{ + NSVGpath* res = NULL; + + if (p == NULL) + return NULL; + + res = (NSVGpath*)malloc(sizeof(NSVGpath)); + if (res == NULL) goto error; + memset(res, 0, sizeof(NSVGpath)); + + res->pts = (float*)malloc(p->npts*2*sizeof(float)); + if (res->pts == NULL) goto error; + memcpy(res->pts, p->pts, p->npts * sizeof(float) * 2); + res->npts = p->npts; + + memcpy(res->bounds, p->bounds, sizeof(p->bounds)); + + res->closed = p->closed; + + return res; + + error: + if (res != NULL) { + free(res->pts); + free(res); + } + return NULL; +} + void nsvgDelete(NSVGimage* image) { NSVGshape *snext, *shape; diff --git a/external/nanosvg/nanosvgrast.h b/external/nanosvg/nanosvgrast.h index 2ec650288..a729a47be 100644 --- a/external/nanosvg/nanosvgrast.h +++ b/external/nanosvg/nanosvgrast.h @@ -25,15 +25,19 @@ #ifndef NANOSVGRAST_H #define NANOSVGRAST_H +#ifndef NANOSVGRAST_CPLUSPLUS #ifdef __cplusplus extern "C" { #endif +#endif typedef struct NSVGrasterizer NSVGrasterizer; /* Example Usage: // Load SVG - struct SNVGImage* image = nsvgParseFromFile("test.svg."); + NSVGimage* image; + image = nsvgParseFromFile("test.svg", "px", 96); + // Create rasterizer (can be used to render multiple images). struct NSVGrasterizer* rast = nsvgCreateRasterizer(); // Allocate memory for image @@ -62,8 +66,10 @@ void nsvgRasterize(NSVGrasterizer* r, void nsvgDeleteRasterizer(NSVGrasterizer*); +#ifndef NANOSVGRAST_CPLUSPLUS #ifdef __cplusplus -}; +} +#endif #endif #endif // NANOSVGRAST_H @@ -153,7 +159,7 @@ NSVGrasterizer* nsvgCreateRasterizer() return r; -error: + error: nsvgDeleteRasterizer(r); return NULL; } @@ -238,7 +244,7 @@ static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags) if (r->npoints > 0) { pt = &r->points[r->npoints-1]; if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) { - pt->flags |= flags; + pt->flags = (unsigned char)(pt->flags | flags); return; } } @@ -387,7 +393,7 @@ enum NSVGpointFlags { NSVG_PT_CORNER = 0x01, NSVG_PT_BEVEL = 0x02, - NSVG_PT_LEFT = 0x04, + NSVG_PT_LEFT = 0x04 }; static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth) @@ -453,7 +459,7 @@ static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0; for (i = 0; i < ncap; i++) { - float a = i/(float)(ncap-1)*NSVG_PI; + float a = (float)i/(float)(ncap-1)*NSVG_PI; float ax = cosf(a) * w, ay = sinf(a) * w; float x = px - dlx*ax - dx*ay; float y = py - dly*ax - dy*ay; @@ -550,7 +556,7 @@ static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right if (da < NSVG_PI) da += NSVG_PI*2; if (da > NSVG_PI) da -= NSVG_PI*2; - n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * ncap); + n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap); if (n < 2) n = 2; if (n > ncap) n = ncap; @@ -560,7 +566,7 @@ static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right ry = right->y; for (i = 0; i < n; i++) { - float u = i/(float)(n-1); + float u = (float)i/(float)(n-1); float a = a0 + u*da; float ax = cosf(a) * w, ay = sinf(a) * w; float lx1 = p1->x - ax, ly1 = p1->y - ay; @@ -731,7 +737,7 @@ static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float int i, j, closed; NSVGpath* path; NSVGpoint* p0, *p1; - float miterLimit = 4; + float miterLimit = shape->miterLimit; int lineJoin = shape->strokeLineJoin; int lineCap = shape->strokeLineCap; float lineWidth = shape->strokeWidth * scale; @@ -770,7 +776,7 @@ static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float nsvg__duplicatePoints(r); r->npoints = 0; - cur = r->points2[0]; + cur = r->points2[0]; nsvg__appendPathPoint(r, cur); // Figure out dash offset. @@ -837,8 +843,8 @@ static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float static int nsvg__cmpEdge(const void *p, const void *q) { - NSVGedge* a = (NSVGedge*)p; - NSVGedge* b = (NSVGedge*)q; + const NSVGedge* a = (const NSVGedge*)p; + const NSVGedge* b = (const NSVGedge*)q; if (a->y0 < b->y0) return -1; if (a->y0 > b->y0) return 1; @@ -848,7 +854,7 @@ static int nsvg__cmpEdge(const void *p, const void *q) static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint) { - NSVGactiveEdge* z; + NSVGactiveEdge* z; if (r->freelist != NULL) { // Restore from freelist. @@ -891,20 +897,20 @@ static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, if (i < len && j >= 0) { if (i == j) { // x0,x1 are the same pixel, so compute combined coverage - scanline[i] += (unsigned char)((x1 - x0) * maxWeight >> NSVG__FIXSHIFT); + scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT)); } else { if (i >= 0) // add antialiasing for x0 - scanline[i] += (unsigned char)(((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT); + scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT)); else i = -1; // clip if (j < len) // add antialiasing for x1 - scanline[j] += (unsigned char)(((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT); + scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT)); else j = len; // clip for (++i; i < j; ++i) // fill pixels between x0 and x1 - scanline[i] += (unsigned char)maxWeight; + scanline[i] = (unsigned char)(scanline[i] + maxWeight); } } } @@ -975,7 +981,7 @@ static unsigned int nsvg__applyOpacity(unsigned int c, float u) static inline int nsvg__div255(int x) { - return ((x+1) * 257) >> 16; + return ((x+1) * 257) >> 16; } static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y, @@ -1020,8 +1026,8 @@ static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* co int i, cr, cg, cb, ca; unsigned int c; - fx = (x - tx) / scale; - fy = (y - ty) / scale; + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; dx = 1.0f / scale; for (i = 0; i < count; i++) { @@ -1065,8 +1071,8 @@ static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* co int i, cr, cg, cb, ca; unsigned int c; - fx = (x - tx) / scale; - fy = (y - ty) / scale; + fx = ((float)x - tx) / scale; + fy = ((float)y - ty) / scale; dx = 1.0f / scale; for (i = 0; i < count; i++) { @@ -1120,7 +1126,7 @@ static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, fl xmax = 0; for (s = 0; s < NSVG__SUBSAMPLES; ++s) { // find center of pixel for this scanline - float scany = y*NSVG__SUBSAMPLES + s + 0.5f; + float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f; NSVGactiveEdge **step = &active; // update all active edges; @@ -1323,6 +1329,7 @@ static void dumpEdges(NSVGrasterizer* r, const char* name) if (r->nedges == 0) return; FILE* fp = fopen(name, "w"); if (fp == NULL) return; + xmin = xmax = r->edges[0].x0; ymin = ymax = r->edges[0].y0; for (i = 0; i < r->nedges; i++) { @@ -1336,16 +1343,20 @@ static void dumpEdges(NSVGrasterizer* r, const char* name) ymax = nsvg__maxf(ymax, e->y0); ymax = nsvg__maxf(ymax, e->y1); } + fprintf(fp, "", xmin, ymin, (xmax - xmin), (ymax - ymin)); + for (i = 0; i < r->nedges; i++) { e = &r->edges[i]; fprintf(fp ,"", e->x0,e->y0, e->x1,e->y1); } + for (i = 0; i < r->npoints; i++) { if (i+1 < r->npoints) fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y); fprintf(fp ,"", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0"); } + fprintf(fp, ""); fclose(fp); }