diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index e3f52eba..be792e0c 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -596,7 +596,7 @@ static bool _rasterImage(SwSurface* surface, const uint32_t *img, uint32_t w, ui /* Gradient */ /************************************************************************/ -static bool _rasterTranslucentLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +static bool _translucentLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) { if (fill->linear.len < FLT_EPSILON) return false; @@ -607,52 +607,88 @@ static bool _rasterTranslucentLinearGradientRect(SwSurface* surface, const SwBBo auto sbuffer = static_cast(alloca(w * sizeof(uint32_t))); if (!sbuffer) return false; - if (surface->compositor) { - auto method = surface->compositor->method; - auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; - - if (method == CompositeMethod::AlphaMask) { - for (uint32_t y = 0; y < h; ++y) { - fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w); - 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, surface->blender.alpha(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); - } - buffer += surface->stride; - cbuffer += surface->stride; - } - return true; - } else if (method == CompositeMethod::InvAlphaMask) { - for (uint32_t y = 0; y < h; ++y) { - fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w); - 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, 255 - surface->blender.alpha(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); - } - buffer += surface->stride; - cbuffer += surface->stride; - } - return true; - } - } - + auto dst = buffer; for (uint32_t y = 0; y < h; ++y) { - auto dst = &buffer[y * surface->stride]; fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w); for (uint32_t x = 0; x < w; ++x) { dst[x] = sbuffer[x] + ALPHA_BLEND(dst[x], 255 - surface->blender.alpha(sbuffer[x])); } + dst += surface->stride; } return true; } +static bool _translucentLinearGradientRectAlphaMask(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + if (fill->linear.len < FLT_EPSILON) return false; + + 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 cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; + + auto sbuffer = static_cast(alloca(w * sizeof(uint32_t))); + if (!sbuffer) return false; + + for (uint32_t y = 0; y < h; ++y) { + fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w); + 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, surface->blender.alpha(*cmp)); + *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); + } + buffer += surface->stride; + cbuffer += surface->stride; + } + return true; +} + + +static bool _translucentLinearGradientRectInvAlphaMask(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + if (fill->linear.len < FLT_EPSILON) return false; + + 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 cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; + + auto sbuffer = static_cast(alloca(w * sizeof(uint32_t))); + if (!sbuffer) return false; + + for (uint32_t y = 0; y < h; ++y) { + fillFetchLinear(fill, sbuffer, region.min.y + y, region.min.x, w); + 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, 255 - surface->blender.alpha(*cmp)); + *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); + } + buffer += surface->stride; + cbuffer += surface->stride; + } + return true; +} + + +static bool _rasterTranslucentLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + if (surface->compositor) { + if (surface->compositor->method == CompositeMethod::AlphaMask) { + return _translucentLinearGradientRectAlphaMask(surface, region, fill); + } + if (surface->compositor->method == CompositeMethod::InvAlphaMask) { + return _translucentLinearGradientRectInvAlphaMask(surface, region, fill); + } + } + return _translucentLinearGradientRect(surface, region, fill); +} + + static bool _rasterOpaqueLinearGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) { if (fill->linear.len < FLT_EPSILON) return false;