diff --git a/Userland/Libraries/LibGfx/Forward.h b/Userland/Libraries/LibGfx/Forward.h index 7348d780d66..b9839cff4d9 100644 --- a/Userland/Libraries/LibGfx/Forward.h +++ b/Userland/Libraries/LibGfx/Forward.h @@ -28,6 +28,7 @@ class Line; class AntiAliasingPainter; class DeprecatedPainter; class Painter; +class PaintingSurface; class Palette; class PaletteImpl; class DeprecatedPath; diff --git a/Userland/Libraries/LibGfx/ImmutableBitmap.cpp b/Userland/Libraries/LibGfx/ImmutableBitmap.cpp index ddff95c21f7..bc8e65f76ee 100644 --- a/Userland/Libraries/LibGfx/ImmutableBitmap.cpp +++ b/Userland/Libraries/LibGfx/ImmutableBitmap.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Aliaksandr Kalenik + * Copyright (c) 2023-2024, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ diff --git a/Userland/Libraries/LibGfx/ImmutableBitmap.h b/Userland/Libraries/LibGfx/ImmutableBitmap.h index a414df16ba1..2ea6a04c4c1 100644 --- a/Userland/Libraries/LibGfx/ImmutableBitmap.h +++ b/Userland/Libraries/LibGfx/ImmutableBitmap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Aliaksandr Kalenik + * Copyright (c) 2023-2024, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ diff --git a/Userland/Libraries/LibGfx/PaintingSurface.cpp b/Userland/Libraries/LibGfx/PaintingSurface.cpp index 13dc73a42b1..39b1a8db8c3 100644 --- a/Userland/Libraries/LibGfx/PaintingSurface.cpp +++ b/Userland/Libraries/LibGfx/PaintingSurface.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -91,13 +92,13 @@ PaintingSurface::PaintingSurface(NonnullOwnPtr&& impl) PaintingSurface::~PaintingSurface() = default; -RefPtr PaintingSurface::create_snapshot() const +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 bitmap; + return ImmutableBitmap::create(bitmap); } void PaintingSurface::read_into_bitmap(Gfx::Bitmap& bitmap) diff --git a/Userland/Libraries/LibGfx/PaintingSurface.h b/Userland/Libraries/LibGfx/PaintingSurface.h index 336070e1d27..0b89c50dab8 100644 --- a/Userland/Libraries/LibGfx/PaintingSurface.h +++ b/Userland/Libraries/LibGfx/PaintingSurface.h @@ -31,7 +31,7 @@ public: static NonnullRefPtr wrap_metal_surface(Gfx::MetalTexture&, RefPtr); #endif - RefPtr create_snapshot() const; + NonnullRefPtr create_snapshot() const; void read_into_bitmap(Bitmap&); IntSize size() const; diff --git a/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp b/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp index 310ac52cfed..1fecd41ebdd 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasPattern.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, MacDue + * Copyright (c) 2024, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ @@ -130,7 +131,10 @@ WebIDL::ExceptionOr> CanvasPattern::create(JS::Realm& r auto bitmap = image.visit( [](JS::Handle const& source) -> RefPtr { return *source->bitmap(); }, [](JS::Handle const& source) -> RefPtr { return *source->bitmap(); }, - [](JS::Handle const& source) -> RefPtr { return source->surface()->create_snapshot(); }, + [](JS::Handle const& source) -> RefPtr { + auto snapshot = source->surface()->create_snapshot(); + return snapshot->bitmap(); + }, [](JS::Handle const& source) -> RefPtr { return *source->bitmap(); }, [](JS::Handle const& source) -> RefPtr { return *source->bitmap(); }); diff --git a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp index eb7ec32d8e3..572cd8af639 100644 --- a/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp +++ b/Userland/Libraries/LibWeb/HTML/CanvasRenderingContext2D.cpp @@ -2,6 +2,7 @@ * Copyright (c) 2020-2024, Andreas Kling * Copyright (c) 2021-2022, Linus Groh * Copyright (c) 2023, MacDue + * Copyright (c) 2024, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ @@ -125,7 +126,10 @@ WebIDL::ExceptionOr CanvasRenderingContext2D::draw_image_internal(CanvasIm auto bitmap = image.visit( [](JS::Handle const& source) -> RefPtr { return *source->bitmap(); }, [](JS::Handle const& source) -> RefPtr { return *source->bitmap(); }, - [](JS::Handle const& source) -> RefPtr { return source->surface()->create_snapshot(); }, + [](JS::Handle const& source) -> RefPtr { + auto snapshot = source->surface()->create_snapshot(); + return snapshot->bitmap(); + }, [](JS::Handle const& source) -> RefPtr { return *source->bitmap(); }, [](JS::Handle const& source) -> RefPtr { return *source->bitmap(); }); if (!bitmap) @@ -389,10 +393,10 @@ 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 bitmap = canvas_element().surface()->create_snapshot(); + auto const snapshot = canvas_element().surface()->create_snapshot(); + auto const& bitmap = snapshot->bitmap(); // 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). - //<<<<<<< HEAD auto source_rect = Gfx::Rect { x, y, abs_width, abs_height }; // NOTE: The spec doesn't seem to define this behavior, but MDN does and the WPT tests @@ -401,17 +405,17 @@ WebIDL::ExceptionOr> CanvasRenderingContext2D::get_image_da if (width < 0 || height < 0) { source_rect = source_rect.translated(min(width, 0), min(height, 0)); } - auto source_rect_intersected = source_rect.intersected(bitmap->rect()); + auto source_rect_intersected = source_rect.intersected(bitmap.rect()); // 6. Set the pixel values of imageData to be the pixels of this's output bitmap in the area specified by the source rectangle in the bitmap's coordinate space units, converted from this's color space to imageData's colorSpace using 'relative-colorimetric' rendering intent. // NOTE: Internally we must use premultiplied alpha, but ImageData should hold unpremultiplied alpha. This conversion // might result in a loss of precision, but is according to spec. // See: https://html.spec.whatwg.org/multipage/canvas.html#premultiplied-alpha-and-the-2d-rendering-context - ASSERT(bitmap->alpha_type() == Gfx::AlphaType::Premultiplied); + ASSERT(bitmap.alpha_type() == Gfx::AlphaType::Premultiplied); ASSERT(image_data->bitmap().alpha_type() == Gfx::AlphaType::Unpremultiplied); auto painter = Gfx::Painter::create(image_data->bitmap()); - painter->draw_bitmap(image_data->bitmap().rect().to_type(), *bitmap, source_rect_intersected, Gfx::ScalingMode::NearestNeighbor, drawing_state().global_alpha); + painter->draw_bitmap(image_data->bitmap().rect().to_type(), bitmap, source_rect_intersected, Gfx::ScalingMode::NearestNeighbor, drawing_state().global_alpha); // 7. Set the pixels values of imageData for areas of the source rectangle that are outside of the output bitmap to transparent black. // NOTE: No-op, already done during creation. diff --git a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp index 48e2b215cc2..b50b4a5aa30 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLCanvasElement.cpp @@ -268,7 +268,8 @@ 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 file = serialize_bitmap(*m_surface->create_snapshot(), type, move(quality)); + auto snapshot = m_surface->create_snapshot(); + auto file = serialize_bitmap(snapshot->bitmap(), type, move(quality)); // 4. If file is null then return "data:,". if (file.is_error()) { @@ -300,7 +301,8 @@ WebIDL::ExceptionOr HTMLCanvasElement::to_blob(JS::NonnullGCPtrcreate_snapshot(); + auto snapshot = m_surface->create_snapshot(); + bitmap_result = snapshot->bitmap(); } // 4. Run these steps in parallel: diff --git a/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp b/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp index 3bb1e68697a..3364a67b1c3 100644 --- a/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp @@ -52,7 +52,7 @@ ErrorOr, WebDriver::Error> draw_boundi // - Height: paint height Gfx::IntRect paint_rect { rect.x(), rect.y(), paint_width, paint_height }; - auto backing_store = Web::Painting::BitmapBackingStore(canvas.surface()->create_snapshot()); + auto backing_store = Web::Painting::BitmapBackingStore(canvas.surface()->create_snapshot()->bitmap()); browsing_context.page().client().paint(paint_rect.to_type(), backing_store); // 7. Return success with canvas. diff --git a/Userland/Libraries/LibWeb/WebGL/OpenGLContext.cpp b/Userland/Libraries/LibWeb/WebGL/OpenGLContext.cpp index 899cf22f7a0..ac3cfff8f7a 100644 --- a/Userland/Libraries/LibWeb/WebGL/OpenGLContext.cpp +++ b/Userland/Libraries/LibWeb/WebGL/OpenGLContext.cpp @@ -6,11 +6,12 @@ #include #include +#include #include namespace Web::WebGL { -OwnPtr OpenGLContext::create(Gfx::Bitmap& bitmap) +OwnPtr OpenGLContext::create(Gfx::PaintingSurface& bitmap) { (void)bitmap; return {}; diff --git a/Userland/Libraries/LibWeb/WebGL/OpenGLContext.h b/Userland/Libraries/LibWeb/WebGL/OpenGLContext.h index 2d08a43d875..92b500dcf8e 100644 --- a/Userland/Libraries/LibWeb/WebGL/OpenGLContext.h +++ b/Userland/Libraries/LibWeb/WebGL/OpenGLContext.h @@ -13,9 +13,9 @@ namespace Web::WebGL { class OpenGLContext { public: - static OwnPtr create(Gfx::Bitmap&); + static OwnPtr create(Gfx::PaintingSurface&); - virtual void present(Gfx::Bitmap&) = 0; + virtual void present(Gfx::Bitmap const&) = 0; void clear_buffer_to_default_values(); virtual GLenum gl_get_error() = 0; diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp index cfe16146274..0c775caf296 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp +++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContext.cpp @@ -46,7 +46,7 @@ JS::ThrowCompletionOr> WebGLRenderingContext::c } VERIFY(canvas_element.surface()); - auto context = OpenGLContext::create(*canvas_element.surface()->create_snapshot()); + auto context = OpenGLContext::create(*canvas_element.surface()); if (!context) { fire_webgl_context_creation_error(canvas_element); diff --git a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp index 15e7d57744e..68c9378094a 100644 --- a/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp +++ b/Userland/Libraries/LibWeb/WebGL/WebGLRenderingContextBase.cpp @@ -53,7 +53,7 @@ void WebGLRenderingContextBase::present() // FIXME: Is this the operation it means? m_context->gl_flush(); - m_context->present(*canvas_element().surface()->create_snapshot()); + m_context->present(canvas_element().surface()->create_snapshot()->bitmap()); // "By default, after compositing the contents of the drawing buffer shall be cleared to their default values, as shown in the table above. // This default behavior can be changed by setting the preserveDrawingBuffer attribute of the WebGLContextAttributes object.