mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-24 07:08:58 +00:00
sw_engine: convert colorspace ARGB -> RGBA in default.
We can use RGBA colorspace rather ARGB for pixel data. This would be better for many rendering system, since it's more widely preferred than ARGB including opengl. Change-Id: Ibbfe6a511d77bf0ef30ce261995467c11164d306
This commit is contained in:
parent
7ab71c52d0
commit
f4d1065d52
34 changed files with 157 additions and 97 deletions
|
@ -311,7 +311,9 @@ class TVG_EXPORT SwCanvas final : public Canvas
|
|||
public:
|
||||
~SwCanvas();
|
||||
|
||||
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept;
|
||||
enum Colorspace { RGBA8888 = 0, ARGB8888 };
|
||||
|
||||
Result target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept;
|
||||
|
||||
static std::unique_ptr<SwCanvas> gen() noexcept;
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ typedef struct _Tvg_Gradient Tvg_Gradient;
|
|||
#define TVG_ENGINE_SW (1 << 1)
|
||||
#define TVG_ENGINE_GL (1 << 2)
|
||||
|
||||
#define TVG_COLORSPACE_RGBA8888 0
|
||||
#define TVG_COLORSPACE_ARGB8888 1
|
||||
|
||||
typedef enum {
|
||||
TVG_RESULT_SUCCESS = 0,
|
||||
|
@ -94,7 +96,7 @@ TVG_EXPORT Tvg_Result tvg_engine_term(unsigned engine_method);
|
|||
/* SwCanvas API */
|
||||
/************************************************************************/
|
||||
TVG_EXPORT Tvg_Canvas* tvg_swcanvas_create();
|
||||
TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||
TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
@ -88,9 +88,9 @@ TVG_EXPORT Tvg_Result tvg_canvas_destroy(Tvg_Canvas* canvas)
|
|||
}
|
||||
|
||||
|
||||
TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h)
|
||||
TVG_EXPORT Tvg_Result tvg_swcanvas_set_target(Tvg_Canvas* canvas, uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs)
|
||||
{
|
||||
return (Tvg_Result) reinterpret_cast<SwCanvas*>(canvas)->target(buffer, stride, w, h);
|
||||
return (Tvg_Result) reinterpret_cast<SwCanvas*>(canvas)->target(buffer, stride, w, h, static_cast<SwCanvas::Colorspace>(cs));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -222,20 +222,26 @@ static inline SwCoord TO_SWCOORD(float val)
|
|||
}
|
||||
|
||||
|
||||
static inline uint32_t COLOR_ALPHA(uint32_t rgba)
|
||||
static inline uint32_t RGBA_ALPHA(uint32_t rgba)
|
||||
{
|
||||
return (rgba >> 24) & 0xff;
|
||||
return rgba & 0x000000ff;
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t COLOR_ALPHA_BLEND(uint32_t rgba, uint32_t alpha)
|
||||
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)
|
||||
{
|
||||
return (((((rgba >> 8) & 0x00ff00ff) * alpha) & 0xff00ff00) +
|
||||
((((rgba & 0x00ff00ff) * alpha) >> 8) & 0x00ff00ff));
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t COLOR_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;
|
||||
rgba1 = (((rgba1 >> 8) & 0xff00ff) * a + ((rgba2 >> 8) & 0xff00ff) * b) & 0xff00ff00;
|
||||
|
@ -243,13 +249,19 @@ static inline uint32_t COLOR_INTERPOLATE(uint32_t rgba1, uint32_t a, uint32_t rg
|
|||
}
|
||||
|
||||
|
||||
static inline uint32_t COLOR_ARGB_JOIN(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
|
||||
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 COLOR_ALPHA_MULTIPLY(uint32_t c, uint32_t a)
|
||||
static inline uint8_t ALPHA_MULTIPLY(uint32_t c, uint32_t a)
|
||||
{
|
||||
return (c * a) >> 8;
|
||||
}
|
||||
|
@ -278,7 +290,7 @@ void shapeResetStroke(SwShape* shape, const Shape* sdata, const Matrix* transfor
|
|||
bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transform, const SwSize& clip);
|
||||
void shapeFree(SwShape* shape);
|
||||
void shapeDelStroke(SwShape* shape);
|
||||
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, bool ctable);
|
||||
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, uint32_t cs, bool ctable);
|
||||
void shapeResetFill(SwShape* shape);
|
||||
void shapeDelFill(SwShape* shape);
|
||||
|
||||
|
@ -287,7 +299,7 @@ bool strokeParseOutline(SwStroke* stroke, const SwOutline& outline);
|
|||
SwOutline* strokeExportOutline(SwStroke* stroke);
|
||||
void strokeFree(SwStroke* stroke);
|
||||
|
||||
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, bool ctable);
|
||||
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, uint32_t cs, bool ctable);
|
||||
void fillReset(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);
|
||||
|
@ -302,7 +314,7 @@ bool rasterStroke(Surface& surface, SwShape* shape, uint8_t r, uint8_t g, uint8_
|
|||
bool rasterClear(Surface& surface);
|
||||
|
||||
|
||||
static inline void rasterARGB32(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)
|
||||
{
|
||||
#ifdef THORVG_AVX_VECTOR_SUPPORT
|
||||
int32_t align = (8 - (offset % 8)) % 8;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#define FIXPT_SIZE (1<<FIXPT_BITS)
|
||||
|
||||
|
||||
static bool _updateColorTable(SwFill* fill, const Fill* fdata)
|
||||
static bool _updateColorTable(SwFill* fill, const Fill* fdata, uint32_t cs)
|
||||
{
|
||||
assert(fill && fdata);
|
||||
|
||||
|
@ -51,11 +51,11 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata)
|
|||
|
||||
if (pColors->a < 255) fill->translucent = true;
|
||||
|
||||
auto r = COLOR_ALPHA_MULTIPLY(pColors->r, pColors->a);
|
||||
auto g = COLOR_ALPHA_MULTIPLY(pColors->g, pColors->a);
|
||||
auto b = COLOR_ALPHA_MULTIPLY(pColors->b, pColors->a);
|
||||
auto r = ALPHA_MULTIPLY(pColors->r, pColors->a);
|
||||
auto g = ALPHA_MULTIPLY(pColors->g, pColors->a);
|
||||
auto b = ALPHA_MULTIPLY(pColors->b, pColors->a);
|
||||
|
||||
auto rgba = COLOR_ARGB_JOIN(r, g, b, pColors->a);
|
||||
auto rgba = (cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, pColors->a) : ARGB_JOIN(r, g, b, pColors->a);
|
||||
auto inc = 1.0f / static_cast<float>(GRADIENT_STOP_SIZE);
|
||||
auto pos = 1.5f * inc;
|
||||
uint32_t i = 0;
|
||||
|
@ -75,17 +75,17 @@ static bool _updateColorTable(SwFill* fill, const Fill* fdata)
|
|||
auto delta = 1.0f / (next->offset - curr->offset);
|
||||
if (next->a < 255) fill->translucent = true;
|
||||
|
||||
auto r = COLOR_ALPHA_MULTIPLY(next->r, next->a);
|
||||
auto g = COLOR_ALPHA_MULTIPLY(next->g, next->a);
|
||||
auto b = COLOR_ALPHA_MULTIPLY(next->b, next->a);
|
||||
auto r = ALPHA_MULTIPLY(next->r, next->a);
|
||||
auto g = ALPHA_MULTIPLY(next->g, next->a);
|
||||
auto b = ALPHA_MULTIPLY(next->b, next->a);
|
||||
|
||||
auto rgba2 = COLOR_ARGB_JOIN(r, g, b, next->a);
|
||||
auto rgba2 = (cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, next->a) : ARGB_JOIN(r, g, b, next->a);
|
||||
|
||||
while (pos < next->offset && i < GRADIENT_STOP_SIZE) {
|
||||
auto t = (pos - curr->offset) * delta;
|
||||
auto dist = static_cast<int32_t>(256 * t);
|
||||
auto dist2 = 256 - dist;
|
||||
fill->ctable[i] = COLOR_INTERPOLATE(rgba, dist2, rgba2, dist);
|
||||
fill->ctable[i] = RGBA_INTERPOLATE(rgba, dist2, rgba2, dist);
|
||||
++i;
|
||||
pos += inc;
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ void fillFetchLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x,
|
|||
|
||||
if (fabsf(inc) < FLT_EPSILON) {
|
||||
auto color = _fixedPixel(fill, static_cast<int32_t>(t * FIXPT_SIZE));
|
||||
rasterARGB32(dst, color, offset, len);
|
||||
rasterRGBA32(dst, color, offset, len);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -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, bool ctable)
|
||||
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, uint32_t cs, bool ctable)
|
||||
{
|
||||
if (!fill) return false;
|
||||
|
||||
|
@ -291,7 +291,7 @@ bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform,
|
|||
fill->spread = fdata->spread();
|
||||
|
||||
if (ctable) {
|
||||
if (!_updateColorTable(fill, fdata)) return false;
|
||||
if (!_updateColorTable(fill, fdata, cs)) return false;
|
||||
}
|
||||
|
||||
if (fdata->id() == FILL_ID_LINEAR) {
|
||||
|
|
|
@ -45,12 +45,12 @@ static bool _rasterTranslucentRect(Surface& surface, const SwBBox& region, uint3
|
|||
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 w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
auto ialpha = 255 - COLOR_ALPHA(color);
|
||||
auto ialpha = 255 - (surface.cs == SwCanvas::RGBA8888)? RGBA_ALPHA(color) : ARGB_ALPHA(color);
|
||||
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
auto dst = &buffer[y * surface.stride];
|
||||
for (uint32_t x = 0; x < w; ++x) {
|
||||
dst[x] = color + COLOR_ALPHA_BLEND(dst[x], ialpha);
|
||||
dst[x] = color + RGBA_ALPHA_BLEND(dst[x], ialpha);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -64,7 +64,7 @@ static bool _rasterSolidRect(Surface& surface, const SwBBox& region, uint32_t co
|
|||
auto h = static_cast<uint32_t>(region.max.y - region.min.y);
|
||||
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
rasterARGB32(buffer + y * surface.stride, color, region.min.x, w);
|
||||
rasterRGBA32(buffer + y * surface.stride, color, region.min.x, w);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -79,11 +79,11 @@ static bool _rasterTranslucentRle(Surface& surface, SwRleData* rle, uint32_t col
|
|||
|
||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
||||
if (span->coverage < 255) src = COLOR_ALPHA_BLEND(color, span->coverage);
|
||||
if (span->coverage < 255) src = RGBA_ALPHA_BLEND(color, span->coverage);
|
||||
else src = color;
|
||||
auto ialpha = 255 - COLOR_ALPHA(src);
|
||||
auto ialpha = 255 - ((surface.cs == SwCanvas::RGBA8888)? RGBA_ALPHA(src) : ARGB_ALPHA(src));
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
dst[i] = src + COLOR_ALPHA_BLEND(dst[i], ialpha);
|
||||
dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha);
|
||||
}
|
||||
++span;
|
||||
}
|
||||
|
@ -99,13 +99,13 @@ static bool _rasterSolidRle(Surface& surface, SwRleData* rle, uint32_t color)
|
|||
|
||||
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||
if (span->coverage == 255) {
|
||||
rasterARGB32(surface.buffer + span->y * surface.stride, color, span->x, span->len);
|
||||
rasterRGBA32(surface.buffer + span->y * surface.stride, color, span->x, span->len);
|
||||
} else {
|
||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
||||
auto src = COLOR_ALPHA_BLEND(color, span->coverage);
|
||||
auto src = RGBA_ALPHA_BLEND(color, span->coverage);
|
||||
auto ialpha = 255 - span->coverage;
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
dst[i] = src + COLOR_ALPHA_BLEND(dst[i], ialpha);
|
||||
dst[i] = src + RGBA_ALPHA_BLEND(dst[i], ialpha);
|
||||
}
|
||||
}
|
||||
++span;
|
||||
|
@ -131,8 +131,14 @@ static bool _rasterLinearGradientRect(Surface& surface, const SwBBox& region, co
|
|||
for (uint32_t y = 0; y < h; ++y) {
|
||||
auto dst = &buffer[y * surface.stride];
|
||||
fillFetchLinear(fill, tmpBuf, region.min.y + y, region.min.x, 0, w);
|
||||
for (uint32_t x = 0; x < w; ++x) {
|
||||
dst[x] = tmpBuf[x] + COLOR_ALPHA_BLEND(dst[x], 255 - COLOR_ALPHA(tmpBuf[x]));
|
||||
if (surface.cs == SwCanvas::RGBA8888) {
|
||||
for (uint32_t x = 0; x < w; ++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
|
||||
|
@ -162,8 +168,14 @@ static bool _rasterRadialGradientRect(Surface& surface, const SwBBox& region, co
|
|||
for (uint32_t y = 0; y < h; ++y) {
|
||||
auto dst = &buffer[y * surface.stride];
|
||||
fillFetchRadial(fill, tmpBuf, region.min.y + y, region.min.x, w);
|
||||
for (uint32_t x = 0; x < w; ++x) {
|
||||
dst[x] = tmpBuf[x] + COLOR_ALPHA_BLEND(dst[x], 255 - COLOR_ALPHA(tmpBuf[x]));
|
||||
if (surface.cs == SwCanvas::RGBA8888) {
|
||||
for (uint32_t x = 0; x < w; ++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
|
||||
|
@ -191,14 +203,27 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF
|
|||
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
||||
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
||||
if (span->coverage == 255) {
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
dst[i] = buf[i] + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(buf[i]));
|
||||
if (surface.cs == SwCanvas::RGBA8888) {
|
||||
if (span->coverage == 255) {
|
||||
for (uint32_t i = 0; i < span->len; ++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 {
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
auto tmp = COLOR_ALPHA_BLEND(buf[i], span->coverage);
|
||||
dst[i] = tmp + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(tmp));
|
||||
if (span->coverage == 255) {
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_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 - ARGB_ALPHA(tmp));
|
||||
}
|
||||
}
|
||||
}
|
||||
++span;
|
||||
|
@ -213,7 +238,7 @@ static bool _rasterLinearGradientRle(Surface& surface, SwRleData* rle, const SwF
|
|||
fillFetchLinear(fill, buf, span->y, span->x, 0, span->len);
|
||||
auto ialpha = 255 - span->coverage;
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
dst[i] = COLOR_ALPHA_BLEND(buf[i], span->coverage) + COLOR_ALPHA_BLEND(dst[i], ialpha);
|
||||
dst[i] = RGBA_ALPHA_BLEND(buf[i], span->coverage) + RGBA_ALPHA_BLEND(dst[i], ialpha);
|
||||
}
|
||||
}
|
||||
++span;
|
||||
|
@ -237,14 +262,27 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF
|
|||
for (uint32_t i = 0; i < rle->size; ++i) {
|
||||
auto dst = &surface.buffer[span->y * surface.stride + span->x];
|
||||
fillFetchRadial(fill, buf, span->y, span->x, span->len);
|
||||
if (span->coverage == 255) {
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
dst[i] = buf[i] + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(buf[i]));
|
||||
if (surface.cs == SwCanvas::RGBA8888) {
|
||||
if (span->coverage == 255) {
|
||||
for (uint32_t i = 0; i < span->len; ++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 {
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
auto tmp = COLOR_ALPHA_BLEND(buf[i], span->coverage);
|
||||
dst[i] = tmp + COLOR_ALPHA_BLEND(dst[i], 255 - COLOR_ALPHA(tmp));
|
||||
if (span->coverage == 255) {
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
dst[i] = buf[i] + RGBA_ALPHA_BLEND(dst[i], 255 - ARGB_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 - ARGB_ALPHA(tmp));
|
||||
}
|
||||
}
|
||||
}
|
||||
++span;
|
||||
|
@ -259,7 +297,7 @@ static bool _rasterRadialGradientRle(Surface& surface, SwRleData* rle, const SwF
|
|||
fillFetchRadial(fill, buf, span->y, span->x, span->len);
|
||||
auto ialpha = 255 - span->coverage;
|
||||
for (uint32_t i = 0; i < span->len; ++i) {
|
||||
dst[i] = COLOR_ALPHA_BLEND(buf[i], span->coverage) + COLOR_ALPHA_BLEND(dst[i], ialpha);
|
||||
dst[i] = RGBA_ALPHA_BLEND(buf[i], span->coverage) + RGBA_ALPHA_BLEND(dst[i], ialpha);
|
||||
}
|
||||
}
|
||||
++span;
|
||||
|
@ -290,18 +328,20 @@ 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)
|
||||
{
|
||||
r = COLOR_ALPHA_MULTIPLY(r, a);
|
||||
g = COLOR_ALPHA_MULTIPLY(g, a);
|
||||
b = COLOR_ALPHA_MULTIPLY(b, a);
|
||||
r = ALPHA_MULTIPLY(r, a);
|
||||
g = ALPHA_MULTIPLY(g, a);
|
||||
b = ALPHA_MULTIPLY(b, a);
|
||||
|
||||
auto color = (surface.cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, a) : ARGB_JOIN(r, g, b, a);
|
||||
|
||||
//Fast Track
|
||||
if (shape->rect) {
|
||||
auto region = _clipRegion(surface, shape->bbox);
|
||||
if (a == 255) return _rasterSolidRect(surface, region, COLOR_ARGB_JOIN(r, g, b, a));
|
||||
return _rasterTranslucentRect(surface, region, COLOR_ARGB_JOIN(r, g, b, a));
|
||||
if (a == 255) return _rasterSolidRect(surface, region, color);
|
||||
return _rasterTranslucentRect(surface, region, color);
|
||||
} else{
|
||||
if (a == 255) return _rasterSolidRle(surface, shape->rle, COLOR_ARGB_JOIN(r, g, b, a));
|
||||
return _rasterTranslucentRle(surface, shape->rle, COLOR_ARGB_JOIN(r, g, b, a));
|
||||
if (a == 255) return _rasterSolidRle(surface, shape->rle, color);
|
||||
return _rasterTranslucentRle(surface, shape->rle, color);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -309,12 +349,14 @@ 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)
|
||||
{
|
||||
r = COLOR_ALPHA_MULTIPLY(r, a);
|
||||
g = COLOR_ALPHA_MULTIPLY(g, a);
|
||||
b = COLOR_ALPHA_MULTIPLY(b, a);
|
||||
r = ALPHA_MULTIPLY(r, a);
|
||||
g = ALPHA_MULTIPLY(g, a);
|
||||
b = ALPHA_MULTIPLY(b, a);
|
||||
|
||||
if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, COLOR_ARGB_JOIN(r, g, b, a));
|
||||
return _rasterTranslucentRle(surface, shape->strokeRle, COLOR_ARGB_JOIN(r, g, b, a));
|
||||
auto color = (surface.cs == SwCanvas::RGBA8888) ? RGBA_JOIN(r, g, b, a) : ARGB_JOIN(r, g, b, a);
|
||||
|
||||
if (a == 255) return _rasterSolidRle(surface, shape->strokeRle, color);
|
||||
return _rasterTranslucentRle(surface, shape->strokeRle, color);
|
||||
}
|
||||
|
||||
|
||||
|
@ -323,10 +365,10 @@ bool rasterClear(Surface& surface)
|
|||
if (!surface.buffer || surface.stride <= 0 || surface.w <= 0 || surface.h <= 0) return false;
|
||||
|
||||
if (surface.w == surface.stride) {
|
||||
rasterARGB32(surface.buffer, 0x00000000, 0, surface.w * surface.h);
|
||||
rasterRGBA32(surface.buffer, 0x00000000, 0, surface.w * surface.h);
|
||||
} else {
|
||||
for (uint32_t i = 0; i < surface.h; i++) {
|
||||
rasterARGB32(surface.buffer + surface.stride * i, 0x00000000, 0, surface.w);
|
||||
rasterRGBA32(surface.buffer + surface.stride * i, 0x00000000, 0, surface.w);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -40,7 +40,7 @@ SwRenderer::~SwRenderer()
|
|||
}
|
||||
|
||||
|
||||
bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h)
|
||||
bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs)
|
||||
{
|
||||
if (!buffer || stride == 0 || w == 0 || h == 0) return false;
|
||||
|
||||
|
@ -48,6 +48,7 @@ bool SwRenderer::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
|||
surface.stride = stride;
|
||||
surface.w = w;
|
||||
surface.h = h;
|
||||
surface.cs = cs;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -129,7 +130,7 @@ void* SwRenderer::prepare(const Shape& sdata, void* data, const RenderTransform*
|
|||
if (fill) {
|
||||
auto ctable = (flags & RenderUpdateFlag::Gradient) ? true : false;
|
||||
if (ctable) shapeResetFill(shape);
|
||||
if (!shapeGenFillColors(shape, fill, matrix, ctable)) return shape;
|
||||
if (!shapeGenFillColors(shape, fill, matrix, surface.cs, ctable)) return shape;
|
||||
} else {
|
||||
shapeDelFill(shape);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
bool dispose(const Shape& shape, void *data) override;
|
||||
bool preRender() override;
|
||||
bool render(const Shape& shape, void *data) override;
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h);
|
||||
bool target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, uint32_t cs);
|
||||
uint32_t ref() override;
|
||||
uint32_t unref() override;
|
||||
|
||||
|
|
|
@ -672,9 +672,9 @@ bool shapeGenStrokeRle(SwShape* shape, const Shape* sdata, const Matrix* transfo
|
|||
}
|
||||
|
||||
|
||||
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, bool ctable)
|
||||
bool shapeGenFillColors(SwShape* shape, const Fill* fill, const Matrix* transform, uint32_t cs, bool ctable)
|
||||
{
|
||||
return fillGenColorTable(shape->fill, fill, transform, ctable);
|
||||
return fillGenColorTable(shape->fill, fill, transform, cs, ctable);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t
|
|||
auto renderer = static_cast<GlRenderer*>(Canvas::pImpl.get()->renderer);
|
||||
if (!renderer) return Result::MemoryCorruption;
|
||||
|
||||
if (!renderer->target(buffer, stride, w, h)) return Result::Unknown;
|
||||
if (!renderer->target(buffer, stride, w, h, 0)) return Result::Unknown;
|
||||
|
||||
return Result::Success;
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,7 @@ struct Surface
|
|||
uint32_t* buffer;
|
||||
uint32_t stride;
|
||||
uint32_t w, h;
|
||||
uint32_t cs;
|
||||
};
|
||||
|
||||
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, All = 32};
|
||||
|
|
|
@ -62,14 +62,14 @@ SwCanvas::~SwCanvas()
|
|||
}
|
||||
|
||||
|
||||
Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h) noexcept
|
||||
Result SwCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t h, Colorspace cs) noexcept
|
||||
{
|
||||
#ifdef THORVG_SW_RASTER_SUPPORT
|
||||
//We know renderer type, avoid dynamic_cast for performance.
|
||||
auto renderer = static_cast<SwRenderer*>(Canvas::pImpl.get()->renderer);
|
||||
if (!renderer) return Result::MemoryCorruption;
|
||||
|
||||
if (!renderer->target(buffer, stride, w, h)) return Result::InvalidArguments;
|
||||
if (!renderer->target(buffer, stride, w, h, cs)) return Result::InvalidArguments;
|
||||
|
||||
return Result::Success;
|
||||
#endif
|
||||
|
|
|
@ -79,7 +79,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -68,7 +68,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
}
|
||||
|
||||
Eina_Bool animSwCb(void* data)
|
||||
|
|
|
@ -62,7 +62,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -51,7 +51,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -16,7 +16,7 @@ void testCapi()
|
|||
tvg_engine_init(TVG_ENGINE_SW | TVG_ENGINE_GL);
|
||||
|
||||
Tvg_Canvas* canvas = tvg_swcanvas_create();
|
||||
tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT);
|
||||
tvg_swcanvas_set_target(canvas, buffer, WIDTH, WIDTH, HEIGHT, TVG_COLORSPACE_ARGB8888);
|
||||
|
||||
Tvg_Paint* shape = tvg_shape_new();
|
||||
tvg_shape_append_rect(shape, 0, 0, 200, 200, 0, 0);
|
||||
|
|
|
@ -92,7 +92,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -55,7 +55,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -120,7 +120,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -80,7 +80,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -40,7 +40,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -57,7 +57,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -94,7 +94,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -80,7 +80,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -87,7 +87,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -116,7 +116,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -30,7 +30,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -77,7 +77,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -114,7 +114,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -72,7 +72,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -55,7 +55,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -83,7 +83,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
|
@ -44,7 +44,7 @@ void tvgSwTest(uint32_t* buffer)
|
|||
{
|
||||
//Create a Canvas
|
||||
swCanvas = tvg::SwCanvas::gen();
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT);
|
||||
swCanvas->target(buffer, WIDTH, WIDTH, HEIGHT, tvg::SwCanvas::ARGB8888);
|
||||
|
||||
/* Push the shape into the Canvas drawing list
|
||||
When this shape is into the canvas list, the shape could update & prepare
|
||||
|
|
Loading…
Add table
Reference in a new issue