summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2023-05-10 19:36:43 +0200
committerAndreas Kling <kling@serenityos.org>2023-05-13 09:08:42 +0200
commit596eabe9e6f95ae43e1cbb42263105b1c3df1e9d (patch)
treee3604528c1c92ae44be0acc73f972b54b0f6892e /Userland
parent420952a4334b05d6ac639429e876150c78866963 (diff)
downloadserenity-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.txt2
-rw-r--r--Userland/Libraries/LibWeb/Forward.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/DecodedImageData.cpp50
-rw-r--r--Userland/Libraries/LibWeb/HTML/DecodedImageData.h44
-rw-r--r--Userland/Libraries/LibWeb/HTML/ImageRequest.cpp100
-rw-r--r--Userland/Libraries/LibWeb/HTML/ImageRequest.h83
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;
+};
+
+}