Changed the structure of returned SVG data to image, shapes and paths
- Needed support to SVG image size, hence added following: - added NSVGImage, which holds image size and list of shapes - added NSVGShape which holds color/store and list of paths
This commit is contained in:
parent
d79b9db71f
commit
572bbb2d4d
21
README.md
21
README.md
@ -14,19 +14,20 @@ NanoSVG supports a wide range of SVG features, if somehing is missing, feel free
|
||||
|
||||
``` C
|
||||
// Load
|
||||
struct SNVGPath* plist;
|
||||
plist = nsvgParseFromFile("test.svg.");
|
||||
|
||||
// Use
|
||||
for (NSVGPath* it = plist; it; it = it->next) {
|
||||
for (i = 0; i < npts-1; i += 3) {
|
||||
float* p = &pts[i*2];
|
||||
drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
|
||||
struct SNVGImage* image;
|
||||
image = nsvgParseFromFile("test.svg.");
|
||||
printf("size: %f x %f\n", image->width, image->height);
|
||||
// Use...
|
||||
for (shape = image->shapes; shape != NULL; shape = shape->next) {
|
||||
for (path = shape->paths; path != NULL; path = path->next) {
|
||||
for (i = 0; i < path->npts-1; i += 3) {
|
||||
float* p = &path->pts[i*2];
|
||||
drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete
|
||||
nsvgDelete(plist);
|
||||
nsvgDelete(image);
|
||||
```
|
||||
|
||||
## Using NanoSVG in your project
|
||||
|
@ -24,7 +24,7 @@
|
||||
#define NANOSVG_IMPLEMENTATION
|
||||
#include "nanosvg.h"
|
||||
|
||||
struct NSVGPath* g_plist = NULL;
|
||||
struct NSVGImage* g_image = NULL;
|
||||
|
||||
static unsigned char bgColor[4] = {205,202,200,255};
|
||||
static unsigned char lineColor[4] = {0,160,192,255};
|
||||
@ -80,21 +80,24 @@ static void cubicBez(float x1, float y1, float x2, float y2,
|
||||
}
|
||||
}
|
||||
|
||||
static void calcBounds(struct NSVGPath* plist, float* bounds)
|
||||
static void calcBounds(struct NSVGImage* image, float* bounds)
|
||||
{
|
||||
struct NSVGPath* it;
|
||||
struct NSVGShape* shape;
|
||||
struct NSVGPath* path;
|
||||
int i;
|
||||
bounds[0] = FLT_MAX;
|
||||
bounds[1] = FLT_MAX;
|
||||
bounds[2] = -FLT_MAX;
|
||||
bounds[3] = -FLT_MAX;
|
||||
for (it = plist; it; it = it->next) {
|
||||
for (i = 0; i < it->npts; i++) {
|
||||
float* p = &it->pts[i*2];
|
||||
bounds[0] = minf(bounds[0], p[0]);
|
||||
bounds[1] = minf(bounds[1], p[1]);
|
||||
bounds[2] = maxf(bounds[2], p[0]);
|
||||
bounds[3] = maxf(bounds[3], p[1]);
|
||||
for (shape = image->shapes; shape != NULL; shape = shape->next) {
|
||||
for (path = shape->paths; path != NULL; path = path->next) {
|
||||
for (i = 0; i < path->npts; i++) {
|
||||
float* p = &path->pts[i*2];
|
||||
bounds[0] = minf(bounds[0], p[0]);
|
||||
bounds[1] = minf(bounds[1], p[1]);
|
||||
bounds[2] = maxf(bounds[2], p[0]);
|
||||
bounds[3] = maxf(bounds[3], p[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -164,7 +167,8 @@ void drawframe(GLFWwindow* window)
|
||||
{
|
||||
int width = 0, height = 0;
|
||||
float bounds[4], view[4], cx, cy, w, h, aspect, px;
|
||||
struct NSVGPath* it;
|
||||
struct NSVGShape* shape;
|
||||
struct NSVGPath* path;
|
||||
|
||||
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
@ -179,7 +183,7 @@ void drawframe(GLFWwindow* window)
|
||||
glLoadIdentity();
|
||||
|
||||
// Fit view to bounds
|
||||
calcBounds(g_plist, bounds);
|
||||
calcBounds(g_image, bounds);
|
||||
cx = (bounds[0]+bounds[2])/2;
|
||||
cy = (bounds[3]+bounds[1])/2;
|
||||
w = (bounds[2]-bounds[0])/2;
|
||||
@ -210,9 +214,11 @@ void drawframe(GLFWwindow* window)
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
for (it = g_plist; it; it = it->next) {
|
||||
drawPath(it->pts, it->npts, it->closed, px * 1.5f);
|
||||
drawControlPts(it->pts, it->npts, it->closed);
|
||||
for (shape = g_image->shapes; shape != NULL; shape = shape->next) {
|
||||
for (path = shape->paths; path != NULL; path = path->next) {
|
||||
drawPath(path->pts, path->npts, path->closed, px * 1.5f);
|
||||
drawControlPts(path->pts, path->npts, path->closed);
|
||||
}
|
||||
}
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
@ -247,9 +253,9 @@ int main()
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
|
||||
g_plist = nsvgParseFromFile("../example/nano.svg");
|
||||
if (g_plist == NULL) {
|
||||
printf("Could not open test.svg\n");
|
||||
g_image = nsvgParseFromFile("../example/nano.svg");
|
||||
if (g_image == NULL) {
|
||||
printf("Could not open SVG image.\n");
|
||||
glfwTerminate();
|
||||
return -1;
|
||||
}
|
||||
@ -260,7 +266,7 @@ int main()
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
nsvgDelete(g_plist);
|
||||
nsvgDelete(g_image);
|
||||
|
||||
glfwTerminate();
|
||||
return 0;
|
||||
|
231
src/nanosvg.h
231
src/nanosvg.h
@ -33,41 +33,58 @@ extern "C" {
|
||||
|
||||
/* Example Usage:
|
||||
// Load
|
||||
struct SNVGPath* plist;
|
||||
plist = nsvgParseFromFile("test.svg.");
|
||||
struct SNVGImage* image;
|
||||
image = nsvgParseFromFile("test.svg.");
|
||||
printf("size: %f x %f\n", image->width, image->height);
|
||||
// Use...
|
||||
for (NSVGPath* it = plist; it; it = it->next) {
|
||||
for (i = 0; i < npts-1; i += 3) {
|
||||
float* p = &pts[i*2];
|
||||
drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
|
||||
for (shape = image->shapes; shape != NULL; shape = shape->next) {
|
||||
for (path = shape->paths; path != NULL; path = path->next) {
|
||||
for (i = 0; i < path->npts-1; i += 3) {
|
||||
float* p = &path->pts[i*2];
|
||||
drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Delete
|
||||
nsvgDelete(plist);
|
||||
nsvgDelete(image);
|
||||
*/
|
||||
|
||||
struct NSVGPath
|
||||
{
|
||||
float* pts; // Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
|
||||
int npts; // Total number of bezier points.
|
||||
unsigned int shapeId; // Sequence number if a SVG shape, used to identify paths belonging to same shape.
|
||||
char closed; // Flag indicating if shapes should be treated as closed.
|
||||
struct NSVGPath* next; // Pointer to next path, or NULL if last element.
|
||||
};
|
||||
|
||||
struct NSVGShape
|
||||
{
|
||||
unsigned int fillColor; // Fill color
|
||||
unsigned int strokeColor; // Stroke color
|
||||
float strokeWidth; // Stroke width (scaled)
|
||||
char hasFill; // Flag indicating if fill exists.
|
||||
char hasStroke; // Flag indicating id store exists
|
||||
char closed; // Flag indicating if shapes should be treated as closed.
|
||||
struct NSVGPath* next; // Pointer to next path, or NULL if last element.
|
||||
struct NSVGPath* paths; // Linked list of paths in the image.
|
||||
struct NSVGShape* next; // Pointer to next shape, or NULL if last element.
|
||||
};
|
||||
|
||||
struct NSVGImage
|
||||
{
|
||||
float width; // Width of the image, or -1.0f of not set.
|
||||
float height; // Height of the image, or -1.0f of not set.
|
||||
char wunits[8]; // Units of the width attribute
|
||||
char hunits[8]; // Units of the height attribute
|
||||
struct NSVGShape* shapes; // Linked list of shapes in the image.
|
||||
};
|
||||
|
||||
// Parses SVG file from a file, returns linked list of paths.
|
||||
struct NSVGPath* nsvgParseFromFile(const char* filename);
|
||||
struct NSVGImage* nsvgParseFromFile(const char* filename);
|
||||
|
||||
// Parses SVG file from a null terminated string, returns linked list of paths.
|
||||
struct NSVGPath* nsvgParse(char* input);
|
||||
struct NSVGImage* nsvgParse(char* input);
|
||||
|
||||
// Deletes list of paths.
|
||||
void nsvgDelete(struct NSVGPath* plist);
|
||||
void nsvgDelete(struct NSVGImage* image);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
@ -99,6 +116,8 @@ static int nsvg__isnum(char c)
|
||||
return strchr("0123456789+-.eE", c) != 0;
|
||||
}
|
||||
|
||||
static inline float nsvg__maxf(float a, float b) { return a > b ? a : b; }
|
||||
|
||||
|
||||
// Simple XML parser
|
||||
|
||||
@ -238,8 +257,8 @@ struct NSVGParser
|
||||
float* pts;
|
||||
int npts;
|
||||
int cpts;
|
||||
unsigned int shapeId;
|
||||
struct NSVGPath* plist;
|
||||
struct NSVGImage* image;
|
||||
char pathFlag;
|
||||
char defsFlag;
|
||||
};
|
||||
@ -324,10 +343,15 @@ static struct NSVGParser* nsvg__createParser()
|
||||
{
|
||||
struct NSVGParser* p;
|
||||
p = (struct NSVGParser*)malloc(sizeof(struct NSVGParser));
|
||||
if (!p)
|
||||
return NULL;
|
||||
if (p == NULL) goto error;
|
||||
memset(p, 0, sizeof(struct NSVGParser));
|
||||
|
||||
p->image = (struct NSVGImage*)malloc(sizeof(struct NSVGImage));
|
||||
if (p->image == NULL) goto error;
|
||||
memset(p->image, 0, sizeof(struct NSVGImage));
|
||||
p->image->width = -1.0f;
|
||||
p->image->height = -1.0f;
|
||||
|
||||
// Init style
|
||||
nsvg__xformSetIdentity(p->attr[0].xform);
|
||||
p->attr[0].fillColor = 0;
|
||||
@ -340,13 +364,18 @@ static struct NSVGParser* nsvg__createParser()
|
||||
p->attr[0].visible = 1;
|
||||
|
||||
return p;
|
||||
|
||||
error:
|
||||
if (p) {
|
||||
if (p->image) free(p->image);
|
||||
free(p);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void nsvg__deleteParser(struct NSVGParser* p)
|
||||
static void nsvg__deletePaths(struct NSVGPath* path)
|
||||
{
|
||||
struct NSVGPath* path;
|
||||
struct NSVGPath* next;
|
||||
path = p->plist;
|
||||
while (path) {
|
||||
next = path->next;
|
||||
if (path->pts)
|
||||
@ -354,9 +383,16 @@ static void nsvg__deleteParser(struct NSVGParser* p)
|
||||
free(path);
|
||||
path = next;
|
||||
}
|
||||
if (p->pts)
|
||||
}
|
||||
|
||||
static void nsvg__deleteParser(struct NSVGParser* p)
|
||||
{
|
||||
if (p != NULL) {
|
||||
nsvg__deletePaths(p->plist);
|
||||
nsvgDelete(p->image);
|
||||
free(p->pts);
|
||||
free(p);
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
static void nsvg__resetPath(struct NSVGParser* p)
|
||||
@ -429,24 +465,56 @@ static void nsvg__popAttr(struct NSVGParser* p)
|
||||
p->attrHead--;
|
||||
}
|
||||
|
||||
static void nsvg__createPath(struct NSVGParser* p, char closed)
|
||||
static void nsvg__addShape(struct NSVGParser* p)
|
||||
{
|
||||
struct NSVGAttrib* attr = nsvg__getAttr(p);
|
||||
float scale = 1.0f;
|
||||
|
||||
if (p->plist == NULL)
|
||||
return;
|
||||
|
||||
struct NSVGShape* shape = (struct NSVGShape*)malloc(sizeof(struct NSVGShape));
|
||||
if (shape == NULL) goto error;
|
||||
memset(shape, 0, sizeof(struct NSVGShape));
|
||||
|
||||
scale = nsvg__maxf(fabsf(attr->xform[0]), fabsf(attr->xform[3]));
|
||||
shape->hasFill = attr->hasFill;
|
||||
shape->hasStroke = attr->hasStroke;
|
||||
shape->strokeWidth = attr->strokeWidth * scale;
|
||||
|
||||
shape->fillColor = attr->fillColor;
|
||||
if (shape->hasFill)
|
||||
shape->fillColor |= (unsigned int)(attr->fillOpacity*255) << 24;
|
||||
|
||||
shape->strokeColor = attr->strokeColor;
|
||||
if (shape->hasStroke)
|
||||
shape->strokeColor |= (unsigned int)(attr->strokeOpacity*255) << 24;
|
||||
|
||||
shape->paths = p->plist;
|
||||
p->plist = NULL;
|
||||
|
||||
shape->next = p->image->shapes;
|
||||
p->image->shapes = shape;
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
if (shape) free(shape);
|
||||
}
|
||||
|
||||
static void nsvg__addPath(struct NSVGParser* p, char closed)
|
||||
{
|
||||
float* t = NULL;
|
||||
struct NSVGAttrib* attr = NULL;
|
||||
struct NSVGAttrib* attr = nsvg__getAttr(p);
|
||||
struct NSVGPath* path = NULL;
|
||||
int i;
|
||||
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
if (p->npts == 0)
|
||||
return;
|
||||
|
||||
if (closed)
|
||||
nsvg__lineTo(p, p->pts[0], p->pts[1]);
|
||||
|
||||
attr = nsvg__getAttr(p);
|
||||
|
||||
path = (struct NSVGPath*)malloc(sizeof(struct NSVGPath));
|
||||
if (path == NULL) goto error;
|
||||
memset(path, 0, sizeof(struct NSVGPath));
|
||||
@ -461,20 +529,6 @@ static void nsvg__createPath(struct NSVGParser* p, char closed)
|
||||
for (i = 0; i < p->npts; ++i)
|
||||
nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], t);
|
||||
|
||||
path->hasFill = attr->hasFill;
|
||||
path->hasStroke = attr->hasStroke;
|
||||
path->strokeWidth = attr->strokeWidth * fabsf(t[0]);
|
||||
|
||||
path->fillColor = attr->fillColor;
|
||||
if (path->hasFill)
|
||||
path->fillColor |= (unsigned int)(attr->fillOpacity*255) << 24;
|
||||
|
||||
path->strokeColor = attr->strokeColor;
|
||||
if (path->hasStroke)
|
||||
path->strokeColor |= (unsigned int)(attr->strokeOpacity*255) << 24;
|
||||
|
||||
path->shapeId = p->shapeId;
|
||||
|
||||
path->next = p->plist;
|
||||
p->plist = path;
|
||||
|
||||
@ -1382,7 +1436,7 @@ static void nsvg__parsePath(struct NSVGParser* p, const char** attr)
|
||||
if (cmd == 'M' || cmd == 'm') {
|
||||
// Commit path.
|
||||
if (p->npts > 0)
|
||||
nsvg__createPath(p, closedFlag);
|
||||
nsvg__addPath(p, closedFlag);
|
||||
// Start new subpath.
|
||||
nsvg__resetPath(p);
|
||||
closedFlag = 0;
|
||||
@ -1392,7 +1446,7 @@ static void nsvg__parsePath(struct NSVGParser* p, const char** attr)
|
||||
closedFlag = 1;
|
||||
// Commit path.
|
||||
if (p->npts > 0)
|
||||
nsvg__createPath(p, closedFlag);
|
||||
nsvg__addPath(p, closedFlag);
|
||||
// Start new subpath.
|
||||
nsvg__resetPath(p);
|
||||
closedFlag = 0;
|
||||
@ -1402,7 +1456,7 @@ static void nsvg__parsePath(struct NSVGParser* p, const char** attr)
|
||||
}
|
||||
// Commit path.
|
||||
if (p->npts)
|
||||
nsvg__createPath(p, closedFlag);
|
||||
nsvg__addPath(p, closedFlag);
|
||||
} else {
|
||||
tmp[0] = attr[i];
|
||||
tmp[1] = attr[i + 1];
|
||||
@ -1411,6 +1465,8 @@ static void nsvg__parsePath(struct NSVGParser* p, const char** attr)
|
||||
nsvg__parseAttribs(p, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
nsvg__addShape(p);
|
||||
}
|
||||
|
||||
static void nsvg__parseRect(struct NSVGParser* p, const char** attr)
|
||||
@ -1462,7 +1518,9 @@ static void nsvg__parseRect(struct NSVGParser* p, const char** attr)
|
||||
nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);
|
||||
}
|
||||
|
||||
nsvg__createPath(p, 1);
|
||||
nsvg__addPath(p, 1);
|
||||
|
||||
nsvg__addShape(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1490,7 +1548,9 @@ static void nsvg__parseCircle(struct NSVGParser* p, const char** attr)
|
||||
nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);
|
||||
nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);
|
||||
|
||||
nsvg__createPath(p, 1);
|
||||
nsvg__addPath(p, 1);
|
||||
|
||||
nsvg__addShape(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1521,7 +1581,9 @@ static void nsvg__parseEllipse(struct NSVGParser* p, const char** attr)
|
||||
nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);
|
||||
nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);
|
||||
|
||||
nsvg__createPath(p, 1);
|
||||
nsvg__addPath(p, 1);
|
||||
|
||||
nsvg__addShape(p);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1547,7 +1609,9 @@ static void nsvg__parseLine(struct NSVGParser* p, const char** attr)
|
||||
nsvg__moveTo(p, x1, y1);
|
||||
nsvg__lineTo(p, x2, y2);
|
||||
|
||||
nsvg__createPath(p, 0);
|
||||
nsvg__addPath(p, 0);
|
||||
|
||||
nsvg__addShape(p);
|
||||
}
|
||||
|
||||
static void nsvg__parsePoly(struct NSVGParser* p, const char** attr, int closeFlag)
|
||||
@ -1581,7 +1645,27 @@ static void nsvg__parsePoly(struct NSVGParser* p, const char** attr, int closeFl
|
||||
}
|
||||
}
|
||||
|
||||
nsvg__createPath(p, closeFlag);
|
||||
nsvg__addPath(p, closeFlag);
|
||||
|
||||
nsvg__addShape(p);
|
||||
}
|
||||
|
||||
static void nsvg__parseSVG(struct NSVGParser* p, const char** attr)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; attr[i]; i += 2) {
|
||||
if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
|
||||
if (strcmp(attr[i], "width") == 0) {
|
||||
p->image->wunits[0] = '\0';
|
||||
sscanf(attr[i + 1], "%f%s", &p->image->width, p->image->wunits);
|
||||
printf("W units='%s'\n", p->image->wunits);
|
||||
} else if (strcmp(attr[i], "height") == 0) {
|
||||
p->image->hunits[0] = '\0';
|
||||
sscanf(attr[i + 1], "%f%s", &p->image->height, p->image->hunits);
|
||||
printf("H units='%s'\n", p->image->hunits);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nsvg__startElement(void* ud, const char* el, const char** attr)
|
||||
@ -1600,40 +1684,35 @@ static void nsvg__startElement(void* ud, const char* el, const char** attr)
|
||||
return;
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parsePath(p, attr);
|
||||
p->pathFlag = 1;
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "rect") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseRect(p, attr);
|
||||
p->shapeId++;
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "circle") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseCircle(p, attr);
|
||||
p->shapeId++;
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "ellipse") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseEllipse(p, attr);
|
||||
p->shapeId++;
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "line") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parseLine(p, attr);
|
||||
p->shapeId++;
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "polyline") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parsePoly(p, attr, 0);
|
||||
p->shapeId++;
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "polygon") == 0) {
|
||||
nsvg__pushAttr(p);
|
||||
nsvg__parsePoly(p, attr, 1);
|
||||
p->shapeId++;
|
||||
nsvg__popAttr(p);
|
||||
} else if (strcmp(el, "defs") == 0) {
|
||||
p->defsFlag = 1;
|
||||
} else if (strcmp(el, "svg") == 0) {
|
||||
nsvg__parseSVG(p, attr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1655,10 +1734,10 @@ static void nsvg__content(void* ud, const char* s)
|
||||
// empty
|
||||
}
|
||||
|
||||
struct NSVGPath* nsvgParse(char* input)
|
||||
struct NSVGImage* nsvgParse(char* input)
|
||||
{
|
||||
struct NSVGParser* p;
|
||||
struct NSVGPath* ret = 0;
|
||||
struct NSVGImage* ret = 0;
|
||||
|
||||
p = nsvg__createParser();
|
||||
if (p == NULL) {
|
||||
@ -1667,20 +1746,20 @@ struct NSVGPath* nsvgParse(char* input)
|
||||
|
||||
nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
|
||||
|
||||
ret = p->plist;
|
||||
p->plist = NULL;
|
||||
ret = p->image;
|
||||
p->image = NULL;
|
||||
|
||||
nsvg__deleteParser(p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct NSVGPath* nsvgParseFromFile(const char* filename)
|
||||
struct NSVGImage* nsvgParseFromFile(const char* filename)
|
||||
{
|
||||
FILE* fp = NULL;
|
||||
int size;
|
||||
char* data = NULL;
|
||||
struct NSVGPath* plist = NULL;
|
||||
struct NSVGImage* image = NULL;
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (!fp) goto error;
|
||||
@ -1692,30 +1771,28 @@ struct NSVGPath* nsvgParseFromFile(const char* filename)
|
||||
fread(data, size, 1, fp);
|
||||
data[size] = '\0'; // Must be null terminated.
|
||||
fclose(fp);
|
||||
plist = nsvgParse(data);
|
||||
image = nsvgParse(data);
|
||||
free(data);
|
||||
|
||||
return plist;
|
||||
return image;
|
||||
|
||||
error:
|
||||
if (fp) fclose(fp);
|
||||
if (data) free(data);
|
||||
if (plist) nsvgDelete(plist);
|
||||
if (image) nsvgDelete(image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nsvgDelete(struct NSVGPath* plist)
|
||||
void nsvgDelete(struct NSVGImage* image)
|
||||
{
|
||||
struct NSVGPath* path;
|
||||
struct NSVGPath* next;
|
||||
if (plist == NULL)
|
||||
return;
|
||||
path = plist;
|
||||
while (path) {
|
||||
next = path->next;
|
||||
if (path->pts) free(path->pts);
|
||||
free(path);
|
||||
path = next;
|
||||
if (image) {
|
||||
struct NSVGShape *next, *shape = image->shapes;
|
||||
while (shape != NULL) {
|
||||
next = shape->next;
|
||||
nsvg__deletePaths(shape->paths);
|
||||
free(shape);
|
||||
shape = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user