summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/nanosvg.h64
1 files changed, 46 insertions, 18 deletions
diff --git a/generic/nanosvg.h b/generic/nanosvg.h
index 862b7d4..77a5913 100644
--- a/generic/nanosvg.h
+++ b/generic/nanosvg.h
@@ -105,6 +105,7 @@ extern "C" {
#endif
enum NSVGpaintType {
+ NSVG_PAINT_UNDEF = -1,
NSVG_PAINT_NONE = 0,
NSVG_PAINT_COLOR = 1,
NSVG_PAINT_LINEAR_GRADIENT = 2,
@@ -176,14 +177,17 @@ typedef struct NSVGshape
float opacity; /* Opacity of the shape. */
float strokeWidth; /* Stroke width (scaled). */
float strokeDashOffset; /* Stroke dash offset (scaled). */
- float strokeDashArray[8]; /* Stroke dash array (scaled). */
- char strokeDashCount; /* Number of dash values in dash array. */
+ float strokeDashArray[8]; /* Stroke dash array (scaled). */
+ 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]. */
+ 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. */
struct NSVGshape* next; /* Pointer to next shape, or NULL if last element. */
} NSVGshape;
@@ -874,9 +878,8 @@ static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
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, char* paintType)
{
- NSVGattrib* attr = nsvg__getAttr(p);
NSVGgradientData* data = NULL;
NSVGgradientData* ref = NULL;
NSVGgradientStop* stops = NULL;
@@ -951,7 +954,7 @@ static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const f
}
nsvg__xformMultiply(grad->xform, data->xform);
- nsvg__xformMultiply(grad->xform, attr->xform);
+ nsvg__xformMultiply(grad->xform, xform);
grad->spread = data->spread;
memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
@@ -1015,6 +1018,9 @@ static void nsvg__addShape(NSVGparser* p)
memset(shape, 0, sizeof(NSVGshape));
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);
shape->strokeWidth = attr->strokeWidth * scale;
shape->strokeDashOffset = attr->strokeDashOffset * scale;
@@ -1050,13 +1056,7 @@ static void nsvg__addShape(NSVGparser* p)
shape->fill.color = attr->fillColor;
shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
} else if (attr->hasFill == 2) {
- float inv[6], localBounds[4];
- 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;
- }
+ shape->fill.type = NSVG_PAINT_UNDEF;
}
/* Set stroke */
@@ -1067,12 +1067,7 @@ static void nsvg__addShape(NSVGparser* p)
shape->stroke.color = attr->strokeColor;
shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
} else if (attr->hasStroke == 2) {
- float inv[6], localBounds[4];
- 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;
+ shape->stroke.type = NSVG_PAINT_UNDEF;
}
/* Set flags */
@@ -3111,6 +3106,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;
+ }
+ }
+ }
+}
+
NANOSVG_SCOPE
NSVGimage* nsvgParse(char* input, const char* units, float dpi)
{
@@ -3125,6 +3150,9 @@ NSVGimage* nsvgParse(char* input, const char* units, float dpi)
nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
+ // Create gradients after all definitions have been parsed
+ nsvg__createGradients(p);
+
/* Scale to viewBox */
nsvg__scaleToViewbox(p, units);