|
@@ -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...
|
|
@@ -167,12 +169,17 @@ 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
|
|
|
|
|
@@ -1415,8 +1422,7 @@ 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;
|
|
@@ -1424,8 +1430,7 @@ static float nsvg__parseOpacity(const char* str)
|
|
|
|
|
|
static float nsvg__parseMiterLimit(const char* str)
|
|
|
{
|
|
|
- float val = 0;
|
|
|
- sscanf(str, "%f", &val);
|
|
|
+ float val = nsvg__atof(str);
|
|
|
if (val < 0.0f) val = 0.0f;
|
|
|
return val;
|
|
|
}
|
|
@@ -1456,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%31s", &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;
|
|
|
}
|
|
|
|
|
@@ -1650,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)
|
|
@@ -2494,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
|
|
@@ -2906,6 +2926,36 @@ error:
|
|
|
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;
|