From eb9b7dc59640ddceeecacedb60edac1fb6c78510 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 26 Nov 2021 12:10:23 +0900 Subject: [PATCH] sw_engine raster: improve the transformed rle image rasterizer. replace the transformed rle rgba image with the texmap raster. this patch removes the several scattered transformed image rasterizer, reuse the unified one texmap method instead. yay, it's much clean and optimal. Change-Id: Ie5c1a99b28c5242639618e1f4e41f8912c443b4c --- src/lib/sw_engine/tvgSwRaster.cpp | 446 +------------------------- src/lib/sw_engine/tvgSwRasterTexmap.h | 29 +- src/lib/sw_engine/tvgSwRasterTexmapInternal.h | 49 ++- src/lib/sw_engine/tvgSwRenderer.cpp | 5 +- src/lib/tvgPaint.cpp | 13 +- src/lib/tvgPaint.h | 3 +- src/lib/tvgRender.h | 2 +- 7 files changed, 81 insertions(+), 466 deletions(-) diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 9987aeb..9ef4cc0 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -265,445 +265,16 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint8 /* RLE Transformed RGBA Image */ /************************************************************************/ -static bool _rasterTransformedMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t (*blendMethod)(uint32_t)) -{ - TVGLOG("SW_ENGINE", "Transformed Masked Translucent Rle Image"); - - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - auto cbuffer = surface->compositor->image.data; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - auto src = ALPHA_BLEND(img[rY * image->stride + rX], alpha); - auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } - return true; -} - - -static bool _rasterTransformedMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t)) -{ - TVGLOG("SW_ENGINE", "Transformed Masked Rle Image"); - - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - auto cbuffer = surface->compositor->image.data; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; - if (span->coverage == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - auto tmp = ALPHA_BLEND(img[rY * image->stride + rX], blendMethod(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } else { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - auto src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage); - auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } - } - return true; -} - - -static bool _rasterTransformedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity) -{ - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - for (uint32_t x = 0; x < span->len; ++x, ++dst) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - auto src = ALPHA_BLEND(img[rY * image->stride + rX], alpha); - *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); - } - } - return true; -} - - -static bool _rasterDownScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t)) -{ - TVGLOG("SW_ENGINE", "Down Scaled Masked Translucent Rle Image"); - - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - auto cbuffer = surface->compositor->image.data; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha); - else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha); - auto tmp = ALPHA_BLEND(src, _multiplyAlpha(alpha, blendMethod(*cmp))); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } - return true; -} - - -static bool _rasterDownScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t)) -{ - TVGLOG("SW_ENGINE", "Down Scaled Masked Rle Image"); - - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - auto cbuffer = surface->compositor->image.data; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; - if (span->coverage == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = img[rY * image->stride + rX]; - else src = _interpDownScaler(img, image->stride, h, rX, rY, halfScale); - auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } else { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage); - else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), span->coverage); - auto tmp = ALPHA_BLEND(src, _multiplyAlpha(span->coverage, blendMethod(*cmp))); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } - } - return true; -} - - -static bool _rasterDownScaledTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t halfScale) -{ - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - for (uint32_t x = 0; x < span->len; ++x, ++dst) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha); - else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha); - *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); - } - } - return true; -} - - -static bool _rasterUpScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t (*blendMethod)(uint32_t)) -{ - TVGLOG("SW_ENGINE", "Up Scaled Masked Translucent Rle Image"); - - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - auto cbuffer = surface->compositor->image.data; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto fX = (span->x + x) * itransform->e11 + ey1; - auto fY = (span->x + x) * itransform->e21 + ey2; - auto rX = static_cast(roundf(fX)); - auto rY = static_cast(roundf(fY)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha); - else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha); - auto tmp = ALPHA_BLEND(src, _multiplyAlpha(alpha, blendMethod(*cmp))); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } - return true; -} - - -static bool _rasterUpScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t)) -{ - TVGLOG("SW_ENGINE", "Up Scaled Masked Rle Image"); - - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - auto cbuffer = surface->compositor->image.data; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x]; - if (span->coverage == 255) { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto fX = (span->x + x) * itransform->e11 + ey1; - auto fY = (span->x + x) * itransform->e21 + ey2; - auto rX = static_cast(roundf(fX)); - auto rY = static_cast(roundf(fY)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX == w - 1 || rY == h - 1) src = img[rY * image->stride + rX]; - else src = _interpUpScaler(img, image->stride, h, fX, fY); - auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } else { - for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) { - auto fX = (span->x + x) * itransform->e11 + ey1; - auto fY = (span->x + x) * itransform->e21 + ey2; - auto rX = static_cast(roundf(fX)); - auto rY = static_cast(roundf(fY)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage); - else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), span->coverage); - auto tmp = ALPHA_BLEND(src, _multiplyAlpha(span->coverage, blendMethod(*cmp))); - *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); - } - } - } - return true; -} - - -static bool _rasterUpScaledTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity) -{ - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - auto alpha = _multiplyAlpha(span->coverage, opacity); - for (uint32_t x = 0; x < span->len; ++x, ++dst) { - auto fX = (span->x + x) * itransform->e11 + ey1; - auto fY = (span->x + x) * itransform->e21 + ey2; - auto rX = static_cast(roundf(fX)); - auto rY = static_cast(roundf(fY)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha); - else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha); - *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); - } - } - return true; -} - - -static bool _rasterTransformedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform) -{ - auto span = image->rle->spans; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - - for (uint32_t x = 0; x < span->len; ++x, ++dst) { - auto rX = static_cast(roundf((span->x + x) * itransform->e11 + ey1)); - auto rY = static_cast(roundf((span->x + x) * itransform->e21 + ey2)); - if (rX >= image->w || rY >= image->h) continue; - auto src = ALPHA_BLEND(image->data[rY * image->stride + rX], span->coverage); - *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); - } - } - return true; -} - - -static bool _rasterDownScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t halfScale) -{ - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { - auto rX = static_cast(roundf(x * itransform->e11 + ey1)); - auto rY = static_cast(roundf(x * itransform->e21 + ey2)); - if (rX >= w || rY >= h) continue; - - uint32_t src; - if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage); - else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), span->coverage); - *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); - } - } - return true; -} - - -static bool _rasterUpScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform) -{ - auto span = image->rle->spans; - auto img = image->data; - auto w = image->w; - auto h = image->h; - - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto ey1 = span->y * itransform->e12 + itransform->e13; - auto ey2 = span->y * itransform->e22 + itransform->e23; - auto dst = &surface->buffer[span->y * surface->stride + span->x]; - for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { - auto fX = x * itransform->e11 + ey1; - auto fY = x * itransform->e21 + ey2; - auto rX = static_cast(roundf(fX)); - auto rY = static_cast(roundf(fY)); - if (rX >= w || rY >= h) continue; - uint32_t src; - if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage); - else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), span->coverage); - *dst = src + ALPHA_BLEND(*dst, _ialpha(src)); - } - } - return true; -} - - static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, uint32_t opacity) { - Matrix itransform; - mathIdentity(&itransform); - if (transform && !mathInverse(transform, &itransform)) return false; - - auto halfScale = _halfScale(image->scale); - if (_compositing(surface)) { - if (opacity == 255) { - //Transformed - if (mathEqual(image->scale, 1.0f)) { - if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterTransformedMaskedRleRGBAImage(surface, image, &itransform, _alpha); - } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterTransformedMaskedRleRGBAImage(surface, image, &itransform, _ialpha); - } - //Transformed + Down Scaled - } else if (image->scale < DOWN_SCALE_TOLERANCE) { - if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterDownScaledMaskedRleRGBAImage(surface, image, &itransform, halfScale, _alpha); - } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterDownScaledMaskedRleRGBAImage(surface, image, &itransform, halfScale, _ialpha); - } - //Transformed + Up Scaled - } else { - if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterUpScaledMaskedRleRGBAImage(surface, image, &itransform, _alpha); - } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterUpScaledMaskedRleRGBAImage(surface, image, &itransform, _ialpha); - } - } - } else { - //Transformed - if (mathEqual(image->scale, 1.0f)) { - if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterTransformedMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, _alpha); - } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterTransformedMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, _ialpha); - } - //Transformed + Down Scaled - } else if (image->scale < DOWN_SCALE_TOLERANCE) { - if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterDownScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale, _alpha); - } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterDownScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale, _ialpha); - } - //Transformed + Up Scaled - } else { - if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterUpScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, _alpha); - } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterUpScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, _ialpha); - } - } + if (surface->compositor->method == CompositeMethod::AlphaMask) { + return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _alpha); + } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { + return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _ialpha); } } else { - if (opacity == 255) { - if (mathEqual(image->scale, 1.0f)) return _rasterTransformedRleRGBAImage(surface, image, &itransform); - else if (image->scale < DOWN_SCALE_TOLERANCE) return _rasterDownScaledRleRGBAImage(surface, image, &itransform, halfScale); - else return _rasterUpScaledRleRGBAImage(surface, image, &itransform); - } else { - if (mathEqual(image->scale, 1.0f)) return _rasterTransformedTranslucentRleRGBAImage(surface, image, &itransform, opacity); - else if (image->scale < DOWN_SCALE_TOLERANCE) return _rasterDownScaledTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale); - else return _rasterUpScaledTranslucentRleRGBAImage(surface, image, &itransform, opacity); - } + return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr); } return false; } @@ -1066,12 +637,12 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons { if (_compositing(surface)) { if (surface->compositor->method == CompositeMethod::AlphaMask) { - return _rasterTexmapPolygon(surface, image, transform, region, opacity, _alpha); + return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, _alpha); } else if (surface->compositor->method == CompositeMethod::InvAlphaMask) { - return _rasterTexmapPolygon(surface, image, transform, region, opacity, _ialpha); + return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, _ialpha); } } else { - return _rasterTexmapPolygon(surface, image, transform, region, opacity, nullptr); + return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, nullptr); } return false; } @@ -1385,7 +956,6 @@ static bool _rasterRGBAImage(SwSurface* surface, SwImage* image, const Matrix* t if (image->rle) { if (image->direct) return _directRleRGBAImage(surface, image, opacity); else if (image->scaled) return _scaledRleRGBAImage(surface, image, transform, region, opacity); - //OPTIMIZE_ME: Replace with the TexMap Rasterizer else return _transformedRleRGBAImage(surface, image, transform, opacity); //Whole Image } else { diff --git a/src/lib/sw_engine/tvgSwRasterTexmap.h b/src/lib/sw_engine/tvgSwRasterTexmap.h index ca4e303..c7d225d 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmap.h +++ b/src/lib/sw_engine/tvgSwRasterTexmap.h @@ -31,6 +31,7 @@ struct Polygon Vertex vertex[3]; }; + static inline void _swap(float& a, float& b, float& tmp) { tmp = a; @@ -44,7 +45,7 @@ static float dxdya, dxdyb, dudya, dvdya; static float xa, xb, ua, va; -static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t opacity, uint32_t (*blendMethod)(uint32_t)) +static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint32_t (*blendMethod)(uint32_t)) { #define TEXMAP_TRANSLUCENT #define TEXMAP_MASKING @@ -54,7 +55,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, } -static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t (*blendMethod)(uint32_t)) +static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t (*blendMethod)(uint32_t)) { #define TEXMAP_MASKING #include "tvgSwRasterTexmapInternal.h" @@ -62,7 +63,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, } -static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t opacity) +static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity) { #define TEXMAP_TRANSLUCENT #include "tvgSwRasterTexmapInternal.h" @@ -70,14 +71,15 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, } -static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend) +static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd) { #include "tvgSwRasterTexmapInternal.h" } + /* This mapping algorithm is based on Mikael Kalms's. */ -static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity, Polygon& polygon, uint32_t (*blendMethod)(uint32_t)) +static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint32_t (*blendMethod)(uint32_t)) { float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x}; float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y}; @@ -139,6 +141,8 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const if (mathEqual(y[0], y[1])) side = x[0] > x[1]; if (mathEqual(y[1], y[2])) side = x[2] > x[1]; + auto regionTop = region ? region->min.y : image->rle->spans->y; //Normal Image or Rle Image? + //Longer edge is on the left side if (!side) { //Calculate slopes along left edge @@ -154,7 +158,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const //Draw upper segment if possibly visible if (yi[0] < yi[1]) { - off_y = y[0] < region.min.y ? (region.min.y - y[0]) : 0; + off_y = y[0] < regionTop ? (regionTop - y[0]) : 0; xa += (off_y * dxdya); ua += (off_y * dudya); va += (off_y * dvdya); @@ -175,7 +179,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const } //Draw lower segment if possibly visible if (yi[1] < yi[2]) { - off_y = y[1] < region.min.y ? (region.min.y - y[1]) : 0; + off_y = y[1] < regionTop ? (regionTop - y[1]) : 0; if (!upper) { xa += (off_y * dxdya); ua += (off_y * dudya); @@ -201,7 +205,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const //Draw upper segment if possibly visible if (yi[0] < yi[1]) { - off_y = y[0] < region.min.y ? (region.min.y - y[0]) : 0; + off_y = y[0] < regionTop ? (regionTop - y[0]) : 0; xb += (off_y *dxdyb); // Set slopes along left edge and perform subpixel pre-stepping @@ -225,7 +229,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const } //Draw lower segment if possibly visible if (yi[1] < yi[2]) { - off_y = y[1] < region.min.y ? (region.min.y - y[1]) : 0; + off_y = y[1] < regionTop ? (regionTop - y[1]) : 0; if (!upper) xb += (off_y *dxdyb); // Set slopes along left edge and perform subpixel pre-stepping @@ -259,8 +263,11 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const | / | 3 -- 2 */ -static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t)) +static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t)) { + //Exceptions: No dedicated drawing area? + if (!region && image->rle->size == 0) return false; + /* Prepare vertices. shift XY coordinates to match the sub-pixeling technique. */ Vertex vertices[4]; @@ -286,6 +293,6 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const polygon.vertex[2] = vertices[3]; _rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod); - + return true; } \ No newline at end of file diff --git a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h index ce234cf..0a93530 100644 --- a/src/lib/sw_engine/tvgSwRasterTexmapInternal.h +++ b/src/lib/sw_engine/tvgSwRasterTexmapInternal.h @@ -33,28 +33,48 @@ int uu = 0; float dx, u, v, iptr; uint32_t* buf; + int regionTop; + int regionBottom; + SwSpan* span = nullptr; //used only when rle based. + #ifdef TEXMAP_MASKING uint32_t* cmp; #endif + if (region) { + regionTop = region->min.y; + regionBottom = region->max.y; + } else { + regionTop = image->rle->spans->y; + regionBottom = image->rle->spans[image->rle->size - 1].y; + } + //Range exception handling - if (ystart >= region.max.y) return; - if (ystart < region.min.y) ystart = region.min.y; - if (yend > region.max.y) yend = region.max.y; + if (yStart >= regionBottom) return; + if (yStart < regionTop) yStart = regionTop; + if (yEnd > regionBottom) yEnd = regionBottom; //Loop through all lines in the segment - y = ystart; + y = yStart; + + if (!region) span = image->rle->spans + (yStart - regionTop); - while (y < yend) { + while (y < yEnd) { x1 = _xa; x2 = _xb; //Range exception handling - if (x1 < region.min.x) x1 = region.min.x; - if (x2 > region.max.x) x2 = region.max.x; - - if ((x2 - x1) < 1) goto next; - if ((x1 >= region.max.x) || (x2 <= region.min.x)) goto next; + if (region) { + if (x1 < region->min.x) x1 = region->min.x; + if (x2 > region->max.x) x2 = region->max.x; + if ((x2 - x1) < 1) goto next; + if ((x1 >= region->max.x) || (x2 <= region->min.x)) goto next; + } else { + if (x1 < span->x) x1 = span->x; + if (x2 > span->x + span->len) x2 = (span->x + span->len); + if ((x2 - x1) < 1) goto next; + if ((x1 >= (span->x + span->len)) || (x2 <= span->x)) goto next; + } //Perform subtexel pre-stepping on UV dx = 1 - (_xa - x1); @@ -105,7 +125,7 @@ #elif defined(TEXMAP_TRANSLUCENT) auto src = ALPHA_BLEND(px, opacity); #else - auto src = px; + auto src = px; #endif *buf = src + ALPHA_BLEND(*buf, _ialpha(src)); ++buf; @@ -123,7 +143,12 @@ next: _ua += _dudya; _va += _dvdya; - y++; + if (span) { + ++span; + y = span->y; + } else { + y++; + } } xa = _xa; xb = _xb; diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 1c0c3c2..672b938 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -111,11 +111,14 @@ struct SwShapeTask : SwTask //Fill if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) { if (visibleFill) { + auto antiAlias = (flags & RenderUpdateFlag::IgnoreAliasing) ? false : true; + /* We assume that if stroke width is bigger than 2, shape outline below stroke could be full covered by stroke drawing. Thus it turns off antialising in that condition. Also, it shouldn't be dash style. */ - auto antiAlias = (strokeAlpha == 255 && sdata->strokeWidth() > 2 && sdata->strokeDash(nullptr) == 0) ? false : true; + if (strokeAlpha == 255 && sdata->strokeWidth() > 2 && sdata->strokeDash(nullptr) == 0) antiAlias = false; + if (!shapeGenRle(&shape, sdata, antiAlias)) goto err; } if (auto fill = sdata->fill()) { diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 909e6be..d258dd5 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -201,7 +201,7 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf if (compData) { auto target = compData->target; auto method = compData->method; - target->pImpl->ctxFlag = ContextFlag::Invalid; //reset + target->pImpl->ctxFlag &= ~ContextFlag::FastTrack; //reset /* If transform has no rotation factors && ClipPath / AlphaMasking is a simple rectangle, we can avoid regular ClipPath / AlphaMasking sequence but use viewport for performance */ @@ -223,7 +223,15 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf } } if (!compFastTrack) { - tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag); + //Bad design!: ignore anti-aliasing if the bitmap image is the source of the clip-path! + auto tempFlag = pFlag; + + if (id == TVG_CLASS_ID_PICTURE) { + auto picture = static_cast(compData->source); + if (picture->data(nullptr, nullptr)) tempFlag |= RenderUpdateFlag::IgnoreAliasing; + } + + tdata = target->pImpl->update(renderer, pTransform, 255, clips, tempFlag); if (method == CompositeMethod::ClipPath) clips.push(tdata); } } @@ -249,6 +257,7 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf return edata; } + bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transformed) { Matrix* m = nullptr; diff --git a/src/lib/tvgPaint.h b/src/lib/tvgPaint.h index 1f36ec3..4003bdb 100644 --- a/src/lib/tvgPaint.h +++ b/src/lib/tvgPaint.h @@ -67,7 +67,8 @@ namespace tvg uint32_t id; uint8_t opacity = 255; - ~Impl() { + ~Impl() + { if (compData) { delete(compData->target); free(compData); diff --git a/src/lib/tvgRender.h b/src/lib/tvgRender.h index 955816e..7621fe2 100644 --- a/src/lib/tvgRender.h +++ b/src/lib/tvgRender.h @@ -28,7 +28,7 @@ namespace tvg { -enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 127}; +enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255, IgnoreAliasing = 256}; struct Surface { -- 2.7.4