sw_engine raster: ++safety of the scaled image rasterization

Prevent out of buffer boundary access.

@Issues: https://github.com/Samsung/thorvg/pull/1119
This commit is contained in:
Hermet Park 2021-12-17 12:43:49 +09:00 committed by Hermet Park
parent e947fef9a4
commit 05fefcf61f
2 changed files with 83 additions and 64 deletions

View file

@ -82,8 +82,8 @@ static inline uint32_t _halfScale(float scale)
//Bilinear Interpolation //Bilinear Interpolation
static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, float sx, float sy) static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, float sx, float sy)
{ {
auto rx = static_cast<uint32_t>(sx); auto rx = (uint32_t)(sx);
auto ry = static_cast<uint32_t>(sy); auto ry = (uint32_t)(sy);
auto rx2 = rx + 1; auto rx2 = rx + 1;
if (rx2 >= w) rx2 = w - 1; if (rx2 >= w) rx2 = w - 1;
auto ry2 = ry + 1; auto ry2 = ry + 1;
@ -102,20 +102,23 @@ static uint32_t _interpUpScaler(const uint32_t *img, uint32_t w, uint32_t h, flo
//2n x 2n Mean Kernel //2n x 2n Mean Kernel
static uint32_t _interpDownScaler(const uint32_t *img, uint32_t w, uint32_t h, uint32_t rX, uint32_t rY, uint32_t n) static uint32_t _interpDownScaler(const uint32_t *img, uint32_t stride, uint32_t w, uint32_t h, uint32_t rx, uint32_t ry, uint32_t n)
{ {
uint32_t c[4] = { 0 }; uint32_t c[4] = {0, 0, 0, 0};
auto n2 = n * n; auto n2 = n * n;
auto src = img + rX - n + (rY - n) * w; auto src = img + rx - n + (ry - n) * stride;
for (auto y = rY - n; y < rY + n; ++y) {
for (auto y = ry - n; y < ry + n; ++y) {
if (y >= h) continue;
auto p = src; auto p = src;
for (auto x = rX - n; x < rX + n; ++x, ++p) { for (auto x = rx - n; x < rx + n; ++x, ++p) {
if (x >= w) continue;
c[0] += *p >> 24; c[0] += *p >> 24;
c[1] += (*p >> 16) & 0xff; c[1] += (*p >> 16) & 0xff;
c[2] += (*p >> 8) & 0xff; c[2] += (*p >> 8) & 0xff;
c[3] += *p & 0xff; c[3] += *p & 0xff;
} }
src += w; src += stride;
} }
for (auto i = 0; i < 4; ++i) { for (auto i = 0; i < 4; ++i) {
c[i] = (c[i] >> 2) / n2; c[i] = (c[i] >> 2) / n2;
@ -292,15 +295,15 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const
//Center (Down-Scaled) //Center (Down-Scaled)
if (image->scale < DOWN_SCALE_TOLERANCE) { if (image->scale < DOWN_SCALE_TOLERANCE) {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23); auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue; if (sy >= image->h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity); auto alpha = _multiplyAlpha(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) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue; if (sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha); auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
} }
@ -308,14 +311,14 @@ static bool _rasterScaledMaskedTranslucentRleRGBAImage(SwSurface* surface, const
//Center (Up-Scaled) //Center (Up-Scaled)
} else { } else {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23); auto sy = span->y * itransform->e22 + itransform->e23;
if (sy >= image->h) continue; if ((uint32_t)sy >= image->h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity); auto alpha = _multiplyAlpha(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) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if (sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha); auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
@ -335,22 +338,22 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i
//Center (Down-Scaled) //Center (Down-Scaled)
if (image->scale < DOWN_SCALE_TOLERANCE) { if (image->scale < DOWN_SCALE_TOLERANCE) {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23); auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue; if (sy >= image->h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
if (span->coverage == 255) { if (span->coverage == 255) {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue; if (sx >= image->w) continue;
auto tmp = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp)); auto tmp = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
} }
} else { } else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue; if (sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), span->coverage); auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage);
auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
} }
@ -359,21 +362,21 @@ static bool _rasterScaledMaskedRleRGBAImage(SwSurface* surface, const SwImage* i
//Center (Up-Scaled) //Center (Up-Scaled)
} else { } else {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23); auto sy = span->y * itransform->e22 + itransform->e23;
if (sy >= image->h) continue; if ((uint32_t)sy >= image->h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x]; auto cmp = &surface->compositor->image.data[span->y * surface->compositor->image.stride + span->x];
if (span->coverage == 255) { if (span->coverage == 255) {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if (sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto tmp = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp)); auto tmp = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
} }
} else { } else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst, ++cmp) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if (sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage); auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage);
auto tmp = ALPHA_BLEND(src, blendMethod(*cmp)); auto tmp = ALPHA_BLEND(src, blendMethod(*cmp));
*dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp)); *dst = tmp + ALPHA_BLEND(*dst, _ialpha(tmp));
@ -392,27 +395,27 @@ static bool _rasterScaledTranslucentRleRGBAImage(SwSurface* surface, const SwIma
//Center (Down-Scaled) //Center (Down-Scaled)
if (image->scale < DOWN_SCALE_TOLERANCE) { if (image->scale < DOWN_SCALE_TOLERANCE) {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23); auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue; if (sy >= image->h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity); auto alpha = _multiplyAlpha(span->coverage, opacity);
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue; if (sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha); auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
} }
//Center (Up-Scaled) //Center (Up-Scaled)
} else { } else {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23); auto sy = span->y * itransform->e22 + itransform->e23;
if (sy >= image->h) continue; if ((uint32_t)sy >= image->h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
auto alpha = _multiplyAlpha(span->coverage, opacity); auto alpha = _multiplyAlpha(span->coverage, opacity);
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if (sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha); auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
@ -429,21 +432,21 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image,
//Center (Down-Scaled) //Center (Down-Scaled)
if (image->scale < DOWN_SCALE_TOLERANCE) { if (image->scale < DOWN_SCALE_TOLERANCE) {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23); auto sy = (uint32_t)(span->y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue; if (sy >= image->h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
if (span->coverage == 255) { if (span->coverage == 255) {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue; if (sx >= image->w) continue;
auto src = _interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale); auto src = _interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
} else { } else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue; if (sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), span->coverage); auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), span->coverage);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
} }
@ -451,20 +454,20 @@ static bool _rasterScaledRleRGBAImage(SwSurface* surface, const SwImage* image,
//Center (Up-Scaled) //Center (Up-Scaled)
} else { } else {
for (uint32_t i = 0; i < image->rle->size; ++i, ++span) { for (uint32_t i = 0; i < image->rle->size; ++i, ++span) {
auto sy = static_cast<uint32_t>(span->y * itransform->e22 + itransform->e23); auto sy = span->y * itransform->e22 + itransform->e23;
if (sy >= image->h) continue; if ((uint32_t)sy >= image->h) continue;
auto dst = &surface->buffer[span->y * surface->stride + span->x]; auto dst = &surface->buffer[span->y * surface->stride + span->x];
if (span->coverage == 255) { if (span->coverage == 255) {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if (sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy); auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
} else { } else {
for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) { for (uint32_t x = static_cast<uint32_t>(span->x); x < static_cast<uint32_t>(span->x) + span->len; ++x, ++dst) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if (sx >= image->w) continue; if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage); auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), span->coverage);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
@ -660,13 +663,15 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
// Down-Scaled // Down-Scaled
if (image->scale < DOWN_SCALE_TOLERANCE) { if (image->scale < DOWN_SCALE_TOLERANCE) {
for (auto y = region.min.y; y < region.max.y; ++y) { for (auto y = region.min.y; y < region.max.y; ++y) {
auto sy = (uint32_t)(y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
auto dst = dbuffer; auto dst = dbuffer;
auto cmp = cbuffer; auto cmp = cbuffer;
auto sy = static_cast<uint32_t>(y * itransform->e22 + itransform->e23);
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
if (sx >= image->w) continue;
auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp)); auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp));
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), alpha);
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
dbuffer += surface->stride; dbuffer += surface->stride;
@ -675,12 +680,14 @@ static bool _rasterScaledMaskedTranslucentRGBAImage(SwSurface* surface, const Sw
// Up-Scaled // Up-Scaled
} else { } else {
for (auto y = region.min.y; y < region.max.y; ++y) { for (auto y = region.min.y; y < region.max.y; ++y) {
auto sy = y * itransform->e22 + itransform->e23;
if ((uint32_t)sy >= image->h) continue;
auto dst = dbuffer; auto dst = dbuffer;
auto cmp = cbuffer; auto cmp = cbuffer;
auto sy = fabsf(y * itransform->e22 + itransform->e23);
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp)); auto alpha = _multiplyAlpha(opacity, blendMethod(*cmp));
auto sx = fabsf(x * itransform->e11 + itransform->e13);
auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha); auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), alpha);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
@ -702,12 +709,14 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag
// Down-Scaled // Down-Scaled
if (image->scale < DOWN_SCALE_TOLERANCE) { if (image->scale < DOWN_SCALE_TOLERANCE) {
for (auto y = region.min.y; y < region.max.y; ++y) { for (auto y = region.min.y; y < region.max.y; ++y) {
auto sy = (uint32_t)(y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
auto dst = dbuffer; auto dst = dbuffer;
auto cmp = cbuffer; auto cmp = cbuffer;
auto sy = static_cast<uint32_t>(y * itransform->e22 + itransform->e23);
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp)); if (sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), blendMethod(*cmp));
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
dbuffer += surface->stride; dbuffer += surface->stride;
@ -716,11 +725,13 @@ static bool _rasterScaledMaskedRGBAImage(SwSurface* surface, const SwImage* imag
// Up-Scaled // Up-Scaled
} else { } else {
for (auto y = region.min.y; y < region.max.y; ++y) { for (auto y = region.min.y; y < region.max.y; ++y) {
auto sy = y * itransform->e22 + itransform->e23;
if ((uint32_t)sy >= image->h) continue;
auto dst = dbuffer; auto dst = dbuffer;
auto cmp = cbuffer; auto cmp = cbuffer;
auto sy = fabsf(y * itransform->e22 + itransform->e23);
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++cmp) {
auto sx = fabsf(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp)); auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), blendMethod(*cmp));
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
@ -739,11 +750,13 @@ static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage*
// Down-Scaled // Down-Scaled
if (image->scale < DOWN_SCALE_TOLERANCE) { if (image->scale < DOWN_SCALE_TOLERANCE) {
for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
auto sy = static_cast<uint32_t>(y * itransform->e22 + itransform->e23); auto sy = (uint32_t)(y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
auto dst = dbuffer; auto dst = dbuffer;
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale), opacity); if (sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale), opacity);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
} }
@ -751,9 +764,11 @@ static bool _rasterScaledTranslucentRGBAImage(SwSurface* surface, const SwImage*
} else { } else {
for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
auto sy = fabsf(y * itransform->e22 + itransform->e23); auto sy = fabsf(y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
auto dst = dbuffer; auto dst = dbuffer;
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = fabsf(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), opacity); auto src = ALPHA_BLEND(_interpUpScaler(image->data, image->w, image->h, sx, sy), opacity);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
@ -770,21 +785,25 @@ static bool _rasterScaledRGBAImage(SwSurface* surface, const SwImage* image, con
// Down-Scaled // Down-Scaled
if (image->scale < DOWN_SCALE_TOLERANCE) { if (image->scale < DOWN_SCALE_TOLERANCE) {
for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
auto sy = static_cast<uint32_t>(y * itransform->e22 + itransform->e23); auto sy = (uint32_t)(y * itransform->e22 + itransform->e23);
if (sy >= image->h) continue;
auto dst = dbuffer; auto dst = dbuffer;
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = static_cast<uint32_t>(x * itransform->e11 + itransform->e13); auto sx = (uint32_t)(x * itransform->e11 + itransform->e13);
auto src = _interpDownScaler(image->data, image->w, image->h, sx, sy, halfScale); if (sx >= image->w) continue;
auto src = _interpDownScaler(image->data, image->stride, image->w, image->h, sx, sy, halfScale);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }
} }
// Up-Scaled // Up-Scaled
} else { } else {
for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) { for (auto y = region.min.y; y < region.max.y; ++y, dbuffer += surface->stride) {
auto sy = fabsf(y * itransform->e22 + itransform->e23); auto sy = y * itransform->e22 + itransform->e23;
if ((uint32_t)sy >= image->h) continue;
auto dst = dbuffer; auto dst = dbuffer;
for (auto x = region.min.x; x < region.max.x; ++x, ++dst) { for (auto x = region.min.x; x < region.max.x; ++x, ++dst) {
auto sx = fabsf(x * itransform->e11 + itransform->e13); auto sx = x * itransform->e11 + itransform->e13;
if ((uint32_t)sx >= image->w) continue;
auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy); auto src = _interpUpScaler(image->data, image->w, image->h, sx, sy);
*dst = src + ALPHA_BLEND(*dst, _ialpha(src)); *dst = src + ALPHA_BLEND(*dst, _ialpha(src));
} }

View file

@ -62,7 +62,7 @@
if (x1 < minx) x1 = minx; if (x1 < minx) x1 = minx;
if (x2 > maxx) x2 = maxx; if (x2 > maxx) x2 = maxx;
//Anti-Aliasing frames //Anti-Aliasing frames
ay = y - aaSpans->yStart; ay = y - aaSpans->yStart;
if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1; if (aaSpans->lines[ay].x[0] > x1) aaSpans->lines[ay].x[0] = x1;