diff --git a/src/loaders/lottie/tvgLottieBuilder.cpp b/src/loaders/lottie/tvgLottieBuilder.cpp index cb544b93..dd100833 100644 --- a/src/loaders/lottie/tvgLottieBuilder.cpp +++ b/src/loaders/lottie/tvgLottieBuilder.cpp @@ -1263,7 +1263,6 @@ void LottieBuilder::updateMasks(LottieLayer* layer, float frameNo) auto method = mask->method; auto opacity = mask->opacity(frameNo); auto expand = mask->expand(frameNo); - auto fastTrack = false; //single clipping //the first mask if (!pShape) { @@ -1276,7 +1275,6 @@ void LottieBuilder::updateMasks(LottieLayer* layer, float frameNo) if (layer->masks.count == 1 && compMethod == CompositeMethod::AlphaMask) { layer->scene->opacity(MULTIPLY(layer->scene->opacity(), opacity)); layer->scene->clip(cast(pShape)); - fastTrack = true; } else { layer->scene->composite(cast(pShape), compMethod); } @@ -1299,9 +1297,6 @@ void LottieBuilder::updateMasks(LottieLayer* layer, float frameNo) auto offset = LottieOffsetModifier(expand); mask->pathset(frameNo, P(pShape)->rs.path.cmds, P(pShape)->rs.path.pts, nullptr, nullptr, &offset, exps); } - - if (fastTrack) return; - pOpacity = opacity; pMethod = method; } diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h index 53c28049..e0109a72 100644 --- a/src/renderer/sw_engine/tvgSwCommon.h +++ b/src/renderer/sw_engine/tvgSwCommon.h @@ -569,7 +569,11 @@ void mpoolRetDashOutline(SwMpool* mpool, unsigned idx); bool rasterCompositor(SwSurface* surface); bool rasterGradientShape(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity); bool rasterShape(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); -bool rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity); +bool rasterTexmapPolygon(SwSurface* surface, const SwImage& image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity); +bool rasterScaledImage(SwSurface* surface, const SwImage& image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity); +bool rasterDirectImage(SwSurface* surface, const SwImage& image, const SwBBox& bbox, uint8_t opacity); +bool rasterScaledRleImage(SwSurface* surface, const SwImage& image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity); +bool rasterDirectRleImage(SwSurface* surface, const SwImage& image, uint8_t opacity); bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint8_t b, uint8_t a); bool rasterGradientStroke(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity); bool rasterClear(SwSurface* surface, uint32_t x, uint32_t y, uint32_t w, uint32_t h, pixel_t val = 0); diff --git a/src/renderer/sw_engine/tvgSwRaster.cpp b/src/renderer/sw_engine/tvgSwRaster.cpp index 5e29d2e2..b5089049 100644 --- a/src/renderer/sw_engine/tvgSwRaster.cpp +++ b/src/renderer/sw_engine/tvgSwRaster.cpp @@ -227,10 +227,10 @@ static inline SwMask _getMaskOp(CompositeMethod method) } -static bool _compositeMaskImage(SwSurface* surface, const SwImage* image, const SwBBox& region) +static bool _compositeMaskImage(SwSurface* surface, const SwImage& image, const SwBBox& region) { 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); + 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; @@ -239,7 +239,7 @@ static bool _compositeMaskImage(SwSurface* surface, const SwImage* image, const *dst = *src + MULTIPLY(*dst, ~*src); } dbuffer += surface->stride; - sbuffer += image->stride; + sbuffer += image.stride; } return true; } @@ -339,7 +339,7 @@ static bool _rasterCompositeMaskedRect(SwSurface* surface, const SwBBox& region, } cbuffer += cstride; } - return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); + return _compositeMaskImage(surface, surface->compositor->image, surface->compositor->bbox); } @@ -387,7 +387,7 @@ static bool _rasterMattedRect(SwSurface* surface, const SwBBox& region, uint8_t auto alpha = surface->alpha(surface->compositor->method); TVGLOG("SW_ENGINE", "Matted(%d) Rect [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h); - + //32bits channels if (surface->channelSize == sizeof(uint32_t)) { auto color = surface->join(r, g, b, a); @@ -506,7 +506,7 @@ static bool _rasterCompositeMaskedRle(SwSurface* surface, SwRle* rle, SwMask mas *cmp = maskOp(src, *cmp, ialpha); } } - return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox); + return _compositeMaskImage(surface, surface->compositor->image, surface->compositor->bbox); } @@ -681,45 +681,45 @@ static bool _rasterRle(SwSurface* surface, SwRle* rle, uint8_t r, uint8_t g, uin #define SCALED_IMAGE_RANGE_Y(y) \ auto sy = (y) * itransform->e22 + itransform->e23 - 0.49f; \ - if (sy <= -0.5f || (uint32_t)(sy + 0.5f) >= image->h) continue; \ + if (sy <= -0.5f || (uint32_t)(sy + 0.5f) >= image.h) continue; \ if (scaleMethod == _interpDownScaler) { \ auto my = (int32_t)nearbyint(sy); \ miny = my - (int32_t)sampleSize; \ if (miny < 0) miny = 0; \ maxy = my + (int32_t)sampleSize; \ - if (maxy >= (int32_t)image->h) maxy = (int32_t)image->h; \ + if (maxy >= (int32_t)image.h) maxy = (int32_t)image.h; \ } #define SCALED_IMAGE_RANGE_X \ auto sx = (x) * itransform->e11 + itransform->e13 - 0.49f; \ - if (sx <= -0.5f || (uint32_t)(sx + 0.5f) >= image->w) continue; \ + if (sx <= -0.5f || (uint32_t)(sx + 0.5f) >= image.w) continue; \ -static bool _rasterScaledMaskedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterScaledMaskedRleImage(SwSurface* surface, const SwImage& image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { TVGERR("SW_ENGINE", "Not Supported Scaled Masked(%d) Rle Image", (int)surface->compositor->method); return false; } -static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage& image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { TVGLOG("SW_ENGINE", "Scaled Matted(%d) Rle Image", (int)surface->compositor->method); - auto span = image->rle->spans; + auto span = image.rle->spans; auto csize = surface->compositor->image.channelSize; auto alpha = surface->alpha(surface->compositor->method); - auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; - auto sampleSize = _sampleSize(image->scale); + auto scaleMethod = image.scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image.scale); int32_t miny = 0, maxy = 0; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image.rle->size; ++i, ++span) { SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto cmp = &surface->compositor->image.buf8[(span->y * surface->compositor->image.stride + span->x) * csize]; auto a = MULTIPLY(span->coverage, opacity); for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst, cmp += csize) { SCALED_IMAGE_RANGE_X - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto src = scaleMethod(image.buf32, image.stride, image.w, image.h, sx, sy, miny, maxy, sampleSize); src = ALPHA_BLEND(src, (a == 255) ? alpha(cmp) : MULTIPLY(alpha(cmp), a)); *dst = src + ALPHA_BLEND(*dst, IA(src)); } @@ -728,28 +728,28 @@ static bool _rasterScaledMattedRleImage(SwSurface* surface, const SwImage* image } -static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage& image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { - auto span = image->rle->spans; - auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; - auto sampleSize = _sampleSize(image->scale); + auto span = image.rle->spans; + auto scaleMethod = image.scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image.scale); int32_t miny = 0, maxy = 0; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image.rle->size; ++i, ++span) { SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); if (alpha == 255) { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { SCALED_IMAGE_RANGE_X - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto src = scaleMethod(image.buf32, image.stride, image.w, image.h, sx, sy, miny, maxy, sampleSize); auto tmp = surface->blender(src, *dst, 255); *dst = INTERPOLATE(tmp, *dst, A(src)); } } else { for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { SCALED_IMAGE_RANGE_X - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto src = scaleMethod(image.buf32, image.stride, image.w, image.h, sx, sy, miny, maxy, sampleSize); auto tmp = surface->blender(src, *dst, 255); *dst = INTERPOLATE(tmp, *dst, MULTIPLY(alpha, A(src))); } @@ -759,20 +759,20 @@ static bool _rasterScaledBlendingRleImage(SwSurface* surface, const SwImage* ima } -static bool _rasterScaledRleImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterScaledRleImage(SwSurface* surface, const SwImage& image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { - auto span = image->rle->spans; - auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; - auto sampleSize = _sampleSize(image->scale); + auto span = image.rle->spans; + auto scaleMethod = image.scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image.scale); int32_t miny = 0, maxy = 0; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image.rle->size; ++i, ++span) { SCALED_IMAGE_RANGE_Y(span->y) auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto alpha = MULTIPLY(span->coverage, opacity); for (uint32_t x = static_cast(span->x); x < static_cast(span->x) + span->len; ++x, ++dst) { SCALED_IMAGE_RANGE_X - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto src = scaleMethod(image.buf32, image.stride, image.w, image.h, sx, sy, miny, maxy, sampleSize); if (alpha < 255) src = ALPHA_BLEND(src, alpha); *dst = src + ALPHA_BLEND(*dst, IA(src)); } @@ -781,46 +781,23 @@ 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 (!inverse(&transform, &itransform)) return true; - - if (_compositing(surface)) { - if (_matting(surface)) return _rasterScaledMattedRleImage(surface, image, &itransform, region, opacity); - else return _rasterScaledMaskedRleImage(surface, image, &itransform, region, opacity); - } else if (_blending(surface)) { - return _rasterScaledBlendingRleImage(surface, image, &itransform, region, opacity); - } else { - return _rasterScaledRleImage(surface, image, &itransform, region, opacity); - } - return false; -} - - /************************************************************************/ /* RLE Direct Image */ /************************************************************************/ -static bool _rasterDirectMattedRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +static bool _rasterDirectMattedRleImage(SwSurface* surface, const SwImage& image, uint8_t opacity) { TVGLOG("SW_ENGINE", "Direct Matted(%d) Rle Image", (int)surface->compositor->method); - auto span = image->rle->spans; + auto span = image.rle->spans; auto csize = surface->compositor->image.channelSize; auto cbuffer = surface->compositor->image.buf8; auto alpha = surface->alpha(surface->compositor->method); - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image.rle->size; ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; auto cmp = &cbuffer[(span->y * surface->compositor->image.stride + span->x) * csize]; - auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto img = image.buf32 + (span->y + image.oy) * image.stride + (span->x + image.ox); auto a = MULTIPLY(span->coverage, opacity); if (a == 255) { for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img, cmp += csize) { @@ -838,13 +815,13 @@ static bool _rasterDirectMattedRleImage(SwSurface* surface, const SwImage* image } -static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage& image, uint8_t opacity) { - auto span = image->rle->spans; + auto span = image.rle->spans; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image.rle->size; ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto img = image.buf32 + (span->y + image.oy) * image.stride + (span->x + image.ox); auto alpha = MULTIPLY(span->coverage, opacity); if (alpha == 255) { for (uint32_t x = 0; x < span->len; ++x, ++dst, ++img) { @@ -861,13 +838,13 @@ static bool _rasterDirectBlendingRleImage(SwSurface* surface, const SwImage* ima } -static bool _rasterDirectRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +static bool _rasterDirectRleImage(SwSurface* surface, const SwImage& image, uint8_t opacity) { - auto span = image->rle->spans; + auto span = image.rle->spans; - for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { + for (uint32_t i = 0; i < image.rle->size; ++i, ++span) { auto dst = &surface->buf32[span->y * surface->stride + span->x]; - auto img = image->buf32 + (span->y + image->oy) * image->stride + (span->x + image->ox); + auto img = image.buf32 + (span->y + image.oy) * image.stride + (span->x + image.ox); auto alpha = MULTIPLY(span->coverage, opacity); rasterTranslucentPixel32(dst, img, span->len, alpha); } @@ -875,44 +852,25 @@ static bool _rasterDirectRleImage(SwSurface* surface, const SwImage* image, uint } -static bool _rasterDirectMaskedRleImage(SwSurface* surface, const SwImage* image, uint8_t opacity) +static bool _rasterDirectMaskedRleImage(SwSurface* surface, const SwImage& image, uint8_t opacity) { TVGERR("SW_ENGINE", "Not Supported Direct Masked(%d) Rle Image", (int)surface->compositor->method); return false; } -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); - } else if (_blending(surface)) { - return _rasterDirectBlendingRleImage(surface, image, opacity); - } else { - return _rasterDirectRleImage(surface, image, opacity); - } - return false; -} - - /************************************************************************/ /*Scaled Image */ /************************************************************************/ -static bool _rasterScaledMaskedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterScaledMaskedImage(SwSurface* surface, const SwImage& image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { TVGERR("SW_ENGINE", "Not Supported Scaled Masked Image!"); return false; } -static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage& image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { if (surface->channelSize == sizeof(uint8_t)) { TVGERR("SW_ENGINE", "Not supported grayscale scaled matted image!"); @@ -926,8 +884,8 @@ static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage* image, c TVGLOG("SW_ENGINE", "Scaled Matted(%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); - auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; - auto sampleSize = _sampleSize(image->scale); + auto scaleMethod = image.scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image.scale); int32_t miny = 0, maxy = 0; for (auto y = region.min.y; y < region.max.y; ++y) { @@ -936,7 +894,7 @@ static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage* image, c auto cmp = cbuffer; for (auto x = region.min.x; x < region.max.x; ++x, ++dst, cmp += csize) { SCALED_IMAGE_RANGE_X - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto src = scaleMethod(image.buf32, image.stride, image.w, image.h, sx, sy, miny, maxy, sampleSize); auto tmp = ALPHA_BLEND(src, opacity == 255 ? alpha(cmp) : MULTIPLY(opacity, alpha(cmp))); *dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); } @@ -947,7 +905,7 @@ static bool _rasterScaledMattedImage(SwSurface* surface, const SwImage* image, c } -static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage& image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { if (surface->channelSize == sizeof(uint8_t)) { TVGERR("SW_ENGINE", "Not supported grayscale scaled blending image!"); @@ -955,8 +913,8 @@ static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image, } auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); - auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; - auto sampleSize = _sampleSize(image->scale); + auto scaleMethod = image.scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image.scale); int32_t miny = 0, maxy = 0; for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { @@ -964,7 +922,7 @@ static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image, auto dst = dbuffer; for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { SCALED_IMAGE_RANGE_X - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto src = scaleMethod(image.buf32, image.stride, image.w, image.h, sx, sy, miny, maxy, sampleSize); auto tmp = surface->blender(src, *dst, 255); *dst = INTERPOLATE(tmp, *dst, MULTIPLY(opacity, A(src))); } @@ -973,10 +931,10 @@ static bool _rasterScaledBlendingImage(SwSurface* surface, const SwImage* image, } -static bool _rasterScaledImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) +static bool _rasterScaledImage(SwSurface* surface, const SwImage& image, const Matrix* itransform, const SwBBox& region, uint8_t opacity) { - auto scaleMethod = image->scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; - auto sampleSize = _sampleSize(image->scale); + auto scaleMethod = image.scale < DOWN_SCALE_TOLERANCE ? _interpDownScaler : _interpUpScaler; + auto sampleSize = _sampleSize(image.scale); int32_t miny = 0, maxy = 0; //32bits channels @@ -987,7 +945,7 @@ static bool _rasterScaledImage(SwSurface* surface, const SwImage* image, const M auto dst = buffer; for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { SCALED_IMAGE_RANGE_X - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto src = scaleMethod(image.buf32, image.stride, image.w, image.h, sx, sy, miny, maxy, sampleSize); if (opacity < 255) src = ALPHA_BLEND(src, opacity); *dst = src + ALPHA_BLEND(*dst, IA(src)); } @@ -999,7 +957,7 @@ static bool _rasterScaledImage(SwSurface* surface, const SwImage* image, const M auto dst = buffer; for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { SCALED_IMAGE_RANGE_X - auto src = scaleMethod(image->buf32, image->stride, image->w, image->h, sx, sy, miny, maxy, sampleSize); + auto src = scaleMethod(image.buf32, image.stride, image.w, image.h, sx, sy, miny, maxy, sampleSize); *dst = MULTIPLY(A(src), opacity); } } @@ -1008,42 +966,24 @@ 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) -{ - Matrix itransform; - - if (!inverse(&transform, &itransform)) return true; - - if (_compositing(surface)) { - if (_matting(surface)) return _rasterScaledMattedImage(surface, image, &itransform, region, opacity); - else return _rasterScaledMaskedImage(surface, image, &itransform, region, opacity); - } else if (_blending(surface)) { - return _rasterScaledBlendingImage(surface, image, &itransform, region, opacity); - } else { - return _rasterScaledImage(surface, image, &itransform, region, opacity); - } - return false; -} - - /************************************************************************/ /* Direct Image */ /************************************************************************/ -static bool _rasterDirectMaskedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +static bool _rasterDirectMaskedImage(SwSurface* surface, const SwImage& image, const SwBBox& region, uint8_t opacity) { TVGERR("SW_ENGINE", "Not Supported: Direct Masked Image"); return false; } -static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage& image, const SwBBox& region, uint8_t opacity) { auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); auto csize = surface->compositor->image.channelSize; auto alpha = surface->alpha(surface->compositor->method); - auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + 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 TVGLOG("SW_ENGINE", "Direct Matted(%d) Image [Region: %lu %lu %u %u]", (int)surface->compositor->method, region.min.x, region.min.y, w, h); @@ -1068,7 +1008,7 @@ static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, c } buffer += surface->stride; cbuffer += surface->compositor->image.stride * csize; - sbuffer += image->stride; + sbuffer += image.stride; } //8 bits } else if (surface->channelSize == sizeof(uint8_t)) { @@ -1090,14 +1030,14 @@ static bool _rasterDirectMattedImage(SwSurface* surface, const SwImage* image, c } buffer += surface->stride; cbuffer += surface->compositor->image.stride * csize; - sbuffer += image->stride; + sbuffer += image.stride; } } return true; } -static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +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!"); @@ -1105,7 +1045,7 @@ static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image, } 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); + auto sbuffer = image.buf32 + (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; @@ -1122,15 +1062,15 @@ static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image, } } dbuffer += surface->stride; - sbuffer += image->stride; + sbuffer += image.stride; } return true; } -static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +static bool _rasterDirectImage(SwSurface* surface, const SwImage& image, const SwBBox& region, uint8_t opacity) { - auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + auto sbuffer = image.buf32 + (region.min.y + image.oy) * image.stride + (region.min.x + image.ox); //32bits channels if (surface->channelSize == sizeof(uint32_t)) { @@ -1138,12 +1078,12 @@ static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const S for (auto y = region.min.y; y < region.max.y; ++y) { rasterTranslucentPixel32(dbuffer, sbuffer, region.max.x - region.min.x, opacity); dbuffer += surface->stride; - sbuffer += image->stride; + sbuffer += image.stride; } //8bits grayscale } else if (surface->channelSize == sizeof(uint8_t)) { auto dbuffer = &surface->buf8[region.min.y * surface->stride + region.min.x]; - for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride, sbuffer += image->stride) { + for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride, sbuffer += image.stride) { auto dst = dbuffer; auto src = sbuffer; if (opacity == 255) { @@ -1161,7 +1101,7 @@ static bool _rasterDirectImage(SwSurface* surface, const SwImage* image, const S } -static bool _rasterDirectMattedBlendingImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) +static bool _rasterDirectMattedBlendingImage(SwSurface* surface, const SwImage& image, const SwBBox& region, uint8_t opacity) { if (surface->channelSize == sizeof(uint8_t)) { TVGERR("SW_ENGINE", "Not supported grayscale image!"); @@ -1172,7 +1112,7 @@ static bool _rasterDirectMattedBlendingImage(SwSurface* surface, const SwImage* auto w = static_cast(region.max.x - region.min.x); auto csize = surface->compositor->image.channelSize; auto alpha = surface->alpha(surface->compositor->method); - auto sbuffer = image->buf32 + (region.min.y + image->oy) * image->stride + (region.min.x + image->ox); + 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 auto buffer = surface->buf32 + (region.min.y * surface->stride) + region.min.x; @@ -1193,46 +1133,12 @@ static bool _rasterDirectMattedBlendingImage(SwSurface* surface, const SwImage* } buffer += surface->stride; cbuffer += surface->compositor->image.stride * csize; - sbuffer += image->stride; + sbuffer += image.stride; } return true; } -//Blenders for the following scenarios: [Composition / Non-Composition] * [Opaque / Translucent] -static bool _directImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint8_t opacity) -{ - if (_compositing(surface)) { - if (_matting(surface)) { - if (_blending(surface)) return _rasterDirectMattedBlendingImage(surface, image, region, opacity); - else return _rasterDirectMattedImage(surface, image, region, opacity); - } else return _rasterDirectMaskedImage(surface, image, region, opacity); - } else if (_blending(surface)) { - return _rasterDirectBlendingImage(surface, image, region, opacity); - } else { - return _rasterDirectImage(surface, image, region, opacity); - } - return false; -} - - -//Blenders for the following scenarios: [RLE / Whole] * [Direct / Scaled / Transformed] -static bool _rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& region, uint8_t opacity) -{ - //RLE Image - if (image->rle) { - if (image->direct) return _directRleImage(surface, image, opacity); - else if (image->scaled) return _scaledRleImage(surface, image, transform, region, 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 _rasterTexmapPolygon(surface, image, transform, ®ion, opacity); - } -} - - /************************************************************************/ /* Rect Gradient */ /************************************************************************/ @@ -1249,7 +1155,7 @@ static bool _rasterCompositeGradientMaskedRect(SwSurface* surface, const SwBBox& 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); + return _compositeMaskImage(surface, surface->compositor->image, surface->compositor->bbox); } @@ -1422,7 +1328,7 @@ static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRle* r 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); + return _compositeMaskImage(surface, surface->compositor->image, surface->compositor->bbox); } @@ -1719,6 +1625,82 @@ void rasterPremultiply(RenderSurface* surface) } +bool rasterScaledImage(SwSurface* surface, const SwImage& image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity) +{ + Matrix itransform; + + if (!inverse(&transform, &itransform)) return true; + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterScaledMattedImage(surface, image, &itransform, bbox, opacity); + else return _rasterScaledMaskedImage(surface, image, &itransform, bbox, opacity); + } else if (_blending(surface)) { + return _rasterScaledBlendingImage(surface, image, &itransform, bbox, opacity); + } else { + return _rasterScaledImage(surface, image, &itransform, bbox, opacity); + } + return false; +} + + +bool rasterDirectImage(SwSurface* surface, const SwImage& image, const SwBBox& bbox, uint8_t opacity) +{ + if (_compositing(surface)) { + if (_matting(surface)) { + if (_blending(surface)) return _rasterDirectMattedBlendingImage(surface, image, bbox, opacity); + else return _rasterDirectMattedImage(surface, image, bbox, opacity); + } else return _rasterDirectMaskedImage(surface, image, bbox, opacity); + } else if (_blending(surface)) { + return _rasterDirectBlendingImage(surface, image, bbox, opacity); + } else { + return _rasterDirectImage(surface, image, bbox, opacity); + } + return false; +} + + +bool rasterScaledRleImage(SwSurface* surface, const SwImage& image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity) +{ + if (surface->channelSize == sizeof(uint8_t)) { + TVGERR("SW_ENGINE", "Not supported scaled rle image!"); + return false; + } + + Matrix itransform; + + if (!inverse(&transform, &itransform)) return true; + + if (_compositing(surface)) { + if (_matting(surface)) return _rasterScaledMattedRleImage(surface, image, &itransform, bbox, opacity); + else return _rasterScaledMaskedRleImage(surface, image, &itransform, bbox, opacity); + } else if (_blending(surface)) { + return _rasterScaledBlendingRleImage(surface, image, &itransform, bbox, opacity); + } else { + return _rasterScaledRleImage(surface, image, &itransform, bbox, opacity); + } + return false; +} + + +bool rasterDirectRleImage(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); + } else if (_blending(surface)) { + return _rasterDirectBlendingRleImage(surface, image, opacity); + } else { + return _rasterDirectRleImage(surface, image, opacity); + } + return false; +} + + bool rasterGradientShape(SwSurface* surface, SwShape* shape, const Fill* fdata, uint8_t opacity) { if (!shape->fill) return false; @@ -1781,15 +1763,6 @@ bool rasterStroke(SwSurface* surface, SwShape* shape, uint8_t r, uint8_t g, uint } -bool rasterImage(SwSurface* surface, SwImage* image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity) -{ - //Outside of the viewport, skip the rendering - if (bbox.max.x < 0 || bbox.max.y < 0 || bbox.min.x >= static_cast(surface->w) || bbox.min.y >= static_cast(surface->h)) return true; - - return _rasterImage(surface, image, transform, bbox, opacity); -} - - bool rasterConvertCS(RenderSurface* surface, ColorSpace to) { ScopedLock lock(surface->key); diff --git a/src/renderer/sw_engine/tvgSwRasterTexmap.h b/src/renderer/sw_engine/tvgSwRasterTexmap.h index cf21c663..9dfdce0b 100644 --- a/src/renderer/sw_engine/tvgSwRasterTexmap.h +++ b/src/renderer/sw_engine/tvgSwRasterTexmap.h @@ -51,86 +51,41 @@ static float dxdya, dxdyb, dudya, dvdya; static float xa, xb, ua, va; -//Y Range exception handling -static bool _arrange(const SwImage* image, const SwBBox* region, int& yStart, int& yEnd) +static inline int32_t _modf(float v) { - int32_t regionTop, regionBottom; - - 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; - } - - if (yStart >= regionBottom) return false; - - if (yStart < regionTop) yStart = regionTop; - if (yEnd > regionBottom) yEnd = regionBottom; - - return true; + return 255 - ((int(v * 256.0f)) & 255); } -static bool _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity, uint8_t dirFlag = 0) +static bool _rasterMaskedPolygonImageSegment(SwSurface* surface, const SwImage& image, const SwBBox& region, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity, uint8_t dirFlag = 0) { TVGERR("SW_ENGINE", "TODO: _rasterMaskedPolygonImageSegment()"); return false; } -static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity) +static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage& image, const SwBBox& bbox, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity) { float _dudx = dudx, _dvdx = dvdx; float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya; float _xa = xa, _xb = xb, _ua = ua, _va = va; - auto sbuf = image->buf32; + auto sbuf = image.buf32; auto dbuf = surface->buf32; - int32_t sw = static_cast(image->w); - int32_t sh = static_cast(image->h); + int32_t sw = static_cast(image.w); + int32_t sh = static_cast(image.h); int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; int32_t vv = 0, uu = 0; - int32_t minx = INT32_MAX, maxx = 0; - float dx, u, v, iptr; + float dx, u, v; uint32_t* buf; - SwSpan* span = nullptr; //used only when rle based. - if (!_arrange(image, region, yStart, yEnd)) return; - - //Loop through all lines in the segment - uint32_t spanIdx = 0; - - if (region) { - minx = region->min.x; - maxx = region->max.x; - } else { - span = image->rle->spans; - while (span->y < yStart) { - ++span; - ++spanIdx; - } - } + if (yStart < bbox.min.y) yStart = bbox.min.y; + if (yEnd > bbox.max.y) yEnd = bbox.max.y; y = yStart; while (y < yEnd) { - x1 = (int32_t)_xa; - x2 = (int32_t)_xb; - - if (!region) { - minx = INT32_MAX; - maxx = 0; - //one single row, could be consisted of multiple spans. - while (span->y == y && spanIdx < image->rle->size) { - if (minx > span->x) minx = span->x; - if (maxx < span->x + span->len) maxx = span->x + span->len; - ++span; - ++spanIdx; - } - } - if (x1 < minx) x1 = minx; - if (x2 > maxx) x2 = maxx; + x1 = std::max((SwCoord)_xa, bbox.min.x); + x2 = std::min((SwCoord)_xb, bbox.max.x); //Anti-Aliasing frames if (aaSpans) { @@ -140,7 +95,7 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage } //Range allowed - if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) { + if ((x2 - x1) >= 1 && (x1 < bbox.max.x) && (x2 > bbox.min.x)) { //Perform subtexel pre-stepping on UV dx = 1 - (_xa - x1); @@ -151,89 +106,45 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage x = x1; - if (opacity == 255) { - //Draw horizontal line - while (x++ < x2) { - uu = (int) u; - vv = (int) v; + //Draw horizontal line + while (x++ < x2) { + uu = (int) u; + vv = (int) v; - if ((uint32_t) uu >= image->w || (uint32_t) vv >= image->h) continue; + if ((uint32_t) uu >= image.w || (uint32_t) vv >= image.h) continue; - ar = (int)(255 * (1 - modff(u, &iptr))); - ab = (int)(255 * (1 - modff(v, &iptr))); - iru = uu + 1; - irv = vv + 1; + ar = _modf(u); + ab = _modf(v); + iru = uu + 1; + irv = vv + 1; - px = *(sbuf + (vv * image->stride) + uu); + px = *(sbuf + (vv * image.stride) + uu); + /* horizontal interpolate */ + if (iru < sw) { + /* right pixel */ + int px2 = *(sbuf + (vv * image.stride) + iru); + px = INTERPOLATE(px, px2, ar); + } + /* vertical interpolate */ + if (irv < sh) { + /* bottom pixel */ + int px2 = *(sbuf + (irv * image.stride) + uu); /* horizontal interpolate */ if (iru < sw) { - /* right pixel */ - int px2 = *(sbuf + (vv * image->stride) + iru); - px = INTERPOLATE(px, px2, ar); + /* bottom right pixel */ + int px3 = *(sbuf + (irv * image.stride) + iru); + px2 = INTERPOLATE(px2, px3, ar); } - /* vertical interpolate */ - if (irv < sh) { - /* bottom pixel */ - int px2 = *(sbuf + (irv * image->stride) + uu); - - /* horizontal interpolate */ - if (iru < sw) { - /* bottom right pixel */ - int px3 = *(sbuf + (irv * image->stride) + iru); - px2 = INTERPOLATE(px2, px3, ar); - } - px = INTERPOLATE(px, px2, ab); - } - *buf = surface->blender(px, *buf, IA(px)); - ++buf; - - //Step UV horizontally - u += _dudx; - v += _dvdx; + px = INTERPOLATE(px, px2, ab); } - } else { - //Draw horizontal line - while (x++ < x2) { - uu = (int) u; - vv = (int) v; + auto tmp = surface->blender(px, *buf, 255); + *buf = INTERPOLATE(tmp, *buf, MULTIPLY(opacity, A(px))); + ++buf; - if ((uint32_t) uu >= image->w || (uint32_t) vv >= image->h) continue; - - ar = (int)(255 * (1 - modff(u, &iptr))); - ab = (int)(255 * (1 - modff(v, &iptr))); - iru = uu + 1; - irv = vv + 1; - - px = *(sbuf + (vv * image->stride) + uu); - - /* horizontal interpolate */ - if (iru < sw) { - /* right pixel */ - int px2 = *(sbuf + (vv * image->stride) + iru); - px = INTERPOLATE(px, px2, ar); - } - /* vertical interpolate */ - if (irv < sh) { - /* bottom pixel */ - int px2 = *(sbuf + (irv * image->stride) + uu); - - /* horizontal interpolate */ - if (iru < sw) { - /* bottom right pixel */ - int px3 = *(sbuf + (irv * image->stride) + iru); - px2 = INTERPOLATE(px2, px3, ar); - } - px = INTERPOLATE(px, px2, ab); - } - auto src = ALPHA_BLEND(px, opacity); - *buf = surface->blender(src, *buf, IA(src)); - ++buf; - - //Step UV horizontally - u += _dudx; - v += _dvdx; - } + //Step UV horizontally + u += _dudx; + v += _dvdx; } } @@ -243,8 +154,6 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage _ua += _dudya; _va += _dvdya; - if (!region && spanIdx >= image->rle->size) break; - ++y; } xa = _xa; @@ -254,62 +163,33 @@ static void _rasterBlendingPolygonImageSegment(SwSurface* surface, const SwImage } -static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity, bool matting) +static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage& image, const SwBBox& bbox, int yStart, int yEnd, AASpans* aaSpans, uint8_t opacity, bool matting) { float _dudx = dudx, _dvdx = dvdx; float _dxdya = dxdya, _dxdyb = dxdyb, _dudya = dudya, _dvdya = dvdya; float _xa = xa, _xb = xb, _ua = ua, _va = va; - auto sbuf = image->buf32; + auto sbuf = image.buf32; auto dbuf = surface->buf32; - int32_t sw = static_cast(image->w); - int32_t sh = static_cast(image->h); + int32_t sw = static_cast(image.w); + int32_t sh = static_cast(image.h); int32_t x1, x2, x, y, ar, ab, iru, irv, px, ay; int32_t vv = 0, uu = 0; - int32_t minx = INT32_MAX, maxx = 0; - float dx, u, v, iptr; + float dx, u, v; uint32_t* buf; - SwSpan* span = nullptr; //used only when rle based. //for matting(composition) auto csize = matting ? surface->compositor->image.channelSize: 0; auto alpha = matting ? surface->alpha(surface->compositor->method) : nullptr; uint8_t* cmp = nullptr; - if (!_arrange(image, region, yStart, yEnd)) return; - - //Loop through all lines in the segment - uint32_t spanIdx = 0; - - if (region) { - minx = region->min.x; - maxx = region->max.x; - } else { - span = image->rle->spans; - while (span->y < yStart) { - ++span; - ++spanIdx; - } - } + if (yStart < bbox.min.y) yStart = bbox.min.y; + if (yEnd > bbox.max.y) yEnd = bbox.max.y; y = yStart; while (y < yEnd) { - x1 = (int32_t)_xa; - x2 = (int32_t)_xb; - - if (!region) { - minx = INT32_MAX; - maxx = 0; - //one single row, could be consisted of multiple spans. - while (span->y == y && spanIdx < image->rle->size) { - if (minx > span->x) minx = span->x; - if (maxx < span->x + span->len) maxx = span->x + span->len; - ++span; - ++spanIdx; - } - } - if (x1 < minx) x1 = minx; - if (x2 > maxx) x2 = maxx; + x1 = std::max((SwCoord)_xa, bbox.min.x); + x2 = std::min((SwCoord)_xb, bbox.max.x); //Anti-Aliasing frames if (aaSpans) { @@ -319,7 +199,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, } //Range allowed - if ((x2 - x1) >= 1 && (x1 < maxx) && (x2 > minx)) { + if ((x2 - x1) >= 1 && (x1 < bbox.max.x) && (x2 > bbox.min.x)) { //Perform subtexel pre-stepping on UV dx = 1 - (_xa - x1); @@ -338,30 +218,31 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, uu = (int) u; vv = (int) v; - if ((uint32_t) uu >= image->w || (uint32_t) vv >= image->h) continue; + if ((uint32_t) uu >= image.w || (uint32_t) vv >= image.h) continue; + + ar = _modf(u); + ab = _modf(v); - ar = (int)(255.0f * (1.0f - modff(u, &iptr))); - ab = (int)(255.0f * (1.0f - modff(v, &iptr))); iru = uu + 1; irv = vv + 1; - px = *(sbuf + (vv * image->stride) + uu); + px = *(sbuf + (vv * image.stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* right pixel */ - int px2 = *(sbuf + (vv * image->stride) + iru); + int px2 = *(sbuf + (vv * image.stride) + iru); px = INTERPOLATE(px, px2, ar); } /* vertical interpolate */ if (irv < sh) { /* bottom pixel */ - int px2 = *(sbuf + (irv * image->stride) + uu); + int px2 = *(sbuf + (irv * image.stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* bottom right pixel */ - int px3 = *(sbuf + (irv * image->stride) + iru); + int px3 = *(sbuf + (irv * image.stride) + iru); px2 = INTERPOLATE(px2, px3, ar); } px = INTERPOLATE(px, px2, ab); @@ -386,30 +267,31 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, uu = (int) u; vv = (int) v; - if ((uint32_t) uu >= image->w || (uint32_t) vv >= image->h) continue; + if ((uint32_t) uu >= image.w || (uint32_t) vv >= image.h) continue; + + ar = _modf(u); + ab = _modf(v); - ar = (int)(255.0f * (1.0f - modff(u, &iptr))); - ab = (int)(255.0f * (1.0f - modff(v, &iptr))); iru = uu + 1; irv = vv + 1; - px = *(sbuf + (vv * sw) + uu); + px = *(sbuf + (vv * image.stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* right pixel */ - int px2 = *(sbuf + (vv * image->stride) + iru); + int px2 = *(sbuf + (vv * image.stride) + iru); px = INTERPOLATE(px, px2, ar); } /* vertical interpolate */ if (irv < sh) { /* bottom pixel */ - int px2 = *(sbuf + (irv * image->stride) + uu); + int px2 = *(sbuf + (irv * image.stride) + uu); /* horizontal interpolate */ if (iru < sw) { /* bottom right pixel */ - int px3 = *(sbuf + (irv * image->stride) + iru); + int px3 = *(sbuf + (irv * image.stride) + iru); px2 = INTERPOLATE(px2, px3, ar); } px = INTERPOLATE(px, px2, ab); @@ -437,8 +319,6 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, _ua += _dudya; _va += _dvdya; - if (!region && spanIdx >= image->rle->size) break; - ++y; } xa = _xa; @@ -449,7 +329,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, /* This mapping algorithm is based on Mikael Kalms's. */ -static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, Polygon& polygon, AASpans* aaSpans, uint8_t opacity) +static void _rasterPolygonImage(SwSurface* surface, const SwImage& image, const SwBBox& bbox, Polygon& polygon, AASpans* aaSpans, uint8_t opacity) { 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}; @@ -510,7 +390,6 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const if (tvg::equal(y[0], y[1])) side = x[0] > x[1]; if (tvg::equal(y[1], y[2])) side = x[2] > x[1]; - auto regionTop = region ? region->min.y : image->rle->spans->y; //Normal Image or Rle Image? auto compositing = _compositing(surface); //Composition required auto blending = _blending(surface); //Blending required @@ -529,7 +408,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] < regionTop ? (regionTop - y[0]) : 0; + off_y = y[0] < bbox.min.y ? (bbox.min.y - y[0]) : 0; xa += (off_y * dxdya); ua += (off_y * dudya); va += (off_y * dvdya); @@ -539,18 +418,18 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const xb = x[0] + dy * dxdyb + (off_y * dxdyb); if (compositing) { - if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, true); - else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, 1); + if (_matting(surface)) _rasterPolygonImageSegment(surface, image, bbox, yi[0], yi[1], aaSpans, opacity, true); + else _rasterMaskedPolygonImageSegment(surface, image, bbox, yi[0], yi[1], aaSpans, opacity, 1); } else if (blending) { - _rasterBlendingPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity); + _rasterBlendingPolygonImageSegment(surface, image, bbox, yi[0], yi[1], aaSpans, opacity); } else { - _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, false); + _rasterPolygonImageSegment(surface, image, bbox, yi[0], yi[1], aaSpans, opacity, false); } upper = true; } //Draw lower segment if possibly visible if (yi[1] < yi[2]) { - off_y = y[1] < regionTop ? (regionTop - y[1]) : 0; + off_y = y[1] < bbox.min.y ? (bbox.min.y - y[1]) : 0; if (!upper) { xa += (off_y * dxdya); ua += (off_y * dudya); @@ -560,12 +439,12 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const dxdyb = dxdy[2]; xb = x[1] + (1 - (y[1] - yi[1])) * dxdyb + (off_y * dxdyb); if (compositing) { - if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, true); - else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, 2); + if (_matting(surface)) _rasterPolygonImageSegment(surface, image, bbox, yi[1], yi[2], aaSpans, opacity, true); + else _rasterMaskedPolygonImageSegment(surface, image, bbox, yi[1], yi[2], aaSpans, opacity, 2); } else if (blending) { - _rasterBlendingPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity); + _rasterBlendingPolygonImageSegment(surface, image, bbox, yi[1], yi[2], aaSpans, opacity); } else { - _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, false); + _rasterPolygonImageSegment(surface, image, bbox, yi[1], yi[2], aaSpans, opacity, false); } } //Longer edge is on the right side @@ -577,7 +456,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] < regionTop ? (regionTop - y[0]) : 0; + off_y = y[0] < bbox.min.y ? (bbox.min.y - y[0]) : 0; xb += (off_y *dxdyb); // Set slopes along left edge and perform subpixel pre-stepping @@ -590,18 +469,18 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const va = v[0] + dy * dvdya + (off_y * dvdya); if (compositing) { - if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, true); - else _rasterMaskedPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, 3); + if (_matting(surface)) _rasterPolygonImageSegment(surface, image, bbox, yi[0], yi[1], aaSpans, opacity, true); + else _rasterMaskedPolygonImageSegment(surface, image, bbox, yi[0], yi[1], aaSpans, opacity, 3); } else if (blending) { - _rasterBlendingPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity); + _rasterBlendingPolygonImageSegment(surface, image, bbox, yi[0], yi[1], aaSpans, opacity); } else { - _rasterPolygonImageSegment(surface, image, region, yi[0], yi[1], aaSpans, opacity, false); + _rasterPolygonImageSegment(surface, image, bbox, yi[0], yi[1], aaSpans, opacity, false); } upper = true; } //Draw lower segment if possibly visible if (yi[1] < yi[2]) { - off_y = y[1] < regionTop ? (regionTop - y[1]) : 0; + off_y = y[1] < bbox.min.y ? (bbox.min.y - y[1]) : 0; if (!upper) xb += (off_y *dxdyb); // Set slopes along left edge and perform subpixel pre-stepping @@ -614,12 +493,12 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const va = v[1] + dy * dvdya + (off_y * dvdya); if (compositing) { - if (_matting(surface)) _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, true); - else _rasterMaskedPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, 4); + if (_matting(surface)) _rasterPolygonImageSegment(surface, image, bbox, yi[1], yi[2], aaSpans, opacity, true); + else _rasterMaskedPolygonImageSegment(surface, image, bbox, yi[1], yi[2], aaSpans, opacity, 4); } else if (blending) { - _rasterBlendingPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity); + _rasterBlendingPolygonImageSegment(surface, image, bbox, yi[1], yi[2], aaSpans, opacity); } else { - _rasterPolygonImageSegment(surface, image, region, yi[1], yi[2], aaSpans, opacity, false); + _rasterPolygonImageSegment(surface, image, bbox, yi[1], yi[2], aaSpans, opacity, false); } } } @@ -906,22 +785,19 @@ static void _apply(SwSurface* surface, AASpans* aaSpans) | / | 3 -- 2 */ -static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix& transform, const SwBBox* region, uint8_t opacity) +bool rasterTexmapPolygon(SwSurface* surface, const SwImage& image, const Matrix& transform, const SwBBox& bbox, uint8_t opacity) { if (surface->channelSize == sizeof(uint8_t)) { TVGERR("SW_ENGINE", "Not supported grayscale Textmap polygon!"); return false; } - //Exceptions: No dedicated drawing area? - if ((!image->rle && !region) || (image->rle && image->rle->size == 0)) return true; - //Prepare vertices. Shift XY coordinates to match the sub-pixeling technique. Vertex vertices[4]; vertices[0] = {{0.0f, 0.0f}, {0.0f, 0.0f}}; - vertices[1] = {{float(image->w), 0.0f}, {float(image->w), 0.0f}}; - vertices[2] = {{float(image->w), float(image->h)}, {float(image->w), float(image->h)}}; - vertices[3] = {{0.0f, float(image->h)}, {0.0f, float(image->h)}}; + vertices[1] = {{float(image.w), 0.0f}, {float(image.w), 0.0f}}; + vertices[2] = {{float(image.w), float(image.h)}, {float(image.w), float(image.h)}}; + vertices[3] = {{0.0f, float(image.h)}, {0.0f, float(image.h)}}; float ys = FLT_MAX, ye = -1.0f; for (int i = 0; i < 4; i++) { @@ -930,10 +806,8 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const if (vertices[i].pt.y > ye) ye = vertices[i].pt.y; } - auto yStart = static_cast(ys); - auto yEnd = static_cast(ye); - - if (!_arrange(image, region, yStart, yEnd)) return true; + auto yStart = std::max(static_cast(ys), bbox.min.y); + auto yEnd = std::min(static_cast(ye), bbox.max.y); auto aaSpans = rightAngle(transform) ? nullptr : _AASpans(yStart, yEnd); Polygon polygon; @@ -943,14 +817,14 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const polygon.vertex[1] = vertices[1]; polygon.vertex[2] = vertices[3]; - _rasterPolygonImage(surface, image, region, polygon, aaSpans, opacity); + _rasterPolygonImage(surface, image, bbox, polygon, aaSpans, opacity); //Draw the second polygon polygon.vertex[0] = vertices[1]; polygon.vertex[1] = vertices[2]; polygon.vertex[2] = vertices[3]; - _rasterPolygonImage(surface, image, region, polygon, aaSpans, opacity); + _rasterPolygonImage(surface, image, bbox, polygon, aaSpans, opacity); #if 0 if (_compositing(surface) && _masking(surface) && !_direct(surface->compositor->method)) { diff --git a/src/renderer/sw_engine/tvgSwRenderer.cpp b/src/renderer/sw_engine/tvgSwRenderer.cpp index cad07f6d..2e8f3c84 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.cpp +++ b/src/renderer/sw_engine/tvgSwRenderer.cpp @@ -403,7 +403,32 @@ bool SwRenderer::renderImage(RenderData data) if (task->opacity == 0) return true; - return rasterImage(surface, &task->image, task->transform, task->bbox, task->opacity); + //Outside of the viewport, skip the rendering + auto& bbox = task->bbox; + if (bbox.max.x <= bbox.min.x || bbox.max.y <= bbox.min.y || bbox.min.x >= surface->w || bbox.min.y >= surface->h) return true; + + auto& image = task->image; + + //RLE Image + if (image.rle) { + if (image.direct) return rasterDirectRleImage(surface, image, task->opacity); + else if (image.scaled) return rasterScaledRleImage(surface, image, task->transform, bbox, task->opacity); + else { + //create a intermediate buffer for rle clipping + auto cmp = request(sizeof(pixel_t), false); + cmp->compositor->method = CompositeMethod::None; + cmp->compositor->valid = true; + cmp->compositor->image.rle = image.rle; + rasterClear(cmp, (uint32_t)bbox.min.x, (uint32_t)bbox.min.y, (uint32_t)(bbox.max.x - bbox.min.x), (uint32_t)(bbox.max.y - bbox.min.y), 0); + rasterTexmapPolygon(cmp, image, task->transform, bbox, 255); + return rasterDirectRleImage(surface, cmp->compositor->image, task->opacity); + } + //Whole Image + } else { + if (image.direct) return rasterDirectImage(surface, image, bbox, task->opacity); + else if (image.scaled) return rasterScaledImage(surface, image, task->transform, bbox, task->opacity); + else return rasterTexmapPolygon(surface, image, task->transform, bbox, task->opacity); + } } @@ -638,8 +663,7 @@ bool SwRenderer::endComposite(RenderCompositor* cmp) //Default is alpha blending if (p->method == CompositeMethod::None) { - Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1}; - return rasterImage(surface, &p->image, m, p->bbox, p->opacity); + return rasterDirectImage(surface, p->image, p->bbox, p->opacity); } return true; @@ -738,7 +762,7 @@ void* SwRenderer::prepareCommon(SwTask* task, const Matrix& transform, const Arr task->clips = clips; task->transform = transform; - + //zero size? if (task->transform.e11 == 0.0f && task->transform.e12 == 0.0f) return task; //zero width if (task->transform.e21 == 0.0f && task->transform.e22 == 0.0f) return task; //zero height diff --git a/src/renderer/sw_engine/tvgSwRenderer.h b/src/renderer/sw_engine/tvgSwRenderer.h index 27868abf..1910dead 100644 --- a/src/renderer/sw_engine/tvgSwRenderer.h +++ b/src/renderer/sw_engine/tvgSwRenderer.h @@ -55,6 +55,8 @@ public: bool target(pixel_t* data, uint32_t stride, uint32_t w, uint32_t h, ColorSpace cs); bool mempool(bool shared); + SwSurface* request(int channelSize, bool square); + RenderCompositor* target(const RenderRegion& region, ColorSpace cs, CompositionFlag flags) override; bool beginComposite(RenderCompositor* cmp, CompositeMethod method, uint8_t opacity) override; bool endComposite(RenderCompositor* cmp) override; @@ -80,7 +82,6 @@ private: SwRenderer(); ~SwRenderer(); - SwSurface* request(int channelSize, bool square); RenderData prepareCommon(SwTask* task, const Matrix& transform, const Array& clips, uint8_t opacity, RenderUpdateFlag flags); };