From 9fbb8d9b0960a6c68cd47ee12c4f84a2669d59fd Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 24 Nov 2021 19:02:07 +0900 Subject: [PATCH] sw_engine image: complete sequeqnce of the scaled rgba rle image drawing. implement composition by translucent / opaque --- src/lib/sw_engine/tvgSwRaster.cpp | 76 ++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 21e58cc4..b6060ac3 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -599,7 +599,7 @@ static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, c /* RLE Scaled RGBA Image */ /************************************************************************/ -static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t)) +static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t)) { auto span = image->rle->spans; @@ -611,7 +611,47 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; auto alpha = _multiplyAlpha(span->coverage, opacity); - if (alpha == 255) { + for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) { + auto sx = static_cast(x * itransform->e11 + itransform->e13); + if (sx >= image->w) continue; + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha); + auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); + *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp)); + } + } + //Center (Up-Scaled) + } else { + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto sy = static_cast(span->y * itransform->e22 + itransform->e23); + if (sy >= image->h) continue; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; + auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; + auto alpha = _multiplyAlpha(span->coverage, opacity); + for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) { + auto sx = static_cast(x * itransform->e11 + itransform->e13); + if (sx >= image->w) continue; + auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha); + auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); + *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp)); + } + } + } + return true; +} + + +static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t)) +{ + auto span = image->rle->spans; + + //Center (Down-Scaled) + if (image->scale < DOWN_SCALE_TOLERANCE) { + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto sy = static_cast(span->y * itransform->e22 + itransform->e23); + if (sy >= image->h) continue; + auto dst = &surface->buffer[span->y * surface->stride + span->x]; + auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; + if (span->coverage == 255) { for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) { auto sx = static_cast(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; @@ -622,7 +662,7 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) { auto sx = static_cast(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha); + auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), span->coverage); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp)); } @@ -635,8 +675,7 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i if (sy >= image->h) continue; auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - if (alpha == 255) { + if (span->coverage == 255) { for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) { auto sx = static_cast(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; @@ -647,7 +686,7 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i for (uint32_t x = span->x; x < ((uint32_t)span->x) + span->len; ++x, ++dst, ++cmp) { auto sx = static_cast(x * itransform->e11 + itransform->e13); if (sx >= image->w) continue; - auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha); + auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); *dst = tmp + ALPHA_BLEND(*dst, surface->blender.ialpha(tmp)); } @@ -750,25 +789,30 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image, static bool _scaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity) { - auto halfScale = _halfScale(image->scale); - Matrix itransform; if (transform && !mathInverse(transform, &itransform)) return false; - if (_translucent(surface, opacity)) { - //TODO: Blenders for the following scenarios: [Opacity / Composition / Opacity + Composition] - if (surface->compositor) { + auto halfScale = _halfScale(image->scale); + + if (_compositing(surface)) { + if (opacity == 255) { if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.alpha); + return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.alpha); } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.ialpha); + return _rasterScaledMaskedRleRGBAImage(surface, image, &itransform, region, halfScale, surface->blender.ialpha); + } + } else { + if (surface->compositor->method == CompositeMethod::AlphaMask) { + return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.alpha); + } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { + return _rasterScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale, surface->blender.ialpha); } } - return _rasterScaledTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale); } else { - //TODO: Blenders for the following scenarios: [No Composition / Composition] - return _rasterScaledRleRGBAImage(surface, image, &itransform, region, opacity, halfScale); + if (opacity == 255) return _rasterScaledRleRGBAImage(surface, image, &itransform, region, opacity, halfScale); + else return _rasterScaledTranslucentRleRGBAImage(surface, image, &itransform, region, opacity, halfScale); } + return false; }