diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2023-09-18 14:49:04 +0200 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2023-09-26 22:43:44 +0200 |
commit | 81949c2cd23e07db9a078b2206b3e43847e051b9 (patch) | |
tree | fc5f074b9563de0b2fc49fc338a39e863040b6c6 /thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp | |
parent | b905959f4382020b424fa093c380e163a7a7f404 (diff) | |
download | redot-engine-81949c2cd23e07db9a078b2206b3e43847e051b9.tar.gz |
thorvg: Update to 0.10.7
Fixes #81618.
Diffstat (limited to 'thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp')
-rw-r--r-- | thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp | 869 |
1 files changed, 396 insertions, 473 deletions
diff --git a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp index bd32bf0b23..8fd54c2a4f 100644 --- a/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp +++ b/thirdparty/thorvg/src/lib/sw_engine/tvgSwRaster.cpp @@ -39,6 +39,16 @@ constexpr auto DOWN_SCALE_TOLERANCE = 0.5f; struct FillLinear { + void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a) + { + fillLinear(fill, dst, y, x, len, op, a); + } + + void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a) + { + fillLinear(fill, dst, y, x, len, cmp, op, a); + } + void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) { fillLinear(fill, dst, y, x, len, op, a); @@ -58,6 +68,16 @@ struct FillLinear struct FillRadial { + void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a) + { + fillRadial(fill, dst, y, x, len, op, a); + } + + void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a) + { + fillRadial(fill, dst, y, x, len, cmp, op, a); + } + void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) { fillRadial(fill, dst, y, x, len, op, a); @@ -75,9 +95,6 @@ struct FillRadial }; -static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity = 255); - - static inline uint8_t _alpha(uint8_t* a) { return *a; @@ -148,70 +165,70 @@ static inline bool _matting(const SwSurface* surface) else return false; } - -static inline bool _masking(const SwSurface* surface) +static inline uint8_t _opMaskNone(uint8_t s, TVG_UNUSED uint8_t d, TVG_UNUSED uint8_t a) { - if ((int)surface->compositor->method >= (int)CompositeMethod::AddMask) return true; - else return false; + return s; } - -static inline uint32_t _opMaskAdd(uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opMaskAdd(uint8_t s, uint8_t d, uint8_t a) { - return s + ALPHA_BLEND(d, a); + return s + MULTIPLY(d, a); } -static inline uint32_t _opMaskSubtract(TVG_UNUSED uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opMaskSubtract(uint8_t s, uint8_t d, TVG_UNUSED uint8_t a) { - return ALPHA_BLEND(d, a); + return MULTIPLY(s, 255 - d); } -static inline uint32_t _opMaskDifference(uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opMaskIntersect(uint8_t s, uint8_t d, TVG_UNUSED uint8_t a) { - return ALPHA_BLEND(s, IA(d)) + ALPHA_BLEND(d, a); + return MULTIPLY(s, d); } -static inline uint32_t _opAMaskAdd(uint32_t s, uint32_t d, uint8_t a) +static inline uint8_t _opMaskDifference(uint8_t s, uint8_t d, uint8_t a) { - return INTERPOLATE(s, d, a); + return MULTIPLY(s, 255 - d) + MULTIPLY(d, a); } -static inline uint32_t _opAMaskSubtract(TVG_UNUSED uint32_t s, uint32_t d, uint8_t a) +static inline bool _direct(CompositeMethod method) { - return ALPHA_BLEND(d, IA(ALPHA_BLEND(s, a))); -} - - -static inline uint32_t _opAMaskDifference(uint32_t s, uint32_t d, uint8_t a) -{ - auto t = ALPHA_BLEND(s, a); - return ALPHA_BLEND(t, IA(d)) + ALPHA_BLEND(d, IA(t)); + //subtract & Intersect allows the direct composition + if (method == CompositeMethod::SubtractMask || method == CompositeMethod::IntersectMask) return true; + return false; } -static inline SwBlender _getMaskOp(CompositeMethod method) +static inline SwMask _getMaskOp(CompositeMethod method) { switch (method) { case CompositeMethod::AddMask: return _opMaskAdd; case CompositeMethod::SubtractMask: return _opMaskSubtract; case CompositeMethod::DifferenceMask: return _opMaskDifference; + case CompositeMethod::IntersectMask: return _opMaskIntersect; default: return nullptr; } } -static inline SwBlender _getAMaskOp(CompositeMethod method) +static bool _compositeMaskImage(SwSurface* surface, const SwImage* image, const SwBBox& region) { - switch (method) { - case CompositeMethod::AddMask: return _opAMaskAdd; - case CompositeMethod::SubtractMask: return _opAMaskSubtract; - case CompositeMethod::DifferenceMask: return _opAMaskDifference; - default: return nullptr; + auto dbuffer = &surface->buf8[region.min.y * surface->stride + region.min.x]; + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + + for (auto y = region.min.y; y < region.max.y; ++y) { + auto dst = dbuffer; + auto src = sbuffer; + for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) { + *dst = *src + MULTIPLY(*dst, ~*src); + } + dbuffer += surface->stride; + sbuffer += image->stride; } + return true; } @@ -284,78 +301,57 @@ static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t /* Rect */ /************************************************************************/ -static void _rasterMaskedRectDup(SwSurface* surface, const SwBBox& region, SwBlender opMask, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static bool _rasterCompositeMaskedRect(SwSurface* surface, const SwBBox& region, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto h = static_cast<uint32_t>(region.max.y - region.min.y); - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * surface->compositor->image.stride + region.min.x); //compositor buffer auto cstride = surface->compositor->image.stride; - auto color = surface->join(r, g, b, a); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); //compositor buffer auto ialpha = 255 - a; for (uint32_t y = 0; y < h; ++y) { auto cmp = cbuffer; for (uint32_t x = 0; x < w; ++x, ++cmp) { - *cmp = opMask(color, *cmp, ialpha); + *cmp = maskOp(a, *cmp, ialpha); } cbuffer += cstride; } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static void _rasterMaskedRectInt(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static bool _rasterDirectMaskedRect(SwSurface* surface, const SwBBox& region, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto h = static_cast<uint32_t>(region.max.y - region.min.y); - auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x); //compositor buffer + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); //destination buffer - for (auto y = surface->compositor->bbox.min.y; y < surface->compositor->bbox.max.y; ++y) { - auto cmp = surface->compositor->image.buf32 + (y * cstride + surface->compositor->bbox.min.x); - if (y == region.min.y) { - for (auto y2 = y; y2 < region.max.y; ++y2) { - auto tmp = cmp; - auto x = surface->compositor->bbox.min.x; - while (x < surface->compositor->bbox.max.x) { - if (x == region.min.x) { - for (uint32_t i = 0; i < w; ++i, ++tmp) { - *tmp = ALPHA_BLEND(*tmp, a); - } - x += w; - } else { - *tmp = 0; - ++tmp; - ++x; - } - } - cmp += cstride; - } - y += (h - 1); - } else { - rasterPixel32(cmp, 0x00000000, 0, w); - cmp += cstride; + for (uint32_t y = 0; y < h; ++y) { + auto cmp = cbuffer; + auto dst = dbuffer; + for (uint32_t x = 0; x < w; ++x, ++cmp, ++dst) { + auto tmp = maskOp(a, *cmp, 0); //not use alpha. + *dst = tmp + MULTIPLY(*dst, ~tmp); } + cbuffer += surface->compositor->image.stride; + dbuffer += surface->stride; } + return true; } static bool _rasterMaskedRect(SwSurface* surface, const SwBBox& region, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { - //32bit channels composition - if (surface->channelSize != sizeof(uint32_t)) return false; - - TVGLOG("SW_ENGINE", "Masked(%d) Rect [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.max.y, region.min.y); + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; - if (surface->compositor->method == CompositeMethod::IntersectMask) { - _rasterMaskedRectInt(surface, region, r, g, b, a); - } else if (auto opMask = _getMaskOp(surface->compositor->method)) { - //Other Masking operations: Add, Subtract, Difference ... - _rasterMaskedRectDup(surface, region, opMask, r, g, b, a); - } else { - return false; - } + TVGLOG("SW_ENGINE", "Masked(%d) Rect [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); - //Masking Composition - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectMaskedRect(surface, region, maskOp, r, g, b, a); + else return _rasterCompositeMaskedRect(surface, region, maskOp, r, g, b, a); + return false; } @@ -444,7 +440,7 @@ static bool _rasterSolidRect(SwSurface* surface, const SwBBox& region, uint8_t r //8bits grayscale if (surface->channelSize == sizeof(uint8_t)) { for (uint32_t y = 0; y < h; ++y) { - rasterGrayscale8(surface->buf8, 255, region.min.y * surface->stride + region.min.x, w); + rasterGrayscale8(surface->buf8, 255, (y + region.min.y) * surface->stride + region.min.x, w); } return true; } @@ -471,53 +467,44 @@ static bool _rasterRect(SwSurface* surface, const SwBBox& region, uint8_t r, uin /* Rle */ /************************************************************************/ -static void _rasterMaskedRleDup(SwSurface* surface, SwRleData* rle, SwBlender maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRleData* rle, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto span = rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; auto cstride = surface->compositor->image.stride; - auto color = surface->join(r, g, b, a); - uint32_t src; + uint8_t src; for (uint32_t i = 0; i < rle->size; ++i, ++span) { auto cmp = &cbuffer[span->y * cstride + span->x]; - if (span->coverage == 255) src = color; - else src = ALPHA_BLEND(color, span->coverage); - auto ialpha = IA(src); + if (span->coverage == 255) src = a; + else src = MULTIPLY(a, span->coverage); + auto ialpha = 255 - src; for (auto x = 0; x < span->len; ++x, ++cmp) { *cmp = maskOp(src, *cmp, ialpha); } } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static void _rasterMaskedRleInt(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, uint8_t b, uint8_t a) +static bool _rasterDirectMaskedRle(SwSurface* surface, SwRleData* rle, SwMask maskOp, uint8_t r, uint8_t g, uint8_t b, uint8_t a) { auto span = rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; auto cstride = surface->compositor->image.stride; - auto color = surface->join(r, g, b, a); - uint32_t src; - - for (auto y = surface->compositor->bbox.min.y; y < surface->compositor->bbox.max.y; ++y) { - auto cmp = &cbuffer[y * cstride]; - auto x = surface->compositor->bbox.min.x; - while (x < surface->compositor->bbox.max.x) { - if (y == span->y && x == span->x && x + span->len <= surface->compositor->bbox.max.x) { - if (span->coverage == 255) src = color; - else src = ALPHA_BLEND(color, span->coverage); - auto alpha = A(src); - for (uint32_t i = 0; i < span->len; ++i) { - cmp[x + i] = ALPHA_BLEND(cmp[x + i], alpha); - } - x += span->len; - ++span; - } else { - cmp[x] = 0; - ++x; - } + uint8_t src; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto cmp = &cbuffer[span->y * cstride + span->x]; + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + if (span->coverage == 255) src = a; + else src = MULTIPLY(a, span->coverage); + for (auto x = 0; x < span->len; ++x, ++cmp, ++dst) { + auto tmp = maskOp(src, *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); } } + return true; } @@ -525,20 +512,13 @@ static bool _rasterMaskedRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint { TVGLOG("SW_ENGINE", "Masked(%d) Rle", (int)surface->compositor->method); - //32bit channels composition - if (surface->channelSize != sizeof(uint32_t)) return false; - - if (surface->compositor->method == CompositeMethod::IntersectMask) { - _rasterMaskedRleInt(surface, rle, r, g, b, a); - } else if (auto opMask = _getMaskOp(surface->compositor->method)) { - //Other Masking operations: Add, Subtract, Difference ... - _rasterMaskedRleDup(surface, rle, opMask, r, g, b, a); - } else { - return false; - } + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; - //Masking Composition - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectMaskedRle(surface, rle, maskOp, r, g, b, a); + else return _rasterCompositeMaskedRle(surface, rle, maskOp, r, g, b, a); + return false; } @@ -644,7 +624,15 @@ static bool _rasterSolidRle(SwSurface* surface, const SwRleData* rle, uint8_t r, //8bit grayscale } else if (surface->channelSize == sizeof(uint8_t)) { for (uint32_t i = 0; i < rle->size; ++i, ++span) { - rasterGrayscale8(surface->buf8, span->coverage, span->y * surface->stride + span->x, span->len); + if (span->coverage == 255) { + rasterGrayscale8(surface->buf8, span->coverage, span->y * surface->stride + span->x, span->len); + } else { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + auto ialpha = 255 - span->coverage; + for (uint32_t x = 0; x < span->len; ++x, ++dst) { + *dst = span->coverage + MULTIPLY(*dst, ialpha); + } + } } } return true; @@ -669,28 +657,11 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint8_t r, uint8_t g, /************************************************************************/ -/* RLE Transformed Image */ -/************************************************************************/ - -static bool _transformedRleImage(SwSurface* surface, const SwImage* image, const Matrix* transform, uint8_t opacity) -{ - auto ret = _rasterTexmapPolygon(surface, image, transform, nullptr, opacity); - - //Masking Composition - if (_compositing(surface) && _masking(surface)) { - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); - } - - return ret; - -} - - -/************************************************************************/ /* RLE Scaled Image */ /************************************************************************/ -static void _rasterScaledMaskedRleImageDup(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); @@ -700,82 +671,77 @@ static void _rasterScaledMaskedRleImageDup(SwSurface* surface, const SwImage* im for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { auto sy = span->y * itransform->e22 + itransform->e23; if ((uint32_t)sy >= image->h) continue; - auto cmp = &surface->compositor->image.buf32[span->y * surface->compositor->image.stride + span->x]; + auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x]; auto a = MULTIPLY(span->coverage, opacity); if (a == 255) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = maskOp(src, *cmp, 255); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + *cmp = maskOp(src, *cmp, ~src); } } else { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = amaskOp(src, *cmp, a); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = MULTIPLY(src, a); + *cmp = maskOp(tmp, *cmp, ~tmp); } } } + return true; } -static void _rasterScaledMaskedRleImageInt(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterDirectScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); auto sampleSize2 = sampleSize * sampleSize; auto span = image->rle->spans; - auto cbuffer = surface->compositor->image.buf32; - auto cstride = surface->compositor->image.stride; - for (auto y = surface->compositor->bbox.min.y; y < surface->compositor->bbox.max.y; ++y) { - auto cmp = &cbuffer[y * cstride]; - for (auto x = surface->compositor->bbox.min.x; x < surface->compositor->bbox.max.x; ++x) { - if (y == span->y && x == span->x && x + span->len <= surface->compositor->bbox.max.x) { - auto sy = span->y * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; - auto alpha = MULTIPLY(span->coverage, opacity); - if (alpha == 255) { - for (uint32_t i = 0; i < span->len; ++i) { - auto sx = (x + i) * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - cmp[x + i] = ALPHA_BLEND(cmp[x + i], A(src)); - } - } else { - for (uint32_t i = 0; i < span->len; ++i) { - auto sx = (x + i) * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - cmp[x + i] = ALPHA_BLEND(cmp[x + i], A(ALPHA_BLEND(src, alpha))); - } - } - x += span->len - 1; - ++span; - } else { - cmp[x] = 0; + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto sy = span->y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; + auto cmp = &surface->compositor->image.buf8[span->y * surface->compositor->image.stride + span->x]; + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + auto a = MULTIPLY(span->coverage, opacity); + if (a == 255) { + for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp, ++dst) { + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = maskOp(src, *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); + } + } else { + for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++cmp, ++dst) { + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = maskOp(MULTIPLY(src, a), *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); } } } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } - +#endif static bool _rasterScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { +#if 0 //Enable it when GRAYSCALE image is supported TVGLOG("SW_ENGINE", "Scaled Masked(%d) Rle Image", (int)surface->compositor->method); - if (surface->compositor->method == CompositeMethod::IntersectMask) { - _rasterScaledMaskedRleImageInt(surface, image, itransform, region, opacity); - } else if (auto opMask = _getMaskOp(surface->compositor->method)) { - //Other Masking operations: Add, Subtract, Difference ... - _rasterScaledMaskedRleImageDup(surface, image, itransform, region, opMask, _getAMaskOp(surface->compositor->method), opacity); - } else { - return false; - } - //Masking Composition - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; + + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectScaledMaskedRleImage(surface, image, itransform, region, maskOp, opacity); + else return _rasterCompositeScaledMaskedRleImage(surface, image, itransform, region, maskOp, opacity); +#endif + return false; } @@ -895,6 +861,11 @@ static bool _rasterScaledRleImage(SwSurface* surface, const SwImage* image, cons static bool _scaledRleImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint8_t opacity) { + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported scaled rle image!"); + return false; + } + Matrix itransform; if (transform) { @@ -917,78 +888,72 @@ static bool _scaledRleImage(SwSurface* surface, const SwImage* image, const Matr /* RLE Direct Image */ /************************************************************************/ -static void _rasterDirectMaskedRleImageDup(SwSurface* surface, const SwImage* image, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeDirectMaskedRleImage(SwSurface* surface, const SwImage* image, SwMask maskOp, uint8_t opacity) { auto span = image->rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; auto ctride = surface->compositor->image.stride; for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { - auto src = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto src = image->buf8 + (span->y + image->oy) * image->stride + (span->x + image->ox); auto cmp = &cbuffer[span->y * ctride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); if (alpha == 255) { for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp) { - *cmp = maskOp(*src, *cmp, IA(*src)); + *cmp = maskOp(*src, *cmp, ~*src); } } else { for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp) { - *cmp = amaskOp(*src, *cmp, alpha); + auto tmp = MULTIPLY(*src, alpha); + *cmp = maskOp(*src, *cmp, ~tmp); } } } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static void _rasterDirectMaskedRleImageInt(SwSurface* surface, const SwImage* image, uint8_t opacity) +static bool _rasterDirectDirectMaskedRleImage(SwSurface* surface, const SwImage* image, SwMask maskOp, uint8_t opacity) { auto span = image->rle->spans; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; auto ctride = surface->compositor->image.stride; - for (auto y = surface->compositor->bbox.min.y; y < surface->compositor->bbox.max.y; ++y) { - auto cmp = &cbuffer[y * ctride]; - auto x = surface->compositor->bbox.min.x; - while (x < surface->compositor->bbox.max.x) { - if (y == span->y && x == span->x && x + span->len <= surface->compositor->bbox.max.x) { - auto alpha = MULTIPLY(span->coverage, opacity); - auto src = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); - if (alpha == 255) { - for (uint32_t i = 0; i < span->len; ++i, ++src) { - cmp[x + i] = ALPHA_BLEND(cmp[x + i], A(*src)); - } - } else { - for (uint32_t i = 0; i < span->len; ++i, ++src) { - auto t = ALPHA_BLEND(*src, alpha); - cmp[x + i] = ALPHA_BLEND(cmp[x + i], A(t)); - } - } - x += span->len; - ++span; - } else { - cmp[x] = 0; - ++x; + for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + auto src = image->buf8 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto cmp = &cbuffer[span->y * ctride + span->x]; + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + auto alpha = MULTIPLY(span->coverage, opacity); + if (alpha == 255) { + for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp, ++dst) { + auto tmp = maskOp(*src, *cmp, 0); //not use alpha + *dst = INTERPOLATE8(tmp, *dst, (255 - tmp)); + } + } else { + for (uint32_t x = 0; x < span->len; ++x, ++src, ++cmp, ++dst) { + auto tmp = maskOp(MULTIPLY(*src, alpha), *cmp, 0); //not use alpha + *dst = INTERPOLATE8(tmp, *dst, (255 - tmp)); } } } + return true; } - +#endif static bool _rasterDirectMaskedRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) { +#if 0 //Enable it when GRAYSCALE image is supported TVGLOG("SW_ENGINE", "Direct Masked(%d) Rle Image", (int)surface->compositor->method); - if (surface->compositor->method == CompositeMethod::IntersectMask) { - _rasterDirectMaskedRleImageInt(surface, image, opacity); - } else if (auto opMask = _getMaskOp(surface->compositor->method)) { - //Other Masking operations: Add, Subtract, Difference ... - _rasterDirectMaskedRleImageDup(surface, image, opMask, _getAMaskOp(surface->compositor->method), opacity); - } else { - return false; - } + //8bit masking channels composition + if (surface->channelSize != sizeof(uint8_t)) return false; - //Masking Composition - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) _rasterDirectDirectMaskedRleImage(surface, image, maskOp, opacity); + else return _rasterCompositeDirectMaskedRleImage(surface, image, maskOp, opacity); +#endif + return false; } @@ -1076,6 +1041,11 @@ static bool _rasterDirectRleImage(SwSurface* surface, const SwImage* image, uint static bool _directRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) { + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale rle image!"); + return false; + } + if (_compositing(surface)) { if (_matting(surface)) return _rasterDirectMattedRleImage(surface, image, opacity); else return _rasterDirectMaskedRleImage(surface, image, opacity); @@ -1089,40 +1059,17 @@ static bool _directRleImage(SwSurface* surface, const SwImage* image, uint8_t op /************************************************************************/ -/* Transformed Image */ -/************************************************************************/ - -static bool _transformedImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint8_t opacity) -{ - auto ret = _rasterTexmapPolygon(surface, image, transform, ®ion, opacity); - - //Masking Composition - if (_compositing(surface) && _masking(surface)) { - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); - } - - return ret; -} - - -static bool _transformedImageMesh(SwSurface* surface, const SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox* region, uint8_t opacity) -{ - //TODO: Not completed for all cases. - return _rasterTexmapPolygonMesh(surface, image, mesh, transform, region, opacity); -} - - -/************************************************************************/ /*Scaled Image */ /************************************************************************/ -static void _rasterScaledMaskedImageDup(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); auto sampleSize2 = sampleSize * sampleSize; auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); for (auto y = region.min.y; y < region.max.y; ++y) { auto sy = y * itransform->e22 + itransform->e23; @@ -1132,92 +1079,73 @@ static void _rasterScaledMaskedImageDup(SwSurface* surface, const SwImage* image for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = maskOp(src, *cmp, IA(src)); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + *cmp = maskOp(src, *cmp, ~src); } } else { for (auto x = region.min.x; x < region.max.x; ++x, ++cmp) { auto sx = x * itransform->e11 + itransform->e13; if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *cmp = amaskOp(src, *cmp, opacity); + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = MULTIPLY(src, opacity); + *cmp = maskOp(tmp, *cmp, ~tmp); } } cbuffer += cstride; } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static void _rasterScaledMaskedImageInt(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) + +static bool _rasterDirectScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; auto sampleSize = _sampleSize(image->scale); auto sampleSize2 = sampleSize * sampleSize; - auto h = static_cast<uint32_t>(region.max.y - region.min.y); - auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (surface->compositor->bbox.min.y * cstride + surface->compositor->bbox.min.x); - - for (auto y = surface->compositor->bbox.min.y; y < surface->compositor->bbox.max.y; ++y) { - if (y == region.min.y) { - auto cbuffer2 = cbuffer; - for (auto y2 = y; y2 < region.max.y; ++y2) { - auto sy = y2 * itransform->e22 + itransform->e23; - if ((uint32_t)sy >= image->h) continue; - auto tmp = cbuffer2; - auto x = surface->compositor->bbox.min.x; - while (x < surface->compositor->bbox.max.x) { - if (x == region.min.x) { - if (opacity == 255) { - for (uint32_t i = 0; i < w; ++i, ++tmp) { - auto sx = (x + i) * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); - *tmp = ALPHA_BLEND(*tmp, A(src)); - } - } else { - for (uint32_t i = 0; i < w; ++i, ++tmp) { - auto sx = (x + i) * itransform->e11 + itransform->e13; - if ((uint32_t)sx >= image->w) continue; - auto src = ALPHA_BLEND(scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2), opacity); - *tmp = ALPHA_BLEND(*tmp, A(src)); - } - } - x += w; - } else { - *tmp = 0; - ++tmp; - ++x; - } - } - cbuffer2 += cstride; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); + + for (auto y = region.min.y; y < region.max.y; ++y) { + auto sy = y * itransform->e22 + itransform->e23; + if ((uint32_t)sy >= image->h) continue; + auto cmp = cbuffer; + auto dst = dbuffer; + if (opacity == 255) { + for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) { + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = maskOp(src, *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); } - y += (h - 1); } else { - auto tmp = cbuffer; - for (auto x = surface->compositor->bbox.min.x; x < surface->compositor->bbox.max.x; ++x, ++tmp) { - *tmp = 0; + for (auto x = region.min.x; x < region.max.x; ++x, ++cmp, ++dst) { + auto sx = x * itransform->e11 + itransform->e13; + if ((uint32_t)sx >= image->w) continue; + auto src = scaleMethod(image->buf8, image->stride, image->w, image->h, sx, sy, sampleSize, sampleSize2); + auto tmp = MULTIPLY(src, opacity); + auto tmp2 = maskOp(tmp, *cmp, 0); //not use alpha + *dst = tmp2 + MULTIPLY(*dst, ~tmp2); } } cbuffer += cstride; + dbuffer += surface->stride; } + return true; } - +#endif static bool _rasterScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { +#if 0 //Enable it when GRAYSCALE image is supported TVGLOG("SW_ENGINE", "Scaled Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); - if (surface->compositor->method == CompositeMethod::IntersectMask) { - _rasterScaledMaskedImageInt(surface, image, itransform, region, opacity); - } else if (auto opMask = _getMaskOp(surface->compositor->method)) { - //Other Masking operations: Add, Subtract, Difference ... - _rasterScaledMaskedImageDup(surface, image, itransform, region, opMask, _getAMaskOp(surface->compositor->method), opacity); - } else { - return false; - } - - //Masking Composition - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectScaledMaskedImage(surface, image, itransform, region, maskOp, opacity); + else return _rasterCompositeScaledMaskedImage(surface, image, itransform, region, maskOp, opacity); +#endif + return false; } @@ -1329,6 +1257,11 @@ static bool _rasterScaledImage(SwSurface* surface, const SwImage* image, const M static bool _scaledImage(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint8_t opacity) { + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale Textmap polygon mesh!"); + return false; + } + Matrix itransform; if (transform) { @@ -1351,125 +1284,135 @@ static bool _scaledImage(SwSurface* surface, const SwImage* image, const Matrix* /* Direct Image */ /************************************************************************/ -static void _rasterDirectMaskedImageDup(SwSurface* surface, const SwImage* image, const SwBBox& region, SwBlender maskOp, SwBlender amaskOp, uint8_t opacity) +#if 0 //Enable it when GRAYSCALE image is supported +static bool _rasterCompositeDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); //compositor buffer - auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); //compositor buffer + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); for (uint32_t y = 0; y < h; ++y) { auto cmp = cbuffer; auto src = sbuffer; if (opacity == 255) { for (uint32_t x = 0; x < w; ++x, ++src, ++cmp) { - *cmp = maskOp(*src, *cmp, IA(*src)); + *cmp = maskOp(*src, *cmp, ~*src); } } else { for (uint32_t x = 0; x < w; ++x, ++src, ++cmp) { - *cmp = amaskOp(*src, *cmp, opacity); + auto tmp = MULTIPLY(*src, opacity); + *cmp = maskOp(tmp, *cmp, ~tmp); } } cbuffer += cstride; sbuffer += image->stride; } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } -static void _rasterDirectMaskedImageInt(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +static bool _rasterDirectDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, SwMask maskOp, uint8_t opacity) { auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (surface->compositor->bbox.min.y * cstride + surface->compositor->bbox.min.x); - - for (auto y = surface->compositor->bbox.min.y; y < surface->compositor->bbox.max.y; ++y) { - if (y == region.min.y) { - auto cbuffer2 = cbuffer; - for (auto y2 = y; y2 < region.max.y; ++y2) { - auto tmp = cbuffer2; - auto x = surface->compositor->bbox.min.x; - while (x < surface->compositor->bbox.max.x) { - if (x == region.min.x) { - auto src = &image->buf32[(y2 + image->oy) * image->stride + (x + image->ox)]; - if (opacity == 255) { - for (uint32_t i = 0; i < w; ++i, ++tmp, ++src) { - *tmp = ALPHA_BLEND(*tmp, A(*src)); - } - } else { - for (uint32_t i = 0; i < w; ++i, ++tmp, ++src) { - auto t = ALPHA_BLEND(*src, opacity); - *tmp = ALPHA_BLEND(*tmp, A(t)); - } - } - x += w; - } else { - *tmp = 0; - ++tmp; - ++x; - } - } - cbuffer2 += cstride; + + auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); //compositor buffer + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); //destination buffer + auto sbuffer = image->buf8 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + + for (uint32_t y = 0; y < h; ++y) { + auto cmp = cbuffer; + auto dst = dbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (uint32_t x = 0; x < w; ++x, ++src, ++cmp, ++dst) { + auto tmp = maskOp(*src, *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); } - y += (h - 1); } else { - rasterPixel32(cbuffer, 0x00000000, 0, surface->compositor->bbox.max.x - surface->compositor->bbox.min.x); + for (uint32_t x = 0; x < w; ++x, ++src, ++cmp, ++dst) { + auto tmp = maskOp(MULTIPLY(*src, opacity), *cmp, 0); //not use alpha + *dst = tmp + MULTIPLY(*dst, ~tmp); + } } cbuffer += cstride; + dbuffer += surface->stride; + sbuffer += image->stride; } + return true; } - +#endif static bool _rasterDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) { - TVGLOG("SW_ENGINE", "Direct Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); + TVGERR("SW_ENGINE", "Not Supported: Direct Masked(%d) Image [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); - if (surface->compositor->method == CompositeMethod::IntersectMask) { - _rasterDirectMaskedImageInt(surface, image, region, opacity); - } else if (auto opMask = _getMaskOp(surface->compositor->method)) { - //Other Masking operations: Add, Subtract, Difference ... - _rasterDirectMaskedImageDup(surface, image, region, opMask, _getAMaskOp(surface->compositor->method), opacity); - } else { - return false; - } - //Masking Composition - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox); +#if 0 //Enable it when GRAYSCALE image is supported + auto maskOp = _getMaskOp(surface->compositor->method); + if (_direct(surface->compositor->method)) return _rasterDirectDirectMaskedImage(surface, image, region, maskOp, opacity); + else return _rasterCompositeDirectMaskedImage(surface, image, region, maskOp, opacity); +#endif + return false; } static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) { - auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto csize = surface->compositor->image.channelSize; auto alpha = surface->alpha(surface->compositor->method); - - TVGLOG("SW_ENGINE", "Direct Matted(%d) Image [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h); - auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); auto cbuffer = surface->compositor->image.buf8 + (region.min.y * surface->compositor->image.stride + region.min.x) * csize; //compositor buffer - for (uint32_t y = 0; y < h; ++y) { - auto dst = buffer; - auto cmp = cbuffer; - auto src = sbuffer; - if (opacity == 255) { - for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { - auto tmp = ALPHA_BLEND(*src, alpha(cmp)); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + TVGLOG("SW_ENGINE", "Direct Matted(%d) Image [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h); + + //32 bits + if (surface->channelSize == sizeof(uint32_t)) { + auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = buffer; + auto cmp = cbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, alpha(cmp)); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } + } else { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + auto tmp = ALPHA_BLEND(*src, MULTIPLY(opacity, alpha(cmp))); + *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + } } - } else { - for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { - auto tmp = ALPHA_BLEND(*src, MULTIPLY(opacity, alpha(cmp))); - *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); + buffer += surface->stride; + cbuffer += surface->compositor->image.stride * csize; + sbuffer += image->stride; + } + //8 bits + } else if (surface->channelSize == sizeof(uint8_t)) { + auto buffer = surface->buf8 + (region.min.y * surface->stride) + region.min.x; + for (uint32_t y = 0; y < h; ++y) { + auto dst = buffer; + auto cmp = cbuffer; + auto src = sbuffer; + if (opacity == 255) { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + *dst = MULTIPLY(A(*src), alpha(cmp)); + } + } else { + for (uint32_t x = 0; x < w; ++x, ++dst, ++src, cmp += csize) { + *dst = MULTIPLY(A(*src), MULTIPLY(opacity, alpha(cmp))); + } } + buffer += surface->stride; + cbuffer += surface->compositor->image.stride * csize; + sbuffer += image->stride; } - buffer += surface->stride; - cbuffer += surface->compositor->image.stride * csize; - sbuffer += image->stride; } return true; } @@ -1477,6 +1420,11 @@ static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, c static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) { + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale image!"); + return false; + } + auto dbuffer = &surface->buf32[region.min.y * surface->stride + region.min.x]; auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); @@ -1504,6 +1452,11 @@ static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image, static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) { + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported grayscale image!"); + return false; + } + auto dbuffer = &surface->buf32[region.min.y * surface->stride + region.min.x]; auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); @@ -1549,12 +1502,12 @@ static bool _rasterImage(SwSurface* surface, SwImage* image, const Matrix* trans if (image->rle) { if (image->direct) return _directRleImage(surface, image, opacity); else if (image->scaled) return _scaledRleImage(surface, image, transform, region, opacity); - else return _transformedRleImage(surface, image, transform, opacity); + else return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity); //Whole Image } else { if (image->direct) return _directImage(surface, image, region, opacity); else if (image->scaled) return _scaledImage(surface, image, transform, region, opacity); - else return _transformedImage(surface, image, transform, region, opacity); + else return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity); } } @@ -1564,52 +1517,36 @@ static bool _rasterImage(SwSurface* surface, SwImage* image, const Matrix* trans /************************************************************************/ template<typename fillMethod> -static void _rasterGradientMaskedRectDup(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwBlender maskOp) +static bool _rasterCompositeGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwMask maskOp) { auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); for (uint32_t y = 0; y < h; ++y) { fillMethod()(fill, cbuffer, region.min.y + y, region.min.x, w, maskOp, 255); cbuffer += surface->stride; } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } template<typename fillMethod> -static void _rasterGradientMaskedRectInt(SwSurface* surface, const SwBBox& region, const SwFill* fill) +static bool _rasterDirectGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwMask maskOp) { auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto cstride = surface->compositor->image.stride; + auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x); + auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x); - for (auto y = surface->compositor->bbox.min.y; y < surface->compositor->bbox.max.y; ++y) { - auto cmp = surface->compositor->image.buf32 + (y * cstride + surface->compositor->bbox.min.x); - if (y == region.min.y) { - for (auto y2 = y; y2 < region.max.y; ++y2) { - auto tmp = cmp; - auto x = surface->compositor->bbox.min.x; - while (x < surface->compositor->bbox.max.x) { - if (x == region.min.x) { - fillMethod()(fill, tmp, y2, x, w, opMaskPreIntersect, 255); - x += w; - tmp += w; - } else { - *tmp = 0; - ++tmp; - ++x; - } - } - cmp += cstride; - } - y += (h - 1); - } else { - rasterPixel32(cmp, 0x00000000, 0, surface->compositor->bbox.max.x -surface->compositor->bbox.min.x); - cmp += cstride; - } + for (uint32_t y = 0; y < h; ++y) { + fillMethod()(fill, dbuffer, region.min.y + y, region.min.x, w, cbuffer, maskOp, 255); + cbuffer += cstride; + dbuffer += surface->stride; } + return true; } @@ -1618,16 +1555,14 @@ static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region, { auto method = surface->compositor->method; - TVGLOG("SW_ENGINE", "Masked(%d) Gradient [Region: %lu %lu %lu %lu]", (int)surface->compositor->method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); + TVGLOG("SW_ENGINE", "Masked(%d) Gradient [Region: %lu %lu %lu %lu]", (int)method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); - if (method == CompositeMethod::AddMask) _rasterGradientMaskedRectDup<fillMethod>(surface, region, fill, opMaskPreAdd); - else if (method == CompositeMethod::SubtractMask) _rasterGradientMaskedRectDup<fillMethod>(surface, region, fill, opMaskPreSubtract); - else if (method == CompositeMethod::DifferenceMask) _rasterGradientMaskedRectDup<fillMethod>(surface, region, fill, opMaskPreDifference); - else if (method == CompositeMethod::IntersectMask) _rasterGradientMaskedRectInt<fillMethod>(surface, region, fill); - else return false; + auto maskOp = _getMaskOp(method); - //Masking Composition - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox, 255); + if (_direct(method)) return _rasterDirectGradientMaskedRect<fillMethod>(surface, region, fill, maskOp); + else return _rasterCompositeGradientMaskedRect<fillMethod>(surface, region, fill, maskOp); + + return false; } @@ -1719,8 +1654,6 @@ static bool _rasterLinearGradientRect(SwSurface* surface, const SwBBox& region, static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) { - if (fill->radial.a < FLT_EPSILON) return false; - if (_compositing(surface)) { if (_matting(surface)) return _rasterGradientMattedRect<FillRadial>(surface, region, fill); else return _rasterGradientMaskedRect<FillRadial>(surface, region, fill); @@ -1734,64 +1667,54 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region, } - /************************************************************************/ /* Rle Gradient */ /************************************************************************/ template<typename fillMethod> -static void _rasterGradientMaskedRleDup(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwBlender maskOp) +static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwMask maskOp) { auto span = rle->spans; auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32; + auto cbuffer = surface->compositor->image.buf8; for (uint32_t i = 0; i < rle->size; ++i, ++span) { auto cmp = &cbuffer[span->y * cstride + span->x]; fillMethod()(fill, cmp, span->y, span->x, span->len, maskOp, span->coverage); } + return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); } template<typename fillMethod> -static void _rasterGradientMaskedRleInt(SwSurface* surface, const SwRleData* rle, const SwFill* fill) +static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwMask maskOp) { auto span = rle->spans; auto cstride = surface->compositor->image.stride; - auto cbuffer = surface->compositor->image.buf32; - - for (auto y = surface->compositor->bbox.min.y; y < surface->compositor->bbox.max.y; ++y) { - auto cmp = &cbuffer[y * cstride]; - auto x = surface->compositor->bbox.min.x; - while (x < surface->compositor->bbox.max.x) { - if (y == span->y && x == span->x && x + span->len <= surface->compositor->bbox.max.x) { - fillMethod()(fill, cmp, span->y, span->x, span->len, opMaskIntersect, span->coverage); - x += span->len; - ++span; - } else { - cmp[x] = 0; - ++x; - } - } + auto cbuffer = surface->compositor->image.buf8; + auto dbuffer = surface->buf8; + + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto cmp = &cbuffer[span->y * cstride + span->x]; + auto dst = &dbuffer[span->y * surface->stride + span->x]; + fillMethod()(fill, dst, span->y, span->x, span->len, cmp, maskOp, span->coverage); } + return true; } template<typename fillMethod> static bool _rasterGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) { - TVGLOG("SW_ENGINE", "Masked(%d) Rle Linear Gradient", (int)surface->compositor->method); - auto method = surface->compositor->method; - if (method == CompositeMethod::AddMask) _rasterGradientMaskedRleDup<fillMethod>(surface, rle, fill, opMaskAdd); - else if (method == CompositeMethod::SubtractMask) _rasterGradientMaskedRleDup<fillMethod>(surface, rle, fill, opMaskSubtract); - else if (method == CompositeMethod::DifferenceMask) _rasterGradientMaskedRleDup<fillMethod>(surface, rle, fill, opMaskDifference); - else if (method == CompositeMethod::IntersectMask) _rasterGradientMaskedRleInt<fillMethod>(surface, rle, fill); - else return false; + TVGLOG("SW_ENGINE", "Masked(%d) Rle Linear Gradient", (int)method); - //Masking Composition - return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox, 255); + auto maskOp = _getMaskOp(method); + + if (_direct(method)) return _rasterDirectGradientMaskedRle<fillMethod>(surface, rle, fill, maskOp); + else return _rasterCompositeGradientMaskedRle<fillMethod>(surface, rle, fill, maskOp); + return false; } @@ -1832,10 +1755,19 @@ static bool _rasterTranslucentGradientRle(SwSurface* surface, const SwRleData* r { auto span = rle->spans; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - auto dst = &surface->buf32[span->y * surface->stride + span->x]; - if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, 255); - else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendNormal, span->coverage); + //32 bits + if (surface->channelSize == sizeof(uint32_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendPreNormal, 255); + else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendNormal, span->coverage); + } + //8 bits + } else if (surface->channelSize == sizeof(uint8_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, 255); + } } return true; } @@ -1846,11 +1778,22 @@ static bool _rasterSolidGradientRle(SwSurface* surface, const SwRleData* rle, co { auto span = rle->spans; - for (uint32_t i = 0; i < rle->size; ++i, ++span) { - auto dst = &surface->buf32[span->y * surface->stride + span->x]; - if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendSrcOver, 255); - else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendInterp, span->coverage); + //32 bits + if (surface->channelSize == sizeof(uint32_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf32[span->y * surface->stride + span->x]; + if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, opBlendSrcOver, 255); + else fillMethod()(fill, dst, span->y, span->x, span->len, opBlendInterp, span->coverage); + } + //8 bits + } else if (surface->channelSize == sizeof(uint8_t)) { + for (uint32_t i = 0; i < rle->size; ++i, ++span) { + auto dst = &surface->buf8[span->y * surface->stride + span->x]; + if (span->coverage == 255) fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskNone, 255); + else fillMethod()(fill, dst, span->y, span->x, span->len, _opMaskAdd, span->coverage); + } } + return true; } @@ -1874,7 +1817,7 @@ static bool _rasterLinearGradientRle(SwSurface* surface, const SwRleData* rle, c static bool _rasterRadialGradientRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) { - if (!rle || fill->radial.a < FLT_EPSILON) return false; + if (!rle) return false; if (_compositing(surface)) { if (_matting(surface)) return _rasterGradientMattedRle<FillRadial>(surface, rle, fill); @@ -2018,11 +1961,6 @@ void rasterPremultiply(Surface* surface) bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id) { - if (surface->channelSize == sizeof(uint8_t)) { - TVGERR("SW_ENGINE", "Not supported grayscale gradient!"); - return false; - } - if (!shape->fill) return false; if (shape->fastTrack) { @@ -2038,11 +1976,6 @@ bool rasterGradientShape(SwSurface* surface, SwShape* shape, unsigned id) bool rasterGradientStroke(SwSurface* surface, SwShape* shape, unsigned id) { - if (surface->channelSize == sizeof(uint8_t)) { - TVGERR("SW_ENGINE", "Not supported grayscale gradient!"); - return false; - } - if (!shape->stroke || !shape->stroke->fill || !shape->strokeRle) return false; if (id == TVG_CLASS_ID_LINEAR) return _rasterLinearGradientRle(surface, shape->strokeRle, shape->stroke->fill); @@ -2059,7 +1992,6 @@ bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8 g = MULTIPLY(g, a); b = MULTIPLY(b, a); } - if (shape->fastTrack) return _rasterRect(surface, shape->bbox, r, g, b, a); else return _rasterRle(surface, shape->rle, r, g, b, a); } @@ -2079,19 +2011,10 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint bool rasterImage(SwSurface* surface, SwImage* image, const RenderMesh* mesh, const Matrix* transform, const SwBBox& bbox, uint8_t opacity) { - if (surface->channelSize == sizeof(uint8_t)) { - TVGERR("SW_ENGINE", "Not supported grayscale image!"); - return false; - } - //Verify Boundary if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast<SwCoord>(surface->w) || bbox.min.y >= static_cast<SwCoord>(surface->h)) return false; - //TOOD: switch (image->format) - //TODO: case: _rasterRGBImageMesh() - //TODO: case: _rasterGrayscaleImageMesh() - //TODO: case: _rasterAlphaImageMesh() - if (mesh && mesh->triangleCnt > 0) return _transformedImageMesh(surface, image, mesh, transform, &bbox, opacity); + if (mesh && mesh->triangleCnt > 0) return _rasterTexmapPolygonMesh(surface, image, mesh, transform, &bbox, opacity); else return _rasterImage(surface, image, transform, bbox, opacity); } |