- added parsing for per shape opacity - added support for per shape opacity in rasteriser
This commit is contained in:
parent
1b894120be
commit
95caf10c0b
@ -112,6 +112,7 @@ struct NSVGshape
|
|||||||
{
|
{
|
||||||
struct NSVGpaint fill; // Fill paint
|
struct NSVGpaint fill; // Fill paint
|
||||||
struct NSVGpaint stroke; // Stroke paint
|
struct NSVGpaint stroke; // Stroke paint
|
||||||
|
float opacity; // Opacity of the shape.
|
||||||
float strokeWidth; // Stroke width (scaled)
|
float strokeWidth; // Stroke width (scaled)
|
||||||
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].
|
||||||
struct NSVGpath* paths; // Linked list of paths in the image.
|
struct NSVGpath* paths; // Linked list of paths in the image.
|
||||||
@ -156,6 +157,8 @@ void nsvgDelete(struct NSVGimage* image);
|
|||||||
#define NSVG_ALIGN_MEET 1
|
#define NSVG_ALIGN_MEET 1
|
||||||
#define NSVG_ALIGN_SLICE 2
|
#define NSVG_ALIGN_SLICE 2
|
||||||
|
|
||||||
|
#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning (disable: 4996) // Switch off security warnings
|
#pragma warning (disable: 4996) // Switch off security warnings
|
||||||
#pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
|
#pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
|
||||||
@ -335,6 +338,7 @@ struct NSVGattrib
|
|||||||
float xform[6];
|
float xform[6];
|
||||||
unsigned int fillColor;
|
unsigned int fillColor;
|
||||||
unsigned int strokeColor;
|
unsigned int strokeColor;
|
||||||
|
float opacity;
|
||||||
float fillOpacity;
|
float fillOpacity;
|
||||||
float strokeOpacity;
|
float strokeOpacity;
|
||||||
char fillGradient[64];
|
char fillGradient[64];
|
||||||
@ -536,13 +540,14 @@ static struct NSVGparser* nsvg__createParser()
|
|||||||
|
|
||||||
// Init style
|
// Init style
|
||||||
nsvg__xformIdentity(p->attr[0].xform);
|
nsvg__xformIdentity(p->attr[0].xform);
|
||||||
p->attr[0].fillColor = 0;
|
p->attr[0].fillColor = NSVG_RGB(0,0,0);
|
||||||
p->attr[0].strokeColor = 0;
|
p->attr[0].strokeColor = NSVG_RGB(0,0,0);
|
||||||
|
p->attr[0].opacity = 1;
|
||||||
p->attr[0].fillOpacity = 1;
|
p->attr[0].fillOpacity = 1;
|
||||||
p->attr[0].strokeOpacity = 1;
|
p->attr[0].strokeOpacity = 1;
|
||||||
p->attr[0].stopOpacity = 1;
|
p->attr[0].stopOpacity = 1;
|
||||||
p->attr[0].strokeWidth = 1;
|
p->attr[0].strokeWidth = 1;
|
||||||
p->attr[0].hasFill = 0;
|
p->attr[0].hasFill = 1;
|
||||||
p->attr[0].hasStroke = 0;
|
p->attr[0].hasStroke = 0;
|
||||||
p->attr[0].visible = 1;
|
p->attr[0].visible = 1;
|
||||||
|
|
||||||
@ -743,6 +748,7 @@ static void nsvg__addShape(struct NSVGparser* p)
|
|||||||
|
|
||||||
scale = nsvg__maxf(fabsf(attr->xform[0]), fabsf(attr->xform[3]));
|
scale = nsvg__maxf(fabsf(attr->xform[0]), fabsf(attr->xform[3]));
|
||||||
shape->strokeWidth = attr->strokeWidth * scale;
|
shape->strokeWidth = attr->strokeWidth * scale;
|
||||||
|
shape->opacity = attr->opacity;
|
||||||
|
|
||||||
shape->paths = p->plist;
|
shape->paths = p->plist;
|
||||||
p->plist = NULL;
|
p->plist = NULL;
|
||||||
@ -929,8 +935,6 @@ static float nsvg__actualLength(struct NSVGparser* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
|
|
||||||
|
|
||||||
static unsigned int nsvg__parseColorHex(const char* str)
|
static unsigned int nsvg__parseColorHex(const char* str)
|
||||||
{
|
{
|
||||||
unsigned int c = 0, r = 0, g = 0, b = 0;
|
unsigned int c = 0, r = 0, g = 0, b = 0;
|
||||||
@ -1389,6 +1393,8 @@ static int nsvg__parseAttr(struct NSVGparser* p, const char* name, const char* v
|
|||||||
attr->hasFill = 1;
|
attr->hasFill = 1;
|
||||||
attr->fillColor = nsvg__parseColor(value);
|
attr->fillColor = nsvg__parseColor(value);
|
||||||
}
|
}
|
||||||
|
} else if (strcmp(name, "opacity") == 0) {
|
||||||
|
attr->opacity = nsvg__parseFloat(p, value, 2);
|
||||||
} else if (strcmp(name, "fill-opacity") == 0) {
|
} else if (strcmp(name, "fill-opacity") == 0) {
|
||||||
attr->fillOpacity = nsvg__parseFloat(p, value, 2);
|
attr->fillOpacity = nsvg__parseFloat(p, value, 2);
|
||||||
} else if (strcmp(name, "stroke") == 0) {
|
} else if (strcmp(name, "stroke") == 0) {
|
||||||
|
@ -394,6 +394,16 @@ static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)
|
|||||||
return nsvg__RGBA(r,g,b,a);
|
return nsvg__RGBA(r,g,b,a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned int nsvg__applyOpacity(unsigned int c, float u)
|
||||||
|
{
|
||||||
|
int iu = (float)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
|
||||||
|
int r = (c) & 0xff;
|
||||||
|
int g = (c>>8) & 0xff;
|
||||||
|
int b = (c>>16) & 0xff;
|
||||||
|
int a = (((c>>24) & 0xff)*iu) >> 8;
|
||||||
|
return nsvg__RGBA(r,g,b,a);
|
||||||
|
}
|
||||||
|
|
||||||
static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y,
|
static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y,
|
||||||
float tx, float ty, float scale, struct NSVGcachedPaint* cache)
|
float tx, float ty, float scale, struct NSVGcachedPaint* cache)
|
||||||
{
|
{
|
||||||
@ -670,7 +680,7 @@ static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int str
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nsvg__initPaint(struct NSVGcachedPaint* cache, struct NSVGpaint* paint)
|
static void nsvg__initPaint(struct NSVGcachedPaint* cache, struct NSVGpaint* paint, float opacity)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
struct NSVGgradient* grad;
|
struct NSVGgradient* grad;
|
||||||
@ -678,7 +688,7 @@ static void nsvg__initPaint(struct NSVGcachedPaint* cache, struct NSVGpaint* pai
|
|||||||
cache->type = paint->type;
|
cache->type = paint->type;
|
||||||
|
|
||||||
if (paint->type == NSVG_PAINT_COLOR) {
|
if (paint->type == NSVG_PAINT_COLOR) {
|
||||||
cache->colors[0] = paint->color;
|
cache->colors[0] = nsvg__applyOpacity(paint->color, opacity);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -692,14 +702,13 @@ static void nsvg__initPaint(struct NSVGcachedPaint* cache, struct NSVGpaint* pai
|
|||||||
cache->colors[i] = 0;
|
cache->colors[i] = 0;
|
||||||
} if (grad->nstops == 1) {
|
} if (grad->nstops == 1) {
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < 256; i++)
|
||||||
cache->colors[i] = grad->stops[i].color;
|
cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity);
|
||||||
} else {
|
} else {
|
||||||
unsigned int ca, cb;
|
unsigned int ca, cb;
|
||||||
float ua, ub, du, u;
|
float ua, ub, du, u;
|
||||||
int ia, ib, count;
|
int ia, ib, count;
|
||||||
|
|
||||||
ca = grad->stops[0].color;
|
ca = nsvg__applyOpacity(grad->stops[0].color, opacity);
|
||||||
cb = grad->stops[grad->nstops-1].color;
|
|
||||||
ua = nsvg__clampf(grad->stops[0].offset, 0, 1);
|
ua = nsvg__clampf(grad->stops[0].offset, 0, 1);
|
||||||
ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);
|
ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);
|
||||||
ia = ua * 255.0f;
|
ia = ua * 255.0f;
|
||||||
@ -709,8 +718,8 @@ static void nsvg__initPaint(struct NSVGcachedPaint* cache, struct NSVGpaint* pai
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < grad->nstops-1; i++) {
|
for (i = 0; i < grad->nstops-1; i++) {
|
||||||
ca = grad->stops[i].color;
|
ca = nsvg__applyOpacity(grad->stops[i].color, opacity);
|
||||||
cb = grad->stops[i+1].color;
|
cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity);
|
||||||
ua = nsvg__clampf(grad->stops[i].offset, 0, 1);
|
ua = nsvg__clampf(grad->stops[i].offset, 0, 1);
|
||||||
ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);
|
ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);
|
||||||
ia = ua * 255.0f;
|
ia = ua * 255.0f;
|
||||||
@ -778,7 +787,7 @@ void nsvgRasterize(struct NSVGrasterizer* r,
|
|||||||
qsort(r->edges, r->nedges, sizeof(struct NSVGedge), nsvg__cmpEdge);
|
qsort(r->edges, r->nedges, sizeof(struct NSVGedge), nsvg__cmpEdge);
|
||||||
|
|
||||||
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
|
||||||
nsvg__initPaint(&cache, &shape->fill);
|
nsvg__initPaint(&cache, &shape->fill, shape->opacity);
|
||||||
|
|
||||||
nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache);
|
nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user