From c2d6fc4fdd243a113a25fe32756476594d494a57 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Wed, 26 May 2021 02:39:38 +0200 Subject: [PATCH] sw_engine: refactoring of the radial gradient rect rastering function The translucent rastering function is split into 3 other (instead of if/else statement). An additional function is introduced to decide which one of the 3 should be called. This refactoring is done to preserve the convention used for all other rastering functs. --- src/lib/sw_engine/tvgSwRaster.cpp | 110 ++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 37 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index be792e0c..05a49717 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -704,7 +704,7 @@ static bool _rasterOpaqueLinearGradientRect(SwSurface* surface, const SwBBox& re } -static bool _rasterTranslucentRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +static bool _translucentRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) { if (fill->radial.a < FLT_EPSILON) return false; @@ -715,52 +715,88 @@ static bool _rasterTranslucentRadialGradientRect(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) { - fillFetchRadial(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) { - fillFetchRadial(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]; fillFetchRadial(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 _translucentRadialGradientRectAlphaMask(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + if (fill->radial.a < 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) { + fillFetchRadial(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 _translucentRadialGradientRectInvAlphaMask(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + if (fill->radial.a < 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) { + fillFetchRadial(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 _rasterTranslucentRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) +{ + if (surface->compositor) { + if (surface->compositor->method == CompositeMethod::AlphaMask) { + return _translucentRadialGradientRectAlphaMask(surface, region, fill); + } + if (surface->compositor->method == CompositeMethod::InvAlphaMask) { + return _translucentRadialGradientRectInvAlphaMask(surface, region, fill); + } + } + return _translucentRadialGradientRect(surface, region, fill); +} + + static bool _rasterOpaqueRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) { if (fill->radial.a < FLT_EPSILON) return false;