From de0791b0a1edf373bdc14fc4a4f84805895dab1d Mon Sep 17 00:00:00 2001 From: Tobias Christiansen Date: Fri, 10 Sep 2021 19:18:49 +0200 Subject: [PATCH] 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. --- Userland/Libraries/LibGfx/Painter.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibGfx/Painter.cpp b/Userland/Libraries/LibGfx/Painter.cpp index 64f0100786..57f5e8ad0a 100644 --- a/Userland/Libraries/LibGfx/Painter.cpp +++ b/Userland/Libraries/LibGfx/Painter.cpp @@ -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);