diff --git a/inc/thorvg.h b/inc/thorvg.h index 3f43a2fc..9ed54988 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -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 gen() noexcept; diff --git a/inc/thorvg_capi.h b/inc/thorvg_capi.h index 763d71b2..2f1bf967 100644 --- a/inc/thorvg_capi.h +++ b/inc/thorvg_capi.h @@ -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); /************************************************************************/ diff --git a/src/bindings/capi/tvgCapi.cpp b/src/bindings/capi/tvgCapi.cpp index e05435a5..ac8cdcb1 100644 --- a/src/bindings/capi/tvgCapi.cpp +++ b/src/bindings/capi/tvgCapi.cpp @@ -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(canvas)->target(buffer, stride, w, h); + return (Tvg_Result) reinterpret_cast(canvas)->target(buffer, stride, w, h, static_cast(cs)); } diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 295f11a5..e5d4719f 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -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; diff --git a/src/lib/sw_engine/tvgSwFill.cpp b/src/lib/sw_engine/tvgSwFill.cpp index ae938fd3..cd68d0f1 100644 --- a/src/lib/sw_engine/tvgSwFill.cpp +++ b/src/lib/sw_engine/tvgSwFill.cpp @@ -34,7 +34,7 @@ #define FIXPT_SIZE (1<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(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(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(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) { diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 46ef4ac0..d07d7eb1 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -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(region.max.y - region.min.y); auto w = static_cast(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(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; diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index eb2f199e..66608f54 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -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); } diff --git a/src/lib/sw_engine/tvgSwRenderer.h b/src/lib/sw_engine/tvgSwRenderer.h index 9a419028..5657602b 100644 --- a/src/lib/sw_engine/tvgSwRenderer.h +++ b/src/lib/sw_engine/tvgSwRenderer.h @@ -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; diff --git a/src/lib/sw_engine/tvgSwShape.cpp b/src/lib/sw_engine/tvgSwShape.cpp index f9537d1b..3704a2cb 100644 --- a/src/lib/sw_engine/tvgSwShape.cpp +++ b/src/lib/sw_engine/tvgSwShape.cpp @@ -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); } diff --git a/src/lib/tvgGlCanvas.cpp b/src/lib/tvgGlCanvas.cpp index 7f2c04b7..1ac57329 100644 --- a/src/lib/tvgGlCanvas.cpp +++ b/src/lib/tvgGlCanvas.cpp @@ -70,7 +70,7 @@ Result GlCanvas::target(uint32_t* buffer, uint32_t stride, uint32_t w, uint32_t auto renderer = static_cast(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 diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 60c76d50..3535bf43 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -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}; diff --git a/src/lib/tvgSwCanvas.cpp b/src/lib/tvgSwCanvas.cpp index e958ea26..755d422d 100644 --- a/src/lib/tvgSwCanvas.cpp +++ b/src/lib/tvgSwCanvas.cpp @@ -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(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 diff --git a/test/testArc.cpp b/test/testArc.cpp index b02196ef..1f158122 100644 --- a/test/testArc.cpp +++ b/test/testArc.cpp @@ -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 diff --git a/test/testAsync.cpp b/test/testAsync.cpp index edc6dde7..608cefb2 100644 --- a/test/testAsync.cpp +++ b/test/testAsync.cpp @@ -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) diff --git a/test/testBlending.cpp b/test/testBlending.cpp index 59a4fad7..743b1e09 100644 --- a/test/testBlending.cpp +++ b/test/testBlending.cpp @@ -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 diff --git a/test/testBoundary.cpp b/test/testBoundary.cpp index 57a3d6c6..38306877 100644 --- a/test/testBoundary.cpp +++ b/test/testBoundary.cpp @@ -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 diff --git a/test/testCapi.c b/test/testCapi.c index 90c4e1d7..c6df3968 100644 --- a/test/testCapi.c +++ b/test/testCapi.c @@ -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); diff --git a/test/testCustomTransform.cpp b/test/testCustomTransform.cpp index 4803ef16..9daa6fc1 100644 --- a/test/testCustomTransform.cpp +++ b/test/testCustomTransform.cpp @@ -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 diff --git a/test/testDirectUpdate.cpp b/test/testDirectUpdate.cpp index 3c275b62..8dcc474a 100644 --- a/test/testDirectUpdate.cpp +++ b/test/testDirectUpdate.cpp @@ -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 diff --git a/test/testGradientTransform.cpp b/test/testGradientTransform.cpp index 4fa426be..77d5f6af 100644 --- a/test/testGradientTransform.cpp +++ b/test/testGradientTransform.cpp @@ -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 diff --git a/test/testLinearGradient.cpp b/test/testLinearGradient.cpp index f98fc970..db11682a 100644 --- a/test/testLinearGradient.cpp +++ b/test/testLinearGradient.cpp @@ -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 diff --git a/test/testMultiShapes.cpp b/test/testMultiShapes.cpp index 5a6d34f9..12009bc2 100644 --- a/test/testMultiShapes.cpp +++ b/test/testMultiShapes.cpp @@ -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 diff --git a/test/testPath.cpp b/test/testPath.cpp index 52c56efb..de6ef60e 100644 --- a/test/testPath.cpp +++ b/test/testPath.cpp @@ -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 diff --git a/test/testPathCopy.cpp b/test/testPathCopy.cpp index 0ae364b7..fb1080b3 100644 --- a/test/testPathCopy.cpp +++ b/test/testPathCopy.cpp @@ -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 diff --git a/test/testRadialGradient.cpp b/test/testRadialGradient.cpp index a6c10ba1..6e772915 100644 --- a/test/testRadialGradient.cpp +++ b/test/testRadialGradient.cpp @@ -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 diff --git a/test/testScene.cpp b/test/testScene.cpp index 5b12020e..daa5d868 100644 --- a/test/testScene.cpp +++ b/test/testScene.cpp @@ -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 diff --git a/test/testSceneTransform.cpp b/test/testSceneTransform.cpp index 49558fb7..e64fa9aa 100644 --- a/test/testSceneTransform.cpp +++ b/test/testSceneTransform.cpp @@ -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 diff --git a/test/testShape.cpp b/test/testShape.cpp index 88519d05..af4d0c47 100644 --- a/test/testShape.cpp +++ b/test/testShape.cpp @@ -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 diff --git a/test/testStroke.cpp b/test/testStroke.cpp index 91748727..778d7c7b 100644 --- a/test/testStroke.cpp +++ b/test/testStroke.cpp @@ -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 diff --git a/test/testStrokeLine.cpp b/test/testStrokeLine.cpp index 445f8406..1205bb14 100644 --- a/test/testStrokeLine.cpp +++ b/test/testStrokeLine.cpp @@ -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 diff --git a/test/testSvg.cpp b/test/testSvg.cpp index e16f19b1..06fe3501 100644 --- a/test/testSvg.cpp +++ b/test/testSvg.cpp @@ -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 diff --git a/test/testSvg2.cpp b/test/testSvg2.cpp index 171db919..2300f217 100644 --- a/test/testSvg2.cpp +++ b/test/testSvg2.cpp @@ -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 diff --git a/test/testTransform.cpp b/test/testTransform.cpp index 7529d140..5ef33f44 100644 --- a/test/testTransform.cpp +++ b/test/testTransform.cpp @@ -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 diff --git a/test/testUpdate.cpp b/test/testUpdate.cpp index 9c213436..3ff6c246 100644 --- a/test/testUpdate.cpp +++ b/test/testUpdate.cpp @@ -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