From 32dcda82410b6d3ed31c62141b92b228b9fb5a44 Mon Sep 17 00:00:00 2001 From: Mira Grudzinska Date: Tue, 25 May 2021 01:50:59 +0200 Subject: [PATCH] sw_engine: refactoring the linear 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 | 139 +++++++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 55 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 916ea49..e3f52eb 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -741,83 +741,112 @@ static bool _rasterOpaqueRadialGradientRect(SwSurface* surface, const SwBBox& re } -static bool _rasterTranslucentLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +static bool _translucentLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) { if (fill->linear.len < FLT_EPSILON) return false; - auto buf = static_cast(alloca(surface->w * sizeof(uint32_t))); - if (!buf) return false; - auto span = rle->spans; + auto buffer = static_cast(alloca(surface->w * sizeof(uint32_t))); + if (!buffer) return false; - if (surface->compositor) { - auto method = surface->compositor->method; - auto cbuffer = surface->compositor->image.data; + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buffer[span->y * surface->stride + span->x]; + fillFetchLinear(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; +} - if (method == CompositeMethod::AlphaMask) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - fillFetchLinear(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)); - } - } + +static bool _translucentLinearGradientRleAlphaMask(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + if (fill->linear.len < 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) { + fillFetchLinear(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)); } - return true; - } else if (method == CompositeMethod::InvAlphaMask) { - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - fillFetchLinear(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)); - } - } + } 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; } } + return true; +} - for (uint32_t i = 0; i < rle->size; ++i) { + +static bool _translucentLinearGradientRleInvAlphaMask(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + if (fill->linear.len < 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) { + fillFetchLinear(fill, buffer, span->y, span->x, span->len); auto dst = &surface->buffer[span->y * surface->stride + span->x]; - fillFetchLinear(fill, buf, span->y, span->x, span->len); + auto cmp = &cbuffer[span->y * surface->stride + span->x]; + auto src = buffer; 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])); + 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 { - 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)); + 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)); } } - ++span; } return true; } +static bool _rasterTranslucentLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +{ + if (!rle) return false; + + if (surface->compositor) { + if (surface->compositor->method == CompositeMethod::AlphaMask) { + return _translucentLinearGradientRleAlphaMask(surface, rle, fill); + } + if (surface->compositor->method == CompositeMethod::InvAlphaMask) { + return _translucentLinearGradientRleInvAlphaMask(surface, rle, fill); + } + } + return _translucentLinearGradientRle(surface, rle, fill); +} + + static bool _rasterOpaqueLinearGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) { if (fill->linear.len < FLT_EPSILON) return false; -- 2.7.4