diff --git a/Libraries/LibGfx/Painter.cpp b/Libraries/LibGfx/Painter.cpp index 3d1fa05ab5..af82aa876f 100644 --- a/Libraries/LibGfx/Painter.cpp +++ b/Libraries/LibGfx/Painter.cpp @@ -690,12 +690,14 @@ void Painter::blit(const IntPoint& position, const Gfx::Bitmap& source, const In } template -ALWAYS_INLINE static void do_draw_integer_scaled_bitmap(Gfx::Bitmap& target, const IntRect& dst_rect, const Gfx::Bitmap& source, int hfactor, int vfactor, GetPixel get_pixel) +ALWAYS_INLINE static void do_draw_integer_scaled_bitmap(Gfx::Bitmap& target, const IntRect& dst_rect, const Gfx::Bitmap& source, int hfactor, int vfactor, GetPixel get_pixel, float opacity) { + u8 src_alpha = opacity * 255; for (int y = source.rect().top(); y <= source.rect().bottom(); ++y) { int dst_y = dst_rect.y() + y * vfactor; for (int x = source.rect().left(); x <= source.rect().right(); ++x) { auto src_pixel = get_pixel(source, x, y); + src_pixel.set_alpha(src_alpha); for (int yo = 0; yo < vfactor; ++yo) { auto* scanline = (Color*)target.scanline(dst_y + yo); int dst_x = dst_rect.x() + x * hfactor; @@ -711,26 +713,29 @@ ALWAYS_INLINE static void do_draw_integer_scaled_bitmap(Gfx::Bitmap& target, con } template -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, int hscale, int vscale, GetPixel get_pixel) +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, int hscale, int vscale, 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(); if (hfactor == 2 && vfactor == 2) - return do_draw_integer_scaled_bitmap(target, dst_rect, source, 2, 2, get_pixel); + return do_draw_integer_scaled_bitmap(target, dst_rect, source, 2, 2, get_pixel, opacity); if (hfactor == 3 && vfactor == 3) - return do_draw_integer_scaled_bitmap(target, dst_rect, source, 3, 3, get_pixel); + return do_draw_integer_scaled_bitmap(target, dst_rect, source, 3, 3, get_pixel, opacity); if (hfactor == 4 && vfactor == 4) - return do_draw_integer_scaled_bitmap(target, dst_rect, source, 4, 4, get_pixel); - return do_draw_integer_scaled_bitmap(target, dst_rect, source, hfactor, vfactor, get_pixel); + return do_draw_integer_scaled_bitmap(target, dst_rect, source, 4, 4, get_pixel, opacity); + return do_draw_integer_scaled_bitmap(target, dst_rect, source, hfactor, vfactor, get_pixel, opacity); } + u8 src_alpha = opacity * 255; + 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, scaled_y); + src_pixel.set_alpha(src_alpha); if constexpr (has_alpha_channel) { scanline[x] = scanline[x].blend(src_pixel); @@ -740,11 +745,11 @@ 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& src_rect) +void Painter::draw_scaled_bitmap(const IntRect& a_dst_rect, const Gfx::Bitmap& source, const IntRect& src_rect, float opacity) { auto dst_rect = a_dst_rect; if (dst_rect.size() == src_rect.size()) - return blit(dst_rect.location(), source, src_rect); + return blit(dst_rect.location(), source, src_rect, opacity); auto safe_src_rect = src_rect.intersected(source.rect()); ASSERT(source.rect().contains(safe_src_rect)); @@ -759,40 +764,40 @@ void Painter::draw_scaled_bitmap(const IntRect& a_dst_rect, const Gfx::Bitmap& s if (source.has_alpha_channel()) { switch (source.format()) { case BitmapFormat::RGB32: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; case BitmapFormat::RGBA32: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; case BitmapFormat::Indexed8: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; case BitmapFormat::Indexed4: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; case BitmapFormat::Indexed2: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; case BitmapFormat::Indexed1: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; default: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; } } else { switch (source.format()) { case BitmapFormat::RGB32: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; case BitmapFormat::RGBA32: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; case BitmapFormat::Indexed8: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; default: - do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel); + do_draw_scaled_bitmap(*m_target, dst_rect, clipped_rect, source, src_rect, hscale, vscale, get_pixel, opacity); break; } } diff --git a/Libraries/LibGfx/Painter.h b/Libraries/LibGfx/Painter.h index 89172c1716..e9173d14b1 100644 --- a/Libraries/LibGfx/Painter.h +++ b/Libraries/LibGfx/Painter.h @@ -65,7 +65,7 @@ public: void set_pixel(const IntPoint&, Color); void draw_line(const IntPoint&, const IntPoint&, Color, int thickness = 1, LineStyle style = LineStyle::Solid); void draw_quadratic_bezier_curve(const IntPoint& control_point, const IntPoint&, const IntPoint&, Color, int thickness = 1, LineStyle style = LineStyle::Solid); - void draw_scaled_bitmap(const IntRect& dst_rect, const Gfx::Bitmap&, const IntRect& src_rect); + void draw_scaled_bitmap(const IntRect& dst_rect, const Gfx::Bitmap&, const IntRect& src_rect, float opacity = 1.0f); void blit(const IntPoint&, const Gfx::Bitmap&, const IntRect& src_rect, float opacity = 1.0f); void blit_dimmed(const IntPoint&, const Gfx::Bitmap&, const IntRect& src_rect); void blit_brightened(const IntPoint&, const Gfx::Bitmap&, const IntRect& src_rect);