32#ifndef NANOSVG_CPLUSPLUS 
  179#ifndef NANOSVG_CPLUSPLUS 
  187#ifdef NANOSVG_IMPLEMENTATION 
  193#define NSVG_PI (3.14159265358979323846264338327f) 
  194#define NSVG_KAPPA90 (0.5522847493f)     
  196#define NSVG_ALIGN_MIN 0 
  197#define NSVG_ALIGN_MID 1 
  198#define NSVG_ALIGN_MAX 2 
  199#define NSVG_ALIGN_NONE 0 
  200#define NSVG_ALIGN_MEET 1 
  201#define NSVG_ALIGN_SLICE 2 
  203#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0) 
  204#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16)) 
  207    #pragma warning (disable: 4996)  
  208    #pragma warning (disable: 4100)  
  210    #define NSVG_INLINE inline 
  215    #define NSVG_INLINE inline 
  219static int nsvg__isspace(
char c)
 
  221    return strchr(
" \t\n\v\f\r", c) != 0;
 
  224static int nsvg__isdigit(
char c)
 
  226    return c >= 
'0' && c <= 
'9';
 
  229static NSVG_INLINE 
float nsvg__minf(
float a, 
float b) { 
return a < b ? a : b; }
 
  230static NSVG_INLINE 
float nsvg__maxf(
float a, 
float b) { 
return a > b ? a : b; }
 
  235#define NSVG_XML_TAG 1 
  236#define NSVG_XML_CONTENT 2 
  237#define NSVG_XML_MAX_ATTRIBS 256 
  239static void nsvg__parseContent(
char* s,
 
  240                               void (*contentCb)(
void* ud, 
const char* s),
 
  244    while (*s && nsvg__isspace(*s)) s++;
 
  251static void nsvg__parseElement(
char* s,
 
  252                               void (*startelCb)(
void* ud, 
const char* el, 
const char** attr),
 
  253                               void (*endelCb)(
void* ud, 
const char* el),
 
  256    const char* attr[NSVG_XML_MAX_ATTRIBS];
 
  264    while (*s && nsvg__isspace(*s)) s++;
 
  275    if (!*s || *s == 
'?' || *s == 
'!')
 
  280    while (*s && !nsvg__isspace(*s)) s++;
 
  281    if (*s) { *s++ = 
'\0'; }
 
  284    while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {
 
  289        while (*s && nsvg__isspace(*s)) s++;
 
  297        while (*s && !nsvg__isspace(*s) && *s != 
'=') s++;
 
  298        if (*s) { *s++ = 
'\0'; }
 
  300        while (*s && *s != 
'\"' && *s != 
'\'') s++;
 
  306        while (*s && *s != quote) s++;
 
  307        if (*s) { *s++ = 
'\0'; }
 
  311            attr[nattr++] = name;
 
  312            attr[nattr++] = value;
 
  321    if (start && startelCb)
 
  322        (*startelCb)(ud, name, attr);
 
  324        (*endelCb)(ud, name);
 
  328                   void (*startelCb)(
void* ud, 
const char* el, 
const char** attr),
 
  329                   void (*endelCb)(
void* ud, 
const char* el),
 
  330                   void (*contentCb)(
void* ud, 
const char* s),
 
  335    int state = NSVG_XML_CONTENT;
 
  337        if (*s == 
'<' && state == NSVG_XML_CONTENT) {
 
  340            nsvg__parseContent(mark, contentCb, ud);
 
  342            state = NSVG_XML_TAG;
 
  343        } 
else if (*s == 
'>' && state == NSVG_XML_TAG) {
 
  346            nsvg__parseElement(mark, startelCb, endelCb, ud);
 
  348            state = NSVG_XML_CONTENT;
 
 
  360#define NSVG_MAX_ATTR 128 
  367#define NSVG_MAX_DASHES 8 
  458static void nsvg__xformIdentity(
float* t)
 
  460    t[0] = 1.0f; t[1] = 0.0f;
 
  461    t[2] = 0.0f; t[3] = 1.0f;
 
  462    t[4] = 0.0f; t[5] = 0.0f;
 
  465static void nsvg__xformSetTranslation(
float* t, 
float tx, 
float ty)
 
  467    t[0] = 1.0f; t[1] = 0.0f;
 
  468    t[2] = 0.0f; t[3] = 1.0f;
 
  469    t[4] = tx; t[5] = ty;
 
  472static void nsvg__xformSetScale(
float* t, 
float sx, 
float sy)
 
  474    t[0] = sx; t[1] = 0.0f;
 
  475    t[2] = 0.0f; t[3] = sy;
 
  476    t[4] = 0.0f; t[5] = 0.0f;
 
  479static void nsvg__xformSetSkewX(
float* t, 
float a)
 
  481    t[0] = 1.0f; t[1] = 0.0f;
 
  482    t[2] = tanf(a); t[3] = 1.0f;
 
  483    t[4] = 0.0f; t[5] = 0.0f;
 
  486static void nsvg__xformSetSkewY(
float* t, 
float a)
 
  488    t[0] = 1.0f; t[1] = tanf(a);
 
  489    t[2] = 0.0f; t[3] = 1.0f;
 
  490    t[4] = 0.0f; t[5] = 0.0f;
 
  493static void nsvg__xformSetRotation(
float* t, 
float a)
 
  495    float cs = cosf(a), sn = sinf(a);
 
  496    t[0] = cs; t[1] = sn;
 
  497    t[2] = -sn; t[3] = cs;
 
  498    t[4] = 0.0f; t[5] = 0.0f;
 
  501static void nsvg__xformMultiply(
float* t, 
float* s)
 
  503    float t0 = t[0] * s[0] + t[1] * s[2];
 
  504    float t2 = t[2] * s[0] + t[3] * s[2];
 
  505    float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
 
  506    t[1] = t[0] * s[1] + t[1] * s[3];
 
  507    t[3] = t[2] * s[1] + t[3] * s[3];
 
  508    t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
 
  514static void nsvg__xformInverse(
float* inv, 
float* t)
 
  516    double invdet, det = (double)t[0] * t[3] - (
double)t[2] * t[1];
 
  517    if (det > -1e-6 && det < 1e-6) {
 
  518        nsvg__xformIdentity(t);
 
  522    inv[0] = (float)(t[3] * invdet);
 
  523    inv[2] = (float)(-t[2] * invdet);
 
  524    inv[4] = (float)(((
double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
 
  525    inv[1] = (float)(-t[1] * invdet);
 
  526    inv[3] = (float)(t[0] * invdet);
 
  527    inv[5] = (float)(((
double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
 
  530static void nsvg__xformPremultiply(
float* t, 
float* s)
 
  533    memcpy(s2, s, 
sizeof(
float)*6);
 
  534    nsvg__xformMultiply(s2, t);
 
  535    memcpy(t, s2, 
sizeof(
float)*6);
 
  538static void nsvg__xformPoint(
float* dx, 
float* dy, 
float x, 
float y, 
float* t)
 
  540    *dx = x*t[0] + y*t[2] + t[4];
 
  541    *dy = x*t[1] + y*t[3] + t[5];
 
  544static void nsvg__xformVec(
float* dx, 
float* dy, 
float x, 
float y, 
float* t)
 
  546    *dx = x*t[0] + y*t[2];
 
  547    *dy = x*t[1] + y*t[3];
 
  550#define NSVG_EPSILON (1e-12) 
  552static int nsvg__ptInBounds(
float* pt, 
float* bounds)
 
  554    return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
 
  558static double nsvg__evalBezier(
double t, 
double p0, 
double p1, 
double p2, 
double p3)
 
  561    return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;
 
  564static void nsvg__curveBounds(
float* bounds, 
float* curve)
 
  567    double roots[2], a, b, c, b2ac, t, v;
 
  568    float* v0 = &curve[0];
 
  569    float* v1 = &curve[2];
 
  570    float* v2 = &curve[4];
 
  571    float* v3 = &curve[6];
 
  574    bounds[0] = nsvg__minf(v0[0], v3[0]);
 
  575    bounds[1] = nsvg__minf(v0[1], v3[1]);
 
  576    bounds[2] = nsvg__maxf(v0[0], v3[0]);
 
  577    bounds[3] = nsvg__maxf(v0[1], v3[1]);
 
  581    if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
 
  585    for (i = 0; i < 2; i++) {
 
  586        a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
 
  587        b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
 
  588        c = 3.0 * v1[i] - 3.0 * v0[i];
 
  590        if (fabs(a) < NSVG_EPSILON) {
 
  591            if (fabs(b) > NSVG_EPSILON) {
 
  593                if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
 
  597            b2ac = b*b - 4.0*c*a;
 
  598            if (b2ac > NSVG_EPSILON) {
 
  599                t = (-b + sqrt(b2ac)) / (2.0 * a);
 
  600                if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
 
  602                t = (-b - sqrt(b2ac)) / (2.0 * a);
 
  603                if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
 
  607        for (j = 0; j < count; j++) {
 
  608            v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
 
  609            bounds[0+i] = nsvg__minf(bounds[0+i], (
float)v);
 
  610            bounds[2+i] = nsvg__maxf(bounds[2+i], (
float)v);
 
  619    if (p == NULL) 
goto error;
 
  623    if (p->
image == NULL) 
goto error;
 
  653static void nsvg__deletePaths(
NSVGpath* path)
 
  657        if (path->
pts != NULL)
 
  664static void nsvg__deletePaint(
NSVGpaint* paint)
 
  673    while (grad != NULL) {
 
  684        nsvg__deletePaths(p->
plist);
 
  697static void nsvg__addPoint(
NSVGparser* p, 
float x, 
float y)
 
  701        p->
pts = (
float*)realloc(p->
pts, p->
cpts*2*
sizeof(
float));
 
  709static void nsvg__moveTo(
NSVGparser* p, 
float x, 
float y)
 
  715        nsvg__addPoint(p, x, y);
 
  719static void nsvg__lineTo(
NSVGparser* p, 
float x, 
float y)
 
  727        nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);
 
  728        nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);
 
  729        nsvg__addPoint(p, x, y);
 
  733static void nsvg__cubicBezTo(
NSVGparser* p, 
float cpx1, 
float cpy1, 
float cpx2, 
float cpy2, 
float x, 
float y)
 
  736        nsvg__addPoint(p, cpx1, cpy1);
 
  737        nsvg__addPoint(p, cpx2, cpy2);
 
  738        nsvg__addPoint(p, x, y);
 
  749    if (p->
attrHead < NSVG_MAX_ATTR-1) {
 
  783    float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
 
  784    return sqrtf(w*w + h*h) / sqrtf(2.0f);
 
  801        default:                    
return c.
value;
 
  809    if (
id == NULL || *
id == 
'\0')
 
  811    while (grad != NULL) {
 
  812        if (strcmp(grad->
id, 
id) == 0)
 
  819static NSVGgradient* nsvg__createGradient(
NSVGparser* p, 
const char* 
id, 
const float* localBounds, 
char* paintType)
 
  826    float ox, oy, sw, sh, sl;
 
  830    data = nsvg__findGradientData(p, 
id);
 
  831    if (data == NULL) 
return NULL;
 
  836    while (ref != NULL) {
 
  838        if (stops == NULL && ref->
stops != NULL) {
 
  843        nextRef = nsvg__findGradientData(p, ref->
ref);
 
  844        if (nextRef == ref) 
break; 
 
  847        if (refIter > 32) 
break; 
 
  849    if (stops == NULL) 
return NULL;
 
  852    if (grad == NULL) 
return NULL;
 
  858        sw = localBounds[2] - localBounds[0];
 
  859        sh = localBounds[3] - localBounds[1];
 
  861        ox = nsvg__actualOrigX(p);
 
  862        oy = nsvg__actualOrigY(p);
 
  863        sw = nsvg__actualWidth(p);
 
  864        sh = nsvg__actualHeight(p);
 
  866    sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f);
 
  869        float x1, y1, x2, y2, dx, dy;
 
  870        x1 = nsvg__convertToPixels(p, data->
linear.
x1, ox, sw);
 
  871        y1 = nsvg__convertToPixels(p, data->
linear.
y1, oy, sh);
 
  872        x2 = nsvg__convertToPixels(p, data->
linear.
x2, ox, sw);
 
  873        y2 = nsvg__convertToPixels(p, data->
linear.
y2, oy, sh);
 
  881        float cx, cy, fx, fy, r;
 
  882        cx = nsvg__convertToPixels(p, data->
radial.
cx, ox, sw);
 
  883        cy = nsvg__convertToPixels(p, data->
radial.
cy, oy, sh);
 
  884        fx = nsvg__convertToPixels(p, data->
radial.
fx, ox, sw);
 
  885        fy = nsvg__convertToPixels(p, data->
radial.
fy, oy, sh);
 
  886        r = nsvg__convertToPixels(p, data->
radial.
r, 0, sl);
 
  891        grad->
fx = (fx - cx) / r;
 
  892        grad->
fy = (fy -cy) / r;
 
  895    nsvg__xformMultiply(grad->
xform, data->
xform);
 
  896    nsvg__xformMultiply(grad->
xform, attr->
xform);
 
  902    *paintType = data->
type;
 
  907static float nsvg__getAverageScale(
float* t)
 
  909    float sx = sqrtf(t[0]*t[0] + t[2]*t[2]);
 
  910    float sy = sqrtf(t[1]*t[1] + t[3]*t[3]);
 
  911    return (sx + sy) * 0.5f;
 
  914static void nsvg__getLocalBounds(
float* bounds, 
NSVGshape *shape, 
float* xform)
 
  917    float curve[4*2], curveBounds[4];
 
  919    for (path = shape->
paths; path != NULL; path = path->
next) {
 
  920        nsvg__xformPoint(&curve[0], &curve[1], path->
pts[0], path->
pts[1], xform);
 
  921        for (i = 0; i < path->
npts-1; i += 3) {
 
  922            nsvg__xformPoint(&curve[2], &curve[3], path->
pts[(i+1)*2], path->
pts[(i+1)*2+1], xform);
 
  923            nsvg__xformPoint(&curve[4], &curve[5], path->
pts[(i+2)*2], path->
pts[(i+2)*2+1], xform);
 
  924            nsvg__xformPoint(&curve[6], &curve[7], path->
pts[(i+3)*2], path->
pts[(i+3)*2+1], xform);
 
  925            nsvg__curveBounds(curveBounds, curve);
 
  927                bounds[0] = curveBounds[0];
 
  928                bounds[1] = curveBounds[1];
 
  929                bounds[2] = curveBounds[2];
 
  930                bounds[3] = curveBounds[3];
 
  933                bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
 
  934                bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
 
  935                bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
 
  936                bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
 
  952    if (p->
plist == NULL)
 
  956    if (shape == NULL) 
goto error;
 
  959    memcpy(shape->
id, attr->
id, 
sizeof shape->
id);
 
  960    scale = nsvg__getAverageScale(attr->
xform);
 
  980    for (path = shape->
paths->
next; path != NULL; path = path->
next) {
 
  990    } 
else if (attr->
hasFill == 1) {
 
  994    } 
else if (attr->
hasFill == 2) {
 
  995        float inv[6], localBounds[4];
 
  996        nsvg__xformInverse(inv, attr->
xform);
 
  997        nsvg__getLocalBounds(localBounds, shape, inv);
 
 1012        float inv[6], localBounds[4];
 
 1013        nsvg__xformInverse(inv, attr->
xform);
 
 1014        nsvg__getLocalBounds(localBounds, shape, inv);
 
 1033    if (shape) free(shape);
 
 1036static void nsvg__addPath(
NSVGparser* p, 
char closed)
 
 1048        nsvg__lineTo(p, p->
pts[0], p->
pts[1]);
 
 1051    if ((p->
npts % 3) != 1)
 
 1055    if (path == NULL) 
goto error;
 
 1058    path->
pts = (
float*)malloc(p->
npts*2*
sizeof(
float));
 
 1059    if (path->
pts == NULL) 
goto error;
 
 1064    for (i = 0; i < p->
npts; ++i)
 
 1065        nsvg__xformPoint(&path->
pts[i*2], &path->
pts[i*2+1], p->
pts[i*2], p->
pts[i*2+1], attr->
xform);
 
 1068    for (i = 0; i < path->
npts-1; i += 3) {
 
 1069        curve = &path->
pts[i*2];
 
 1070        nsvg__curveBounds(bounds, curve);
 
 1072            path->
bounds[0] = bounds[0];
 
 1073            path->
bounds[1] = bounds[1];
 
 1074            path->
bounds[2] = bounds[2];
 
 1075            path->
bounds[3] = bounds[3];
 
 1077            path->
bounds[0] = nsvg__minf(path->
bounds[0], bounds[0]);
 
 1078            path->
bounds[1] = nsvg__minf(path->
bounds[1], bounds[1]);
 
 1079            path->
bounds[2] = nsvg__maxf(path->
bounds[2], bounds[2]);
 
 1080            path->
bounds[3] = nsvg__maxf(path->
bounds[3], bounds[3]);
 
 1091        if (path->
pts != NULL) free(path->
pts);
 
 1097static double nsvg__atof(
const char* s)
 
 1099    char* cur = (
char*)s;
 
 1101    double res = 0.0, sign = 1.0;
 
 1102    long long intPart = 0, fracPart = 0;
 
 1103    char hasIntPart = 0, hasFracPart = 0;
 
 1108    } 
else if (*cur == 
'-') {
 
 1114    if (nsvg__isdigit(*cur)) {
 
 1116        intPart = strtoll(cur, &end, 10);
 
 1118            res = (double)intPart;
 
 1127        if (nsvg__isdigit(*cur)) {
 
 1129            fracPart = strtoll(cur, &end, 10);
 
 1131                res += (double)fracPart / pow(10.0, (
double)(end - cur));
 
 1139    if (!hasIntPart && !hasFracPart)
 
 1143    if (*cur == 
'e' || *cur == 
'E') {
 
 1146        expPart = strtol(cur, &end, 10); 
 
 1148            res *= pow(10.0, (
double)expPart);
 
 1156static const char* nsvg__parseNumber(
const char* s, 
char* it, 
const int size)
 
 1158    const int last = size-1;
 
 1162    if (*s == 
'-' || *s == 
'+') {
 
 1163        if (i < last) it[i++] = *s;
 
 1167    while (*s && nsvg__isdigit(*s)) {
 
 1168        if (i < last) it[i++] = *s;
 
 1173        if (i < last) it[i++] = *s;
 
 1176        while (*s && nsvg__isdigit(*s)) {
 
 1177            if (i < last) it[i++] = *s;
 
 1182    if ((*s == 
'e' || *s == 
'E') && (s[1] != 
'm' && s[1] != 
'x')) {
 
 1183        if (i < last) it[i++] = *s;
 
 1185        if (*s == 
'-' || *s == 
'+') {
 
 1186            if (i < last) it[i++] = *s;
 
 1189        while (*s && nsvg__isdigit(*s)) {
 
 1190            if (i < last) it[i++] = *s;
 
 1199static const char* nsvg__getNextPathItem(
const char* s, 
char* it)
 
 1203    while (*s && (nsvg__isspace(*s) || *s == 
',')) s++;
 
 1205    if (*s == 
'-' || *s == 
'+' || *s == 
'.' || nsvg__isdigit(*s)) {
 
 1206        s = nsvg__parseNumber(s, it, 64);
 
 1217static unsigned int nsvg__parseColorHex(
const char* str)
 
 1219    unsigned int r=0, g=0, b=0;
 
 1220    if (sscanf(str, 
"#%2x%2x%2x", &r, &g, &b) == 3 )        
 
 1221        return NSVG_RGB(r, g, b);
 
 1222    if (sscanf(str, 
"#%1x%1x%1x", &r, &g, &b) == 3 )        
 
 1223        return NSVG_RGB(r*17, g*17, b*17);          
 
 1224    return NSVG_RGB(128, 128, 128);
 
 1227static unsigned int nsvg__parseColorRGB(
const char* str)
 
 1229    unsigned int r=0, g=0, b=0;
 
 1230    if (sscanf(str, 
"rgb(%u, %u, %u)", &r, &g, &b) == 3)        
 
 1231        return NSVG_RGB(r, g, b);
 
 1232    if (sscanf(str, 
"rgb(%u%%, %u%%, %u%%)", &r, &g, &b) == 3)  
 
 1233        return NSVG_RGB(r*255/100, g*255/100, b*255/100);
 
 1234    return NSVG_RGB(128, 128, 128);
 
 1244    { 
"red", NSVG_RGB(255, 0, 0) },
 
 1245    { 
"green", NSVG_RGB( 0, 128, 0) },
 
 1246    { 
"blue", NSVG_RGB( 0, 0, 255) },
 
 1247    { 
"yellow", NSVG_RGB(255, 255, 0) },
 
 1248    { 
"cyan", NSVG_RGB( 0, 255, 255) },
 
 1249    { 
"magenta", NSVG_RGB(255, 0, 255) },
 
 1250    { 
"black", NSVG_RGB( 0, 0, 0) },
 
 1251    { 
"grey", NSVG_RGB(128, 128, 128) },
 
 1252    { 
"gray", NSVG_RGB(128, 128, 128) },
 
 1253    { 
"white", NSVG_RGB(255, 255, 255) },
 
 1255#ifdef NANOSVG_ALL_COLOR_KEYWORDS 
 1256    { 
"aliceblue", NSVG_RGB(240, 248, 255) },
 
 1257    { 
"antiquewhite", NSVG_RGB(250, 235, 215) },
 
 1258    { 
"aqua", NSVG_RGB( 0, 255, 255) },
 
 1259    { 
"aquamarine", NSVG_RGB(127, 255, 212) },
 
 1260    { 
"azure", NSVG_RGB(240, 255, 255) },
 
 1261    { 
"beige", NSVG_RGB(245, 245, 220) },
 
 1262    { 
"bisque", NSVG_RGB(255, 228, 196) },
 
 1263    { 
"blanchedalmond", NSVG_RGB(255, 235, 205) },
 
 1264    { 
"blueviolet", NSVG_RGB(138, 43, 226) },
 
 1265    { 
"brown", NSVG_RGB(165, 42, 42) },
 
 1266    { 
"burlywood", NSVG_RGB(222, 184, 135) },
 
 1267    { 
"cadetblue", NSVG_RGB( 95, 158, 160) },
 
 1268    { 
"chartreuse", NSVG_RGB(127, 255, 0) },
 
 1269    { 
"chocolate", NSVG_RGB(210, 105, 30) },
 
 1270    { 
"coral", NSVG_RGB(255, 127, 80) },
 
 1271    { 
"cornflowerblue", NSVG_RGB(100, 149, 237) },
 
 1272    { 
"cornsilk", NSVG_RGB(255, 248, 220) },
 
 1273    { 
"crimson", NSVG_RGB(220, 20, 60) },
 
 1274    { 
"darkblue", NSVG_RGB( 0, 0, 139) },
 
 1275    { 
"darkcyan", NSVG_RGB( 0, 139, 139) },
 
 1276    { 
"darkgoldenrod", NSVG_RGB(184, 134, 11) },
 
 1277    { 
"darkgray", NSVG_RGB(169, 169, 169) },
 
 1278    { 
"darkgreen", NSVG_RGB( 0, 100, 0) },
 
 1279    { 
"darkgrey", NSVG_RGB(169, 169, 169) },
 
 1280    { 
"darkkhaki", NSVG_RGB(189, 183, 107) },
 
 1281    { 
"darkmagenta", NSVG_RGB(139, 0, 139) },
 
 1282    { 
"darkolivegreen", NSVG_RGB( 85, 107, 47) },
 
 1283    { 
"darkorange", NSVG_RGB(255, 140, 0) },
 
 1284    { 
"darkorchid", NSVG_RGB(153, 50, 204) },
 
 1285    { 
"darkred", NSVG_RGB(139, 0, 0) },
 
 1286    { 
"darksalmon", NSVG_RGB(233, 150, 122) },
 
 1287    { 
"darkseagreen", NSVG_RGB(143, 188, 143) },
 
 1288    { 
"darkslateblue", NSVG_RGB( 72, 61, 139) },
 
 1289    { 
"darkslategray", NSVG_RGB( 47, 79, 79) },
 
 1290    { 
"darkslategrey", NSVG_RGB( 47, 79, 79) },
 
 1291    { 
"darkturquoise", NSVG_RGB( 0, 206, 209) },
 
 1292    { 
"darkviolet", NSVG_RGB(148, 0, 211) },
 
 1293    { 
"deeppink", NSVG_RGB(255, 20, 147) },
 
 1294    { 
"deepskyblue", NSVG_RGB( 0, 191, 255) },
 
 1295    { 
"dimgray", NSVG_RGB(105, 105, 105) },
 
 1296    { 
"dimgrey", NSVG_RGB(105, 105, 105) },
 
 1297    { 
"dodgerblue", NSVG_RGB( 30, 144, 255) },
 
 1298    { 
"firebrick", NSVG_RGB(178, 34, 34) },
 
 1299    { 
"floralwhite", NSVG_RGB(255, 250, 240) },
 
 1300    { 
"forestgreen", NSVG_RGB( 34, 139, 34) },
 
 1301    { 
"fuchsia", NSVG_RGB(255, 0, 255) },
 
 1302    { 
"gainsboro", NSVG_RGB(220, 220, 220) },
 
 1303    { 
"ghostwhite", NSVG_RGB(248, 248, 255) },
 
 1304    { 
"gold", NSVG_RGB(255, 215, 0) },
 
 1305    { 
"goldenrod", NSVG_RGB(218, 165, 32) },
 
 1306    { 
"greenyellow", NSVG_RGB(173, 255, 47) },
 
 1307    { 
"honeydew", NSVG_RGB(240, 255, 240) },
 
 1308    { 
"hotpink", NSVG_RGB(255, 105, 180) },
 
 1309    { 
"indianred", NSVG_RGB(205, 92, 92) },
 
 1310    { 
"indigo", NSVG_RGB( 75, 0, 130) },
 
 1311    { 
"ivory", NSVG_RGB(255, 255, 240) },
 
 1312    { 
"khaki", NSVG_RGB(240, 230, 140) },
 
 1313    { 
"lavender", NSVG_RGB(230, 230, 250) },
 
 1314    { 
"lavenderblush", NSVG_RGB(255, 240, 245) },
 
 1315    { 
"lawngreen", NSVG_RGB(124, 252, 0) },
 
 1316    { 
"lemonchiffon", NSVG_RGB(255, 250, 205) },
 
 1317    { 
"lightblue", NSVG_RGB(173, 216, 230) },
 
 1318    { 
"lightcoral", NSVG_RGB(240, 128, 128) },
 
 1319    { 
"lightcyan", NSVG_RGB(224, 255, 255) },
 
 1320    { 
"lightgoldenrodyellow", NSVG_RGB(250, 250, 210) },
 
 1321    { 
"lightgray", NSVG_RGB(211, 211, 211) },
 
 1322    { 
"lightgreen", NSVG_RGB(144, 238, 144) },
 
 1323    { 
"lightgrey", NSVG_RGB(211, 211, 211) },
 
 1324    { 
"lightpink", NSVG_RGB(255, 182, 193) },
 
 1325    { 
"lightsalmon", NSVG_RGB(255, 160, 122) },
 
 1326    { 
"lightseagreen", NSVG_RGB( 32, 178, 170) },
 
 1327    { 
"lightskyblue", NSVG_RGB(135, 206, 250) },
 
 1328    { 
"lightslategray", NSVG_RGB(119, 136, 153) },
 
 1329    { 
"lightslategrey", NSVG_RGB(119, 136, 153) },
 
 1330    { 
"lightsteelblue", NSVG_RGB(176, 196, 222) },
 
 1331    { 
"lightyellow", NSVG_RGB(255, 255, 224) },
 
 1332    { 
"lime", NSVG_RGB( 0, 255, 0) },
 
 1333    { 
"limegreen", NSVG_RGB( 50, 205, 50) },
 
 1334    { 
"linen", NSVG_RGB(250, 240, 230) },
 
 1335    { 
"maroon", NSVG_RGB(128, 0, 0) },
 
 1336    { 
"mediumaquamarine", NSVG_RGB(102, 205, 170) },
 
 1337    { 
"mediumblue", NSVG_RGB( 0, 0, 205) },
 
 1338    { 
"mediumorchid", NSVG_RGB(186, 85, 211) },
 
 1339    { 
"mediumpurple", NSVG_RGB(147, 112, 219) },
 
 1340    { 
"mediumseagreen", NSVG_RGB( 60, 179, 113) },
 
 1341    { 
"mediumslateblue", NSVG_RGB(123, 104, 238) },
 
 1342    { 
"mediumspringgreen", NSVG_RGB( 0, 250, 154) },
 
 1343    { 
"mediumturquoise", NSVG_RGB( 72, 209, 204) },
 
 1344    { 
"mediumvioletred", NSVG_RGB(199, 21, 133) },
 
 1345    { 
"midnightblue", NSVG_RGB( 25, 25, 112) },
 
 1346    { 
"mintcream", NSVG_RGB(245, 255, 250) },
 
 1347    { 
"mistyrose", NSVG_RGB(255, 228, 225) },
 
 1348    { 
"moccasin", NSVG_RGB(255, 228, 181) },
 
 1349    { 
"navajowhite", NSVG_RGB(255, 222, 173) },
 
 1350    { 
"navy", NSVG_RGB( 0, 0, 128) },
 
 1351    { 
"oldlace", NSVG_RGB(253, 245, 230) },
 
 1352    { 
"olive", NSVG_RGB(128, 128, 0) },
 
 1353    { 
"olivedrab", NSVG_RGB(107, 142, 35) },
 
 1354    { 
"orange", NSVG_RGB(255, 165, 0) },
 
 1355    { 
"orangered", NSVG_RGB(255, 69, 0) },
 
 1356    { 
"orchid", NSVG_RGB(218, 112, 214) },
 
 1357    { 
"palegoldenrod", NSVG_RGB(238, 232, 170) },
 
 1358    { 
"palegreen", NSVG_RGB(152, 251, 152) },
 
 1359    { 
"paleturquoise", NSVG_RGB(175, 238, 238) },
 
 1360    { 
"palevioletred", NSVG_RGB(219, 112, 147) },
 
 1361    { 
"papayawhip", NSVG_RGB(255, 239, 213) },
 
 1362    { 
"peachpuff", NSVG_RGB(255, 218, 185) },
 
 1363    { 
"peru", NSVG_RGB(205, 133, 63) },
 
 1364    { 
"pink", NSVG_RGB(255, 192, 203) },
 
 1365    { 
"plum", NSVG_RGB(221, 160, 221) },
 
 1366    { 
"powderblue", NSVG_RGB(176, 224, 230) },
 
 1367    { 
"purple", NSVG_RGB(128, 0, 128) },
 
 1368    { 
"rosybrown", NSVG_RGB(188, 143, 143) },
 
 1369    { 
"royalblue", NSVG_RGB( 65, 105, 225) },
 
 1370    { 
"saddlebrown", NSVG_RGB(139, 69, 19) },
 
 1371    { 
"salmon", NSVG_RGB(250, 128, 114) },
 
 1372    { 
"sandybrown", NSVG_RGB(244, 164, 96) },
 
 1373    { 
"seagreen", NSVG_RGB( 46, 139, 87) },
 
 1374    { 
"seashell", NSVG_RGB(255, 245, 238) },
 
 1375    { 
"sienna", NSVG_RGB(160, 82, 45) },
 
 1376    { 
"silver", NSVG_RGB(192, 192, 192) },
 
 1377    { 
"skyblue", NSVG_RGB(135, 206, 235) },
 
 1378    { 
"slateblue", NSVG_RGB(106, 90, 205) },
 
 1379    { 
"slategray", NSVG_RGB(112, 128, 144) },
 
 1380    { 
"slategrey", NSVG_RGB(112, 128, 144) },
 
 1381    { 
"snow", NSVG_RGB(255, 250, 250) },
 
 1382    { 
"springgreen", NSVG_RGB( 0, 255, 127) },
 
 1383    { 
"steelblue", NSVG_RGB( 70, 130, 180) },
 
 1384    { 
"tan", NSVG_RGB(210, 180, 140) },
 
 1385    { 
"teal", NSVG_RGB( 0, 128, 128) },
 
 1386    { 
"thistle", NSVG_RGB(216, 191, 216) },
 
 1387    { 
"tomato", NSVG_RGB(255, 99, 71) },
 
 1388    { 
"turquoise", NSVG_RGB( 64, 224, 208) },
 
 1389    { 
"violet", NSVG_RGB(238, 130, 238) },
 
 1390    { 
"wheat", NSVG_RGB(245, 222, 179) },
 
 1391    { 
"whitesmoke", NSVG_RGB(245, 245, 245) },
 
 1392    { 
"yellowgreen", NSVG_RGB(154, 205, 50) },
 
 
 1396static unsigned int nsvg__parseColorName(
const char* str)
 
 1400    for (i = 0; i < ncolors; i++) {
 
 1406    return NSVG_RGB(128, 128, 128);
 
 1409static unsigned int nsvg__parseColor(
const char* str)
 
 1412    while(*str == 
' ') ++str;
 
 1414    if (len >= 1 && *str == 
'#')
 
 1415        return nsvg__parseColorHex(str);
 
 1416    else if (len >= 4 && str[0] == 
'r' && str[1] == 
'g' && str[2] == 
'b' && str[3] == 
'(')
 
 1417        return nsvg__parseColorRGB(str);
 
 1418    return nsvg__parseColorName(str);
 
 1421static float nsvg__parseOpacity(
const char* str)
 
 1423    float val = nsvg__atof(str);
 
 1424    if (val < 0.0f) val = 0.0f;
 
 1425    if (val > 1.0f) val = 1.0f;
 
 1429static float nsvg__parseMiterLimit(
const char* str)
 
 1431    float val = nsvg__atof(str);
 
 1432    if (val < 0.0f) val = 0.0f;
 
 1436static int nsvg__parseUnits(
const char* units)
 
 1438    if (units[0] == 
'p' && units[1] == 
'x')
 
 1440    else if (units[0] == 
'p' && units[1] == 
't')
 
 1442    else if (units[0] == 
'p' && units[1] == 
'c')
 
 1444    else if (units[0] == 
'm' && units[1] == 
'm')
 
 1446    else if (units[0] == 
'c' && units[1] == 
'm')
 
 1448    else if (units[0] == 
'i' && units[1] == 
'n')
 
 1450    else if (units[0] == 
'%')
 
 1452    else if (units[0] == 
'e' && units[1] == 
'm')
 
 1454    else if (units[0] == 
'e' && units[1] == 
'x')
 
 1459static int nsvg__isCoordinate(
const char* s)
 
 1462    if (*s == 
'-' || *s == 
'+')
 
 1465    return (nsvg__isdigit(*s) || *s == 
'.');
 
 1472    coord.
units = nsvg__parseUnits(nsvg__parseNumber(str, buf, 64));
 
 1473    coord.
value = nsvg__atof(buf);
 
 1483static float nsvg__parseCoordinate(
NSVGparser* p, 
const char* str, 
float orig, 
float length)
 
 1486    return nsvg__convertToPixels(p, coord, orig, length);
 
 1489static int nsvg__parseTransformArgs(
const char* str, 
float* args, 
int maxNa, 
int* na)
 
 1497    while (*ptr && *ptr != 
'(') ++ptr;
 
 1501    while (*end && *end != 
')') ++end;
 
 1506        if (*ptr == 
'-' || *ptr == 
'+' || *ptr == 
'.' || nsvg__isdigit(*ptr)) {
 
 1507            if (*na >= maxNa) 
return 0;
 
 1508            ptr = nsvg__parseNumber(ptr, it, 64);
 
 1509            args[(*na)++] = (float)nsvg__atof(it);
 
 1514    return (
int)(end - str);
 
 1518static int nsvg__parseMatrix(
float* xform, 
const char* str)
 
 1522    int len = nsvg__parseTransformArgs(str, t, 6, &na);
 
 1523    if (na != 6) 
return len;
 
 1524    memcpy(xform, t, 
sizeof(
float)*6);
 
 1528static int nsvg__parseTranslate(
float* xform, 
const char* str)
 
 1533    int len = nsvg__parseTransformArgs(str, args, 2, &na);
 
 1534    if (na == 1) args[1] = 0.0;
 
 1536    nsvg__xformSetTranslation(t, args[0], args[1]);
 
 1537    memcpy(xform, t, 
sizeof(
float)*6);
 
 1541static int nsvg__parseScale(
float* xform, 
const char* str)
 
 1546    int len = nsvg__parseTransformArgs(str, args, 2, &na);
 
 1547    if (na == 1) args[1] = args[0];
 
 1548    nsvg__xformSetScale(t, args[0], args[1]);
 
 1549    memcpy(xform, t, 
sizeof(
float)*6);
 
 1553static int nsvg__parseSkewX(
float* xform, 
const char* str)
 
 1558    int len = nsvg__parseTransformArgs(str, args, 1, &na);
 
 1559    nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI);
 
 1560    memcpy(xform, t, 
sizeof(
float)*6);
 
 1564static int nsvg__parseSkewY(
float* xform, 
const char* str)
 
 1569    int len = nsvg__parseTransformArgs(str, args, 1, &na);
 
 1570    nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI);
 
 1571    memcpy(xform, t, 
sizeof(
float)*6);
 
 1575static int nsvg__parseRotate(
float* xform, 
const char* str)
 
 1581    int len = nsvg__parseTransformArgs(str, args, 3, &na);
 
 1583        args[1] = args[2] = 0.0f;
 
 1584    nsvg__xformIdentity(m);
 
 1587        nsvg__xformSetTranslation(t, -args[1], -args[2]);
 
 1588        nsvg__xformMultiply(m, t);
 
 1591    nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI);
 
 1592    nsvg__xformMultiply(m, t);
 
 1595        nsvg__xformSetTranslation(t, args[1], args[2]);
 
 1596        nsvg__xformMultiply(m, t);
 
 1599    memcpy(xform, m, 
sizeof(
float)*6);
 
 1604static void nsvg__parseTransform(
float* xform, 
const char* str)
 
 1608    nsvg__xformIdentity(xform);
 
 1611        if (strncmp(str, 
"matrix", 6) == 0)
 
 1612            len = nsvg__parseMatrix(t, str);
 
 1613        else if (strncmp(str, 
"translate", 9) == 0)
 
 1614            len = nsvg__parseTranslate(t, str);
 
 1615        else if (strncmp(str, 
"scale", 5) == 0)
 
 1616            len = nsvg__parseScale(t, str);
 
 1617        else if (strncmp(str, 
"rotate", 6) == 0)
 
 1618            len = nsvg__parseRotate(t, str);
 
 1619        else if (strncmp(str, 
"skewX", 5) == 0)
 
 1620            len = nsvg__parseSkewX(t, str);
 
 1621        else if (strncmp(str, 
"skewY", 5) == 0)
 
 1622            len = nsvg__parseSkewY(t, str);
 
 1634        nsvg__xformPremultiply(xform, t);
 
 1638static void nsvg__parseUrl(
char* 
id, 
const char* str)
 
 1644    while (i < 63 && *str != 
')') {
 
 1651static char nsvg__parseLineCap(
const char* str)
 
 1653    if (strcmp(str, 
"butt") == 0)
 
 1655    else if (strcmp(str, 
"round") == 0)
 
 1657    else if (strcmp(str, 
"square") == 0)
 
 1663static char nsvg__parseLineJoin(
const char* str)
 
 1665    if (strcmp(str, 
"miter") == 0)
 
 1667    else if (strcmp(str, 
"round") == 0)
 
 1669    else if (strcmp(str, 
"bevel") == 0)
 
 1675static char nsvg__parseFillRule(
const char* str)
 
 1677    if (strcmp(str, 
"nonzero") == 0)
 
 1679    else if (strcmp(str, 
"evenodd") == 0)
 
 1685static const char* nsvg__getNextDashItem(
const char* s, 
char* it)
 
 1690    while (*s && (nsvg__isspace(*s) || *s == 
',')) s++;
 
 1692    while (*s && (!nsvg__isspace(*s) && *s != 
',')) {
 
 1701static int nsvg__parseStrokeDashArray(
NSVGparser* p, 
const char* str, 
float* strokeDashArray)
 
 1713        str = nsvg__getNextDashItem(str, item);
 
 1715        if (count < NSVG_MAX_DASHES)
 
 1716            strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
 
 1719    for (i = 0; i < count; i++)
 
 1720        sum += strokeDashArray[i];
 
 1727static void nsvg__parseStyle(
NSVGparser* p, 
const char* str);
 
 1729static int nsvg__parseAttr(
NSVGparser* p, 
const char* name, 
const char* value)
 
 1733    if (!attr) 
return 0;
 
 1735    if (strcmp(name, 
"style") == 0) {
 
 1736        nsvg__parseStyle(p, value);
 
 1737    } 
else if (strcmp(name, 
"display") == 0) {
 
 1738        if (strcmp(value, 
"none") == 0)
 
 1742    } 
else if (strcmp(name, 
"fill") == 0) {
 
 1743        if (strcmp(value, 
"none") == 0) {
 
 1745        } 
else if (strncmp(value, 
"url(", 4) == 0) {
 
 1750            attr->
fillColor = nsvg__parseColor(value);
 
 1752    } 
else if (strcmp(name, 
"opacity") == 0) {
 
 1753        attr->
opacity = nsvg__parseOpacity(value);
 
 1754    } 
else if (strcmp(name, 
"fill-opacity") == 0) {
 
 1756    } 
else if (strcmp(name, 
"stroke") == 0) {
 
 1757        if (strcmp(value, 
"none") == 0) {
 
 1759        } 
else if (strncmp(value, 
"url(", 4) == 0) {
 
 1766    } 
else if (strcmp(name, 
"stroke-width") == 0) {
 
 1767        attr->
strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
 
 1768    } 
else if (strcmp(name, 
"stroke-dasharray") == 0) {
 
 1770    } 
else if (strcmp(name, 
"stroke-dashoffset") == 0) {
 
 1771        attr->
strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
 
 1772    } 
else if (strcmp(name, 
"stroke-opacity") == 0) {
 
 1774    } 
else if (strcmp(name, 
"stroke-linecap") == 0) {
 
 1776    } 
else if (strcmp(name, 
"stroke-linejoin") == 0) {
 
 1778    } 
else if (strcmp(name, 
"stroke-miterlimit") == 0) {
 
 1779        attr->
miterLimit = nsvg__parseMiterLimit(value);
 
 1780    } 
else if (strcmp(name, 
"fill-rule") == 0) {
 
 1781        attr->
fillRule = nsvg__parseFillRule(value);
 
 1782    } 
else if (strcmp(name, 
"font-size") == 0) {
 
 1783        attr->
fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
 
 1784    } 
else if (strcmp(name, 
"transform") == 0) {
 
 1785        nsvg__parseTransform(xform, value);
 
 1786        nsvg__xformPremultiply(attr->
xform, xform);
 
 1787    } 
else if (strcmp(name, 
"stop-color") == 0) {
 
 1788        attr->
stopColor = nsvg__parseColor(value);
 
 1789    } 
else if (strcmp(name, 
"stop-opacity") == 0) {
 
 1791    } 
else if (strcmp(name, 
"offset") == 0) {
 
 1792        attr->
stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
 
 1793    } 
else if (strcmp(name, 
"id") == 0) {
 
 1794        strncpy(attr->
id, value, 63);
 
 1795        attr->
id[63] = 
'\0';
 
 1802static int nsvg__parseNameValue(
NSVGparser* p, 
const char* start, 
const char* end)
 
 1811    while (str < end && *str != 
':') ++str;
 
 1816    while (str > start &&  (*str == 
':' || nsvg__isspace(*str))) --str;
 
 1819    n = (int)(str - start);
 
 1820    if (n > 511) n = 511;
 
 1821    if (n) memcpy(name, start, n);
 
 1824    while (val < end && (*val == 
':' || nsvg__isspace(*val))) ++val;
 
 1826    n = (int)(end - val);
 
 1827    if (n > 511) n = 511;
 
 1828    if (n) memcpy(value, val, n);
 
 1831    return nsvg__parseAttr(p, name, value);
 
 1834static void nsvg__parseStyle(
NSVGparser* p, 
const char* str)
 
 1841        while(*str && nsvg__isspace(*str)) ++str;
 
 1843        while(*str && *str != 
';') ++str;
 
 1847        while (end > start &&  (*end == 
';' || nsvg__isspace(*end))) --end;
 
 1850        nsvg__parseNameValue(p, start, end);
 
 1855static void nsvg__parseAttribs(
NSVGparser* p, 
const char** attr)
 
 1858    for (i = 0; attr[i]; i += 2)
 
 1860        if (strcmp(attr[i], 
"style") == 0)
 
 1861            nsvg__parseStyle(p, attr[i + 1]);
 
 1863            nsvg__parseAttr(p, attr[i], attr[i + 1]);
 
 1867static int nsvg__getArgsPerElement(
char cmd)
 
 1900static void nsvg__pathMoveTo(
NSVGparser* p, 
float* cpx, 
float* cpy, 
float* args, 
int rel)
 
 1909    nsvg__moveTo(p, *cpx, *cpy);
 
 1912static void nsvg__pathLineTo(
NSVGparser* p, 
float* cpx, 
float* cpy, 
float* args, 
int rel)
 
 1921    nsvg__lineTo(p, *cpx, *cpy);
 
 1924static void nsvg__pathHLineTo(
NSVGparser* p, 
float* cpx, 
float* cpy, 
float* args, 
int rel)
 
 1930    nsvg__lineTo(p, *cpx, *cpy);
 
 1933static void nsvg__pathVLineTo(
NSVGparser* p, 
float* cpx, 
float* cpy, 
float* args, 
int rel)
 
 1939    nsvg__lineTo(p, *cpx, *cpy);
 
 1942static void nsvg__pathCubicBezTo(
NSVGparser* p, 
float* cpx, 
float* cpy,
 
 1943                                 float* cpx2, 
float* cpy2, 
float* args, 
int rel)
 
 1945    float x2, y2, cx1, cy1, cx2, cy2;
 
 1948        cx1 = *cpx + args[0];
 
 1949        cy1 = *cpy + args[1];
 
 1950        cx2 = *cpx + args[2];
 
 1951        cy2 = *cpy + args[3];
 
 1952        x2 = *cpx + args[4];
 
 1953        y2 = *cpy + args[5];
 
 1963    nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
 
 1971static void nsvg__pathCubicBezShortTo(
NSVGparser* p, 
float* cpx, 
float* cpy,
 
 1972                                      float* cpx2, 
float* cpy2, 
float* args, 
int rel)
 
 1974    float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
 
 1979        cx2 = *cpx + args[0];
 
 1980        cy2 = *cpy + args[1];
 
 1981        x2 = *cpx + args[2];
 
 1982        y2 = *cpy + args[3];
 
 1993    nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
 
 2001static void nsvg__pathQuadBezTo(
NSVGparser* p, 
float* cpx, 
float* cpy,
 
 2002                                float* cpx2, 
float* cpy2, 
float* args, 
int rel)
 
 2004    float x1, y1, x2, y2, cx, cy;
 
 2005    float cx1, cy1, cx2, cy2;
 
 2010        cx = *cpx + args[0];
 
 2011        cy = *cpy + args[1];
 
 2012        x2 = *cpx + args[2];
 
 2013        y2 = *cpy + args[3];
 
 2022    cx1 = x1 + 2.0f/3.0f*(cx - x1);
 
 2023    cy1 = y1 + 2.0f/3.0f*(cy - y1);
 
 2024    cx2 = x2 + 2.0f/3.0f*(cx - x2);
 
 2025    cy2 = y2 + 2.0f/3.0f*(cy - y2);
 
 2027    nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
 
 2035static void nsvg__pathQuadBezShortTo(
NSVGparser* p, 
float* cpx, 
float* cpy,
 
 2036                                     float* cpx2, 
float* cpy2, 
float* args, 
int rel)
 
 2038    float x1, y1, x2, y2, cx, cy;
 
 2039    float cx1, cy1, cx2, cy2;
 
 2044        x2 = *cpx + args[0];
 
 2045        y2 = *cpy + args[1];
 
 2055    cx1 = x1 + 2.0f/3.0f*(cx - x1);
 
 2056    cy1 = y1 + 2.0f/3.0f*(cy - y1);
 
 2057    cx2 = x2 + 2.0f/3.0f*(cx - x2);
 
 2058    cy2 = y2 + 2.0f/3.0f*(cy - y2);
 
 2060    nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
 
 2068static float nsvg__sqr(
float x) { 
return x*x; }
 
 2069static float nsvg__vmag(
float x, 
float y) { 
return sqrtf(x*x + y*y); }
 
 2071static float nsvg__vecrat(
float ux, 
float uy, 
float vx, 
float vy)
 
 2073    return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy));
 
 2076static float nsvg__vecang(
float ux, 
float uy, 
float vx, 
float vy)
 
 2078    float r = nsvg__vecrat(ux,uy, vx,vy);
 
 2079    if (r < -1.0f) r = -1.0f;
 
 2080    if (r > 1.0f) r = 1.0f;
 
 2081    return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r);
 
 2084static void nsvg__pathArcTo(
NSVGparser* p, 
float* cpx, 
float* cpy, 
float* args, 
int rel)
 
 2088    float x1, y1, x2, y2, cx, cy, dx, dy, d;
 
 2089    float x1p, y1p, cxp, cyp, s, sa, sb;
 
 2090    float ux, uy, vx, vy, a1, da;
 
 2091    float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
 
 2097    rx = fabsf(args[0]);                
 
 2098    ry = fabsf(args[1]);                
 
 2099    rotx = args[2] / 180.0f * NSVG_PI;      
 
 2100    fa = fabsf(args[3]) > 1e-6 ? 1 : 0; 
 
 2101    fs = fabsf(args[4]) > 1e-6 ? 1 : 0; 
 
 2105        x2 = *cpx + args[5];
 
 2106        y2 = *cpy + args[6];
 
 2114    d = sqrtf(dx*dx + dy*dy);
 
 2115    if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
 
 2117        nsvg__lineTo(p, x2, y2);
 
 2129    x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
 
 2130    y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
 
 2131    d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry);
 
 2139    sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p);
 
 2140    sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p);
 
 2141    if (sa < 0.0f) sa = 0.0f;
 
 2146    cxp = s * rx * y1p / ry;
 
 2147    cyp = s * -ry * x1p / rx;
 
 2150    cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp;
 
 2151    cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp;
 
 2154    ux = (x1p - cxp) / rx;
 
 2155    uy = (y1p - cyp) / ry;
 
 2156    vx = (-x1p - cxp) / rx;
 
 2157    vy = (-y1p - cyp) / ry;
 
 2158    a1 = nsvg__vecang(1.0f,0.0f, ux,uy);    
 
 2159    da = nsvg__vecang(ux,uy, vx,vy);        
 
 2164    if (fs == 0 && da > 0)
 
 2166    else if (fs == 1 && da < 0)
 
 2170    t[0] = cosrx; t[1] = sinrx;
 
 2171    t[2] = -sinrx; t[3] = cosrx;
 
 2172    t[4] = cx; t[5] = cy;
 
 2176    ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
 
 2177    hda = (da / (float)ndivs) / 2.0f;
 
 2179    if ((hda < 1e-3f) && (hda > -1e-3f))
 
 2182        hda = (1.0f - cosf(hda)) / sinf(hda);
 
 2183    kappa = fabsf(4.0f / 3.0f * hda);
 
 2187    for (i = 0; i <= ndivs; i++) {
 
 2188        a = a1 + da * ((float)i/(
float)ndivs);
 
 2191        nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); 
 
 2192        nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); 
 
 2194            nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y);
 
 2205static void nsvg__parsePath(
NSVGparser* p, 
const char** attr)
 
 2207    const char* s = NULL;
 
 2213    float cpx, cpy, cpx2, cpy2;
 
 2219    for (i = 0; attr[i]; i += 2) {
 
 2220        if (strcmp(attr[i], 
"d") == 0) {
 
 2224            tmp[1] = attr[i + 1];
 
 2227            nsvg__parseAttribs(p, tmp);
 
 2240            s = nsvg__getNextPathItem(s, item);
 
 2242            if (cmd != 
'\0' && nsvg__isCoordinate(item)) {
 
 2244                    args[nargs++] = (float)nsvg__atof(item);
 
 2245                if (nargs >= rargs) {
 
 2249                            nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 
'm' ? 1 : 0);
 
 2252                            cmd = (cmd == 
'm') ? 
'l' : 
'L';
 
 2253                            rargs = nsvg__getArgsPerElement(cmd);
 
 2254                            cpx2 = cpx; cpy2 = cpy;
 
 2259                            nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 
'l' ? 1 : 0);
 
 2260                            cpx2 = cpx; cpy2 = cpy;
 
 2264                            nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 
'h' ? 1 : 0);
 
 2265                            cpx2 = cpx; cpy2 = cpy;
 
 2269                            nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 
'v' ? 1 : 0);
 
 2270                            cpx2 = cpx; cpy2 = cpy;
 
 2274                            nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 
'c' ? 1 : 0);
 
 2278                            nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 
's' ? 1 : 0);
 
 2282                            nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 
'q' ? 1 : 0);
 
 2286                            nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 
't' ? 1 : 0);
 
 2290                            nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 
'a' ? 1 : 0);
 
 2291                            cpx2 = cpx; cpy2 = cpy;
 
 2295                                cpx = args[nargs-2];
 
 2296                                cpy = args[nargs-1];
 
 2297                                cpx2 = cpx; cpy2 = cpy;
 
 2305                if (cmd == 
'M' || cmd == 
'm') {
 
 2308                        nsvg__addPath(p, closedFlag);
 
 2313                } 
else if (initPoint == 0) {
 
 2317                if (cmd == 
'Z' || cmd == 
'z') {
 
 2324                        cpx2 = cpx; cpy2 = cpy;
 
 2325                        nsvg__addPath(p, closedFlag);
 
 2329                    nsvg__moveTo(p, cpx, cpy);
 
 2333                rargs = nsvg__getArgsPerElement(cmd);
 
 2343            nsvg__addPath(p, closedFlag);
 
 2349static void nsvg__parseRect(
NSVGparser* p, 
const char** attr)
 
 2359    for (i = 0; attr[i]; i += 2) {
 
 2360        if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 
 2361            if (strcmp(attr[i], 
"x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 
 2362            if (strcmp(attr[i], 
"y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 
 2363            if (strcmp(attr[i], 
"width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p));
 
 2364            if (strcmp(attr[i], 
"height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p));
 
 2365            if (strcmp(attr[i], 
"rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
 
 2366            if (strcmp(attr[i], 
"ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
 
 2370    if (rx < 0.0f && ry > 0.0f) rx = ry;
 
 2371    if (ry < 0.0f && rx > 0.0f) ry = rx;
 
 2372    if (rx < 0.0f) rx = 0.0f;
 
 2373    if (ry < 0.0f) ry = 0.0f;
 
 2374    if (rx > w/2.0f) rx = w/2.0f;
 
 2375    if (ry > h/2.0f) ry = h/2.0f;
 
 2377    if (w != 0.0f && h != 0.0f) {
 
 2380        if (rx < 0.00001f || ry < 0.0001f) {
 
 2381            nsvg__moveTo(p, x, y);
 
 2382            nsvg__lineTo(p, x+w, y);
 
 2383            nsvg__lineTo(p, x+w, y+h);
 
 2384            nsvg__lineTo(p, x, y+h);
 
 2387            nsvg__moveTo(p, x+rx, y);
 
 2388            nsvg__lineTo(p, x+w-rx, y);
 
 2389            nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry);
 
 2390            nsvg__lineTo(p, x+w, y+h-ry);
 
 2391            nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h);
 
 2392            nsvg__lineTo(p, x+rx, y+h);
 
 2393            nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry);
 
 2394            nsvg__lineTo(p, x, y+ry);
 
 2395            nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);
 
 2398        nsvg__addPath(p, 1);
 
 2404static void nsvg__parseCircle(
NSVGparser* p, 
const char** attr)
 
 2411    for (i = 0; attr[i]; i += 2) {
 
 2412        if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 
 2413            if (strcmp(attr[i], 
"cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 
 2414            if (strcmp(attr[i], 
"cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 
 2415            if (strcmp(attr[i], 
"r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)));
 
 2422        nsvg__moveTo(p, cx+r, cy);
 
 2423        nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r);
 
 2424        nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy);
 
 2425        nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);
 
 2426        nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);
 
 2428        nsvg__addPath(p, 1);
 
 2434static void nsvg__parseEllipse(
NSVGparser* p, 
const char** attr)
 
 2442    for (i = 0; attr[i]; i += 2) {
 
 2443        if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 
 2444            if (strcmp(attr[i], 
"cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 
 2445            if (strcmp(attr[i], 
"cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 
 2446            if (strcmp(attr[i], 
"rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
 
 2447            if (strcmp(attr[i], 
"ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
 
 2451    if (rx > 0.0f && ry > 0.0f) {
 
 2455        nsvg__moveTo(p, cx+rx, cy);
 
 2456        nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry);
 
 2457        nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy);
 
 2458        nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);
 
 2459        nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);
 
 2461        nsvg__addPath(p, 1);
 
 2467static void nsvg__parseLine(
NSVGparser* p, 
const char** attr)
 
 2475    for (i = 0; attr[i]; i += 2) {
 
 2476        if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 
 2477            if (strcmp(attr[i], 
"x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 
 2478            if (strcmp(attr[i], 
"y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 
 2479            if (strcmp(attr[i], 
"x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 
 2480            if (strcmp(attr[i], 
"y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 
 2486    nsvg__moveTo(p, x1, y1);
 
 2487    nsvg__lineTo(p, x2, y2);
 
 2489    nsvg__addPath(p, 0);
 
 2494static void nsvg__parsePoly(
NSVGparser* p, 
const char** attr, 
int closeFlag)
 
 2499    int nargs, npts = 0;
 
 2504    for (i = 0; attr[i]; i += 2) {
 
 2505        if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 
 2506            if (strcmp(attr[i], 
"points") == 0) {
 
 2510                    s = nsvg__getNextPathItem(s, item);
 
 2511                    args[nargs++] = (float)nsvg__atof(item);
 
 2514                            nsvg__moveTo(p, args[0], args[1]);
 
 2516                            nsvg__lineTo(p, args[0], args[1]);
 
 2525    nsvg__addPath(p, (
char)closeFlag);
 
 2530static void nsvg__parseSVG(
NSVGparser* p, 
const char** attr)
 
 2533    for (i = 0; attr[i]; i += 2) {
 
 2534        if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 
 2535            if (strcmp(attr[i], 
"width") == 0) {
 
 2536                p->
image->
width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
 
 2537            } 
else if (strcmp(attr[i], 
"height") == 0) {
 
 2538                p->
image->
height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 0.0f);
 
 2539            } 
else if (strcmp(attr[i], 
"viewBox") == 0) {
 
 2540                const char *s = attr[i + 1];
 
 2542                s = nsvg__parseNumber(s, buf, 64);
 
 2544                while (*s && (nsvg__isspace(*s) || *s == 
'%' || *s == 
',')) s++;
 
 2546                s = nsvg__parseNumber(s, buf, 64);
 
 2548                while (*s && (nsvg__isspace(*s) || *s == 
'%' || *s == 
',')) s++;
 
 2550                s = nsvg__parseNumber(s, buf, 64);
 
 2552                while (*s && (nsvg__isspace(*s) || *s == 
'%' || *s == 
',')) s++;
 
 2554                s = nsvg__parseNumber(s, buf, 64);
 
 2556            } 
else if (strcmp(attr[i], 
"preserveAspectRatio") == 0) {
 
 2557                if (strstr(attr[i + 1], 
"none") != 0) {
 
 2562                    if (strstr(attr[i + 1], 
"xMin") != 0)
 
 2563                        p->
alignX = NSVG_ALIGN_MIN;
 
 2564                    else if (strstr(attr[i + 1], 
"xMid") != 0)
 
 2565                        p->
alignX = NSVG_ALIGN_MID;
 
 2566                    else if (strstr(attr[i + 1], 
"xMax") != 0)
 
 2567                        p->
alignX = NSVG_ALIGN_MAX;
 
 2569                    if (strstr(attr[i + 1], 
"yMin") != 0)
 
 2570                        p->
alignY = NSVG_ALIGN_MIN;
 
 2571                    else if (strstr(attr[i + 1], 
"yMid") != 0)
 
 2572                        p->
alignY = NSVG_ALIGN_MID;
 
 2573                    else if (strstr(attr[i + 1], 
"yMax") != 0)
 
 2574                        p->
alignY = NSVG_ALIGN_MAX;
 
 2577                    if (strstr(attr[i + 1], 
"slice") != 0)
 
 2585static void nsvg__parseGradient(
NSVGparser* p, 
const char** attr, 
char type)
 
 2589    if (grad == NULL) 
return;
 
 2604    nsvg__xformIdentity(grad->
xform);
 
 2606    for (i = 0; attr[i]; i += 2) {
 
 2607        if (strcmp(attr[i], 
"id") == 0) {
 
 2608            strncpy(grad->
id, attr[i+1], 63);
 
 2609            grad->
id[63] = 
'\0';
 
 2610        } 
else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 
 2611            if (strcmp(attr[i], 
"gradientUnits") == 0) {
 
 2612                if (strcmp(attr[i+1], 
"objectBoundingBox") == 0)
 
 2616            } 
else if (strcmp(attr[i], 
"gradientTransform") == 0) {
 
 2617                nsvg__parseTransform(grad->
xform, attr[i + 1]);
 
 2618            } 
else if (strcmp(attr[i], 
"cx") == 0) {
 
 2619                grad->
radial.
cx = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2620            } 
else if (strcmp(attr[i], 
"cy") == 0) {
 
 2621                grad->
radial.
cy = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2622            } 
else if (strcmp(attr[i], 
"r") == 0) {
 
 2623                grad->
radial.
r = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2624            } 
else if (strcmp(attr[i], 
"fx") == 0) {
 
 2625                grad->
radial.
fx = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2626            } 
else if (strcmp(attr[i], 
"fy") == 0) {
 
 2627                grad->
radial.
fy = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2628            } 
else if (strcmp(attr[i], 
"x1") == 0) {
 
 2629                grad->
linear.
x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2630            } 
else if (strcmp(attr[i], 
"y1") == 0) {
 
 2631                grad->
linear.
y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2632            } 
else if (strcmp(attr[i], 
"x2") == 0) {
 
 2633                grad->
linear.
x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2634            } 
else if (strcmp(attr[i], 
"y2") == 0) {
 
 2635                grad->
linear.
y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
 
 2636            } 
else if (strcmp(attr[i], 
"spreadMethod") == 0) {
 
 2637                if (strcmp(attr[i+1], 
"pad") == 0)
 
 2639                else if (strcmp(attr[i+1], 
"reflect") == 0)
 
 2641                else if (strcmp(attr[i+1], 
"repeat") == 0)
 
 2643            } 
else if (strcmp(attr[i], 
"xlink:href") == 0) {
 
 2644                const char *href = attr[i+1];
 
 2645                strncpy(grad->
ref, href+1, 62);
 
 2646                grad->
ref[62] = 
'\0';
 
 2655static void nsvg__parseGradientStop(
NSVGparser* p, 
const char** attr)
 
 2666    for (i = 0; attr[i]; i += 2) {
 
 2667        nsvg__parseAttr(p, attr[i], attr[i + 1]);
 
 2672    if (grad == NULL) 
return;
 
 2676    if (grad->
stops == NULL) 
return;
 
 2680    for (i = 0; i < grad->
nstops-1; i++) {
 
 2686    if (idx != grad->
nstops-1) {
 
 2687        for (i = grad->
nstops-1; i > idx; i--)
 
 2691    stop = &grad->
stops[idx];
 
 2697static void nsvg__startElement(
void* ud, 
const char* el, 
const char** attr)
 
 2703        if (strcmp(el, 
"linearGradient") == 0) {
 
 2705        } 
else if (strcmp(el, 
"radialGradient") == 0) {
 
 2707        } 
else if (strcmp(el, 
"stop") == 0) {
 
 2708            nsvg__parseGradientStop(p, attr);
 
 2713    if (strcmp(el, 
"g") == 0) {
 
 2715        nsvg__parseAttribs(p, attr);
 
 2716    } 
else if (strcmp(el, 
"path") == 0) {
 
 2720        nsvg__parsePath(p, attr);
 
 2722    } 
else if (strcmp(el, 
"rect") == 0) {
 
 2724        nsvg__parseRect(p, attr);
 
 2726    } 
else if (strcmp(el, 
"circle") == 0) {
 
 2728        nsvg__parseCircle(p, attr);
 
 2730    } 
else if (strcmp(el, 
"ellipse") == 0) {
 
 2732        nsvg__parseEllipse(p, attr);
 
 2734    } 
else if (strcmp(el, 
"line") == 0)  {
 
 2736        nsvg__parseLine(p, attr);
 
 2738    } 
else if (strcmp(el, 
"polyline") == 0)  {
 
 2740        nsvg__parsePoly(p, attr, 0);
 
 2742    } 
else if (strcmp(el, 
"polygon") == 0)  {
 
 2744        nsvg__parsePoly(p, attr, 1);
 
 2746    } 
else  if (strcmp(el, 
"linearGradient") == 0) {
 
 2748    } 
else if (strcmp(el, 
"radialGradient") == 0) {
 
 2750    } 
else if (strcmp(el, 
"stop") == 0) {
 
 2751        nsvg__parseGradientStop(p, attr);
 
 2752    } 
else if (strcmp(el, 
"defs") == 0) {
 
 2754    } 
else if (strcmp(el, 
"svg") == 0) {
 
 2755        nsvg__parseSVG(p, attr);
 
 2759static void nsvg__endElement(
void* ud, 
const char* el)
 
 2763    if (strcmp(el, 
"g") == 0) {
 
 2765    } 
else if (strcmp(el, 
"path") == 0) {
 
 2767    } 
else if (strcmp(el, 
"defs") == 0) {
 
 2772static void nsvg__content(
void* ud, 
const char* s)
 
 2779static void nsvg__imageBounds(
NSVGparser* p, 
float* bounds)
 
 2783    if (shape == NULL) {
 
 2784        bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
 
 2787    bounds[0] = shape->
bounds[0];
 
 2788    bounds[1] = shape->
bounds[1];
 
 2789    bounds[2] = shape->
bounds[2];
 
 2790    bounds[3] = shape->
bounds[3];
 
 2791    for (shape = shape->
next; shape != NULL; shape = shape->
next) {
 
 2792        bounds[0] = nsvg__minf(bounds[0], shape->
bounds[0]);
 
 2793        bounds[1] = nsvg__minf(bounds[1], shape->
bounds[1]);
 
 2794        bounds[2] = nsvg__maxf(bounds[2], shape->
bounds[2]);
 
 2795        bounds[3] = nsvg__maxf(bounds[3], shape->
bounds[3]);
 
 2799static float nsvg__viewAlign(
float content, 
float container, 
int type)
 
 2801    if (type == NSVG_ALIGN_MIN)
 
 2803    else if (type == NSVG_ALIGN_MAX)
 
 2804        return container - content;
 
 2806    return (container - content) * 0.5f;
 
 2809static void nsvg__scaleGradient(
NSVGgradient* grad, 
float tx, 
float ty, 
float sx, 
float sy)
 
 2812    nsvg__xformSetTranslation(t, tx, ty);
 
 2813    nsvg__xformMultiply (grad->
xform, t);
 
 2815    nsvg__xformSetScale(t, sx, sy);
 
 2816    nsvg__xformMultiply (grad->
xform, t);
 
 2819static void nsvg__scaleToViewbox(
NSVGparser* p, 
const char* units)
 
 2823    float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
 
 2828    nsvg__imageBounds(p, bounds);
 
 2856    us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
 
 2861        sx = sy = nsvg__minf(sx, sy);
 
 2864    } 
else if (p->
alignType == NSVG_ALIGN_SLICE) {
 
 2866        sx = sy = nsvg__maxf(sx, sy);
 
 2874    avgs = (sx+sy) / 2.0f;
 
 2880        for (path = shape->
paths; path != NULL; path = path->
next) {
 
 2885            for (i =0; i < path->
npts; i++) {
 
 2886                pt = &path->
pts[i*2];
 
 2887                pt[0] = (pt[0] + tx) * sx;
 
 2888                pt[1] = (pt[1] + ty) * sy;
 
 2893            nsvg__scaleGradient(shape->
fill.
gradient, tx,ty, sx,sy);
 
 2915    p = nsvg__createParser();
 
 2921    nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
 
 2924    nsvg__scaleToViewbox(p, units);
 
 2929    nsvg__deleteParser(p);
 
 
 2941    fp = fopen(filename, 
"rb");
 
 2942    if (!fp) 
goto error;
 
 2943    fseek(fp, 0, SEEK_END);
 
 2945    fseek(fp, 0, SEEK_SET);
 
 2946    data = (
char*)malloc(size+1);
 
 2947    if (data == NULL) 
goto error;
 
 2948    if (fread(data, 1, size, fp) != size) 
goto error;
 
 2958    if (data) free(data);
 
 
 2971    if (res == NULL) 
goto error;
 
 2974    res->
pts = (
float*)malloc(p->
npts*2*
sizeof(
float));
 
 2975    if (res->
pts == NULL) 
goto error;
 
 2976    memcpy(res->
pts, p->
pts, p->
npts * 
sizeof(
float) * 2);
 
 
 2996    if (image == NULL) 
return;
 
 2998    while (shape != NULL) {
 
 2999        snext = shape->
next;
 
 3000        nsvg__deletePaths(shape->
paths);
 
 3001        nsvg__deletePaint(&shape->
fill);
 
 3002        nsvg__deletePaint(&shape->
stroke);
 
 
NSVGimage * nsvgParseFromFile(const char *filename, const char *units, float dpi)
int nsvg__parseXML(char *input, void(*startelCb)(void *ud, const char *el, const char **attr), void(*endelCb)(void *ud, const char *el), void(*contentCb)(void *ud, const char *s), void *ud)
NSVGpath * nsvgDuplicatePath(NSVGpath *p)
@ NSVG_PAINT_RADIAL_GRADIENT
@ NSVG_PAINT_LINEAR_GRADIENT
NSVGimage * nsvgParse(char *input, const char *units, float dpi)
NSVGNamedColor nsvg__colors[]
void nsvgDelete(NSVGimage *image)
float strokeDashArray[NSVG_MAX_DASHES]
struct NSVGgradientData * next
NSVGgradientStop stops[1]
NSVGgradientData * gradients
NSVGattrib attr[NSVG_MAX_ATTR]