LibGfx: Increase bit-width of variables used in do_draw_scaled_bitmap

To avoid expensive floating point operations the values are put in the
upper half of an integer which is then used for calculations.
When the src_rect is sufficiently large (when, say, PixelPaint is zoomed
in x100), the precision provided by this strategy with regular
32-bit-long ints  is no longer enough.
This patch changes the used types to i64, which are 64 bits wide and the
shifting is increased to 32 bits.
On the 32-bit-arch a i64 doesn't fit in a single register anymore but
it's probably okay to trust the compiler to do clever stuff around this
issue.
This commit is contained in:
Tobias Christiansen 2021-09-10 19:18:49 +02:00 committed by Andreas Kling
parent d7578ddebb
commit de0791b0a1
Notes: sideshowbarker 2024-07-18 04:19:22 +09:00

View File

@ -1088,16 +1088,17 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, const IntRe
}
bool has_opacity = opacity != 1.0f;
int hscale = (src_rect.width() * (1 << 16)) / dst_rect.width();
int vscale = (src_rect.height() * (1 << 16)) / dst_rect.height();
int src_left = src_rect.left() * (1 << 16);
int src_top = src_rect.top() * (1 << 16);
i64 shift = (i64)1 << 32;
i64 hscale = (src_rect.width() * shift) / dst_rect.width();
i64 vscale = (src_rect.height() * shift) / dst_rect.height();
i64 src_left = src_rect.left() * shift;
i64 src_top = src_rect.top() * shift;
for (int y = clipped_rect.top(); y <= clipped_rect.bottom(); ++y) {
auto* scanline = (Color*)target.scanline(y);
for (int x = clipped_rect.left(); x <= clipped_rect.right(); ++x) {
auto scaled_x = ((x - dst_rect.x()) * hscale + src_left) >> 16;
auto scaled_y = ((y - dst_rect.y()) * vscale + src_top) >> 16;
auto scaled_x = ((x - dst_rect.x()) * hscale + src_left) >> 32;
auto scaled_y = ((y - dst_rect.y()) * vscale + src_top) >> 32;
auto src_pixel = get_pixel(source, scaled_x, scaled_y);
if (has_opacity)
src_pixel.set_alpha(src_pixel.alpha() * opacity);