diff --git a/Userland/Libraries/LibGfx/Bitmap.h b/Userland/Libraries/LibGfx/Bitmap.h index 7481a0058e5..7a7915ca71c 100644 --- a/Userland/Libraries/LibGfx/Bitmap.h +++ b/Userland/Libraries/LibGfx/Bitmap.h @@ -95,6 +95,11 @@ public: [[nodiscard]] ARGB32* scanline(int physical_y); [[nodiscard]] ARGB32 const* scanline(int physical_y) const; + [[nodiscard]] u8* unchecked_scanline_u8(int physical_y); + [[nodiscard]] u8 const* unchecked_scanline_u8(int physical_y) const; + [[nodiscard]] ARGB32* unchecked_scanline(int physical_y); + [[nodiscard]] ARGB32 const* unchecked_scanline(int physical_y) const; + [[nodiscard]] ARGB32* begin(); [[nodiscard]] ARGB32 const* begin() const; [[nodiscard]] ARGB32* end(); @@ -139,6 +144,9 @@ public: [[nodiscard]] static constexpr size_t size_in_bytes(size_t pitch, int height) { return pitch * height; } [[nodiscard]] size_t size_in_bytes() const { return size_in_bytes(m_pitch, height()); } + template + [[nodiscard]] Color unchecked_get_pixel(int physical_x, int physical_y) const; + template [[nodiscard]] Color get_pixel(int physical_x, int physical_y) const; [[nodiscard]] Color get_pixel(int physical_x, int physical_y) const; @@ -178,18 +186,38 @@ private: Function m_destruction_callback; }; +ALWAYS_INLINE u8* Bitmap::unchecked_scanline_u8(int y) +{ + return reinterpret_cast(m_data) + (y * m_pitch); +} + +ALWAYS_INLINE u8 const* Bitmap::unchecked_scanline_u8(int y) const +{ + return reinterpret_cast(m_data) + (y * m_pitch); +} + +ALWAYS_INLINE ARGB32* Bitmap::unchecked_scanline(int y) +{ + return reinterpret_cast(unchecked_scanline_u8(y)); +} + +ALWAYS_INLINE ARGB32 const* Bitmap::unchecked_scanline(int y) const +{ + return reinterpret_cast(unchecked_scanline_u8(y)); +} + ALWAYS_INLINE u8* Bitmap::scanline_u8(int y) { VERIFY(y >= 0); VERIFY(y < height()); - return reinterpret_cast(m_data) + (y * m_pitch); + return unchecked_scanline_u8(y); } ALWAYS_INLINE u8 const* Bitmap::scanline_u8(int y) const { VERIFY(y >= 0); VERIFY(y < height()); - return reinterpret_cast(m_data) + (y * m_pitch); + return unchecked_scanline_u8(y); } ALWAYS_INLINE ARGB32* Bitmap::scanline(int y) @@ -228,19 +256,23 @@ ALWAYS_INLINE size_t Bitmap::data_size() const } template<> -ALWAYS_INLINE Color Bitmap::get_pixel(int x, int y) const +ALWAYS_INLINE Color Bitmap::unchecked_get_pixel(int x, int y) const { - VERIFY(x >= 0); - VERIFY(x < width()); - return Color::from_rgb(scanline(y)[x]); + return Color::from_rgb(unchecked_scanline(y)[x]); } template<> -ALWAYS_INLINE Color Bitmap::get_pixel(int x, int y) const +ALWAYS_INLINE Color Bitmap::unchecked_get_pixel(int x, int y) const +{ + return Color::from_argb(unchecked_scanline(y)[x]); +} + +template +ALWAYS_INLINE Color Bitmap::get_pixel(int x, int y) const { VERIFY(x >= 0); VERIFY(x < width()); - return Color::from_argb(scanline(y)[x]); + return unchecked_get_pixel(x, y); } ALWAYS_INLINE Color Bitmap::get_pixel(int x, int y) const diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp index 809fb0aee0d..0f557aa8d82 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp @@ -430,25 +430,38 @@ void DisplayListPlayerSkia::restore(Restore const&) canvas.restore(); } -static SkBitmap alpha_mask_from_bitmap(Gfx::Bitmap const& bitmap, Gfx::Bitmap::MaskKind kind) +template +[[maybe_unused]] static SkBitmap alpha_mask_from_bitmap_impl(Gfx::Bitmap const& bitmap) { SkBitmap alpha_mask; alpha_mask.allocPixels(SkImageInfo::MakeA8(bitmap.width(), bitmap.height())); - for (int y = 0; y < bitmap.height(); y++) { - for (int x = 0; x < bitmap.width(); x++) { - if (kind == Gfx::Bitmap::MaskKind::Luminance) { - auto color = bitmap.get_pixel(x, y); - *alpha_mask.getAddr8(x, y) = color.alpha() * color.luminosity() / 255; - } else { - VERIFY(kind == Gfx::Bitmap::MaskKind::Alpha); - auto color = bitmap.get_pixel(x, y); - *alpha_mask.getAddr8(x, y) = color.alpha(); + int width = bitmap.width(); + int height = bitmap.height(); + for (int y = 0; y < height; y++) { + auto* dst = alpha_mask.getAddr8(0, y); + for (int x = 0; x < width; x++, ++dst) { + auto color = bitmap.unchecked_get_pixel(x, y); + if constexpr (mask_kind == Gfx::Bitmap::MaskKind::Luminance) { + *dst = color.alpha() * color.luminosity() / 255; + } else if constexpr (mask_kind == Gfx::Bitmap::MaskKind::Alpha) { + *dst = color.alpha(); } } } return alpha_mask; } +[[maybe_unused]] static SkBitmap alpha_mask_from_bitmap(Gfx::Bitmap const& bitmap, Gfx::Bitmap::MaskKind kind) +{ + if (bitmap.format() == Gfx::BitmapFormat::BGRA8888) { + if (kind == Gfx::Bitmap::MaskKind::Luminance) + return alpha_mask_from_bitmap_impl(bitmap); + VERIFY(kind == Gfx::Bitmap::MaskKind::Alpha); + return alpha_mask_from_bitmap_impl(bitmap); + } + VERIFY_NOT_REACHED(); +} + void DisplayListPlayerSkia::push_stacking_context(PushStackingContext const& command) { auto& canvas = surface().canvas();