diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index 38718b10..0e9029bf 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -241,7 +241,7 @@ struct SwImage struct SwBlender { uint32_t (*join)(uint8_t r, uint8_t g, uint8_t b, uint8_t a); - uint32_t (*lumaValue)(uint32_t c); + uint8_t (*luma)(uint8_t* c); }; struct SwCompositor; diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 0d4e23b9..2e29c175 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -37,8 +37,8 @@ /************************************************************************/ constexpr auto DOWN_SCALE_TOLERANCE = 0.5f; - -static inline uint32_t _multiplyAlpha(uint32_t c, uint32_t a) +template +static inline T _multiply(T c, T a) { return ((c * a + 0xff) >> 8); } @@ -56,15 +56,29 @@ static inline uint32_t _ialpha(uint32_t c) } -static inline uint32_t _abgrLumaValue(uint32_t c) +static inline uint8_t _alpha(uint8_t* a) { - return ((((c&0xff)*54) + (((c>>8)&0xff)*183) + (((c>>16)&0xff)*19))) >> 8; //0.2125*R + 0.7154*G + 0.0721*B + return *a; } -static inline uint32_t _argbLumaValue(uint32_t c) +static inline uint8_t _ialpha(uint8_t* a) { - return ((((c&0xff)*19) + (((c>>8)&0xff)*183) + (((c>>16)&0xff)*54))) >> 8; //0.0721*B + 0.7154*G + 0.2125*R + return ~(*a); +} + + +static inline uint8_t _abgrLuma(uint8_t* c) +{ + auto v = *(uint32_t*)c; + return ((((v&0xff)*54) + (((v>>8)&0xff)*183) + (((v>>16)&0xff)*19))) >> 8; //0.2125*R + 0.7154*G + 0.0721*B +} + + +static inline uint8_t _argbLuma(uint8_t* c) +{ + auto v = *(uint32_t*)c; + return ((((v&0xff)*19) + (((v>>8)&0xff)*183) + (((v>>16)&0xff)*54))) >> 8; //0.0721*B + 0.7154*G + 0.2125*R } @@ -148,65 +162,95 @@ static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t } +void _rasterGrayscale8(uint8_t *dst, uint32_t val, uint32_t offset, int32_t len) +{ + cRasterPixels(dst, val, offset, len); +} + /************************************************************************/ /* Rect */ /************************************************************************/ -static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint32_t color, uint32_t (*blender)(uint32_t)) +static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t(*blender)(uint8_t*)) { - auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; auto w = static_cast(region.max.x - region.min.x); auto h = static_cast(region.max.y - region.min.y); + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8 + ((region.min.y * surface->compositor->image.stride + region.min.x) * csize); //compositor buffer TVGLOG("SW_ENGINE", "Masked Rect [Region: %lu %lu %u %u]", region.min.x, region.min.y, w, h); - - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer - - for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface->stride]; - auto cmp = &cbuffer[y * surface->stride]; - for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp) { - auto tmp = ALPHA_BLEND(color, blender(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); + + //32bits channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->blender.join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + auto cmp = &cbuffer[y * surface->stride * csize]; + for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) { + auto tmp = ALPHA_BLEND(color, blender(cmp)); + *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); + } + } + //8bits grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + auto cmp = &cbuffer[y * surface->stride * csize]; + for (uint32_t x = 0; x < w; ++x, ++dst, cmp += csize) { + auto tmp = _multiply(a, blender(cmp)); + *dst = tmp + _multiply(*dst, _ialpha(tmp)); + } } } return true; } -static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint32_t color) +static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b) { - auto buffer = surface->buf32 + (region.min.y * surface->stride); auto w = static_cast(region.max.x - region.min.x); auto h = static_cast(region.max.y - region.min.y); - for (uint32_t y = 0; y < h; ++y) { - rasterRGBA32(buffer + y * surface->stride, color, region.min.x, w); + //32bits channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->blender.join(r, g, b, 255); + auto buffer = surface->buf32 + (region.min.y * surface->stride); + for (uint32_t y = 0; y < h; ++y) { + rasterRGBA32(buffer + y * surface->stride, color, region.min.x, w); + } + //8bits grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + auto buffer = surface->buf8 + (region.min.y * surface->stride); + for (uint32_t y = 0; y < h; ++y) { + _rasterGrayscale8(buffer + y * surface->stride, 255, region.min.x, w); + } } return true; } -static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint32_t color, uint8_t opacity) +static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { if (_compositing(surface)) { if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterMaskedRect(surface, region, color, _alpha); + return _rasterMaskedRect(surface, region, r, g, b, a, _alpha); } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterMaskedRect(surface, region, color, _ialpha); + return _rasterMaskedRect(surface, region, r, g, b, a, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterMaskedRect(surface, region, color, surface->blender.lumaValue); + return _rasterMaskedRect(surface, region, r, g, b, a, surface->blender.luma); } } else { - if (opacity == 255) { - return _rasterSolidRect(surface, region, color); + if (a == 255) { + return _rasterSolidRect(surface, region, r, g, b); } else { #if defined(THORVG_AVX_VECTOR_SUPPORT) - return avxRasterTranslucentRect(surface, region, color); + return avxRasterTranslucentRect(surface, region, r, g, b, a); #elif defined(THORVG_NEON_VECTOR_SUPPORT) - return neonRasterTranslucentRect(surface, region, color); + return neonRasterTranslucentRect(surface, region, r, g, b, a); #else - return cRasterTranslucentRect(surface, region, color); + return cRasterTranslucentRect(surface, region, r, g, b, a); #endif } } @@ -218,41 +262,38 @@ static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint32_t color /* Rle */ /************************************************************************/ -static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint32_t (*blender)(uint32_t)) +static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a, uint8_t(*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Masked Rle"); auto span = rle->spans; uint32_t src; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; + auto csize = surface->compositor->image.channelSize; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; - if (span->coverage == 255) src = color; - else src = ALPHA_BLEND(color, span->coverage); - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto tmp = ALPHA_BLEND(src, blender(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } - return true; -} - - -static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint32_t color) -{ - auto span = rle->spans; - - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - if (span->coverage == 255) { - rasterRGBA32(surface->buf32 + span->y * surface->stride, color, span->x, span->len); - } else { + //32bit channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->blender.join(r, g, b, a); + for (uint32_t i = 0; i < rle->size; ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto src = ALPHA_BLEND(color, span->coverage); - auto ialpha = 255 - span->coverage; - for (uint32_t x = 0; x < span->len; ++x, ++dst) { - *dst = src + ALPHA_BLEND(*dst, ialpha); + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; + if (span->coverage == 255) src = color; + else src = ALPHA_BLEND(color, span->coverage); + for (uint32_t x = 0; x < span->len; ++x, ++dst, cmp += csize) { + auto tmp = ALPHA_BLEND(src, blender(cmp)); + *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); + } + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; + if (span->coverage == 255) src = a; + else src = _multiply(a, span->coverage); + for (uint32_t x = 0; x < span->len; ++x, ++dst, cmp += csize) { + auto tmp = _multiply(src, blender(cmp)); + *dst = tmp + _multiply(*dst, _ialpha(tmp)); } } } @@ -260,28 +301,64 @@ static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint32_t c } -static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint8_t opacity) +static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b) +{ + auto span = rle->spans; + + //32bit channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->blender.join(r, g, b, 255); + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + if (span->coverage == 255) { + rasterRGBA32(surface->buf32 + span->y * surface->stride, color, span->x, span->len); + } else { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + auto src = ALPHA_BLEND(color, span->coverage); + auto ialpha = 255 - span->coverage; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = src + ALPHA_BLEND(*dst, ialpha); + } + } + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + if (span->coverage == 255) { + _rasterGrayscale8(surface->buf8 + span->y * surface->stride, 255, span->x, span->len); + } else { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = span->coverage; + } + } + } + } + return true; +} + + +static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { if (!rle) return false; if (_compositing(surface)) { if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterMaskedRle(surface, rle, color, _alpha); + return _rasterMaskedRle(surface, rle, r, g, b, a, _alpha); } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterMaskedRle(surface, rle, color, _ialpha); + return _rasterMaskedRle(surface, rle, r, g, b, a, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterMaskedRle(surface, rle, color, surface->blender.lumaValue); + return _rasterMaskedRle(surface, rle, r, g, b, a, surface->blender.luma); } } else { - if (opacity == 255) { - return _rasterSolidRle(surface, rle, color); + if (a == 255) { + return _rasterSolidRle(surface, rle, r, g, b); } else { #if defined(THORVG_AVX_VECTOR_SUPPORT) - return avxRasterTranslucentRle(surface, rle, color); + return avxRasterTranslucentRle(surface, rle, r, g, b, a); #elif defined(THORVG_NEON_VECTOR_SUPPORT) - return neonRasterTranslucentRle(surface, rle, color); + return neonRasterTranslucentRle(surface, rle, r, g, b, a); #else - return cRasterTranslucentRle(surface, rle, color); + return cRasterTranslucentRle(surface, rle, r, g, b, a); #endif } } @@ -301,7 +378,7 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, surface->blender.lumaValue); + return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, surface->blender.luma); } } else { return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr); @@ -313,11 +390,12 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c /* RLE Scaled RGBA Image */ /************************************************************************/ -static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint32_t (*blender)(uint32_t)) +static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint8_t(*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Scaled Masked Translucent Rle Image"); auto span = image->rle->spans; + auto csize = surface->compositor->image.channelSize; //Center (Down-Scaled) if (image->scale < DOWN_SCALE_TOLERANCE) { @@ -325,13 +403,13 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23); if (sy >= image->h) continue; auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &surface->compositor->image.buf32[span->y * surface->compositor->image.stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { + auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize]; + auto alpha = _multiply(span->coverage, opacity); + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, cmp += csize) { auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), alpha); - auto tmp = ALPHA_BLEND(src, blender(*cmp)); + auto tmp = ALPHA_BLEND(src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -341,13 +419,13 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const auto sy = span->y * itransform->e22 + itransform->e23; if ((uint32_t)sy >= image->h) continue; auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &surface->compositor->image.buf32[span->y * surface->compositor->image.stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { + auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize]; + auto alpha = _multiply(span->coverage, opacity); + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, cmp += csize) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), alpha); - auto tmp = ALPHA_BLEND(src, blender(*cmp)); + auto tmp = ALPHA_BLEND(src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -356,11 +434,12 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const } -static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint32_t(*blender)(uint32_t)) +static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint8_t(*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Scaled Masked Rle Image"); auto span = image->rle->spans; + auto csize = surface->compositor->image.channelSize; //Center (Down-Scaled) if (image->scale < DOWN_SCALE_TOLERANCE) { @@ -368,20 +447,20 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23); if (sy >= image->h) continue; auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &surface->compositor->image.buf32[span->y * surface->compositor->image.stride + span->x]; + auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize]; if (span->coverage == 255) { - for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, cmp += csize) { auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto tmp = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), blender(*cmp)); + auto tmp = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } else { - for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, cmp += csize) { auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage); - auto tmp = ALPHA_BLEND(src, blender(*cmp)); + auto tmp = ALPHA_BLEND(src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -392,20 +471,20 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i auto sy = span->y * itransform->e22 + itransform->e23; if ((uint32_t)sy >= image->h) continue; auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &surface->compositor->image.buf32[span->y * surface->compositor->image.stride + span->x]; + auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize]; if (span->coverage == 255) { - for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, cmp += csize) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto tmp = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), blender(*cmp)); + auto tmp = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } else { - for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, ++cmp) { + for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, cmp += csize) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), span->coverage); - auto tmp = ALPHA_BLEND(src, blender(*cmp)); + auto tmp = ALPHA_BLEND(src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -425,7 +504,7 @@ static bool _rasterScaledTranslucentRleRGBAImage(SwSurface* surface, const SwIma auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23); if (sy >= image->h) continue; auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); + auto alpha = _multiply(span->coverage, opacity); for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; @@ -439,7 +518,7 @@ static bool _rasterScaledTranslucentRleRGBAImage(SwSurface* surface, const SwIma auto sy = span->y * itransform->e22 + itransform->e23; if ((uint32_t)sy >= image->h) continue; auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); + auto alpha = _multiply(span->coverage, opacity); for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; @@ -522,7 +601,7 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.lumaValue); + return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.luma); } } else { if (surface->compositor->method == CompositeMethod::AlphaMask) { @@ -530,7 +609,7 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.lumaValue); + return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.luma); } } } else { @@ -545,26 +624,27 @@ static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const /* RLE Direct RGBA Image */ /************************************************************************/ -static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, uint32_t(*blender)(uint32_t)) +static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t opacity, uint8_t(*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Direct Masked Rle Image"); auto span = image->rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); - auto alpha = _multiplyAlpha(span->coverage, opacity); + auto alpha = _multiply(span->coverage, opacity); if (alpha == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) { - auto tmp = ALPHA_BLEND(*img, blender(*cmp)); + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) { + auto tmp = ALPHA_BLEND(*img, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } else { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) { - auto tmp = ALPHA_BLEND(*img, _multiplyAlpha(alpha, blender(*cmp))); + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) { + auto tmp = ALPHA_BLEND(*img, _multiply(alpha, blender(cmp))); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -573,25 +653,26 @@ static bool _rasterDirectMaskedTranslucentRleRGBAImage(SwSurface* surface, const } -static bool _rasterDirectMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, uint32_t(*blender)(uint32_t)) +static bool _rasterDirectMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, uint8_t(*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Direct Masked Rle Image"); auto span = image->rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); if (span->coverage == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) { - auto tmp = ALPHA_BLEND(*img, blender(*cmp)); + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) { + auto tmp = ALPHA_BLEND(*img, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } else { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++img) { - auto tmp = ALPHA_BLEND(*img, _multiplyAlpha(span->coverage, blender(*cmp))); + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) { + auto tmp = ALPHA_BLEND(*img, _multiply(span->coverage, blender(cmp))); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -607,7 +688,7 @@ static bool _rasterDirectTranslucentRleRGBAImage(SwSurface* surface, const SwIma for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); - auto alpha = _multiplyAlpha(span->coverage, opacity); + auto alpha = _multiply(span->coverage, opacity); for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { auto src = ALPHA_BLEND(*img, alpha); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); @@ -648,7 +729,7 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32 } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterDirectMaskedRleRGBAImage(surface, image, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.lumaValue); + return _rasterDirectMaskedRleRGBAImage(surface, image, surface->blender.luma); } } else { if (surface->compositor->method == CompositeMethod::AlphaMask) { @@ -656,7 +737,7 @@ static bool _directRleRGBAImage(SwSurface* surface, const SwImage* image, uint32 } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.lumaValue); + return _rasterDirectMaskedTranslucentRleRGBAImage(surface, image, opacity, surface->blender.luma); } } } else { @@ -679,7 +760,7 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, surface->blender.lumaValue); + return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, surface->blender.luma); } } else { return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, nullptr); @@ -695,7 +776,7 @@ static bool _transformedRGBAImageMesh(SwSurface* surface, const SwImage* image, } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, surface->blender.lumaValue); + return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, surface->blender.luma); } } else { return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity, nullptr); @@ -708,12 +789,13 @@ static bool _transformedRGBAImageMesh(SwSurface* surface, const SwImage* image, /*Scaled RGBA Image */ /************************************************************************/ -static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint32_t (*blender)(uint32_t)) +static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint8_t(*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Scaled Masked Image"); auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride + region.min.x); + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; // Down-Scaled if (image->scale < DOWN_SCALE_TOLERANCE) { @@ -722,15 +804,15 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw if (sy >= image->h) continue; auto dst = dbuffer; auto cmp = cbuffer; - for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto alpha = _multiplyAlpha(opacity, blender(*cmp)); + auto alpha = _multiply(opacity, blender(cmp)); auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), alpha); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } dbuffer += surface->stride; - cbuffer += surface->compositor->image.stride; + cbuffer += surface->compositor->image.stride * csize; } // Up-Scaled } else { @@ -739,27 +821,28 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw if ((uint32_t)sy >= image->h) continue; auto dst = dbuffer; auto cmp = cbuffer; - for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto alpha = _multiplyAlpha(opacity, blender(*cmp)); + auto alpha = _multiply(opacity, blender(cmp)); auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), alpha); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } dbuffer += surface->stride; - cbuffer += surface->compositor->image.stride; + cbuffer += surface->compositor->image.stride * csize; } } return true; } -static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint32_t (*blender)(uint32_t)) +static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint8_t (*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Scaled Masked Image"); auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride + region.min.x); + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; // Down-Scaled if (image->scale < DOWN_SCALE_TOLERANCE) { @@ -768,14 +851,14 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag if (sy >= image->h) continue; auto dst = dbuffer; auto cmp = cbuffer; - for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { auto sx = (uint32_t)(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), blender(*cmp)); + auto src = ALPHA_BLEND(_interpDownScaler(image->buf32, image->stride, image->w, image->h, sx, sy, halfScale), blender(cmp)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } dbuffer += surface->stride; - cbuffer += surface->compositor->image.stride; + cbuffer += surface->compositor->image.stride * csize; } // Up-Scaled } else { @@ -784,14 +867,14 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag if ((uint32_t)sy >= image->h) continue; auto dst = dbuffer; auto cmp = cbuffer; - for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { + for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), blender(*cmp)); + auto src = ALPHA_BLEND(_interpUpScaler(image->buf32, image->w, image->h, sx, sy), blender(cmp)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); } dbuffer += surface->stride; - cbuffer += surface->compositor->image.stride; + cbuffer += surface->compositor->image.stride * csize; } } return true; @@ -885,7 +968,7 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.lumaValue); + return _rasterScaledMaskedRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.luma); } } else { if (surface->compositor->method == CompositeMethod::AlphaMask) { @@ -893,7 +976,7 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.lumaValue); + return _rasterScaledMaskedTranslucentRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.luma); } } } else { @@ -908,54 +991,56 @@ static bool _scaledRGBAImage(SwSurface* surface, const SwImage* image, const Mat /* Direct RGBA Image */ /************************************************************************/ -static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t (*blender)(uint32_t)) +static bool _rasterDirectMaskedRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t (*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Direct Masked Image"); auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; auto h2 = static_cast(region.max.y - region.min.y); auto w2 = static_cast(region.max.x - region.min.x); + auto csize = surface->compositor->image.channelSize; auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer for (uint32_t y = 0; y < h2; ++y) { auto dst = buffer; auto cmp = cbuffer; auto src = sbuffer; - for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) { - auto tmp = ALPHA_BLEND(*src, blender(*cmp)); + for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } buffer += surface->stride; - cbuffer += surface->compositor->image.stride; + cbuffer += surface->compositor->image.stride * csize; sbuffer += image->stride; } return true; } -static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity, uint32_t (*blender)(uint32_t)) +static bool _rasterDirectMaskedTranslucentRGBAImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity, uint8_t (*blender)(uint8_t*)) { TVGLOG("SW_ENGINE", "Direct Masked Translucent Image"); auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; auto h2 = static_cast(region.max.y - region.min.y); auto w2 = static_cast(region.max.x - region.min.x); + auto csize = surface->compositor->image.channelSize; auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride) + region.min.x; //compositor buffer + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer for (uint32_t y = 0; y < h2; ++y) { auto dst = buffer; auto cmp = cbuffer; auto src = sbuffer; - for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, ++cmp) { - auto tmp = ALPHA_BLEND(*src, _multiplyAlpha(opacity, blender(*cmp))); + for (uint32_t x = 0; x < w2; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, _multiply(opacity, blender(cmp))); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } buffer += surface->stride; - cbuffer += surface->compositor->image.stride; + cbuffer += surface->compositor->image.stride * csize; sbuffer += image->stride; } return true; @@ -1009,7 +1094,7 @@ static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwB } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterDirectMaskedRGBAImage(surface, image, region, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.lumaValue); + return _rasterDirectMaskedRGBAImage(surface, image, region, surface->blender.luma); } } else { if (surface->compositor->method == CompositeMethod::AlphaMask) { @@ -1017,7 +1102,7 @@ static bool _directRGBAImage(SwSurface* surface, const SwImage* image, const SwB } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.lumaValue); + return _rasterDirectMaskedTranslucentRGBAImage(surface, image, region, opacity, surface->blender.luma); } } } else { @@ -1049,14 +1134,15 @@ static bool _rasterRGBAImage(SwSurface* surface, SwImage* image, const Matrix* t /* Rect Linear Gradient */ /************************************************************************/ -static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint32_t (*blender)(uint32_t)) +static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint8_t (*blender)(uint8_t*)) { if (fill->linear.len < FLT_EPSILON) return false; auto buffer = surface->buf32 + (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 cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride) + region.min.x; + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; auto sbuffer = static_cast(alloca(w * sizeof(uint32_t))); if (!sbuffer) return false; @@ -1066,12 +1152,12 @@ static bool _rasterLinearGradientMaskedRect(SwSurface* surface, const SwBBox& re auto dst = buffer; auto cmp = cbuffer; auto src = sbuffer; - for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, blender(*cmp)); + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } buffer += surface->stride; - cbuffer += surface->stride; + cbuffer += surface->stride * csize; } return true; } @@ -1123,7 +1209,7 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterLinearGradientMaskedRect(surface, region, fill, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.lumaValue); + return _rasterLinearGradientMaskedRect(surface, region, fill, surface->blender.luma); } } else { if (fill->translucent) return _rasterTranslucentLinearGradientRect(surface, region, fill); @@ -1137,29 +1223,30 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, /* Rle Linear Gradient */ /************************************************************************/ -static bool _rasterLinearGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint32_t (*blender)(uint32_t)) +static bool _rasterLinearGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint8_t (*blender)(uint8_t*)) { if (fill->linear.len < FLT_EPSILON) return false; auto span = rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8; auto buffer = static_cast(alloca(surface->w * sizeof(uint32_t))); if (!buffer) return false; for (uint32_t i = 0; i < rle->size; ++i, ++span) { fillFetchLinear(fill, buffer, span->y, span->x, span->len); auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; auto src = buffer; if (span->coverage == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, blender(*cmp)); + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } else { auto ialpha = 255 - span->coverage; - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, blender(*cmp)); + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, blender(cmp)); tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } @@ -1229,7 +1316,7 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterLinearGradientMaskedRle(surface, rle, fill, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.lumaValue); + return _rasterLinearGradientMaskedRle(surface, rle, fill, surface->blender.luma); } } else { if (fill->translucent) return _rasterTranslucentLinearGradientRle(surface, rle, fill); @@ -1243,14 +1330,15 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c /* Rect Radial Gradient */ /************************************************************************/ -static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint32_t (*blender)(uint32_t)) +static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, uint8_t(*blender)(uint8_t*)) { if (fill->radial.a < FLT_EPSILON) return false; auto buffer = surface->buf32 + (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 cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride) + region.min.x; + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; auto sbuffer = static_cast(alloca(w * sizeof(uint32_t))); if (!sbuffer) return false; @@ -1260,12 +1348,12 @@ static bool _rasterRadialGradientMaskedRect(SwSurface* surface, const SwBBox& re auto dst = buffer; auto cmp = cbuffer; auto src = sbuffer; - for (uint32_t x = 0; x < w; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, blender(*cmp)); + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } buffer += surface->stride; - cbuffer += surface->stride; + cbuffer += surface->stride * csize; } return true; } @@ -1318,7 +1406,7 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterRadialGradientMaskedRect(surface, region, fill, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.lumaValue); + return _rasterRadialGradientMaskedRect(surface, region, fill, surface->blender.luma); } } else { if (fill->translucent) return _rasterTranslucentRadialGradientRect(surface, region, fill); @@ -1332,28 +1420,29 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, /* RLE Radial Gradient */ /************************************************************************/ -static bool _rasterRadialGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint32_t (*blender)(uint32_t)) +static bool _rasterRadialGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, uint8_t(*blender)(uint8_t*)) { if (fill->radial.a < FLT_EPSILON) return false; auto span = rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto csize = surface->compositor->image.channelSize; + auto cbuffer = surface->compositor->image.buf8; auto buffer = static_cast(alloca(surface->w * sizeof(uint32_t))); if (!buffer) return false; for (uint32_t i = 0; i < rle->size; ++i, ++span) { fillFetchRadial(fill, buffer, span->y, span->x, span->len); auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; + auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; auto src = buffer; if (span->coverage == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, blender(*cmp)); + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, blender(cmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } else { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { - auto tmp = INTERPOLATE(span->coverage, ALPHA_BLEND(*src, blender(*cmp)), *dst); + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++src, cmp += csize) { + auto tmp = INTERPOLATE(span->coverage, ALPHA_BLEND(*src, blender(cmp)), *dst); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); } } @@ -1423,7 +1512,7 @@ static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, c } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { return _rasterRadialGradientMaskedRle(surface, rle, fill, _ialpha); } else if (surface->compositor->method == CompositeMethod::LumaMask) { - return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.lumaValue); + return _rasterRadialGradientMaskedRle(surface, rle, fill, surface->blender.luma); } } else { if (fill->translucent) _rasterTranslucentRadialGradientRle(surface, rle, fill); @@ -1432,7 +1521,6 @@ static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, c return false; } - /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -1444,7 +1532,7 @@ void rasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) #elif defined(THORVG_NEON_VECTOR_SUPPORT) neonRasterRGBA32(dst, val, offset, len); #else - cRasterRGBA32(dst, val, offset, len); + cRasterPixels(dst, val, offset, len); #endif } @@ -1453,12 +1541,12 @@ bool rasterCompositor(SwSurface* surface) { if (surface->cs == ColorSpace::ABGR8888 || surface->cs == ColorSpace::ABGR8888S) { surface->blender.join = _abgrJoin; - surface->blender.lumaValue = _abgrLumaValue; + surface->blender.luma = _abgrLuma; } else if (surface->cs == ColorSpace::ARGB8888 || surface->cs == ColorSpace::ARGB8888S) { surface->blender.join = _argbJoin; - surface->blender.lumaValue = _argbLumaValue; + surface->blender.luma = _argbLuma; } else { - //What Color Space ??? + TVGERR("SW_ENGINE", "Unsupported Colorspace(%d) is expected!", surface->cs); return false; } return true; @@ -1470,21 +1558,34 @@ bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_ if (!surface || !surface->buf32 || surface->stride == 0 || surface->w == 0 || surface->h == 0) return false; //full clear - if (surface->w == surface->stride) { - rasterRGBA32(surface->buf32 + (surface->stride * y + x), 0x00000000, x, w * h); - } else { - auto offset = surface->stride * y + x; - for (uint32_t i = 0; i < h; i++) { - rasterRGBA32(surface->buf32 + (offset * i), 0x00000000, x, w); + if (surface->channelSize == sizeof(uint32_t)) { + if (w == surface->stride) { + rasterRGBA32(surface->buf32 + (surface->stride * y), 0x00000000, 0, w * h); + } else { + auto buffer = surface->buf32 + (surface->stride * y + x); + for (uint32_t i = 0; i < h; i++) { + rasterRGBA32(buffer + (surface->stride * i), 0x00000000, 0, w); + } + } + //partial clear + } else if (surface->channelSize == sizeof(uint8_t)) { + if (w == surface->stride) { + _rasterGrayscale8(surface->buf8 + (surface->stride * y), 0x00, 0, w * h); + } else { + auto buffer = surface->buf8 + (surface->stride * y + x); + for (uint32_t i = 0; i < h; i++) { + _rasterGrayscale8(buffer + (surface->stride * i), 0x00, 0, w); + } } } - return true; } void rasterUnpremultiply(Surface* surface) { + if (surface->channelSize != sizeof(uint32_t)) return; + TVGLOG("SW_ENGINE", "Unpremultiply [Size: %d x %d]", surface->w, surface->h); //OPTIMIZE_ME: +SIMD @@ -1513,6 +1614,8 @@ void rasterUnpremultiply(Surface* surface) void rasterPremultiply(Surface* surface) { + if (surface->channelSize != sizeof(uint32_t)) return; + TVGLOG("SW_ENGINE", "Premultiply [Size: %d x %d]", surface->w, surface->h); //OPTIMIZE_ME: +SIMD @@ -1531,6 +1634,11 @@ void rasterPremultiply(Surface* surface) bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id) { + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale gradient!"); + return false; + } + if (!shape->fill) return false; if (shape->fastTrack) { @@ -1546,6 +1654,11 @@ bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id) bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id) { + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale gradient!"); + return false; + } + if (!shape->stroke || !shape->stroke->fill || !shape->strokeRle) return false; if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRle(surface, shape->strokeRle, shape->stroke->fill); @@ -1558,34 +1671,35 @@ bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id) bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { if (a < 255) { - r = _multiplyAlpha(r, a); - g = _multiplyAlpha(g, a); - b = _multiplyAlpha(b, a); + r = _multiply(r, a); + g = _multiply(g, a); + b = _multiply(b, a); } - auto color = surface->blender.join(r, g, b, a); - - if (shape->fastTrack) return _rasterRect(surface, shape->bbox, color, a); - else return _rasterRle(surface, shape->rle, color, a); + if (shape->fastTrack) return _rasterRect(surface, shape->bbox, r, g, b, a); + else return _rasterRle(surface, shape->rle, r, g, b, a); } bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { if (a < 255) { - r = _multiplyAlpha(r, a); - g = _multiplyAlpha(g, a); - b = _multiplyAlpha(b, a); + r = _multiply(r, a); + g = _multiply(g, a); + b = _multiply(b, a); } - auto color = surface->blender.join(r, g, b, a); - - return _rasterRle(surface, shape->strokeRle, color, a); + return _rasterRle(surface, shape->strokeRle, r, g, b, a); } bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint32_t opacity) { + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale image!"); + return false; + } + //Verify Boundary if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast(surface->w) || bbox.min.y >= static_cast(surface->h)) return false; diff --git a/src/lib/sw_engine/tvgSwRasterAvx.h b/src/lib/sw_engine/tvgSwRasterAvx.h index b5a2a3c7..b38a5605 100644 --- a/src/lib/sw_engine/tvgSwRasterAvx.h +++ b/src/lib/sw_engine/tvgSwRasterAvx.h @@ -82,8 +82,14 @@ static void avxRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_ } -static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color) +static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + if (surface->channelSize != sizeof(uint32_t)) { + TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize); + return false; + } + + auto color = surface->blender.join(r, g, b, a); 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); @@ -125,8 +131,14 @@ static bool avxRasterTranslucentRect(SwSurface* surface, const SwBBox& region, u } -static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color) +static bool avxRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + if (surface->channelSize != sizeof(uint32_t)) { + TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize); + return false; + } + + auto color = surface->blender.join(r, g, b, a); auto span = rle->spans; uint32_t src; diff --git a/src/lib/sw_engine/tvgSwRasterC.h b/src/lib/sw_engine/tvgSwRasterC.h index c269355e..18a09664 100644 --- a/src/lib/sw_engine/tvgSwRasterC.h +++ b/src/lib/sw_engine/tvgSwRasterC.h @@ -20,43 +20,70 @@ * SOFTWARE. */ -static void inline cRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32_t len) +template +static void inline cRasterPixels(PIXEL_T* dst, uint32_t val, uint32_t offset, int32_t len) { dst += offset; while (len--) *dst++ = val; } -static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color) +static bool inline cRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto span = rle->spans; - uint32_t src; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - auto dst = &surface->buf32[span->y * surface->stride + span->x]; - - if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); - else src = color; - - for (uint32_t x = 0; x < span->len; ++x, ++dst) { - *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); + //32bit channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->blender.join(r, g, b, a); + uint32_t src; + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + if (span->coverage < 255) src = ALPHA_BLEND(color, span->coverage); + else src = color; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); + } + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + uint8_t src; + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + if (span->coverage < 255) src = _multiply(span->coverage, a); + else src = a; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = src + _multiply(*dst, ~src); + } } } return true; } -static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color) +static bool inline cRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - auto buffer = surface->buf32 + (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 = _ialpha(color); - for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface->stride]; - for (uint32_t x = 0; x < w; ++x, ++dst) { - *dst = color + ALPHA_BLEND(*dst, ialpha); + //32bits channels + if (surface->channelSize == sizeof(uint32_t)) { + auto color = surface->blender.join(r, g, b, a); + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + auto ialpha = _ialpha(color); + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + for (uint32_t x = 0; x < w; ++x, ++dst) { + *dst = color + ALPHA_BLEND(*dst, ialpha); + } + } + //8bit grayscale + } else if (surface->channelSize == sizeof(uint8_t)) { + auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = &buffer[y * surface->stride]; + for (uint32_t x = 0; x < w; ++x, ++dst) { + *dst = a + _multiply(*dst, ~a); + } } } return true; diff --git a/src/lib/sw_engine/tvgSwRasterNeon.h b/src/lib/sw_engine/tvgSwRasterNeon.h index d7c71fbe..18e39a59 100644 --- a/src/lib/sw_engine/tvgSwRasterNeon.h +++ b/src/lib/sw_engine/tvgSwRasterNeon.h @@ -49,8 +49,14 @@ static void neonRasterRGBA32(uint32_t *dst, uint32_t val, uint32_t offset, int32 } -static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint32_t color) +static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + if (surface->channelSize != sizeof(uint32_t)) { + TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize); + return false; + } + + auto color = surface->blender.join(r, g, b, a); auto span = rle->spans; uint32_t src; uint8x8_t *vDst = nullptr; @@ -88,8 +94,14 @@ static bool neonRasterTranslucentRle(SwSurface* surface, const SwRleData* rle, u } -static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint32_t color) +static bool neonRasterTranslucentRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { + if (surface->channelSize != sizeof(uint32_t)) { + TVGERR("SW_ENGINE", "Unsupported Channel Size = %d", surface->channelSize); + return false; + } + + auto color = surface->blender.join(r, g, b, a); 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); diff --git a/src/lib/sw_engine/tvgSwRasterTexmap.h b/src/lib/sw_engine/tvgSwRasterTexmap.h index 66bd7080..52585162 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmap.h +++ b/src/lib/sw_engine/tvgSwRasterTexmap.h @@ -69,7 +69,7 @@ static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, in } -static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint32_t (*blender)(uint32_t), AASpans* aaSpans) +static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint8_t(*blender)(uint8_t*), AASpans* aaSpans) { #define TEXMAP_TRANSLUCENT #define TEXMAP_MASKING @@ -79,7 +79,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, } -static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t (*blender)(uint32_t), AASpans* aaSpans) +static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint8_t(*blender)(uint8_t*), AASpans* aaSpans) { #define TEXMAP_MASKING #include "tvgSwRasterTexmapInternal.h" @@ -102,7 +102,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, /* This mapping algorithm is based on Mikael Kalms's. */ -static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint32_t (*blender)(uint32_t), AASpans* aaSpans) +static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint8_t(*blender)(uint8_t*), AASpans* aaSpans) { float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x}; float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y}; @@ -545,7 +545,7 @@ static bool _apply(SwSurface* surface, AASpans* aaSpans) | / | 3 -- 2 */ -static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blender)(uint32_t)) +static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*)) { //Exceptions: No dedicated drawing area? if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false; @@ -602,7 +602,7 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Should provide two Polygons, one for each triangle. // TODO: region? */ -static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blender)(uint32_t)) +static bool _rasterTexmapPolygonMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint8_t(*blender)(uint8_t*)) { //Exceptions: No dedicated drawing area? if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return false; diff --git a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h index bc215d04..51685fe6 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h +++ b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h @@ -37,7 +37,8 @@ SwSpan* span = nullptr; //used only when rle based. #ifdef TEXMAP_MASKING - uint32_t* cmp; + uint8_t* cmp; + auto csize = surface->compositor->image.channelSize; #endif if (!_arrange(image, region, yStart, yEnd)) return; @@ -94,7 +95,7 @@ x = x1; #ifdef TEXMAP_MASKING - cmp = &surface->compositor->image.buf32[y * surface->compositor->image.stride + x1]; + cmp = &surface->compositor->image.buf8[(y * surface->compositor->image.stride + x1) * csize]; #endif //Draw horizontal line while (x++ < x2) { @@ -130,9 +131,9 @@ px = INTERPOLATE(ab, px, px2); } #if defined(TEXMAP_MASKING) && defined(TEXMAP_TRANSLUCENT) - auto src = ALPHA_BLEND(px, _multiplyAlpha(opacity, blender(*cmp))); + auto src = ALPHA_BLEND(px, _multiply(opacity, blender(cmp))); #elif defined(TEXMAP_MASKING) - auto src = ALPHA_BLEND(px, blender(*cmp)); + auto src = ALPHA_BLEND(px, blender(cmp)); #elif defined(TEXMAP_TRANSLUCENT) auto src = ALPHA_BLEND(px, opacity); #else @@ -141,7 +142,7 @@ *buf = src + ALPHA_BLEND(*buf, _ialpha(src)); ++buf; #ifdef TEXMAP_MASKING - ++cmp; + cmp += csize; #endif //Step UV horizontally u += _dudx; diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 6d406af0..c7030aac 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -167,8 +167,7 @@ bool Paint::Impl::render(RenderMethod& renderer) if (compData && compData->method != CompositeMethod::ClipPath && !(compData->target->pImpl->ctxFlag & ContextFlag::FastTrack)) { auto region = smethod->bounds(renderer); if (region.w == 0 || region.h == 0) return true; - //cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method)); - cmp = renderer.target(region, renderer.colorSpace()); + cmp = renderer.target(region, COMPOSITE_TO_COLORSPACE(renderer, compData->method)); if (renderer.beginComposite(cmp, CompositeMethod::None, 255)) { compData->target->pImpl->render(renderer); }