nanosvg: Sync with upstream 93ce879

93ce879dc4
This commit is contained in:
Rémi Verschelde 2024-04-05 11:19:09 +02:00
parent 1a9b5b7c99
commit abee48d063
No known key found for this signature in database
GPG key ID: C3336907360768E1
3 changed files with 60 additions and 30 deletions

View file

@ -400,7 +400,7 @@ Collection of single-file libraries used in Godot components.
## nanosvg ## nanosvg
- Upstream: https://github.com/memononen/nanosvg - Upstream: https://github.com/memononen/nanosvg
- Version: git (f0a3e1034dd22e2e87e5db22401e44998383124e, 2022) - Version: git (93ce879dc4c04a3ef1758428ec80083c38610b1f, 2023)
- License: zlib - License: zlib
Files extracted from the upstream source: Files extracted from the upstream source:

View file

@ -72,6 +72,7 @@ extern "C" {
*/ */
enum NSVGpaintType { enum NSVGpaintType {
NSVG_PAINT_UNDEF = -1,
NSVG_PAINT_NONE = 0, NSVG_PAINT_NONE = 0,
NSVG_PAINT_COLOR = 1, NSVG_PAINT_COLOR = 1,
NSVG_PAINT_LINEAR_GRADIENT = 2, NSVG_PAINT_LINEAR_GRADIENT = 2,
@ -119,7 +120,7 @@ typedef struct NSVGgradient {
} NSVGgradient; } NSVGgradient;
typedef struct NSVGpaint { typedef struct NSVGpaint {
char type; signed char type;
union { union {
unsigned int color; unsigned int color;
NSVGgradient* gradient; NSVGgradient* gradient;
@ -151,6 +152,9 @@ typedef struct NSVGshape
char fillRule; // Fill rule, see NSVGfillRule. char fillRule; // Fill rule, see NSVGfillRule.
unsigned char flags; // Logical or of NSVG_FLAGS_* flags unsigned char flags; // Logical or of NSVG_FLAGS_* flags
float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy]. float bounds[4]; // Tight bounding box of the shape [minx,miny,maxx,maxy].
char fillGradient[64]; // Optional 'id' of fill gradient
char strokeGradient[64]; // Optional 'id' of stroke gradient
float xform[6]; // Root transformation for fill/stroke gradient
NSVGpath* paths; // Linked list of paths in the image. NSVGpath* paths; // Linked list of paths in the image.
struct NSVGshape* next; // Pointer to next shape, or NULL if last element. struct NSVGshape* next; // Pointer to next shape, or NULL if last element.
} NSVGshape; } NSVGshape;
@ -394,7 +398,7 @@ typedef struct NSVGgradientData
{ {
char id[64]; char id[64];
char ref[64]; char ref[64];
char type; signed char type;
union { union {
NSVGlinearData linear; NSVGlinearData linear;
NSVGradialData radial; NSVGradialData radial;
@ -814,9 +818,8 @@ static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
return NULL; return NULL;
} }
static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType) static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, float *xform, signed char* paintType)
{ {
NSVGattrib* attr = nsvg__getAttr(p);
NSVGgradientData* data = NULL; NSVGgradientData* data = NULL;
NSVGgradientData* ref = NULL; NSVGgradientData* ref = NULL;
NSVGgradientStop* stops = NULL; NSVGgradientStop* stops = NULL;
@ -891,7 +894,7 @@ static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const f
} }
nsvg__xformMultiply(grad->xform, data->xform); nsvg__xformMultiply(grad->xform, data->xform);
nsvg__xformMultiply(grad->xform, attr->xform); nsvg__xformMultiply(grad->xform, xform);
grad->spread = data->spread; grad->spread = data->spread;
memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop)); memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
@ -955,6 +958,9 @@ static void nsvg__addShape(NSVGparser* p)
memset(shape, 0, sizeof(NSVGshape)); memset(shape, 0, sizeof(NSVGshape));
memcpy(shape->id, attr->id, sizeof shape->id); memcpy(shape->id, attr->id, sizeof shape->id);
memcpy(shape->fillGradient, attr->fillGradient, sizeof shape->fillGradient);
memcpy(shape->strokeGradient, attr->strokeGradient, sizeof shape->strokeGradient);
memcpy(shape->xform, attr->xform, sizeof shape->xform);
scale = nsvg__getAverageScale(attr->xform); scale = nsvg__getAverageScale(attr->xform);
shape->strokeWidth = attr->strokeWidth * scale; shape->strokeWidth = attr->strokeWidth * scale;
shape->strokeDashOffset = attr->strokeDashOffset * scale; shape->strokeDashOffset = attr->strokeDashOffset * scale;
@ -990,13 +996,7 @@ static void nsvg__addShape(NSVGparser* p)
shape->fill.color = attr->fillColor; shape->fill.color = attr->fillColor;
shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24; shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
} else if (attr->hasFill == 2) { } else if (attr->hasFill == 2) {
float inv[6], localBounds[4]; shape->fill.type = NSVG_PAINT_UNDEF;
nsvg__xformInverse(inv, attr->xform);
nsvg__getLocalBounds(localBounds, shape, inv);
shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
if (shape->fill.gradient == NULL) {
shape->fill.type = NSVG_PAINT_NONE;
}
} }
// Set stroke // Set stroke
@ -1007,12 +1007,7 @@ static void nsvg__addShape(NSVGparser* p)
shape->stroke.color = attr->strokeColor; shape->stroke.color = attr->strokeColor;
shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24; shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
} else if (attr->hasStroke == 2) { } else if (attr->hasStroke == 2) {
float inv[6], localBounds[4]; shape->stroke.type = NSVG_PAINT_UNDEF;
nsvg__xformInverse(inv, attr->xform);
nsvg__getLocalBounds(localBounds, shape, inv);
shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type);
if (shape->stroke.gradient == NULL)
shape->stroke.type = NSVG_PAINT_NONE;
} }
// Set flags // Set flags
@ -2641,7 +2636,7 @@ static void nsvg__parseSVG(NSVGparser* p, const char** attr)
} }
} }
static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type) static void nsvg__parseGradient(NSVGparser* p, const char** attr, signed char type)
{ {
int i; int i;
NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData)); NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
@ -2966,6 +2961,36 @@ static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
} }
} }
static void nsvg__createGradients(NSVGparser* p)
{
NSVGshape* shape;
for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
if (shape->fill.type == NSVG_PAINT_UNDEF) {
if (shape->fillGradient[0] != '\0') {
float inv[6], localBounds[4];
nsvg__xformInverse(inv, shape->xform);
nsvg__getLocalBounds(localBounds, shape, inv);
shape->fill.gradient = nsvg__createGradient(p, shape->fillGradient, localBounds, shape->xform, &shape->fill.type);
}
if (shape->fill.type == NSVG_PAINT_UNDEF) {
shape->fill.type = NSVG_PAINT_NONE;
}
}
if (shape->stroke.type == NSVG_PAINT_UNDEF) {
if (shape->strokeGradient[0] != '\0') {
float inv[6], localBounds[4];
nsvg__xformInverse(inv, shape->xform);
nsvg__getLocalBounds(localBounds, shape, inv);
shape->stroke.gradient = nsvg__createGradient(p, shape->strokeGradient, localBounds, shape->xform, &shape->stroke.type);
}
if (shape->stroke.type == NSVG_PAINT_UNDEF) {
shape->stroke.type = NSVG_PAINT_NONE;
}
}
}
}
NSVGimage* nsvgParse(char* input, const char* units, float dpi) NSVGimage* nsvgParse(char* input, const char* units, float dpi)
{ {
NSVGparser* p; NSVGparser* p;
@ -2979,6 +3004,9 @@ NSVGimage* nsvgParse(char* input, const char* units, float dpi)
nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p); nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
// Create gradients after all definitions have been parsed
nsvg__createGradients(p);
// Scale to viewBox // Scale to viewBox
nsvg__scaleToViewbox(p, units); nsvg__scaleToViewbox(p, units);

View file

@ -114,7 +114,7 @@ typedef struct NSVGmemPage {
} NSVGmemPage; } NSVGmemPage;
typedef struct NSVGcachedPaint { typedef struct NSVGcachedPaint {
char type; signed char type;
char spread; char spread;
float xform[6]; float xform[6];
unsigned int colors[256]; unsigned int colors[256];
@ -331,6 +331,7 @@ static float nsvg__normalize(float *x, float* y)
} }
static float nsvg__absf(float x) { return x < 0 ? -x : x; } static float nsvg__absf(float x) { return x < 0 ? -x : x; }
static float nsvg__roundf(float x) { return (x >= 0) ? floorf(x + 0.5) : ceilf(x - 0.5); }
static void nsvg__flattenCubicBez(NSVGrasterizer* r, static void nsvg__flattenCubicBez(NSVGrasterizer* r,
float x1, float y1, float x2, float y2, float x1, float y1, float x2, float y2,
@ -353,8 +354,8 @@ static void nsvg__flattenCubicBez(NSVGrasterizer* r,
dx = x4 - x1; dx = x4 - x1;
dy = y4 - y1; dy = y4 - y1;
d2 = nsvg__absf(((x2 - x4) * dy - (y2 - y4) * dx)); d2 = nsvg__absf((x2 - x4) * dy - (y2 - y4) * dx);
d3 = nsvg__absf(((x3 - x4) * dy - (y3 - y4) * dx)); d3 = nsvg__absf((x3 - x4) * dy - (y3 - y4) * dx);
if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) { if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) {
nsvg__addPathPoint(r, x4, y4, type); nsvg__addPathPoint(r, x4, y4, type);
@ -872,10 +873,10 @@ static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float sta
// STBTT_assert(e->y0 <= start_point); // STBTT_assert(e->y0 <= start_point);
// round dx down to avoid going too far // round dx down to avoid going too far
if (dxdy < 0) if (dxdy < 0)
z->dx = (int)(-floorf(NSVG__FIX * -dxdy)); z->dx = (int)(-nsvg__roundf(NSVG__FIX * -dxdy));
else else
z->dx = (int)floorf(NSVG__FIX * dxdy); z->dx = (int)nsvg__roundf(NSVG__FIX * dxdy);
z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0))); z->x = (int)nsvg__roundf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
// z->x -= off_x * FIX; // z->x -= off_x * FIX;
z->ey = e->y1; z->ey = e->y1;
z->next = 0; z->next = 0;
@ -1282,9 +1283,10 @@ static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opac
if (grad->nstops == 0) { if (grad->nstops == 0) {
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
cache->colors[i] = 0; cache->colors[i] = 0;
} if (grad->nstops == 1) { } else if (grad->nstops == 1) {
unsigned int color = nsvg__applyOpacity(grad->stops[0].color, opacity);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity); cache->colors[i] = color;
} else { } else {
unsigned int ca, cb = 0; unsigned int ca, cb = 0;
float ua, ub, du, u; float ua, ub, du, u;