mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-30 04:39:06 +00:00
LibWeb: Factor out canvas serialization algorihtm
Factor out canvas serialization algorihtm from HTMLCanvasElement to seperate file. This makes it usable by other things too.
This commit is contained in:
parent
8ef7df2a95
commit
49500ac386
Notes:
github-actions[bot]
2025-06-30 15:47:56 +00:00
Author: https://github.com/Totto16
Commit: 49500ac386
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3788
Reviewed-by: https://github.com/ADKaster ✅
Reviewed-by: https://github.com/tcl3
4 changed files with 68 additions and 34 deletions
|
@ -343,6 +343,7 @@ set(SOURCES
|
||||||
HTML/Canvas/CanvasDrawImage.cpp
|
HTML/Canvas/CanvasDrawImage.cpp
|
||||||
HTML/Canvas/CanvasPath.cpp
|
HTML/Canvas/CanvasPath.cpp
|
||||||
HTML/Canvas/CanvasState.cpp
|
HTML/Canvas/CanvasState.cpp
|
||||||
|
HTML/Canvas/SerializeBitmap.cpp
|
||||||
HTML/CanvasGradient.cpp
|
HTML/CanvasGradient.cpp
|
||||||
HTML/CanvasPattern.cpp
|
HTML/CanvasPattern.cpp
|
||||||
HTML/CanvasRenderingContext2D.cpp
|
HTML/CanvasRenderingContext2D.cpp
|
||||||
|
|
36
Libraries/LibWeb/HTML/Canvas/SerializeBitmap.cpp
Normal file
36
Libraries/LibWeb/HTML/Canvas/SerializeBitmap.cpp
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Ladybird contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <AK/MemoryStream.h>
|
||||||
|
#include <LibGfx/ImageFormats/JPEGWriter.h>
|
||||||
|
#include <LibGfx/ImageFormats/PNGWriter.h>
|
||||||
|
#include <LibWeb/HTML/Canvas/SerializeBitmap.h>
|
||||||
|
|
||||||
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/canvas.html#a-serialisation-of-the-bitmap-as-a-file
|
||||||
|
ErrorOr<SerializeBitmapResult> serialize_bitmap(Gfx::Bitmap const& bitmap, StringView type, Optional<double> quality)
|
||||||
|
{
|
||||||
|
// If type is an image format that supports variable quality (such as "image/jpeg"), quality is given, and type is not "image/png", then,
|
||||||
|
// if quality is a Number in the range 0.0 to 1.0 inclusive, the user agent must treat quality as the desired quality level.
|
||||||
|
// Otherwise, the user agent must use its default quality value, as if the quality argument had not been given.
|
||||||
|
bool valid_quality = quality.has_value() and quality.value() >= 0.0 && quality.value() <= 1.0;
|
||||||
|
|
||||||
|
if (type.equals_ignoring_ascii_case("image/jpeg"sv)) {
|
||||||
|
AllocatingMemoryStream file;
|
||||||
|
Gfx::JPEGWriter::Options jpeg_options;
|
||||||
|
if (valid_quality)
|
||||||
|
jpeg_options.quality = static_cast<int>(quality.value() * 100);
|
||||||
|
TRY(Gfx::JPEGWriter::encode(file, bitmap, jpeg_options));
|
||||||
|
return SerializeBitmapResult { TRY(file.read_until_eof()), "image/jpeg"sv };
|
||||||
|
}
|
||||||
|
|
||||||
|
// User agents must support PNG ("image/png"). User agents may support other types.
|
||||||
|
// If the user agent does not support the requested type, then it must create the file using the PNG format. [PNG]
|
||||||
|
return SerializeBitmapResult { TRY(Gfx::PNGWriter::encode(bitmap)), "image/png"sv };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
23
Libraries/LibWeb/HTML/Canvas/SerializeBitmap.h
Normal file
23
Libraries/LibWeb/HTML/Canvas/SerializeBitmap.h
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Ladybird contributors
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/ByteBuffer.h>
|
||||||
|
#include <LibGfx/Bitmap.h>
|
||||||
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
|
||||||
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
struct SerializeBitmapResult {
|
||||||
|
ByteBuffer buffer;
|
||||||
|
StringView mime_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/canvas.html#a-serialisation-of-the-bitmap-as-a-file
|
||||||
|
ErrorOr<SerializeBitmapResult> serialize_bitmap(Gfx::Bitmap const& bitmap, StringView type, Optional<double> quality);
|
||||||
|
|
||||||
|
}
|
|
@ -6,10 +6,7 @@
|
||||||
|
|
||||||
#include <AK/Base64.h>
|
#include <AK/Base64.h>
|
||||||
#include <AK/Checked.h>
|
#include <AK/Checked.h>
|
||||||
#include <AK/MemoryStream.h>
|
|
||||||
#include <LibGfx/Bitmap.h>
|
#include <LibGfx/Bitmap.h>
|
||||||
#include <LibGfx/ImageFormats/JPEGWriter.h>
|
|
||||||
#include <LibGfx/ImageFormats/PNGWriter.h>
|
|
||||||
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
#include <LibWeb/Bindings/ExceptionOrUtils.h>
|
||||||
#include <LibWeb/Bindings/HTMLCanvasElementPrototype.h>
|
#include <LibWeb/Bindings/HTMLCanvasElementPrototype.h>
|
||||||
#include <LibWeb/CSS/ComputedProperties.h>
|
#include <LibWeb/CSS/ComputedProperties.h>
|
||||||
|
@ -19,6 +16,7 @@
|
||||||
#include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
|
#include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
|
||||||
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
|
#include <LibWeb/CSS/StyleValues/StyleValueList.h>
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
|
#include <LibWeb/HTML/Canvas/SerializeBitmap.h>
|
||||||
#include <LibWeb/HTML/CanvasRenderingContext2D.h>
|
#include <LibWeb/HTML/CanvasRenderingContext2D.h>
|
||||||
#include <LibWeb/HTML/HTMLCanvasElement.h>
|
#include <LibWeb/HTML/HTMLCanvasElement.h>
|
||||||
#include <LibWeb/HTML/Numbers.h>
|
#include <LibWeb/HTML/Numbers.h>
|
||||||
|
@ -289,35 +287,8 @@ Gfx::IntSize HTMLCanvasElement::bitmap_size_for_canvas(size_t minimum_width, siz
|
||||||
return Gfx::IntSize(width, height);
|
return Gfx::IntSize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerializeBitmapResult {
|
|
||||||
ByteBuffer buffer;
|
|
||||||
StringView mime_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/canvas.html#a-serialisation-of-the-bitmap-as-a-file
|
|
||||||
static ErrorOr<SerializeBitmapResult> serialize_bitmap(Gfx::Bitmap const& bitmap, StringView type, JS::Value quality)
|
|
||||||
{
|
|
||||||
// If type is an image format that supports variable quality (such as "image/jpeg"), quality is given, and type is not "image/png", then,
|
|
||||||
// if quality is a Number in the range 0.0 to 1.0 inclusive, the user agent must treat quality as the desired quality level.
|
|
||||||
// Otherwise, the user agent must use its default quality value, as if the quality argument had not been given.
|
|
||||||
bool valid_quality = quality.is_number() && quality.as_double() >= 0.0 && quality.as_double() <= 1.0;
|
|
||||||
|
|
||||||
if (type.equals_ignoring_ascii_case("image/jpeg"sv)) {
|
|
||||||
AllocatingMemoryStream file;
|
|
||||||
Gfx::JPEGWriter::Options jpeg_options;
|
|
||||||
if (valid_quality)
|
|
||||||
jpeg_options.quality = static_cast<int>(quality.as_double() * 100);
|
|
||||||
TRY(Gfx::JPEGWriter::encode(file, bitmap, jpeg_options));
|
|
||||||
return SerializeBitmapResult { TRY(file.read_until_eof()), "image/jpeg"sv };
|
|
||||||
}
|
|
||||||
|
|
||||||
// User agents must support PNG ("image/png"). User agents may support other types.
|
|
||||||
// If the user agent does not support the requested type, then it must create the file using the PNG format. [PNG]
|
|
||||||
return SerializeBitmapResult { TRY(Gfx::PNGWriter::encode(bitmap)), "image/png"sv };
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-todataurl
|
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-todataurl
|
||||||
String HTMLCanvasElement::to_data_url(StringView type, JS::Value quality)
|
String HTMLCanvasElement::to_data_url(StringView type, JS::Value js_quality)
|
||||||
{
|
{
|
||||||
// It is possible the canvas doesn't have a associated bitmap so create one
|
// It is possible the canvas doesn't have a associated bitmap so create one
|
||||||
allocate_painting_surface_if_needed();
|
allocate_painting_surface_if_needed();
|
||||||
|
@ -340,7 +311,8 @@ String HTMLCanvasElement::to_data_url(StringView type, JS::Value quality)
|
||||||
auto snapshot = Gfx::ImmutableBitmap::create_snapshot_from_painting_surface(*surface);
|
auto snapshot = Gfx::ImmutableBitmap::create_snapshot_from_painting_surface(*surface);
|
||||||
auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied, surface->size()));
|
auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied, surface->size()));
|
||||||
surface->read_into_bitmap(*bitmap);
|
surface->read_into_bitmap(*bitmap);
|
||||||
auto file = serialize_bitmap(bitmap, type, move(quality));
|
Optional<double> quality = js_quality.is_number() ? js_quality.as_double() : Optional<double>();
|
||||||
|
auto file = serialize_bitmap(bitmap, type, quality);
|
||||||
|
|
||||||
// 4. If file is null, then return "data:,".
|
// 4. If file is null, then return "data:,".
|
||||||
if (file.is_error()) {
|
if (file.is_error()) {
|
||||||
|
@ -357,7 +329,7 @@ String HTMLCanvasElement::to_data_url(StringView type, JS::Value quality)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-toblob
|
// https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-toblob
|
||||||
WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(GC::Ref<WebIDL::CallbackType> callback, StringView type, JS::Value quality)
|
WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(GC::Ref<WebIDL::CallbackType> callback, StringView type, JS::Value js_quality)
|
||||||
{
|
{
|
||||||
// It is possible the canvas doesn't have a associated bitmap so create one
|
// It is possible the canvas doesn't have a associated bitmap so create one
|
||||||
allocate_painting_surface_if_needed();
|
allocate_painting_surface_if_needed();
|
||||||
|
@ -381,12 +353,14 @@ WebIDL::ExceptionOr<void> HTMLCanvasElement::to_blob(GC::Ref<WebIDL::CallbackTyp
|
||||||
surface->read_into_bitmap(*bitmap_result);
|
surface->read_into_bitmap(*bitmap_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Optional<double> quality = js_quality.is_number() ? js_quality.as_double() : Optional<double>();
|
||||||
|
|
||||||
// 4. Run these steps in parallel:
|
// 4. Run these steps in parallel:
|
||||||
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(heap(), [this, callback, bitmap_result, type, quality] {
|
Platform::EventLoopPlugin::the().deferred_invoke(GC::create_function(heap(), [this, callback, bitmap_result, type, quality] {
|
||||||
// 1. If result is non-null, then set result to a serialization of result as a file with type and quality if given.
|
// 1. If result is non-null, then set result to a serialization of result as a file with type and quality if given.
|
||||||
Optional<SerializeBitmapResult> file_result;
|
Optional<SerializeBitmapResult> file_result;
|
||||||
if (bitmap_result) {
|
if (bitmap_result) {
|
||||||
if (auto result = serialize_bitmap(*bitmap_result, type, move(quality)); !result.is_error())
|
if (auto result = serialize_bitmap(*bitmap_result, type, quality); !result.is_error())
|
||||||
file_result = result.release_value();
|
file_result = result.release_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue