sw_engine raster: improve the transformed rle image rasterizer.

replace the transformed rle rgba image with the texmap raster.

this patch removes the several scattered transformed image rasterizer,
reuse the unified one texmap method instead.

yay, it's much clean and optimal.
This commit is contained in:
Hermet Park 2021-11-26 12:10:23 +09:00 committed by Hermet Park
parent 36da47af80
commit 45132a7051
7 changed files with 81 additions and 466 deletions

View file

@ -265,445 +265,16 @@ static bool _rasterRle(SwSurface* surface, SwRleData* rle, uint32_t color, uint8
/* RLE Transformed RGBA Image */
/************************************************************************/
static bool _rasterTransformedMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
{
TVGLOG("SW_ENGINE", "Transformed Masked Translucent Rle Image");
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
auto cbuffer = surface->compositor->image.data;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
auto src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
return true;
}
static bool _rasterTransformedMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t))
{
TVGLOG("SW_ENGINE", "Transformed Masked Rle Image");
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
auto cbuffer = surface->compositor->image.data;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
if (span->coverage == 255) {
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
auto tmp = ALPHA_BLEND(img[rY * image->stride + rX], blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
auto src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
}
return true;
}
static bool _rasterTransformedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity)
{
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
auto src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
return true;
}
static bool _rasterDownScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
{
TVGLOG("SW_ENGINE", "Down Scaled Masked Translucent Rle Image");
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
auto cbuffer = surface->compositor->image.data;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha);
auto tmp = ALPHA_BLEND(src, _multiplyAlpha(alpha, blendMethod(*cmp)));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
return true;
}
static bool _rasterDownScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t halfScale, uint32_t (*blendMethod)(uint32_t))
{
TVGLOG("SW_ENGINE", "Down Scaled Masked Rle Image");
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
auto cbuffer = surface->compositor->image.data;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
if (span->coverage == 255) {
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = img[rY * image->stride + rX];
else src = _interpDownScaler(img, image->stride, h, rX, rY, halfScale);
auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), span->coverage);
auto tmp = ALPHA_BLEND(src, _multiplyAlpha(span->coverage, blendMethod(*cmp)));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
}
return true;
}
static bool _rasterDownScaledTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t halfScale)
{
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
return true;
}
static bool _rasterUpScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
{
TVGLOG("SW_ENGINE", "Up Scaled Masked Translucent Rle Image");
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
auto cbuffer = surface->compositor->image.data;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto fX = (span->x + x) * itransform->e11 + ey1;
auto fY = (span->x + x) * itransform->e21 + ey2;
auto rX = static_cast<uint32_t>(roundf(fX));
auto rY = static_cast<uint32_t>(roundf(fY));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha);
auto tmp = ALPHA_BLEND(src, _multiplyAlpha(alpha, blendMethod(*cmp)));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
return true;
}
static bool _rasterUpScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t (*blendMethod)(uint32_t))
{
TVGLOG("SW_ENGINE", "Up Scaled Masked Rle Image");
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
auto cbuffer = surface->compositor->image.data;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &cbuffer[span->y * surface->compositor->image.stride + span->x];
if (span->coverage == 255) {
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto fX = (span->x + x) * itransform->e11 + ey1;
auto fY = (span->x + x) * itransform->e21 + ey2;
auto rX = static_cast<uint32_t>(roundf(fX));
auto rY = static_cast<uint32_t>(roundf(fY));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX == w - 1 || rY == h - 1) src = img[rY * image->stride + rX];
else src = _interpUpScaler(img, image->stride, h, fX, fY);
auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
} else {
for (uint32_t x = 0; x < span->len; ++x, ++dst, ++cmp) {
auto fX = (span->x + x) * itransform->e11 + ey1;
auto fY = (span->x + x) * itransform->e21 + ey2;
auto rX = static_cast<uint32_t>(roundf(fX));
auto rY = static_cast<uint32_t>(roundf(fY));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), span->coverage);
auto tmp = ALPHA_BLEND(src, _multiplyAlpha(span->coverage, blendMethod(*cmp)));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
}
}
}
return true;
}
static bool _rasterUpScaledTranslucentRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t opacity)
{
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity);
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
auto fX = (span->x + x) * itransform->e11 + ey1;
auto fY = (span->x + x) * itransform->e21 + ey2;
auto rX = static_cast<uint32_t>(roundf(fX));
auto rY = static_cast<uint32_t>(roundf(fY));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], alpha);
else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
return true;
}
static bool _rasterTransformedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform)
{
auto span = image->rle->spans;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
for (uint32_t x = 0; x < span->len; ++x, ++dst) {
auto rX = static_cast<uint32_t>(roundf((span->x + x) * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf((span->x + x) * itransform->e21 + ey2));
if (rX >= image->w || rY >= image->h) continue;
auto src = ALPHA_BLEND(image->data[rY * image->stride + rX], span->coverage);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
return true;
}
static bool _rasterDownScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform, uint32_t halfScale)
{
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto rX = static_cast<uint32_t>(roundf(x * itransform->e11 + ey1));
auto rY = static_cast<uint32_t>(roundf(x * itransform->e21 + ey2));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX < halfScale || rY < halfScale || rX >= w - halfScale || rY >= h - halfScale) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
else src = ALPHA_BLEND(_interpDownScaler(img, image->stride, h, rX, rY, halfScale), span->coverage);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
return true;
}
static bool _rasterUpScaledRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* itransform)
{
auto span = image->rle->spans;
auto img = image->data;
auto w = image->w;
auto h = image->h;
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto ey1 = span->y * itransform->e12 + itransform->e13;
auto ey2 = span->y * itransform->e22 + itransform->e23;
auto dst = &surface->buffer[span->y * surface->stride + span->x];
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto fX = x * itransform->e11 + ey1;
auto fY = x * itransform->e21 + ey2;
auto rX = static_cast<uint32_t>(roundf(fX));
auto rY = static_cast<uint32_t>(roundf(fY));
if (rX >= w || rY >= h) continue;
uint32_t src;
if (rX == w - 1 || rY == h - 1) src = ALPHA_BLEND(img[rY * image->stride + rX], span->coverage);
else src = ALPHA_BLEND(_interpUpScaler(img, image->stride, h, fX, fY), span->coverage);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src));
}
}
return true;
}
static bool _transformedRleRGBAImage(SwSurface* surface, const SwImage* image, const Matrix* transform, uint32_t opacity)
{
Matrix itransform;
mathIdentity(&itransform);
if (transform && !mathInverse(transform, &itransform)) return false;
auto halfScale = _halfScale(image->scale);
if (_compositing(surface)) {
if (opacity == 255) {
//Transformed
if (mathEqual(image->scale, 1.0f)) {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterTransformedMaskedRleRGBAImage(surface, image, &itransform, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTransformedMaskedRleRGBAImage(surface, image, &itransform, _ialpha);
}
//Transformed + Down Scaled
} else if (image->scale < DOWN_SCALE_TOLERANCE) {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterDownScaledMaskedRleRGBAImage(surface, image, &itransform, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDownScaledMaskedRleRGBAImage(surface, image, &itransform, halfScale, _ialpha);
}
//Transformed + Up Scaled
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterUpScaledMaskedRleRGBAImage(surface, image, &itransform, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterUpScaledMaskedRleRGBAImage(surface, image, &itransform, _ialpha);
}
}
} else {
//Transformed
if (mathEqual(image->scale, 1.0f)) {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterTransformedMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTransformedMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, _ialpha);
}
//Transformed + Down Scaled
} else if (image->scale < DOWN_SCALE_TOLERANCE) {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterDownScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterDownScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale, _ialpha);
}
//Transformed + Up Scaled
} else {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterUpScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterUpScaledMaskedTranslucentRleRGBAImage(surface, image, &itransform, opacity, _ialpha);
}
}
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, _ialpha);
}
} else {
if (opacity == 255) {
if (mathEqual(image->scale, 1.0f)) return _rasterTransformedRleRGBAImage(surface, image, &itransform);
else if (image->scale < DOWN_SCALE_TOLERANCE) return _rasterDownScaledRleRGBAImage(surface, image, &itransform, halfScale);
else return _rasterUpScaledRleRGBAImage(surface, image, &itransform);
} else {
if (mathEqual(image->scale, 1.0f)) return _rasterTransformedTranslucentRleRGBAImage(surface, image, &itransform, opacity);
else if (image->scale < DOWN_SCALE_TOLERANCE) return _rasterDownScaledTranslucentRleRGBAImage(surface, image, &itransform, opacity, halfScale);
else return _rasterUpScaledTranslucentRleRGBAImage(surface, image, &itransform, opacity);
}
return _rasterTexmapPolygon(surface, image, transform, nullptr, opacity, nullptr);
}
return false;
}
@ -1063,12 +634,12 @@ static bool _transformedRGBAImage(SwSurface* surface, const SwImage* image, cons
{
if (_compositing(surface)) {
if (surface->compositor->method == CompositeMethod::AlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, region, opacity, _alpha);
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _alpha);
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
return _rasterTexmapPolygon(surface, image, transform, region, opacity, _ialpha);
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, _ialpha);
}
} else {
return _rasterTexmapPolygon(surface, image, transform, region, opacity, nullptr);
return _rasterTexmapPolygon(surface, image, transform, &region, opacity, nullptr);
}
return false;
}
@ -1379,7 +950,6 @@ static bool _rasterRGBAImage(SwSurface* surface, SwImage* image, const Matrix* t
if (image->rle) {
if (image->direct) return _directRleRGBAImage(surface, image, opacity);
else if (image->scaled) return _scaledRleRGBAImage(surface, image, transform, region, opacity);
//OPTIMIZE_ME: Replace with the TexMap Rasterizer
else return _transformedRleRGBAImage(surface, image, transform, opacity);
//Whole Image
} else {

View file

@ -31,6 +31,7 @@ struct Polygon
Vertex vertex[3];
};
static inline void _swap(float& a, float& b, float& tmp)
{
tmp = a;
@ -44,7 +45,7 @@ static float dxdya, dxdyb, dudya, dvdya;
static float xa, xb, ua, va;
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
{
#define TEXMAP_TRANSLUCENT
#define TEXMAP_MASKING
@ -54,7 +55,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
}
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t (*blendMethod)(uint32_t))
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t (*blendMethod)(uint32_t))
{
#define TEXMAP_MASKING
#include "tvgSwRasterTexmapInternal.h"
@ -62,7 +63,7 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
}
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend, uint32_t opacity)
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd, uint32_t opacity)
{
#define TEXMAP_TRANSLUCENT
#include "tvgSwRasterTexmapInternal.h"
@ -70,14 +71,15 @@ static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image,
}
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox& region, int ystart, int yend)
static void _rasterPolygonImageSegment(SwSurface* surface, const SwImage* image, const SwBBox* region, int yStart, int yEnd)
{
#include "tvgSwRasterTexmapInternal.h"
}
/* This mapping algorithm is based on Mikael Kalms's. */
static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox& region, uint32_t opacity, Polygon& polygon, uint32_t (*blendMethod)(uint32_t))
static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const SwBBox* region, uint32_t opacity, Polygon& polygon, uint32_t (*blendMethod)(uint32_t))
{
float x[3] = {polygon.vertex[0].pt.x, polygon.vertex[1].pt.x, polygon.vertex[2].pt.x};
float y[3] = {polygon.vertex[0].pt.y, polygon.vertex[1].pt.y, polygon.vertex[2].pt.y};
@ -139,6 +141,8 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
if (mathEqual(y[0], y[1])) side = x[0] > x[1];
if (mathEqual(y[1], y[2])) side = x[2] > x[1];
auto regionTop = region ? region->min.y : image->rle->spans->y; //Normal Image or Rle Image?
//Longer edge is on the left side
if (!side) {
//Calculate slopes along left edge
@ -154,7 +158,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
//Draw upper segment if possibly visible
if (yi[0] < yi[1]) {
off_y = y[0] < region.min.y ? (region.min.y - y[0]) : 0;
off_y = y[0] < regionTop ? (regionTop - y[0]) : 0;
xa += (off_y * dxdya);
ua += (off_y * dudya);
va += (off_y * dvdya);
@ -175,7 +179,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
}
//Draw lower segment if possibly visible
if (yi[1] < yi[2]) {
off_y = y[1] < region.min.y ? (region.min.y - y[1]) : 0;
off_y = y[1] < regionTop ? (regionTop - y[1]) : 0;
if (!upper) {
xa += (off_y * dxdya);
ua += (off_y * dudya);
@ -201,7 +205,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
//Draw upper segment if possibly visible
if (yi[0] < yi[1]) {
off_y = y[0] < region.min.y ? (region.min.y - y[0]) : 0;
off_y = y[0] < regionTop ? (regionTop - y[0]) : 0;
xb += (off_y *dxdyb);
// Set slopes along left edge and perform subpixel pre-stepping
@ -225,7 +229,7 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
}
//Draw lower segment if possibly visible
if (yi[1] < yi[2]) {
off_y = y[1] < region.min.y ? (region.min.y - y[1]) : 0;
off_y = y[1] < regionTop ? (regionTop - y[1]) : 0;
if (!upper) xb += (off_y *dxdyb);
// Set slopes along left edge and perform subpixel pre-stepping
@ -259,8 +263,11 @@ static void _rasterPolygonImage(SwSurface* surface, const SwImage* image, const
| / |
3 -- 2
*/
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox& region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const Matrix* transform, const SwBBox* region, uint32_t opacity, uint32_t (*blendMethod)(uint32_t))
{
//Exceptions: No dedicated drawing area?
if (!region && image->rle->size == 0) return false;
/* Prepare vertices.
shift XY coordinates to match the sub-pixeling technique. */
Vertex vertices[4];
@ -286,6 +293,6 @@ static bool _rasterTexmapPolygon(SwSurface* surface, const SwImage* image, const
polygon.vertex[2] = vertices[3];
_rasterPolygonImage(surface, image, region, opacity, polygon, blendMethod);
return true;
}

View file

@ -33,28 +33,48 @@
int uu = 0;
float dx, u, v, iptr;
uint32_t* buf;
int regionTop;
int regionBottom;
SwSpan* span = nullptr; //used only when rle based.
#ifdef TEXMAP_MASKING
uint32_t* cmp;
#endif
if (region) {
regionTop = region->min.y;
regionBottom = region->max.y;
} else {
regionTop = image->rle->spans->y;
regionBottom = image->rle->spans[image->rle->size - 1].y;
}
//Range exception handling
if (ystart >= region.max.y) return;
if (ystart < region.min.y) ystart = region.min.y;
if (yend > region.max.y) yend = region.max.y;
if (yStart >= regionBottom) return;
if (yStart < regionTop) yStart = regionTop;
if (yEnd > regionBottom) yEnd = regionBottom;
//Loop through all lines in the segment
y = ystart;
y = yStart;
while (y < yend) {
if (!region) span = image->rle->spans + (yStart - regionTop);
while (y < yEnd) {
x1 = _xa;
x2 = _xb;
//Range exception handling
if (x1 < region.min.x) x1 = region.min.x;
if (x2 > region.max.x) x2 = region.max.x;
if ((x2 - x1) < 1) goto next;
if ((x1 >= region.max.x) || (x2 <= region.min.x)) goto next;
if (region) {
if (x1 < region->min.x) x1 = region->min.x;
if (x2 > region->max.x) x2 = region->max.x;
if ((x2 - x1) < 1) goto next;
if ((x1 >= region->max.x) || (x2 <= region->min.x)) goto next;
} else {
if (x1 < span->x) x1 = span->x;
if (x2 > span->x + span->len) x2 = (span->x + span->len);
if ((x2 - x1) < 1) goto next;
if ((x1 >= (span->x + span->len)) || (x2 <= span->x)) goto next;
}
//Perform subtexel pre-stepping on UV
dx = 1 - (_xa - x1);
@ -105,7 +125,7 @@
#elif defined(TEXMAP_TRANSLUCENT)
auto src = ALPHA_BLEND(px, opacity);
#else
auto src = px;
auto src = px;
#endif
*buf = src + ALPHA_BLEND(*buf, _ialpha(src));
++buf;
@ -123,7 +143,12 @@ next:
_ua += _dudya;
_va += _dvdya;
y++;
if (span) {
++span;
y = span->y;
} else {
y++;
}
}
xa = _xa;
xb = _xb;

View file

@ -111,11 +111,14 @@ struct SwShapeTask : SwTask
//Fill
if (flags & (RenderUpdateFlag::Gradient | RenderUpdateFlag::Transform | RenderUpdateFlag::Color)) {
if (visibleFill) {
auto antiAlias = (flags & RenderUpdateFlag::IgnoreAliasing) ? false : true;
/* We assume that if stroke width is bigger than 2,
shape outline below stroke could be full covered by stroke drawing.
Thus it turns off antialising in that condition.
Also, it shouldn't be dash style. */
auto antiAlias = (strokeAlpha == 255 && sdata->strokeWidth() > 2 && sdata->strokeDash(nullptr) == 0) ? false : true;
if (strokeAlpha == 255 && sdata->strokeWidth() > 2 && sdata->strokeDash(nullptr) == 0) antiAlias = false;
if (!shapeGenRle(&shape, sdata, antiAlias)) goto err;
}
if (auto fill = sdata->fill()) {

View file

@ -201,7 +201,7 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
if (compData) {
auto target = compData->target;
auto method = compData->method;
target->pImpl->ctxFlag = ContextFlag::Invalid; //reset
target->pImpl->ctxFlag &= ~ContextFlag::FastTrack; //reset
/* If transform has no rotation factors && ClipPath / AlphaMasking is a simple rectangle,
we can avoid regular ClipPath / AlphaMasking sequence but use viewport for performance */
@ -223,7 +223,15 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
}
}
if (!compFastTrack) {
tdata = target->pImpl->update(renderer, pTransform, 255, clips, pFlag);
//Bad design!: ignore anti-aliasing if the bitmap image is the source of the clip-path!
auto tempFlag = pFlag;
if (id == TVG_CLASS_ID_PICTURE) {
auto picture = static_cast<Picture*>(compData->source);
if (picture->data(nullptr, nullptr)) tempFlag |= RenderUpdateFlag::IgnoreAliasing;
}
tdata = target->pImpl->update(renderer, pTransform, 255, clips, tempFlag);
if (method == CompositeMethod::ClipPath) clips.push(tdata);
}
}
@ -249,6 +257,7 @@ void* Paint::Impl::update(RenderMethod& renderer, const RenderTransform* pTransf
return edata;
}
bool Paint::Impl::bounds(float* x, float* y, float* w, float* h, bool transformed)
{
Matrix* m = nullptr;

View file

@ -67,7 +67,8 @@ namespace tvg
uint32_t id;
uint8_t opacity = 255;
~Impl() {
~Impl()
{
if (compData) {
delete(compData->target);
free(compData);

View file

@ -28,7 +28,7 @@
namespace tvg
{
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 127};
enum RenderUpdateFlag {None = 0, Path = 1, Color = 2, Gradient = 4, Stroke = 8, Transform = 16, Image = 32, GradientStroke = 64, All = 255, IgnoreAliasing = 256};
struct Surface
{