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:
Hermet Park 2020-08-15 16:29:46 +09:00
parent 7ab71c52d0
commit f4d1065d52
34 changed files with 157 additions and 97 deletions

View file

@ -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;

View file

@ -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);
/************************************************************************/

View file

@ -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));
}

View file

@ -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;

View file

@ -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) {

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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};

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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