diff options
author | Simon Wanner <skyrising@pvpctutorials.de> | 2022-03-21 22:03:15 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-22 02:06:21 +0100 |
commit | 4f348f17337a4959e8f2401e1ade0dde759e4a61 (patch) | |
tree | 540a56a8e40596821c619b86aae51fa66ec5a65c /Userland/Libraries/LibGfx/Painter.cpp | |
parent | 145efbe07a6337fdc58246552bde014c1008fd0f (diff) | |
download | serenity-4f348f17337a4959e8f2401e1ade0dde759e4a61.zip |
LibGfx: Clip away coordinates outside the source bitmap
This prevents accessing the source pixels out of bounds.
Diffstat (limited to 'Userland/Libraries/LibGfx/Painter.cpp')
-rw-r--r-- | Userland/Libraries/LibGfx/Painter.cpp | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/Userland/Libraries/LibGfx/Painter.cpp b/Userland/Libraries/LibGfx/Painter.cpp index fdf8525bc7..ad0c2f6d47 100644 --- a/Userland/Libraries/LibGfx/Painter.cpp +++ b/Userland/Libraries/LibGfx/Painter.cpp @@ -1096,6 +1096,10 @@ ALWAYS_INLINE static void do_draw_integer_scaled_bitmap(Gfx::Bitmap& target, Int template<bool has_alpha_channel, bool do_bilinear_blend, typename GetPixel> ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect const& dst_rect, IntRect const& clipped_rect, Gfx::Bitmap const& source, FloatRect const& src_rect, GetPixel get_pixel, float opacity) { + auto clipped_src_rect = enclosing_int_rect(src_rect).intersected(source.rect()); + if (clipped_src_rect.is_empty()) + return; + if constexpr (!do_bilinear_blend) { IntRect int_src_rect = enclosing_int_rect(src_rect); if (dst_rect == clipped_rect && int_src_rect == src_rect && !(dst_rect.width() % int_src_rect.width()) && !(dst_rect.height() % int_src_rect.height())) { @@ -1122,16 +1126,20 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con for (int y = clipped_rect.top(); y <= clipped_rect.bottom(); ++y) { auto* scanline = (Color*)target.scanline(y); + auto desired_y = ((y - dst_rect.y()) * vscale + src_top); + if (desired_y < clipped_src_rect.left() || desired_y > clipped_src_rect.bottom() * shift) + continue; for (int x = clipped_rect.left(); x <= clipped_rect.right(); ++x) { auto desired_x = ((x - dst_rect.x()) * hscale + src_left); - auto desired_y = ((y - dst_rect.y()) * vscale + src_top); + if (desired_x < clipped_src_rect.left() || desired_x > clipped_src_rect.right() * shift) + continue; Color src_pixel; if constexpr (do_bilinear_blend) { - auto scaled_x0 = clamp((desired_x - half_pixel) >> 32, src_rect.left(), src_rect.right()); - auto scaled_x1 = clamp((desired_x + half_pixel) >> 32, src_rect.left(), src_rect.right()); - auto scaled_y0 = clamp((desired_y - half_pixel) >> 32, src_rect.top(), src_rect.bottom()); - auto scaled_y1 = clamp((desired_y + half_pixel) >> 32, src_rect.top(), src_rect.bottom()); + auto scaled_x0 = clamp((desired_x - half_pixel) >> 32, clipped_src_rect.left(), clipped_src_rect.right()); + auto scaled_x1 = clamp((desired_x + half_pixel) >> 32, clipped_src_rect.left(), clipped_src_rect.right()); + auto scaled_y0 = clamp((desired_y - half_pixel) >> 32, clipped_src_rect.top(), clipped_src_rect.bottom()); + auto scaled_y1 = clamp((desired_y + half_pixel) >> 32, clipped_src_rect.top(), clipped_src_rect.bottom()); float x_ratio = (((desired_x + half_pixel) & fractional_mask) / (float)shift); float y_ratio = (((desired_y + half_pixel) & fractional_mask) / (float)shift); @@ -1146,8 +1154,8 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, IntRect con src_pixel = top.interpolate(bottom, y_ratio); } else { - auto scaled_x = desired_x >> 32; - auto scaled_y = desired_y >> 32; + auto scaled_x = clamp(desired_x >> 32, clipped_src_rect.left(), clipped_src_rect.right()); + auto scaled_y = clamp(desired_y >> 32, clipped_src_rect.top(), clipped_src_rect.bottom()); src_pixel = get_pixel(source, scaled_x, scaled_y); } |