diff options
author | Andreas Kling <kling@serenityos.org> | 2023-05-10 19:36:43 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-05-13 09:08:42 +0200 |
commit | 596eabe9e6f95ae43e1cbb42263105b1c3df1e9d (patch) | |
tree | e3604528c1c92ae44be0acc73f972b54b0f6892e /Userland | |
parent | 420952a4334b05d6ac639429e876150c78866963 (diff) | |
download | serenity-596eabe9e6f95ae43e1cbb42263105b1c3df1e9d.zip |
LibWeb: Start fleshing out HTML "image requests" and "image data"
This patch adds HTML::ImageRequest and HTML::DecodedImageData.
The latter had to use a different name than "ImageData", as there is
already an IDL-exposed ImageData class in HTML.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/DecodedImageData.cpp | 50 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/DecodedImageData.h | 44 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/ImageRequest.cpp | 100 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/HTML/ImageRequest.h | 83 |
6 files changed, 281 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 5efc844bb1..a0ad7fc120 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -223,6 +223,7 @@ set(SOURCES HTML/CustomElements/CustomElementName.cpp HTML/CustomElements/CustomElementReactionNames.cpp HTML/CustomElements/CustomElementRegistry.cpp + HTML/DecodedImageData.cpp HTML/DocumentState.cpp HTML/DOMParser.cpp HTML/DOMStringMap.cpp @@ -313,6 +314,7 @@ set(SOURCES HTML/HTMLUnknownElement.cpp HTML/HTMLVideoElement.cpp HTML/ImageData.cpp + HTML/ImageRequest.cpp HTML/Location.cpp HTML/MediaError.cpp HTML/MessageChannel.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 8cec154ee1..aa7dc45915 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -288,6 +288,7 @@ class ClassicScript; class CloseEvent; class CustomElementDefinition; class CustomElementRegistry; +class DecodedImageData; class DocumentState; class DOMParser; class DOMStringMap; @@ -371,6 +372,7 @@ class HTMLUListElement; class HTMLUnknownElement; class HTMLVideoElement; class ImageData; +class ImageRequest; class Location; class MediaError; class MessageChannel; diff --git a/Userland/Libraries/LibWeb/HTML/DecodedImageData.cpp b/Userland/Libraries/LibWeb/HTML/DecodedImageData.cpp new file mode 100644 index 0000000000..f8dbe2f7b7 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/DecodedImageData.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibGfx/Bitmap.h> +#include <LibWeb/HTML/DecodedImageData.h> + +namespace Web::HTML { + +ErrorOr<NonnullRefPtr<DecodedImageData>> DecodedImageData::create(Vector<Frame>&& frames, size_t loop_count, bool animated) +{ + return adopt_nonnull_ref_or_enomem(new (nothrow) DecodedImageData(move(frames), loop_count, animated)); +} + +DecodedImageData::DecodedImageData(Vector<Frame>&& frames, size_t loop_count, bool animated) + : m_frames(move(frames)) + , m_loop_count(loop_count) + , m_animated(animated) +{ +} + +DecodedImageData::~DecodedImageData() = default; + +RefPtr<Gfx::Bitmap const> DecodedImageData::bitmap(size_t frame_index) const +{ + if (frame_index >= m_frames.size()) + return nullptr; + return m_frames[frame_index].bitmap; +} + +int DecodedImageData::frame_duration(size_t frame_index) const +{ + if (frame_index >= m_frames.size()) + return 0; + return m_frames[frame_index].duration; +} + +Optional<int> DecodedImageData::natural_width() const +{ + return m_frames.first().bitmap->width(); +} + +Optional<int> DecodedImageData::natural_height() const +{ + return m_frames.first().bitmap->height(); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/DecodedImageData.h b/Userland/Libraries/LibWeb/HTML/DecodedImageData.h new file mode 100644 index 0000000000..41f062abd5 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/DecodedImageData.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/RefCounted.h> +#include <LibGfx/Forward.h> +#include <LibJS/Heap/Cell.h> + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/images.html#img-req-data +class DecodedImageData final : public RefCounted<DecodedImageData> { +public: + struct Frame { + RefPtr<Gfx::Bitmap const> bitmap; + int duration { 0 }; + }; + + static ErrorOr<NonnullRefPtr<DecodedImageData>> create(Vector<Frame>&&, size_t loop_count, bool animated); + ~DecodedImageData(); + + RefPtr<Gfx::Bitmap const> bitmap(size_t frame_index) const; + int frame_duration(size_t frame_index) const; + + size_t frame_count() const { return m_frames.size(); } + size_t loop_count() const { return m_loop_count; } + bool is_animated() const { return m_animated; } + + Optional<int> natural_width() const; + Optional<int> natural_height() const; + +private: + DecodedImageData(Vector<Frame>&&, size_t loop_count, bool animated); + + Vector<Frame> m_frames; + size_t m_loop_count { 0 }; + bool m_animated { false }; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp b/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp new file mode 100644 index 0000000000..01b6afa6f0 --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/ImageRequest.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibGfx/Bitmap.h> +#include <LibWeb/Fetch/Infrastructure/FetchController.h> +#include <LibWeb/HTML/DecodedImageData.h> +#include <LibWeb/HTML/ImageRequest.h> + +namespace Web::HTML { + +ErrorOr<NonnullRefPtr<ImageRequest>> ImageRequest::create() +{ + return adopt_nonnull_ref_or_enomem(new (nothrow) ImageRequest); +} + +ImageRequest::ImageRequest() = default; + +ImageRequest::~ImageRequest() = default; + +// https://html.spec.whatwg.org/multipage/images.html#img-available +bool ImageRequest::is_available() const +{ + // When an image request's state is either partially available or completely available, the image request is said to be available. + return m_state == State::PartiallyAvailable || m_state == State::CompletelyAvailable; +} + +ImageRequest::State ImageRequest::state() const +{ + return m_state; +} + +void ImageRequest::set_state(State state) +{ + m_state = state; +} + +AK::URL const& ImageRequest::current_url() const +{ + return m_current_url; +} + +void ImageRequest::set_current_url(AK::URL url) +{ + m_current_url = move(url); +} + +// https://html.spec.whatwg.org/multipage/images.html#abort-the-image-request +void ImageRequest::abort(JS::Realm& realm) +{ + // 1. Forget image request's image data, if any. + m_image_data = nullptr; + + // 2. Abort any instance of the fetching algorithm for image request, + // discarding any pending tasks generated by that algorithm. + if (m_fetch_controller) + m_fetch_controller->abort(realm, {}); + + m_fetch_controller = nullptr; +} + +RefPtr<DecodedImageData const> ImageRequest::image_data() const +{ + return m_image_data; +} + +void ImageRequest::set_image_data(RefPtr<DecodedImageData const> data) +{ + m_image_data = move(data); +} + +// https://html.spec.whatwg.org/multipage/images.html#prepare-an-image-for-presentation +void ImageRequest::prepare_for_presentation(HTMLImageElement&) +{ + // FIXME: 1. Let exifTagMap be the EXIF tags obtained from req's image data, as defined by the relevant codec. [EXIF] + // FIXME: 2. Let physicalWidth and physicalHeight be the width and height obtained from req's image data, as defined by the relevant codec. + // FIXME: 3. Let dimX be the value of exifTagMap's tag 0xA002 (PixelXDimension). + // FIXME: 4. Let dimY be the value of exifTagMap's tag 0xA003 (PixelYDimension). + // FIXME: 5. Let resX be the value of exifTagMap's tag 0x011A (XResolution). + // FIXME: 6. Let resY be the value of exifTagMap's tag 0x011B (YResolution). + // FIXME: 7. Let resUnit be the value of exifTagMap's tag 0x0128 (ResolutionUnit). + // FIXME: 8. If either dimX or dimY is not a positive integer, then return. + // FIXME: 9. If either resX or resY is not a positive floating-point number, then return. + // FIXME: 10. If resUnit is not equal to 2 (Inch), then return. + // FIXME: 11. Let widthFromDensity be the value of physicalWidth, multiplied by 72 and divided by resX. + // FIXME: 12. Let heightFromDensity be the value of physicalHeight, multiplied by 72 and divided by resY. + // FIXME: 13. If widthFromDensity is not equal to dimX or heightFromDensity is not equal to dimY, then return. + // FIXME: 14. If req's image data is CORS-cross-origin, then set img's intrinsic dimensions to dimX and dimY, scale img's pixel data accordingly, and return. + // FIXME: 15. Set req's preferred density-corrected dimensions to a struct with its width set to dimX and its height set to dimY. + // FIXME: 16. Update req's img element's presentation appropriately. +} + +void ImageRequest::set_fetch_controller(JS::GCPtr<Fetch::Infrastructure::FetchController> fetch_controller) +{ + m_fetch_controller = move(fetch_controller); +} + +} diff --git a/Userland/Libraries/LibWeb/HTML/ImageRequest.h b/Userland/Libraries/LibWeb/HTML/ImageRequest.h new file mode 100644 index 0000000000..24bdd5661d --- /dev/null +++ b/Userland/Libraries/LibWeb/HTML/ImageRequest.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023, Andreas Kling <kling@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Error.h> +#include <AK/OwnPtr.h> +#include <AK/URL.h> +#include <LibGfx/Size.h> +#include <LibJS/Heap/Handle.h> +#include <LibWeb/Forward.h> + +namespace Web::HTML { + +// https://html.spec.whatwg.org/multipage/images.html#image-request +class ImageRequest : public RefCounted<ImageRequest> { +public: + static ErrorOr<NonnullRefPtr<ImageRequest>> create(); + ~ImageRequest(); + + // https://html.spec.whatwg.org/multipage/images.html#img-req-state + enum class State { + Unavailable, + PartiallyAvailable, + CompletelyAvailable, + Broken, + }; + + bool is_available() const; + + State state() const; + void set_state(State); + + AK::URL const& current_url() const; + void set_current_url(AK::URL); + + // https://html.spec.whatwg.org/multipage/images.html#abort-the-image-request + void abort(JS::Realm&); + + [[nodiscard]] RefPtr<DecodedImageData const> image_data() const; + void set_image_data(RefPtr<DecodedImageData const>); + + [[nodiscard]] float current_pixel_density() const { return m_current_pixel_density; } + void set_current_pixel_density(float density) { m_current_pixel_density = density; } + + [[nodiscard]] Optional<Gfx::FloatSize> const& preferred_density_corrected_dimensions() const { return m_preferred_density_corrected_dimensions; } + void set_preferred_density_corrected_dimensions(Optional<Gfx::FloatSize> dimensions) { m_preferred_density_corrected_dimensions = move(dimensions); } + + // https://html.spec.whatwg.org/multipage/images.html#prepare-an-image-for-presentation + void prepare_for_presentation(HTMLImageElement&); + + void set_fetch_controller(JS::GCPtr<Fetch::Infrastructure::FetchController>); + +private: + ImageRequest(); + + // https://html.spec.whatwg.org/multipage/images.html#img-req-state + // An image request's state is initially unavailable. + State m_state { State::Unavailable }; + + // https://html.spec.whatwg.org/multipage/images.html#img-req-url + // An image request's current URL is initially the empty string. + AK::URL m_current_url; + + // https://html.spec.whatwg.org/multipage/images.html#img-req-data + RefPtr<DecodedImageData const> m_image_data; + + // https://html.spec.whatwg.org/multipage/images.html#current-pixel-density + // Each image request has a current pixel density, which must initially be 1. + float m_current_pixel_density { 1 }; + + // https://html.spec.whatwg.org/multipage/images.html#preferred-density-corrected-dimensions + // Each image request has preferred density-corrected dimensions, + // which is either a struct consisting of a width and a height or is null. It must initially be null. + Optional<Gfx::FloatSize> m_preferred_density_corrected_dimensions; + + JS::Handle<Fetch::Infrastructure::FetchController> m_fetch_controller; +}; + +} |