diff --git a/Userland/Libraries/LibGfx/ImmutableBitmap.cpp b/Userland/Libraries/LibGfx/ImmutableBitmap.cpp index 79a52b15210..67dc2bf5077 100644 --- a/Userland/Libraries/LibGfx/ImmutableBitmap.cpp +++ b/Userland/Libraries/LibGfx/ImmutableBitmap.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -14,7 +15,7 @@ namespace Gfx { struct ImmutableBitmapImpl { sk_sp sk_image; SkBitmap sk_bitmap; - RefPtr gfx_bitmap; + Variant, NonnullRefPtr, Empty> source; }; int ImmutableBitmap::width() const @@ -49,15 +50,14 @@ SkImage const* ImmutableBitmap::sk_image() const RefPtr ImmutableBitmap::bitmap() const { - return m_impl->gfx_bitmap; + // FIXME: Implement for PaintingSurface + return m_impl->source.get>(); } Color ImmutableBitmap::get_pixel(int x, int y) const { - if (m_impl->gfx_bitmap) { - return m_impl->gfx_bitmap->get_pixel(x, y); - } - VERIFY_NOT_REACHED(); + // FIXME: Implement for PaintingSurface + return m_impl->source.get>()->get_pixel(x, y); } static SkColorType to_skia_color_type(Gfx::BitmapFormat format) @@ -96,7 +96,15 @@ NonnullRefPtr ImmutableBitmap::create(NonnullRefPtr bit impl.sk_bitmap.installPixels(info, const_cast(static_cast(bitmap->scanline(0))), bitmap->pitch()); impl.sk_bitmap.setImmutable(); impl.sk_image = impl.sk_bitmap.asImage(); - impl.gfx_bitmap = bitmap; + impl.source = bitmap; + return adopt_ref(*new ImmutableBitmap(make(impl))); +} + +NonnullRefPtr ImmutableBitmap::create_snapshot_from_painting_surface(NonnullRefPtr painting_surface) +{ + ImmutableBitmapImpl impl; + impl.sk_image = painting_surface->sk_image_snapshot>(); + impl.source = painting_surface; return adopt_ref(*new ImmutableBitmap(make(impl))); } diff --git a/Userland/Libraries/LibGfx/ImmutableBitmap.h b/Userland/Libraries/LibGfx/ImmutableBitmap.h index e6b491c1e3d..e5eca00f760 100644 --- a/Userland/Libraries/LibGfx/ImmutableBitmap.h +++ b/Userland/Libraries/LibGfx/ImmutableBitmap.h @@ -22,6 +22,7 @@ struct ImmutableBitmapImpl; class ImmutableBitmap final : public RefCounted { public: static NonnullRefPtr create(NonnullRefPtr bitmap); + static NonnullRefPtr create_snapshot_from_painting_surface(NonnullRefPtr); ~ImmutableBitmap(); diff --git a/Userland/Libraries/LibGfx/PaintingSurface.cpp b/Userland/Libraries/LibGfx/PaintingSurface.cpp index 39b1a8db8c3..a94b14ab621 100644 --- a/Userland/Libraries/LibGfx/PaintingSurface.cpp +++ b/Userland/Libraries/LibGfx/PaintingSurface.cpp @@ -92,15 +92,6 @@ PaintingSurface::PaintingSurface(NonnullOwnPtr&& impl) PaintingSurface::~PaintingSurface() = default; -NonnullRefPtr PaintingSurface::create_snapshot() const -{ - auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied, size()).value(); - auto image_info = SkImageInfo::Make(bitmap->width(), bitmap->height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType); - SkPixmap const pixmap(image_info, bitmap->begin(), bitmap->pitch()); - sk_surface().readPixels(pixmap, 0, 0); - return ImmutableBitmap::create(bitmap); -} - void PaintingSurface::read_into_bitmap(Gfx::Bitmap& bitmap) { auto color_type = to_skia_color_type(bitmap.format()); @@ -130,6 +121,12 @@ SkSurface& PaintingSurface::sk_surface() const return *m_impl->surface; } +template<> +sk_sp PaintingSurface::sk_image_snapshot() const +{ + return m_impl->surface->makeImageSnapshot(); +} + void PaintingSurface::flush() const { if (auto context = m_impl->context) { diff --git a/Userland/Libraries/LibGfx/PaintingSurface.h b/Userland/Libraries/LibGfx/PaintingSurface.h index 0b89c50dab8..eed6782a92c 100644 --- a/Userland/Libraries/LibGfx/PaintingSurface.h +++ b/Userland/Libraries/LibGfx/PaintingSurface.h @@ -31,7 +31,6 @@ public: static NonnullRefPtr wrap_metal_surface(Gfx::MetalTexture&, RefPtr); #endif - NonnullRefPtr create_snapshot() const; void read_into_bitmap(Bitmap&); IntSize size() const; @@ -40,6 +39,9 @@ public: SkCanvas& canvas() const; SkSurface& sk_surface() const; + template + T sk_image_snapshot() const; + void flush() const; ~PaintingSurface(); diff --git a/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp b/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp index 384f4c3787c..54fe700086d 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp @@ -131,7 +131,7 @@ WebIDL::ExceptionOr> CanvasPattern::create(JS::Realm& r auto bitmap = image.visit( [](JS::Handle const& source) -> RefPtr { return source->immutable_bitmap(); }, [](JS::Handle const& source) -> RefPtr { return source->current_image_bitmap(); }, - [](JS::Handle const& source) -> RefPtr { return source->surface()->create_snapshot(); }, + [](JS::Handle const& source) -> RefPtr { return Gfx::ImmutableBitmap::create_snapshot_from_painting_surface(*source->surface()); }, [](JS::Handle const& source) -> RefPtr { return Gfx::ImmutableBitmap::create(*source->bitmap()); }, [](JS::Handle const& source) -> RefPtr { return Gfx::ImmutableBitmap::create(*source->bitmap()); }); diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index 811b9a4ccdb..351490247d3 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -134,7 +134,7 @@ WebIDL::ExceptionOr CanvasRenderingContext2D::draw_image_internal(CanvasIm auto surface = source->surface(); if (!surface) return {}; - return source->surface()->create_snapshot(); + return Gfx::ImmutableBitmap::create_snapshot_from_painting_surface(*surface); }, [](JS::Handle const& source) -> RefPtr { return Gfx::ImmutableBitmap::create(*source->bitmap()); }, [](JS::Handle const& source) -> RefPtr { @@ -401,7 +401,7 @@ WebIDL::ExceptionOr> CanvasRenderingContext2D::get_image_da // NOTE: We don't attempt to create the underlying bitmap here; if it doesn't exist, it's like copying only transparent black pixels (which is a no-op). if (!canvas_element().surface()) return image_data; - auto const snapshot = canvas_element().surface()->create_snapshot(); + auto const snapshot = Gfx::ImmutableBitmap::create_snapshot_from_painting_surface(*canvas_element().surface()); // 5. Let the source rectangle be the rectangle whose corners are the four points (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh). auto source_rect = Gfx::Rect { x, y, abs_width, abs_height }; diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp index e11f4bec403..9f9ca5d2ede 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp @@ -268,7 +268,7 @@ String HTMLCanvasElement::to_data_url(StringView type, Optional quality) return "data:,"_string; // 3. Let file be a serialization of this canvas element's bitmap as a file, passing type and quality if given. - auto snapshot = m_surface->create_snapshot(); + auto snapshot = Gfx::ImmutableBitmap::create_snapshot_from_painting_surface(*m_surface); auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied, m_surface->size())); m_surface->read_into_bitmap(*bitmap); auto file = serialize_bitmap(bitmap, type, move(quality));