mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
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:
parent
36da47af80
commit
45132a7051
7 changed files with 81 additions and 466 deletions
|
@ -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, ®ion, opacity, _alpha);
|
||||
} else if (surface->compositor->method == CompositeMethod::InvAlphaMask) {
|
||||
return _rasterTexmapPolygon(surface, image, transform, region, opacity, _ialpha);
|
||||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, _ialpha);
|
||||
}
|
||||
} else {
|
||||
return _rasterTexmapPolygon(surface, image, transform, region, opacity, nullptr);
|
||||
return _rasterTexmapPolygon(surface, image, transform, ®ion, opacity, nullptr);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -67,7 +67,8 @@ namespace tvg
|
|||
uint32_t id;
|
||||
uint8_t opacity = 255;
|
||||
|
||||
~Impl() {
|
||||
~Impl()
|
||||
{
|
||||
if (compData) {
|
||||
delete(compData->target);
|
||||
free(compData);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue