diff options
-rw-r--r-- | Userland/Demos/LibGfxScaleDemo/main.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Painter.cpp | 39 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Painter.h | 1 | ||||
-rw-r--r-- | Userland/Services/WindowServer/Compositor.cpp | 7 |
4 files changed, 31 insertions, 20 deletions
diff --git a/Userland/Demos/LibGfxScaleDemo/main.cpp b/Userland/Demos/LibGfxScaleDemo/main.cpp index e8dffe98f1..72a7c6885a 100644 --- a/Userland/Demos/LibGfxScaleDemo/main.cpp +++ b/Userland/Demos/LibGfxScaleDemo/main.cpp @@ -100,8 +100,8 @@ void Canvas::draw(Gfx::Painter& painter) auto buggie = Gfx::Bitmap::load_from_file("/res/graphics/buggie.png"); painter.blit({ 25, 39 }, *buggie, { 2, 30, 62, 20 }); - painter.draw_scaled_bitmap({ 88, 39, 62 * 2, 20 * 2 }, *buggie, { 2, 30, 62, 20 }); - painter.draw_scaled_bitmap({ 202, 39, 80, 40 }, *buggie, { 2, 30, 62, 20 }); + painter.draw_scaled_bitmap({ 88, 39, 62 * 2, 20 * 2 }, *buggie, Gfx::IntRect { 2, 30, 62, 20 }); + painter.draw_scaled_bitmap({ 202, 39, 80, 40 }, *buggie, Gfx::IntRect { 2, 30, 62, 20 }); } int main(int argc, char** argv) diff --git a/Userland/Libraries/LibGfx/Painter.cpp b/Userland/Libraries/LibGfx/Painter.cpp index 89d84ec925..f45dfccd04 100644 --- a/Userland/Libraries/LibGfx/Painter.cpp +++ b/Userland/Libraries/LibGfx/Painter.cpp @@ -783,30 +783,33 @@ ALWAYS_INLINE static void do_draw_integer_scaled_bitmap(Gfx::Bitmap& target, con } template<bool has_alpha_channel, typename GetPixel> -ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, const IntRect& dst_rect, const IntRect& clipped_rect, const Gfx::Bitmap& source, const IntRect& src_rect, GetPixel get_pixel, float opacity) +ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, const IntRect& dst_rect, const IntRect& clipped_rect, const Gfx::Bitmap& source, const FloatRect& src_rect, GetPixel get_pixel, float opacity) { - if (dst_rect == clipped_rect && !(dst_rect.width() % src_rect.width()) && !(dst_rect.height() % src_rect.height())) { - int hfactor = dst_rect.width() / src_rect.width(); - int vfactor = dst_rect.height() / src_rect.height(); + 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())) { + int hfactor = dst_rect.width() / int_src_rect.width(); + int vfactor = dst_rect.height() / int_src_rect.height(); if (hfactor == 2 && vfactor == 2) - return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, src_rect, source, 2, 2, get_pixel, opacity); + return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, int_src_rect, source, 2, 2, get_pixel, opacity); if (hfactor == 3 && vfactor == 3) - return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, src_rect, source, 3, 3, get_pixel, opacity); + return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, int_src_rect, source, 3, 3, get_pixel, opacity); if (hfactor == 4 && vfactor == 4) - return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, src_rect, source, 4, 4, get_pixel, opacity); - return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, src_rect, source, hfactor, vfactor, get_pixel, opacity); + return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, int_src_rect, source, 4, 4, get_pixel, opacity); + return do_draw_integer_scaled_bitmap<has_alpha_channel>(target, dst_rect, int_src_rect, source, hfactor, vfactor, get_pixel, opacity); } bool has_opacity = opacity != 1.0f; - int hscale = (src_rect.width() << 16) / dst_rect.width(); - int vscale = (src_rect.height() << 16) / dst_rect.height(); + 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); 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) >> 16; - auto scaled_y = ((y - dst_rect.y()) * vscale) >> 16; - auto src_pixel = get_pixel(source, scaled_x + src_rect.left(), scaled_y + src_rect.top()); + auto scaled_x = ((x - dst_rect.x()) * hscale + src_left) >> 16; + auto scaled_y = ((y - dst_rect.y()) * vscale + src_top) >> 16; + auto src_pixel = get_pixel(source, scaled_x, scaled_y); if (has_opacity) src_pixel.set_alpha(src_pixel.alpha() * opacity); if constexpr (has_alpha_channel) { @@ -819,8 +822,14 @@ ALWAYS_INLINE static void do_draw_scaled_bitmap(Gfx::Bitmap& target, const IntRe void Painter::draw_scaled_bitmap(const IntRect& a_dst_rect, const Gfx::Bitmap& source, const IntRect& a_src_rect, float opacity) { - if (scale() == source.scale() && a_dst_rect.size() == a_src_rect.size()) - return blit(a_dst_rect.location(), source, a_src_rect, opacity); + draw_scaled_bitmap(a_dst_rect, source, FloatRect { a_src_rect }, opacity); +} + +void Painter::draw_scaled_bitmap(const IntRect& a_dst_rect, const Gfx::Bitmap& source, const FloatRect& a_src_rect, float opacity) +{ + IntRect int_src_rect = enclosing_int_rect(a_src_rect); + if (scale() == source.scale() && a_src_rect == int_src_rect && a_dst_rect.size() == int_src_rect.size()) + return blit(a_dst_rect.location(), source, int_src_rect, opacity); auto dst_rect = to_physical(a_dst_rect); auto src_rect = a_src_rect * source.scale(); diff --git a/Userland/Libraries/LibGfx/Painter.h b/Userland/Libraries/LibGfx/Painter.h index 617867510e..08cacd4965 100644 --- a/Userland/Libraries/LibGfx/Painter.h +++ b/Userland/Libraries/LibGfx/Painter.h @@ -62,6 +62,7 @@ public: void draw_bitmap(const IntPoint&, const CharacterBitmap&, Color = Color()); void draw_bitmap(const IntPoint&, const GlyphBitmap&, Color = Color()); void draw_scaled_bitmap(const IntRect& dst_rect, const Gfx::Bitmap&, const IntRect& src_rect, float opacity = 1.0f); + void draw_scaled_bitmap(const IntRect& dst_rect, const Gfx::Bitmap&, const FloatRect& src_rect, float opacity = 1.0f); void draw_triangle(const IntPoint&, const IntPoint&, const IntPoint&, Color); void draw_ellipse_intersecting(const IntRect&, Color, int thickness = 1); void set_pixel(const IntPoint&, Color); diff --git a/Userland/Services/WindowServer/Compositor.cpp b/Userland/Services/WindowServer/Compositor.cpp index e93d4fddbf..1be79338bb 100644 --- a/Userland/Services/WindowServer/Compositor.cpp +++ b/Userland/Services/WindowServer/Compositor.cpp @@ -262,11 +262,12 @@ void Compositor::compose() } else if (m_wallpaper_mode == WallpaperMode::Tile) { painter.draw_tiled_bitmap(rect, *m_wallpaper); } else if (m_wallpaper_mode == WallpaperMode::Stretch) { - float hscale = (float)m_wallpaper->size().width() / (float)ws.size().width(); - float vscale = (float)m_wallpaper->size().height() / (float)ws.size().height(); + float hscale = (float)m_wallpaper->width() / (float)ws.width(); + float vscale = (float)m_wallpaper->height() / (float)ws.height(); // TODO: this may look ugly, we should scale to a backing bitmap and then blit - painter.draw_scaled_bitmap(rect, *m_wallpaper, { rect.x() * hscale, rect.y() * vscale, rect.width() * hscale, rect.height() * vscale }); + auto src_rect = Gfx::FloatRect { rect.x() * hscale, rect.y() * vscale, rect.width() * hscale, rect.height() * vscale }; + painter.draw_scaled_bitmap(rect, *m_wallpaper, src_rect); } else { ASSERT_NOT_REACHED(); } |