summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibGfx/Painter.cpp
diff options
context:
space:
mode:
authorSimon Wanner <skyrising@pvpctutorials.de>2022-03-21 22:03:15 +0100
committerAndreas Kling <kling@serenityos.org>2022-03-22 02:06:21 +0100
commit4f348f17337a4959e8f2401e1ade0dde759e4a61 (patch)
tree540a56a8e40596821c619b86aae51fa66ec5a65c /Userland/Libraries/LibGfx/Painter.cpp
parent145efbe07a6337fdc58246552bde014c1008fd0f (diff)
downloadserenity-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.cpp22
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);
}