Skip to content

Commit

Permalink
fix handling of <defs> after <g>
Browse files Browse the repository at this point in the history
  • Loading branch information
poke1024 committed Jul 9, 2018
1 parent 06c1f0f commit 8e75cda
Showing 1 changed file with 59 additions and 18 deletions.
77 changes: 59 additions & 18 deletions src/nanosvg.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ 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,
NSVG_PAINT_GRADIENT_LINK = 4
};

enum NSVGspreadType {
Expand Down Expand Up @@ -103,6 +104,11 @@ enum NSVGflags {
NSVG_FLAGS_VISIBLE = 0x01
};

typedef struct NSVGgradientLink {
char id[64];
float xform[6];
} NSVGgradientLink;

typedef struct NSVGgradientStop {
unsigned int color;
float offset;
Expand All @@ -121,6 +127,7 @@ typedef struct NSVGpaint {
union {
unsigned int color;
NSVGgradient* gradient;
NSVGgradientLink* gradientLink;
};
} NSVGpaint;

Expand Down Expand Up @@ -809,17 +816,28 @@ 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 NSVGgradientLink* nsvg__createGradientLink(const char* id, const float *xform)
{
NSVGgradientLink* grad = (NSVGgradientLink*)malloc(sizeof(NSVGgradientLink));
if (grad == NULL) return NULL;
strncpy(grad->id, id, 63);
grad->id[63] = '\0';
memcpy(grad->xform, xform, sizeof(float)*6);
return grad;
}

static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform);

static NSVGgradient* nsvg__createGradient(NSVGparser* p, NSVGshape* shape, NSVGgradientLink* link, char* paintType)
{
NSVGattrib* attr = nsvg__getAttr(p);
NSVGgradientData* data = NULL;
NSVGgradientData* ref = NULL;
NSVGgradientStop* stops = NULL;
NSVGgradient* grad;
float ox, oy, sw, sh, sl;
int nstops = 0;

data = nsvg__findGradientData(p, id);
data = nsvg__findGradientData(p, link->id);
if (data == NULL) return NULL;

// TODO: use ref to fill in all unset values too.
Expand All @@ -839,6 +857,10 @@ static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const f

// The shape width and height.
if (data->units == NSVG_OBJECT_SPACE) {
float inv[6], localBounds[4];
nsvg__xformInverse(inv, link->xform);
nsvg__getLocalBounds(localBounds, shape, inv);

ox = localBounds[0];
oy = localBounds[1];
sw = localBounds[2] - localBounds[0];
Expand Down Expand Up @@ -879,7 +901,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, link->xform);

grad->spread = data->spread;
memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
Expand Down Expand Up @@ -978,13 +1000,9 @@ 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_GRADIENT_LINK;
shape->fill.gradientLink = nsvg__createGradientLink(attr->fillGradient, attr->xform);
if (shape->fill.gradientLink == NULL) goto error;
}

// Set stroke
Expand All @@ -995,12 +1013,9 @@ 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_GRADIENT_LINK;
shape->stroke.gradientLink = nsvg__createGradientLink(attr->strokeGradient, attr->xform);
if (shape->stroke.gradientLink == NULL) goto error;
}

// Set flags
Expand Down Expand Up @@ -2722,6 +2737,30 @@ static void nsvg__content(void* ud, const char* s)
// empty
}

static void nsvg__assignGradients(NSVGparser* p)
{
for (NSVGshape* shape = p->image->shapes; shape != NULL; shape = shape->next) {
if (shape->fill.type == NSVG_PAINT_GRADIENT_LINK) {
NSVGgradientLink* link = shape->fill.gradientLink;
shape->fill.gradient = nsvg__createGradient(
p, shape, link, &shape->fill.type);
free(link);
if (shape->fill.gradient == NULL) {
shape->fill.type = NSVG_PAINT_NONE;
}
}
if (shape->stroke.type == NSVG_PAINT_GRADIENT_LINK) {
NSVGgradientLink* link = shape->stroke.gradientLink;
shape->stroke.gradient = nsvg__createGradient(
p, shape, link, &shape->stroke.type);
free(link);
if (shape->stroke.gradient == NULL) {
shape->stroke.type = NSVG_PAINT_NONE;
}
}
}
}

static void nsvg__imageBounds(NSVGparser* p, float* bounds)
{
NSVGshape* shape;
Expand Down Expand Up @@ -2866,6 +2905,8 @@ NSVGimage* nsvgParse(char* input, const char* units, float dpi)

nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);

nsvg__assignGradients(p);

// Scale to viewBox
nsvg__scaleToViewbox(p, units);

Expand Down

0 comments on commit 8e75cda

Please sign in to comment.