mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-23 14:48:24 +00:00
sw_engine: revised the texture clipping
previous logic doesn't work if the clipping shape has any inner corners. replace the logic with a intermediate composition approach for stability. - performance can be drop at texture clipping by ~11% - size is reduced by -0.5kb issue: https://github.com/thorvg/thorvg/issues/3520
This commit is contained in:
parent
b1bfd22487
commit
d9960203b0
6 changed files with 282 additions and 411 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<uint32_t>(span->x); x < static_cast<uint32_t>(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<uint32_t>(span->x); x < static_cast<uint32_t>(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<uint32_t>(span->x); x < static_cast<uint32_t>(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<uint32_t>(span->x); x < static_cast<uint32_t>(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<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);
|
||||
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<uint32_t>(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<SwCoord>(surface->w) || bbox.min.y >= static_cast<SwCoord>(surface->h)) return true;
|
||||
|
||||
return _rasterImage(surface, image, transform, bbox, opacity);
|
||||
}
|
||||
|
||||
|
||||
bool rasterConvertCS(RenderSurface* surface, ColorSpace to)
|
||||
{
|
||||
ScopedLock lock(surface->key);
|
||||
|
|
|
@ -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<int32_t>(image->w);
|
||||
int32_t sh = static_cast<int32_t>(image->h);
|
||||
int32_t sw = static_cast<int32_t>(image.w);
|
||||
int32_t sh = static_cast<int32_t>(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<int32_t>(image->w);
|
||||
int32_t sh = static_cast<int32_t>(image->h);
|
||||
int32_t sw = static_cast<int32_t>(image.w);
|
||||
int32_t sh = static_cast<int32_t>(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<int>(ys);
|
||||
auto yEnd = static_cast<int>(ye);
|
||||
|
||||
if (!_arrange(image, region, yStart, yEnd)) return true;
|
||||
auto yStart = std::max(static_cast<SwCoord>(ys), bbox.min.y);
|
||||
auto yEnd = std::min(static_cast<SwCoord>(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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<RenderData>& clips, uint8_t opacity, RenderUpdateFlag flags);
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue