mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
3rdparty/nanosvg: Re-base on latest upstream.
Now based on upstream cc6c08d3a80f1a305021af3d6394cdf1535d02a2. Among other things, this version is supposed to be less sensitive to the global locale.
This commit is contained in:
parent
a89f9b274e
commit
f390ea1004
7 changed files with 288 additions and 121 deletions
8
3rdparty/nanosvg/README.md
vendored
8
3rdparty/nanosvg/README.md
vendored
|
@ -1,9 +1,11 @@
|
|||
*This project is not actively maintained.*
|
||||
|
||||
Nano SVG
|
||||
==========
|
||||
|
||||
## Parser
|
||||
|
||||
![screenshot of some splines rendered witht the sample program](/example/screenshot-1.png?raw=true)
|
||||
![screenshot of some splines rendered with the sample program](/example/screenshot-1.png?raw=true)
|
||||
|
||||
NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.
|
||||
|
||||
|
@ -17,7 +19,7 @@ That is, you should get the same looking data as your designed in your favorite
|
|||
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.
|
||||
|
@ -97,4 +99,4 @@ $ ./example
|
|||
|
||||
# License
|
||||
|
||||
The library is licensed under [zlib license](LICENSE.txt)
|
||||
The library is licensed under [zlib license](LICENSE.txt)
|
||||
|
|
2
3rdparty/nanosvg/example/example2.c
vendored
2
3rdparty/nanosvg/example/example2.c
vendored
|
@ -32,7 +32,7 @@ int main()
|
|||
NSVGrasterizer *rast = NULL;
|
||||
unsigned char* img = NULL;
|
||||
int w, h;
|
||||
const char* filename = "../example/_test.svg";
|
||||
const char* filename = "../example/23.svg";
|
||||
|
||||
printf("parsing %s\n", filename);
|
||||
image = nsvgParseFromFile(filename, "px", 96.0f);
|
||||
|
|
2
3rdparty/nanosvg/premake4.lua
vendored
2
3rdparty/nanosvg/premake4.lua
vendored
|
@ -14,7 +14,7 @@ solution "nanosvg"
|
|||
targetdir("build")
|
||||
|
||||
configuration { "linux" }
|
||||
links { "X11","Xrandr", "rt", "GL", "GLU", "pthread" }
|
||||
links { "X11","Xrandr", "rt", "GL", "GLU", "pthread", "glfw" }
|
||||
|
||||
configuration { "windows" }
|
||||
links { "glu32","opengl32", "gdi32", "winmm", "user32" }
|
||||
|
|
331
3rdparty/nanosvg/src/nanosvg.h
vendored
331
3rdparty/nanosvg/src/nanosvg.h
vendored
|
@ -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 {
|
||||
|
@ -146,6 +148,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].
|
||||
|
@ -167,24 +170,28 @@ 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
|
||||
|
||||
#ifdef NANOSVG_IMPLEMENTATION
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#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
|
||||
|
@ -216,12 +223,7 @@ static int nsvg__isspace(char c)
|
|||
|
||||
static int nsvg__isdigit(char c)
|
||||
{
|
||||
return strchr("0123456789", c) != 0;
|
||||
}
|
||||
|
||||
static int nsvg__isnum(char c)
|
||||
{
|
||||
return strchr("0123456789+-.eE", c) != 0;
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
|
||||
|
@ -280,6 +282,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;
|
||||
|
@ -287,7 +292,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'; }
|
||||
|
@ -297,9 +302,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
|
||||
|
@ -350,7 +361,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
|
||||
|
@ -365,7 +376,7 @@ enum NSVGunits {
|
|||
NSVG_UNITS_IN,
|
||||
NSVG_UNITS_PERCENT,
|
||||
NSVG_UNITS_EM,
|
||||
NSVG_UNITS_EX,
|
||||
NSVG_UNITS_EX
|
||||
};
|
||||
|
||||
typedef struct NSVGcoordinate {
|
||||
|
@ -416,6 +427,7 @@ typedef struct NSVGattrib
|
|||
int strokeDashCount;
|
||||
char strokeLineJoin;
|
||||
char strokeLineCap;
|
||||
float miterLimit;
|
||||
char fillRule;
|
||||
float fontSize;
|
||||
unsigned int stopColor;
|
||||
|
@ -436,6 +448,7 @@ typedef struct NSVGparser
|
|||
NSVGpath* plist;
|
||||
NSVGimage* image;
|
||||
NSVGgradientData* gradients;
|
||||
NSVGshape* shapesTail;
|
||||
float viewMinx, viewMiny, viewWidth, viewHeight;
|
||||
int alignX, alignY, alignType;
|
||||
float dpi;
|
||||
|
@ -625,6 +638,7 @@ 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;
|
||||
|
@ -721,9 +735,11 @@ static void nsvg__lineTo(NSVGparser* p, float x, float y)
|
|||
|
||||
static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
|
||||
{
|
||||
nsvg__addPoint(p, cpx1, cpy1);
|
||||
nsvg__addPoint(p, cpx2, cpy2);
|
||||
nsvg__addPoint(p, x, y);
|
||||
if (p->npts > 0) {
|
||||
nsvg__addPoint(p, cpx1, cpy1);
|
||||
nsvg__addPoint(p, cpx2, cpy2);
|
||||
nsvg__addPoint(p, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
static NSVGattrib* nsvg__getAttr(NSVGparser* p)
|
||||
|
@ -793,7 +809,9 @@ static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig,
|
|||
static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
|
||||
{
|
||||
NSVGgradientData* grad = p->gradients;
|
||||
while (grad) {
|
||||
if (id == NULL || *id == '\0')
|
||||
return NULL;
|
||||
while (grad != NULL) {
|
||||
if (strcmp(grad->id, id) == 0)
|
||||
return grad;
|
||||
grad = grad->next;
|
||||
|
@ -810,19 +828,26 @@ static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const f
|
|||
NSVGgradient* grad;
|
||||
float ox, oy, sw, sh, sl;
|
||||
int nstops = 0;
|
||||
int refIter;
|
||||
|
||||
data = nsvg__findGradientData(p, id);
|
||||
if (data == NULL) return NULL;
|
||||
|
||||
// TODO: use ref to fill in all unset values too.
|
||||
ref = data;
|
||||
refIter = 0;
|
||||
while (ref != NULL) {
|
||||
NSVGgradientData* nextRef = NULL;
|
||||
if (stops == NULL && ref->stops != NULL) {
|
||||
stops = ref->stops;
|
||||
nstops = ref->nstops;
|
||||
break;
|
||||
}
|
||||
ref = nsvg__findGradientData(p, ref->ref);
|
||||
nextRef = nsvg__findGradientData(p, ref->ref);
|
||||
if (nextRef == ref) break; // prevent infite loops on malformed data
|
||||
ref = nextRef;
|
||||
refIter++;
|
||||
if (refIter > 32) break; // prevent infite loops on malformed data
|
||||
}
|
||||
if (stops == NULL) return NULL;
|
||||
|
||||
|
@ -923,7 +948,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;
|
||||
|
||||
|
@ -939,11 +964,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;
|
||||
|
||||
|
@ -999,16 +1025,11 @@ 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;
|
||||
|
||||
|
@ -1030,6 +1051,10 @@ static void nsvg__addPath(NSVGparser* p, char closed)
|
|||
if (closed)
|
||||
nsvg__lineTo(p, p->pts[0], p->pts[1]);
|
||||
|
||||
// Expect 1 + N*3 points (N = number of cubic bezier segments).
|
||||
if ((p->npts % 3) != 1)
|
||||
return;
|
||||
|
||||
path = (NSVGpath*)malloc(sizeof(NSVGpath));
|
||||
if (path == NULL) goto error;
|
||||
memset(path, 0, sizeof(NSVGpath));
|
||||
|
@ -1072,6 +1097,66 @@ error:
|
|||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
@ -1098,7 +1183,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 == '+') {
|
||||
|
@ -1352,13 +1437,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')
|
||||
|
@ -1382,12 +1473,21 @@ static int nsvg__parseUnits(const char* units)
|
|||
return NSVG_UNITS_USER;
|
||||
}
|
||||
|
||||
static int nsvg__isCoordinate(const char* s)
|
||||
{
|
||||
// optional sign
|
||||
if (*s == '-' || *s == '+')
|
||||
s++;
|
||||
// must have at least one digit
|
||||
return nsvg__isdigit(*s);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1423,7 +1523,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;
|
||||
}
|
||||
|
@ -1521,25 +1621,32 @@ static int nsvg__parseRotate(float* xform, const char* str)
|
|||
static void nsvg__parseTransform(float* xform, const char* str)
|
||||
{
|
||||
float t[6];
|
||||
int len;
|
||||
nsvg__xformIdentity(xform);
|
||||
while (*str)
|
||||
{
|
||||
if (strncmp(str, "matrix", 6) == 0)
|
||||
str += nsvg__parseMatrix(t, str);
|
||||
len = nsvg__parseMatrix(t, str);
|
||||
else if (strncmp(str, "translate", 9) == 0)
|
||||
str += nsvg__parseTranslate(t, str);
|
||||
len = nsvg__parseTranslate(t, str);
|
||||
else if (strncmp(str, "scale", 5) == 0)
|
||||
str += nsvg__parseScale(t, str);
|
||||
len = nsvg__parseScale(t, str);
|
||||
else if (strncmp(str, "rotate", 6) == 0)
|
||||
str += nsvg__parseRotate(t, str);
|
||||
len = nsvg__parseRotate(t, str);
|
||||
else if (strncmp(str, "skewX", 5) == 0)
|
||||
str += nsvg__parseSkewX(t, str);
|
||||
len = nsvg__parseSkewX(t, str);
|
||||
else if (strncmp(str, "skewY", 5) == 0)
|
||||
str += nsvg__parseSkewY(t, str);
|
||||
len = nsvg__parseSkewY(t, str);
|
||||
else{
|
||||
++str;
|
||||
continue;
|
||||
}
|
||||
if (len != 0) {
|
||||
str += len;
|
||||
} else {
|
||||
++str;
|
||||
continue;
|
||||
}
|
||||
|
||||
nsvg__xformPremultiply(xform, t);
|
||||
}
|
||||
|
@ -1579,7 +1686,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)
|
||||
|
@ -1685,6 +1792,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) {
|
||||
|
@ -1798,8 +1907,11 @@ static int nsvg__getArgsPerElement(char cmd)
|
|||
case 'a':
|
||||
case 'A':
|
||||
return 7;
|
||||
case 'z':
|
||||
case 'Z':
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
|
||||
|
@ -2001,7 +2113,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
|
||||
|
@ -2066,13 +2178,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;
|
||||
|
@ -2088,7 +2197,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
|
||||
|
@ -2112,6 +2221,7 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
|
|||
float args[10];
|
||||
int nargs;
|
||||
int rargs = 0;
|
||||
char initPoint;
|
||||
float cpx, cpy, cpx2, cpy2;
|
||||
const char* tmp[4];
|
||||
char closedFlag;
|
||||
|
@ -2134,15 +2244,16 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
|
|||
nsvg__resetPath(p);
|
||||
cpx = 0; cpy = 0;
|
||||
cpx2 = 0; cpy2 = 0;
|
||||
initPoint = 0;
|
||||
closedFlag = 0;
|
||||
nargs = 0;
|
||||
|
||||
while (*s) {
|
||||
s = nsvg__getNextPathItem(s, item);
|
||||
if (!*item) break;
|
||||
if (nsvg__isnum(item[0])) {
|
||||
if (cmd != '\0' && nsvg__isCoordinate(item)) {
|
||||
if (nargs < 10)
|
||||
args[nargs++] = (float)atof(item);
|
||||
args[nargs++] = (float)nsvg__atof(item);
|
||||
if (nargs >= rargs) {
|
||||
switch (cmd) {
|
||||
case 'm':
|
||||
|
@ -2151,23 +2262,24 @@ 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;
|
||||
initPoint = 1;
|
||||
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':
|
||||
|
@ -2188,13 +2300,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;
|
||||
}
|
||||
|
@ -2202,7 +2314,6 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
|
|||
}
|
||||
} else {
|
||||
cmd = item[0];
|
||||
rargs = nsvg__getArgsPerElement(cmd);
|
||||
if (cmd == 'M' || cmd == 'm') {
|
||||
// Commit path.
|
||||
if (p->npts > 0)
|
||||
|
@ -2211,7 +2322,11 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
|
|||
nsvg__resetPath(p);
|
||||
closedFlag = 0;
|
||||
nargs = 0;
|
||||
} else if (cmd == 'Z' || cmd == 'z') {
|
||||
} else if (initPoint == 0) {
|
||||
// Do not allow other commands until initial point has been set (moveTo called once).
|
||||
cmd = '\0';
|
||||
}
|
||||
if (cmd == 'Z' || cmd == 'z') {
|
||||
closedFlag = 1;
|
||||
// Commit path.
|
||||
if (p->npts > 0) {
|
||||
|
@ -2227,6 +2342,12 @@ static void nsvg__parsePath(NSVGparser* p, const char** attr)
|
|||
closedFlag = 0;
|
||||
nargs = 0;
|
||||
}
|
||||
rargs = nsvg__getArgsPerElement(cmd);
|
||||
if (rargs == -1) {
|
||||
// Command not recognized
|
||||
cmd = '\0';
|
||||
rargs = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Commit path.
|
||||
|
@ -2399,7 +2520,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]);
|
||||
|
@ -2424,11 +2545,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
|
||||
|
@ -2593,7 +2729,6 @@ static void nsvg__startElement(void* ud, const char* el, const char** attr)
|
|||
if (p->pathFlag) // Do not allow nested paths.
|
||||
return;
|
||||
nsvg__pushAttr(p);
|
||||
p->pathFlag = 1;
|
||||
p->shapeFlag = 1;
|
||||
nsvg__parsePath(p, attr);
|
||||
nsvg__popAttr(p);
|
||||
|
@ -2721,12 +2856,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)
|
||||
|
@ -2873,6 +3008,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;
|
||||
|
|
43
3rdparty/nanosvg/src/nanosvgrast.h
vendored
43
3rdparty/nanosvg/src/nanosvgrast.h
vendored
|
@ -25,15 +25,18 @@
|
|||
#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();
|
||||
|
@ -63,8 +66,10 @@ void nsvgRasterize(NSVGrasterizer* r,
|
|||
void nsvgDeleteRasterizer(NSVGrasterizer*);
|
||||
|
||||
|
||||
#ifndef NANOSVGRAST_CPLUSPLUS
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // NANOSVGRAST_H
|
||||
|
@ -239,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;
|
||||
}
|
||||
}
|
||||
|
@ -388,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)
|
||||
|
@ -454,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;
|
||||
|
@ -551,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;
|
||||
|
||||
|
@ -561,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;
|
||||
|
@ -732,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;
|
||||
|
@ -838,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;
|
||||
|
@ -892,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1021,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++) {
|
||||
|
@ -1066,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++) {
|
||||
|
@ -1121,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;
|
||||
|
|
|
@ -94,19 +94,10 @@ private:
|
|||
|
||||
screen_device::svg_renderer::svg_renderer(memory_region *region)
|
||||
{
|
||||
// nanosvg makes assumptions about the global locale
|
||||
{
|
||||
const std::unique_ptr<char []> s(new char[region->bytes() + 1]);
|
||||
memcpy(s.get(), region->base(), region->bytes());
|
||||
s[region->bytes()] = 0;
|
||||
const std::string lcctype(std::setlocale(LC_CTYPE, nullptr));
|
||||
const std::string lcnumeric(std::setlocale(LC_NUMERIC, nullptr));
|
||||
std::setlocale(LC_CTYPE, "C");
|
||||
std::setlocale(LC_NUMERIC, "C");
|
||||
m_image = nsvgParse(s.get(), "px", 72);
|
||||
std::setlocale(LC_CTYPE, lcctype.c_str());
|
||||
std::setlocale(LC_NUMERIC, lcnumeric.c_str());
|
||||
}
|
||||
const std::unique_ptr<char []> s(new char[region->bytes() + 1]);
|
||||
memcpy(s.get(), region->base(), region->bytes());
|
||||
s[region->bytes()] = 0;
|
||||
m_image = nsvgParse(s.get(), "px", 72);
|
||||
m_rasterizer = nsvgCreateRasterizer();
|
||||
|
||||
m_key_count = 0;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define NANOSVG_ALL_COLOR_KEYWORDS
|
||||
#define NANOSVG_IMPLEMENTATION
|
||||
#define NANOSVGRAST_IMPLEMENTATION
|
||||
#define NANOSVG_ALL_COLOR_KEYWORDS
|
||||
|
||||
#include <nanosvg/src/nanosvg.h>
|
||||
#include <nanosvg/src/nanosvgrast.h>
|
||||
|
|
Loading…
Reference in a new issue