From aeb10fafeccacbaaefdfd66340d72685e114f068 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Wed, 26 May 2021 02:54:15 +0200 Subject: [PATCH] sw_engine: refactoring of the radial gradient rle 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 | 171 +++++++++++++++++------------- 1 file changed, 99 insertions(+), 72 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 05a49717..b41da003 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -928,7 +928,7 @@ static bool _rasterOpaqueLinearGradientRle(SwSurface* surface, const SwRleData* auto span = rle->spans; - for (uint32_t i = 0; i < rle->size; ++i) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { if (span->coverage == 255) { fillFetchLinear(fill, surface->buffer + span->y * surface->stride + span->x, span->y, span->x, span->len); } else { @@ -939,7 +939,96 @@ static bool _rasterOpaqueLinearGradientRle(SwSurface* surface, const SwRleData* dst[i] = ALPHA_BLEND(buf[i], span->coverage) + ALPHA_BLEND(dst[i], ialpha); } } - ++span; + } + return true; +} + + +static bool _translucentRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + if (fill->radial.a < FLT_EPSILON) return false; + + auto span = rle->spans; + auto buffer = static_cast(alloca(surface->w * sizeof(uint32_t))); + if (!buffer) return false; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buffer[span->y * surface->stride + span->x]; + fillFetchRadial(fill, buffer, span->y, span->x, span->len); + if (span->coverage == 255) { + for (uint32_t i = 0; i < span->len; ++i) { + dst[i] = buffer[i] + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(buffer[i])); + } + } else { + for (uint32_t i = 0; i < span->len; ++i) { + auto tmp = ALPHA_BLEND(buffer[i], span->coverage); + dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(tmp)); + } + } + } + return true; +} + + +static bool _translucentRadialGradientRleAlphaMask(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + if (fill->radial.a < FLT_EPSILON) return false; + + auto span = rle->spans; + auto cbuffer = surface->compositor->image.data; + 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->buffer[span->y * surface->stride + span->x]; + auto cmp = &cbuffer[span->y * surface->stride + span->x]; + auto src = buffer; + if (span->coverage == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { + auto tmp = ALPHA_BLEND(*src, surface->blender.alpha(*cmp)); + *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); + } + } else { + auto ialpha = 255 - span->coverage; + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { + auto tmp = ALPHA_BLEND(*src, surface->blender.alpha(*cmp)); + tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha); + *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); + } + } + } + return true; +} + + +static bool _translucentRadialGradientRleInvAlphaMask(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + if (fill->radial.a < FLT_EPSILON) return false; + + auto span = rle->spans; + auto cbuffer = surface->compositor->image.data; + 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->buffer[span->y * surface->stride + span->x]; + auto cmp = &cbuffer[span->y * surface->stride + span->x]; + auto src = buffer; + if (span->coverage == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { + auto tmp = ALPHA_BLEND(*src, 255 - surface->blender.alpha(*cmp)); + *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); + } + } else { + auto ialpha = 255 - span->coverage; + for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { + auto tmp = ALPHA_BLEND(*src, 255 - surface->blender.alpha(*cmp)); + tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha); + *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); + } + } } return true; } @@ -947,78 +1036,17 @@ static bool _rasterOpaqueLinearGradientRle(SwSurface* surface, const SwRleData* static bool _rasterTranslucentRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) { - if (fill->radial.a < FLT_EPSILON) return false; - - auto buf = static_cast(alloca(surface->w * sizeof(uint32_t))); - if (!buf) return false; - - auto span = rle->spans; + if (!rle) return false; if (surface->compositor) { - auto method = surface->compositor->method; - auto cbuffer = surface->compositor->image.data; - - if (method == CompositeMethod::AlphaMask) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - fillFetchRadial(fill, buf, span->y, span->x, span->len); - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->stride + span->x]; - auto src = buf; - if (span->coverage == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, surface->blender.alpha(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); - } - } else { - auto ialpha = 255 - span->coverage; - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, surface->blender.alpha(*cmp)); - tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha); - *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); - } - } - } - return true; - } else if (method == CompositeMethod::InvAlphaMask) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - fillFetchRadial(fill, buf, span->y, span->x, span->len); - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->stride + span->x]; - auto src = buf; - if (span->coverage == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, 255 - surface->blender.alpha(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); - } - } else { - auto ialpha = 255 - span->coverage; - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp, ++src) { - auto tmp = ALPHA_BLEND(*src, 255 - surface->blender.alpha(*cmp)); - tmp = ALPHA_BLEND(tmp, span->coverage) + ALPHA_BLEND(*dst, ialpha); - *dst = tmp + ALPHA_BLEND(*dst, 255 - surface->blender.alpha(tmp)); - } - } - } - return true; + if (surface->compositor->method == CompositeMethod::AlphaMask) { + return _translucentRadialGradientRleAlphaMask(surface, rle, fill); + } + if (surface->compositor->method == CompositeMethod::InvAlphaMask) { + return _translucentRadialGradientRleInvAlphaMask(surface, rle, fill); } } - - 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] + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(buf[i])); - } - } else { - for (uint32_t i = 0; i < span->len; ++i) { - auto tmp = ALPHA_BLEND(buf[i], span->coverage); - dst[i] = tmp + ALPHA_BLEND(dst[i], 255 - surface->blender.alpha(tmp)); - } - } - ++span; - } - return true; + return _translucentRadialGradientRle(surface, rle, fill); } @@ -1031,7 +1059,7 @@ static bool _rasterOpaqueRadialGradientRle(SwSurface* surface, const SwRleData* auto span = rle->spans; - for (uint32_t i = 0; i < rle->size; ++i) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { auto dst = &surface->buffer[span->y * surface->stride + span->x]; if (span->coverage == 255) { fillFetchRadial(fill, dst, span->y, span->x, span->len); @@ -1042,7 +1070,6 @@ static bool _rasterOpaqueRadialGradientRle(SwSurface* surface, const SwRleData* dst[i] = ALPHA_BLEND(buf[i], span->coverage) + ALPHA_BLEND(dst[i], ialpha); } } - ++span; } return true; }