mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-15 04:24:28 +00:00
sw_engine: code refactoring
introduce compositor table for runtime colorspace switching. Change-Id: If179d1e1625f995e114d66cf1bf13742c54ed4f7
This commit is contained in:
parent
f4d1065d52
commit
a5beca7369
6 changed files with 149 additions and 159 deletions
|
@ -38,8 +38,6 @@ static double timeStamp()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace tvg;
|
|
||||||
|
|
||||||
#define SW_CURVE_TYPE_POINT 0
|
#define SW_CURVE_TYPE_POINT 0
|
||||||
#define SW_CURVE_TYPE_CUBIC 1
|
#define SW_CURVE_TYPE_CUBIC 1
|
||||||
#define SW_OUTLINE_FILL_WINDING 0
|
#define SW_OUTLINE_FILL_WINDING 0
|
||||||
|
@ -215,58 +213,40 @@ struct SwShape
|
||||||
bool rect; //Fast Track: Othogonal rectangle?
|
bool rect; //Fast Track: Othogonal rectangle?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SwCompositor
|
||||||
|
{
|
||||||
|
uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||||
|
uint32_t (*alpha)(uint32_t rgba);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SwSurface : Surface
|
||||||
|
{
|
||||||
|
SwCompositor comp;
|
||||||
|
};
|
||||||
|
|
||||||
static inline SwCoord TO_SWCOORD(float val)
|
static inline SwCoord TO_SWCOORD(float val)
|
||||||
{
|
{
|
||||||
return SwCoord(val * 64);
|
return SwCoord(val * 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline uint32_t RGBA_ALPHA(uint32_t rgba)
|
|
||||||
{
|
|
||||||
return rgba & 0x000000ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint32_t ARGB_ALPHA(uint32_t argb)
|
|
||||||
{
|
|
||||||
return (argb >> 24) & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint32_t RGBA_ALPHA_BLEND(uint32_t rgba, uint32_t alpha)
|
static inline uint32_t RGBA_ALPHA_BLEND(uint32_t rgba, uint32_t alpha)
|
||||||
{
|
{
|
||||||
return (((((rgba >> 8) & 0x00ff00ff) * alpha) & 0xff00ff00) +
|
return (((((rgba >> 8) & 0x00ff00ff) * alpha) & 0xff00ff00) +
|
||||||
((((rgba & 0x00ff00ff) * alpha) >> 8) & 0x00ff00ff));
|
((((rgba & 0x00ff00ff) * alpha) >> 8) & 0x00ff00ff));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline uint32_t RGBA_INTERPOLATE(uint32_t rgba1, uint32_t a, uint32_t rgba2, uint32_t b)
|
static inline uint32_t RGBA_INTERPOLATE(uint32_t rgba1, uint32_t a, uint32_t rgba2, uint32_t b)
|
||||||
{
|
{
|
||||||
auto t = (((rgba1 & 0xff00ff) * a + (rgba2 & 0xff00ff) * b) >> 8) & 0xff00ff;
|
auto t = (((rgba1 & 0xff00ff) * a + (rgba2 & 0xff00ff) * b) >> 8) & 0xff00ff;
|
||||||
rgba1 = (((rgba1 >> 8) & 0xff00ff) * a + ((rgba2 >> 8) & 0xff00ff) * b) & 0xff00ff00;
|
rgba1 = (((rgba1 >> 8) & 0xff00ff) * a + ((rgba2 >> 8) & 0xff00ff) * b) & 0xff00ff00;
|
||||||
return (rgba1 |= t);
|
return (rgba1 |= t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline uint32_t RGBA_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
|
||||||
{
|
|
||||||
return (r << 24 | g << 16 | b << 8 | a);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint32_t ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
|
||||||
{
|
|
||||||
return (a << 24 | r << 16 | g << 8 | b);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint8_t ALPHA_MULTIPLY(uint32_t c, uint32_t a)
|
static inline uint8_t ALPHA_MULTIPLY(uint32_t c, uint32_t a)
|
||||||
{
|
{
|
||||||
return (c * a) >> 8;
|
return (c * a) >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int64_t mathMultiply(int64_t a, int64_t b);
|
int64_t mathMultiply(int64_t a, int64_t b);
|
||||||
int64_t mathDivide(int64_t a, int64_t b);
|
int64_t mathDivide(int64_t a, int64_t b);
|
||||||
int64_t mathMulDiv(int64_t a, int64_t b, int64_t c);
|
int64_t mathMulDiv(int64_t a, int64_t b, int64_t c);
|
||||||
|
@ -290,7 +270,7 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor
|
||||||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip);
|
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip);
|
||||||
void shapeFree(SwShape* shape);
|
void shapeFree(SwShape* shape);
|
||||||
void shapeDelStroke(SwShape* shape);
|
void shapeDelStroke(SwShape* shape);
|
||||||
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, uint32_t cs, bool ctable);
|
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, bool ctable);
|
||||||
void shapeResetFill(SwShape* shape);
|
void shapeResetFill(SwShape* shape);
|
||||||
void shapeDelFill(SwShape* shape);
|
void shapeDelFill(SwShape* shape);
|
||||||
|
|
||||||
|
@ -299,7 +279,7 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
|
||||||
SwOutline* strokeExportOutline(SwStroke* stroke);
|
SwOutline* strokeExportOutline(SwStroke* stroke);
|
||||||
void strokeFree(SwStroke* stroke);
|
void strokeFree(SwStroke* stroke);
|
||||||
|
|
||||||
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, uint32_t cs, bool ctable);
|
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, bool ctable);
|
||||||
void fillReset(SwFill* fill);
|
void fillReset(SwFill* fill);
|
||||||
void fillFree(SwFill* fill);
|
void fillFree(SwFill* fill);
|
||||||
void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t offset, uint32_t len);
|
void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t offset, uint32_t len);
|
||||||
|
@ -308,10 +288,11 @@ void fillFetchRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x,
|
||||||
SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias);
|
SwRleData* rleRender(const SwOutline* outline, const SwBBox& bbox, const SwSize& clip, bool antiAlias);
|
||||||
void rleFree(SwRleData* rle);
|
void rleFree(SwRleData* rle);
|
||||||
|
|
||||||
bool rasterGradientShape(Surface& surface, SwShape* shape, unsigned id);
|
bool rasterCompositor(SwSurface* surface);
|
||||||
bool rasterSolidShape(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id);
|
||||||
bool rasterStroke(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||||
bool rasterClear(Surface& surface);
|
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
|
||||||
|
bool rasterClear(SwSurface* surface);
|
||||||
|
|
||||||
|
|
||||||
static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
|
static inline void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len)
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
#define FIXPT_SIZE (1<<FIXPT_BITS)
|
#define FIXPT_SIZE (1<<FIXPT_BITS)
|
||||||
|
|
||||||
|
|
||||||
static bool _updateColorTable(SwFill* fill, const Fill* fdata, uint32_t cs)
|
static bool _updateColorTable(SwFill* fill, const Fill* fdata, SwSurface* surface)
|
||||||
{
|
{
|
||||||
assert(fill && fdata);
|
assert(fill && fdata);
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, uint32_t cs)
|
||||||
auto g = ALPHA_MULTIPLY(pColors->g, pColors->a);
|
auto g = ALPHA_MULTIPLY(pColors->g, pColors->a);
|
||||||
auto b = ALPHA_MULTIPLY(pColors->b, pColors->a);
|
auto b = ALPHA_MULTIPLY(pColors->b, pColors->a);
|
||||||
|
|
||||||
auto rgba = (cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, pColors->a) : ARGB_JOIN(r, g, b, pColors->a);
|
auto rgba = surface->comp.join(r, g, b, pColors->a);
|
||||||
auto inc = 1.0f / static_cast<float>(GRADIENT_STOP_SIZE);
|
auto inc = 1.0f / static_cast<float>(GRADIENT_STOP_SIZE);
|
||||||
auto pos = 1.5f * inc;
|
auto pos = 1.5f * inc;
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
|
@ -79,7 +79,7 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata, uint32_t cs)
|
||||||
auto g = ALPHA_MULTIPLY(next->g, next->a);
|
auto g = ALPHA_MULTIPLY(next->g, next->a);
|
||||||
auto b = ALPHA_MULTIPLY(next->b, next->a);
|
auto b = ALPHA_MULTIPLY(next->b, next->a);
|
||||||
|
|
||||||
auto rgba2 = (cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, next->a) : ARGB_JOIN(r, g, b, next->a);
|
auto rgba2 = surface->comp.join(r, g, b, next->a);
|
||||||
|
|
||||||
while (pos < next->offset && i < GRADIENT_STOP_SIZE) {
|
while (pos < next->offset && i < GRADIENT_STOP_SIZE) {
|
||||||
auto t = (pos - curr->offset) * delta;
|
auto t = (pos - curr->offset) * delta;
|
||||||
|
@ -282,7 +282,7 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, uint32_t cs, bool ctable)
|
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, bool ctable)
|
||||||
{
|
{
|
||||||
if (!fill) return false;
|
if (!fill) return false;
|
||||||
|
|
||||||
|
@ -291,7 +291,7 @@ bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform,
|
||||||
fill->spread = fdata->spread();
|
fill->spread = fdata->spread();
|
||||||
|
|
||||||
if (ctable) {
|
if (ctable) {
|
||||||
if (!_updateColorTable(fill, fdata, cs)) return false;
|
if (!_updateColorTable(fill, fdata, surface)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fdata->id() == FILL_ID_LINEAR) {
|
if (fdata->id() == FILL_ID_LINEAR) {
|
||||||
|
|
|
@ -28,27 +28,51 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static SwBBox _clipRegion(Surface& surface, SwBBox& in)
|
static uint32_t _rgbaAlpha(uint32_t rgba)
|
||||||
|
{
|
||||||
|
return rgba & 0x000000ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t _argbAlpha(uint32_t argb)
|
||||||
|
{
|
||||||
|
return (argb >> 24) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t _rgbaJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
|
{
|
||||||
|
return (r << 24 | g << 16 | b << 8 | a);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
|
{
|
||||||
|
return (a << 24 | r << 16 | g << 8 | b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static SwBBox _clipRegion(Surface* surface, SwBBox& in)
|
||||||
{
|
{
|
||||||
auto bbox = in;
|
auto bbox = in;
|
||||||
|
|
||||||
if (bbox.min.x < 0) bbox.min.x = 0;
|
if (bbox.min.x < 0) bbox.min.x = 0;
|
||||||
if (bbox.min.y < 0) bbox.min.y = 0;
|
if (bbox.min.y < 0) bbox.min.y = 0;
|
||||||
if (bbox.max.x > static_cast<SwCoord>(surface.w)) bbox.max.x = surface.w;
|
if (bbox.max.x > static_cast<SwCoord>(surface->w)) bbox.max.x = surface->w;
|
||||||
if (bbox.max.y > static_cast<SwCoord>(surface.h)) bbox.max.y = surface.h;
|
if (bbox.max.y > static_cast<SwCoord>(surface->h)) bbox.max.y = surface->h;
|
||||||
|
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _rasterTranslucentRect(Surface& surface, const SwBBox& region, uint32_t color)
|
static bool _rasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
||||||
{
|
{
|
||||||
auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x;
|
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
||||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
auto ialpha = 255 - (surface.cs == SwCanvas::RGBA8888)? RGBA_ALPHA(color) : ARGB_ALPHA(color);
|
auto ialpha = 255 - surface->comp.alpha(color);
|
||||||
|
|
||||||
for (uint32_t y = 0; y < h; ++y) {
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
auto dst = &buffer[y * surface.stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
for (uint32_t x = 0; x < w; ++x) {
|
for (uint32_t x = 0; x < w; ++x) {
|
||||||
dst[x] = color + RGBA_ALPHA_BLEND(dst[x], ialpha);
|
dst[x] = color + RGBA_ALPHA_BLEND(dst[x], ialpha);
|
||||||
}
|
}
|
||||||
|
@ -57,20 +81,20 @@ static bool _rasterTranslucentRect(Surface& surface, const SwBBox& region, uint3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _rasterSolidRect(Surface& surface, const SwBBox& region, uint32_t color)
|
static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint32_t color)
|
||||||
{
|
{
|
||||||
auto buffer = surface.buffer + (region.min.y * surface.stride);
|
auto buffer = surface->buffer + (region.min.y * surface->stride);
|
||||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
|
|
||||||
for (uint32_t y = 0; y < h; ++y) {
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
rasterRGBA32(buffer + y * surface.stride, color, region.min.x, w);
|
rasterRGBA32(buffer + y * surface->stride, color, region.min.x, w);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t color)
|
static bool _rasterTranslucentRle(SwSurface* surface, SwRleData* rle, uint32_t color)
|
||||||
{
|
{
|
||||||
if (!rle) return false;
|
if (!rle) return false;
|
||||||
|
|
||||||
|
@ -78,10 +102,10 @@ static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t col
|
||||||
uint32_t src;
|
uint32_t src;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
||||||
if (span->coverage < 255) src = RGBA_ALPHA_BLEND(color, span->coverage);
|
if (span->coverage < 255) src = RGBA_ALPHA_BLEND(color, span->coverage);
|
||||||
else src = color;
|
else src = color;
|
||||||
auto ialpha = 255 - ((surface.cs == SwCanvas::RGBA8888)? RGBA_ALPHA(src) : ARGB_ALPHA(src));
|
auto ialpha = 255 - surface->comp.alpha(src);
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha);
|
dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +115,7 @@ static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t col
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color)
|
static bool _rasterSolidRle(SwSurface* surface, SwRleData* rle, uint32_t color)
|
||||||
{
|
{
|
||||||
if (!rle) return false;
|
if (!rle) return false;
|
||||||
|
|
||||||
|
@ -99,9 +123,9 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color)
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
rasterRGBA32(surface.buffer + span->y * surface.stride, color, span->x, span->len);
|
rasterRGBA32(surface->buffer + span->y * surface->stride, color, span->x, span->len);
|
||||||
} else {
|
} else {
|
||||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
||||||
auto src = RGBA_ALPHA_BLEND(color, span->coverage);
|
auto src = RGBA_ALPHA_BLEND(color, span->coverage);
|
||||||
auto ialpha = 255 - span->coverage;
|
auto ialpha = 255 - span->coverage;
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
|
@ -114,74 +138,62 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _rasterLinearGradientRect(Surface& surface, const SwBBox& region, const SwFill* fill)
|
static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
|
||||||
{
|
{
|
||||||
if (!fill) return false;
|
if (!fill) return false;
|
||||||
|
|
||||||
auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x;
|
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
||||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
|
|
||||||
//Translucent Gradient
|
//Translucent Gradient
|
||||||
if (fill->translucent) {
|
if (fill->translucent) {
|
||||||
|
|
||||||
auto tmpBuf = static_cast<uint32_t*>(alloca(surface.w * sizeof(uint32_t)));
|
auto tmpBuf = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
|
||||||
if (!tmpBuf) return false;
|
if (!tmpBuf) return false;
|
||||||
|
|
||||||
for (uint32_t y = 0; y < h; ++y) {
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
auto dst = &buffer[y * surface.stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w);
|
fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w);
|
||||||
if (surface.cs == SwCanvas::RGBA8888) {
|
for (uint32_t x = 0; x < w; ++x) {
|
||||||
for (uint32_t x = 0; x < w; ++x) {
|
dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x]));
|
||||||
dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - RGBA_ALPHA(tmpBuf[x]));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (uint32_t x = 0; x < w; ++x) {
|
|
||||||
dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - ARGB_ALPHA(tmpBuf[x]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Opaque Gradient
|
//Opaque Gradient
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t y = 0; y < h; ++y) {
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
fillFetchLinear(fill, buffer + y * surface.stride, region.min.y + y, region.min.x, 0, w);
|
fillFetchLinear(fill, buffer + y * surface->stride, region.min.y + y, region.min.x, 0, w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _rasterRadialGradientRect(Surface& surface, const SwBBox& region, const SwFill* fill)
|
static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
|
||||||
{
|
{
|
||||||
if (!fill) return false;
|
if (!fill) return false;
|
||||||
|
|
||||||
auto buffer = surface.buffer + (region.min.y * surface.stride) + region.min.x;
|
auto buffer = surface->buffer + (region.min.y * surface->stride) + region.min.x;
|
||||||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||||
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
auto w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||||
|
|
||||||
//Translucent Gradient
|
//Translucent Gradient
|
||||||
if (fill->translucent) {
|
if (fill->translucent) {
|
||||||
|
|
||||||
auto tmpBuf = static_cast<uint32_t*>(alloca(surface.w * sizeof(uint32_t)));
|
auto tmpBuf = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
|
||||||
if (!tmpBuf) return false;
|
if (!tmpBuf) return false;
|
||||||
|
|
||||||
for (uint32_t y = 0; y < h; ++y) {
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
auto dst = &buffer[y * surface.stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w);
|
fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w);
|
||||||
if (surface.cs == SwCanvas::RGBA8888) {
|
for (uint32_t x = 0; x < w; ++x) {
|
||||||
for (uint32_t x = 0; x < w; ++x) {
|
dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - surface->comp.alpha(tmpBuf[x]));
|
||||||
dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - RGBA_ALPHA(tmpBuf[x]));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (uint32_t x = 0; x < w; ++x) {
|
|
||||||
dst[x] = tmpBuf[x] + RGBA_ALPHA_BLEND(dst[x], 255 - ARGB_ALPHA(tmpBuf[x]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Opaque Gradient
|
//Opaque Gradient
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t y = 0; y < h; ++y) {
|
for (uint32_t y = 0; y < h; ++y) {
|
||||||
auto dst = &buffer[y * surface.stride];
|
auto dst = &buffer[y * surface->stride];
|
||||||
fillFetchRadial(fill, dst, region.min.y + y, region.min.x, w);
|
fillFetchRadial(fill, dst, region.min.y + y, region.min.x, w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,11 +201,11 @@ static bool _rasterRadialGradientRect(Surface& surface, const SwBBox& region, co
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwFill* fill)
|
static bool _rasterLinearGradientRle(SwSurface* surface, SwRleData* rle, const SwFill* fill)
|
||||||
{
|
{
|
||||||
if (!rle || !fill) return false;
|
if (!rle || !fill) return false;
|
||||||
|
|
||||||
auto buf = static_cast<uint32_t*>(alloca(surface.w * sizeof(uint32_t)));
|
auto buf = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
|
||||||
if (!buf) return false;
|
if (!buf) return false;
|
||||||
|
|
||||||
auto span = rle->spans;
|
auto span = rle->spans;
|
||||||
|
@ -201,29 +213,16 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF
|
||||||
//Translucent Gradient
|
//Translucent Gradient
|
||||||
if (fill->translucent) {
|
if (fill->translucent) {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
||||||
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
||||||
if (surface.cs == SwCanvas::RGBA8888) {
|
if (span->coverage == 255) {
|
||||||
if (span->coverage == 255) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i]));
|
||||||
dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(buf[i]));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
|
||||||
auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage);
|
|
||||||
dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(tmp));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (span->coverage == 255) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage);
|
||||||
dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(buf[i]));
|
dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp));
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
|
||||||
auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage);
|
|
||||||
dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(tmp));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++span;
|
++span;
|
||||||
|
@ -232,9 +231,9 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
fillFetchLinear(fill, surface.buffer + span->y * surface.stride, span->y, span->x, span->x, span->len);
|
fillFetchLinear(fill, surface->buffer + span->y * surface->stride, span->y, span->x, span->x, span->len);
|
||||||
} else {
|
} else {
|
||||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
||||||
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
||||||
auto ialpha = 255 - span->coverage;
|
auto ialpha = 255 - span->coverage;
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
|
@ -248,11 +247,11 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwFill* fill)
|
static bool _rasterRadialGradientRle(SwSurface* surface, SwRleData* rle, const SwFill* fill)
|
||||||
{
|
{
|
||||||
if (!rle || !fill) return false;
|
if (!rle || !fill) return false;
|
||||||
|
|
||||||
auto buf = static_cast<uint32_t*>(alloca(surface.w * sizeof(uint32_t)));
|
auto buf = static_cast<uint32_t*>(alloca(surface->w * sizeof(uint32_t)));
|
||||||
if (!buf) return false;
|
if (!buf) return false;
|
||||||
|
|
||||||
auto span = rle->spans;
|
auto span = rle->spans;
|
||||||
|
@ -260,29 +259,16 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF
|
||||||
//Translucent Gradient
|
//Translucent Gradient
|
||||||
if (fill->translucent) {
|
if (fill->translucent) {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
||||||
fillFetchRadial(fill, buf, span->y, span->x, span->len);
|
fillFetchRadial(fill, buf, span->y, span->x, span->len);
|
||||||
if (surface.cs == SwCanvas::RGBA8888) {
|
if (span->coverage == 255) {
|
||||||
if (span->coverage == 255) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(buf[i]));
|
||||||
dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(buf[i]));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
|
||||||
auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage);
|
|
||||||
dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - RGBA_ALPHA(tmp));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (span->coverage == 255) {
|
for (uint32_t i = 0; i < span->len; ++i) {
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage);
|
||||||
dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(buf[i]));
|
dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - surface->comp.alpha(tmp));
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (uint32_t i = 0; i < span->len; ++i) {
|
|
||||||
auto tmp = RGBA_ALPHA_BLEND(buf[i], span->coverage);
|
|
||||||
dst[i] = tmp + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_ALPHA(tmp));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++span;
|
++span;
|
||||||
|
@ -290,7 +276,7 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF
|
||||||
//Opaque Gradient
|
//Opaque Gradient
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
auto dst = &surface->buffer[span->y * surface->stride + span->x];
|
||||||
if (span->coverage == 255) {
|
if (span->coverage == 255) {
|
||||||
fillFetchRadial(fill, dst, span->y, span->x, span->len);
|
fillFetchRadial(fill, dst, span->y, span->x, span->len);
|
||||||
} else {
|
} else {
|
||||||
|
@ -311,7 +297,24 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
bool rasterGradientShape(Surface& surface, SwShape* shape, unsigned id)
|
bool rasterCompositor(SwSurface* surface)
|
||||||
|
{
|
||||||
|
if (surface->cs == SwCanvas::RGBA8888) {
|
||||||
|
surface->comp.alpha = _rgbaAlpha;
|
||||||
|
surface->comp.join = _rgbaJoin;
|
||||||
|
} else if (surface->cs == SwCanvas::ARGB8888) {
|
||||||
|
surface->comp.alpha = _argbAlpha;
|
||||||
|
surface->comp.join = _argbJoin;
|
||||||
|
} else {
|
||||||
|
//What Color Space ???
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id)
|
||||||
{
|
{
|
||||||
//Fast Track
|
//Fast Track
|
||||||
if (shape->rect) {
|
if (shape->rect) {
|
||||||
|
@ -326,13 +329,13 @@ bool rasterGradientShape(Surface& surface, SwShape* shape, unsigned id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rasterSolidShape(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
bool rasterSolidShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
r = ALPHA_MULTIPLY(r, a);
|
r = ALPHA_MULTIPLY(r, a);
|
||||||
g = ALPHA_MULTIPLY(g, a);
|
g = ALPHA_MULTIPLY(g, a);
|
||||||
b = ALPHA_MULTIPLY(b, a);
|
b = ALPHA_MULTIPLY(b, a);
|
||||||
|
|
||||||
auto color = (surface.cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, a) : ARGB_JOIN(r, g, b, a);
|
auto color = surface->comp.join(r, g, b, a);
|
||||||
|
|
||||||
//Fast Track
|
//Fast Track
|
||||||
if (shape->rect) {
|
if (shape->rect) {
|
||||||
|
@ -347,28 +350,28 @@ bool rasterSolidShape(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, ui
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rasterStroke(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||||
{
|
{
|
||||||
r = ALPHA_MULTIPLY(r, a);
|
r = ALPHA_MULTIPLY(r, a);
|
||||||
g = ALPHA_MULTIPLY(g, a);
|
g = ALPHA_MULTIPLY(g, a);
|
||||||
b = ALPHA_MULTIPLY(b, a);
|
b = ALPHA_MULTIPLY(b, a);
|
||||||
|
|
||||||
auto color = (surface.cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, a) : ARGB_JOIN(r, g, b, a);
|
auto color = surface->comp.join(r, g, b, a);
|
||||||
|
|
||||||
if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color);
|
if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color);
|
||||||
return _rasterTranslucentRle(surface, shape->strokeRle, color);
|
return _rasterTranslucentRle(surface, shape->strokeRle, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool rasterClear(Surface& surface)
|
bool rasterClear(SwSurface* surface)
|
||||||
{
|
{
|
||||||
if (!surface.buffer || surface.stride <= 0 || surface.w <= 0 || surface.h <= 0) return false;
|
if (!surface || !surface->buffer || surface->stride <= 0 || surface->w <= 0 || surface->h <= 0) return false;
|
||||||
|
|
||||||
if (surface.w == surface.stride) {
|
if (surface->w == surface->stride) {
|
||||||
rasterRGBA32(surface.buffer, 0x00000000, 0, surface.w * surface.h);
|
rasterRGBA32(surface->buffer, 0x00000000, 0, surface->w * surface->h);
|
||||||
} else {
|
} else {
|
||||||
for (uint32_t i = 0; i < surface.h; i++) {
|
for (uint32_t i = 0; i < surface->h; i++) {
|
||||||
rasterRGBA32(surface.buffer + surface.stride * i, 0x00000000, 0, surface.w);
|
rasterRGBA32(surface->buffer + surface->stride * i, 0x00000000, 0, surface->w);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -37,6 +37,7 @@ static RenderInitializer renderInit;
|
||||||
|
|
||||||
SwRenderer::~SwRenderer()
|
SwRenderer::~SwRenderer()
|
||||||
{
|
{
|
||||||
|
if (surface) delete(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,13 +45,18 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
||||||
{
|
{
|
||||||
if (!buffer || stride == 0 || w == 0 || h == 0) return false;
|
if (!buffer || stride == 0 || w == 0 || h == 0) return false;
|
||||||
|
|
||||||
surface.buffer = buffer;
|
if (!surface) {
|
||||||
surface.stride = stride;
|
surface = new SwSurface;
|
||||||
surface.w = w;
|
if (!surface) return false;
|
||||||
surface.h = h;
|
}
|
||||||
surface.cs = cs;
|
|
||||||
|
|
||||||
return true;
|
surface->buffer = buffer;
|
||||||
|
surface->stride = stride;
|
||||||
|
surface->w = w;
|
||||||
|
surface->h = h;
|
||||||
|
surface->cs = cs;
|
||||||
|
|
||||||
|
return rasterCompositor(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,7 +106,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
|
||||||
|
|
||||||
if (flags == RenderUpdateFlag::None) return shape;
|
if (flags == RenderUpdateFlag::None) return shape;
|
||||||
|
|
||||||
SwSize clip = {static_cast<SwCoord>(surface.w), static_cast<SwCoord>(surface.h)};
|
SwSize clip = {static_cast<SwCoord>(surface->w), static_cast<SwCoord>(surface->h)};
|
||||||
|
|
||||||
//Valid Stroking?
|
//Valid Stroking?
|
||||||
uint8_t strokeAlpha = 0;
|
uint8_t strokeAlpha = 0;
|
||||||
|
@ -130,7 +136,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
|
||||||
if (fill) {
|
if (fill) {
|
||||||
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
|
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
|
||||||
if (ctable) shapeResetFill(shape);
|
if (ctable) shapeResetFill(shape);
|
||||||
if (!shapeGenFillColors(shape, fill, matrix, surface.cs, ctable)) return shape;
|
if (!shapeGenFillColors(shape, fill, matrix, surface, ctable)) return shape;
|
||||||
} else {
|
} else {
|
||||||
shapeDelFill(shape);
|
shapeDelFill(shape);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
#ifndef _TVG_SW_RENDERER_H_
|
#ifndef _TVG_SW_RENDERER_H_
|
||||||
#define _TVG_SW_RENDERER_H_
|
#define _TVG_SW_RENDERER_H_
|
||||||
|
|
||||||
|
struct SwSurface;
|
||||||
|
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
|
||||||
struct SwTask;
|
|
||||||
|
|
||||||
class SwRenderer : public RenderMethod
|
class SwRenderer : public RenderMethod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -43,7 +43,7 @@ public:
|
||||||
static int term();
|
static int term();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Surface surface = {nullptr, 0, 0, 0};
|
SwSurface* surface = nullptr;
|
||||||
|
|
||||||
SwRenderer(){};
|
SwRenderer(){};
|
||||||
~SwRenderer();
|
~SwRenderer();
|
||||||
|
|
|
@ -672,9 +672,9 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, uint32_t cs, bool ctable)
|
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, SwSurface* surface, bool ctable)
|
||||||
{
|
{
|
||||||
return fillGenColorTable(shape->fill, fill, transform, cs, ctable);
|
return fillGenColorTable(shape->fill, fill, transform, surface, ctable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue