diff options
-rw-r--r-- | generic/nanosvg.h | 64 |
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); |