From 2ebb3639aa7b0dcfb3514ee88fc2b3d3dc4a4f0b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 11 Jun 2023 16:09:46 +0200 Subject: [PATCH] LibWeb: Remove ImageLoader and ImageResource The old image loading mechanism is no longer used, as everything has been moved on top of HTML::ImageRequest! :^) --- Userland/Libraries/LibWeb/CMakeLists.txt | 2 - .../Libraries/LibWeb/Loader/ImageLoader.cpp | 165 ------------------ .../Libraries/LibWeb/Loader/ImageLoader.h | 67 ------- .../Libraries/LibWeb/Loader/ImageResource.cpp | 153 ---------------- .../Libraries/LibWeb/Loader/ImageResource.h | 74 -------- Userland/Libraries/LibWeb/Loader/Resource.cpp | 3 - Userland/Libraries/LibWeb/Loader/Resource.h | 1 - 7 files changed, 465 deletions(-) delete mode 100644 Userland/Libraries/LibWeb/Loader/ImageLoader.cpp delete mode 100644 Userland/Libraries/LibWeb/Loader/ImageLoader.h delete mode 100644 Userland/Libraries/LibWeb/Loader/ImageResource.cpp delete mode 100644 Userland/Libraries/LibWeb/Loader/ImageResource.h diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index d9180f3a7e..0576fff3e2 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -431,8 +431,6 @@ set(SOURCES Loader/ContentFilter.cpp Loader/FileRequest.cpp Loader/FrameLoader.cpp - Loader/ImageLoader.cpp - Loader/ImageResource.cpp Loader/LoadRequest.cpp Loader/ProxyMappings.cpp Loader/Resource.cpp diff --git a/Userland/Libraries/LibWeb/Loader/ImageLoader.cpp b/Userland/Libraries/LibWeb/Loader/ImageLoader.cpp deleted file mode 100644 index 127250b4fd..0000000000 --- a/Userland/Libraries/LibWeb/Loader/ImageLoader.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include -#include - -namespace Web { - -ImageLoader::ImageLoader(DOM::Element& owner_element) - : m_owner_element(owner_element) - , m_timer(Platform::Timer::create()) -{ -} - -void ImageLoader::adopt_object_resource(Badge, Resource& resource) -{ - auto image_resource = ImageResource::convert_from_resource(resource); - set_resource(image_resource); -} - -void ImageLoader::load(const AK::URL& url) -{ - m_redirects_count = 0; - load_without_resetting_redirect_counter(url); -} - -void ImageLoader::load_without_resetting_redirect_counter(AK::URL const& url) -{ - m_loading_state = LoadingState::Loading; - - auto request = LoadRequest::create_for_url_on_page(url, m_owner_element->document().page()); - set_resource(ResourceLoader::the().load_resource(Resource::Type::Image, request)); -} - -void ImageLoader::set_visible_in_viewport(bool visible_in_viewport) const -{ - if (m_visible_in_viewport == visible_in_viewport) - return; - m_visible_in_viewport = visible_in_viewport; - - // FIXME: Don't update volatility every time. If we're here, we're probably scanning through - // the whole document, updating "is visible in viewport" flags, and this could lead - // to the same bitmap being marked volatile back and forth unnecessarily. - if (resource()) - const_cast(resource())->update_volatility(); -} - -void ImageLoader::resource_did_load() -{ - VERIFY(resource()); - - // For 3xx (Redirection) responses, the Location value refers to the preferred target resource for automatically redirecting the request. - auto status_code = resource()->status_code(); - if (status_code.has_value() && *status_code >= 300 && *status_code <= 399) { - auto location = resource()->response_headers().get("Location"); - if (location.has_value()) { - if (m_redirects_count > maximum_redirects_allowed) { - m_redirects_count = 0; - m_loading_state = LoadingState::Failed; - if (on_fail) - on_fail(); - return; - } - m_redirects_count++; - load_without_resetting_redirect_counter(resource()->url().complete_url(location.value())); - return; - } - } - m_redirects_count = 0; - - if (!resource()->mime_type().starts_with("image/"sv)) { - m_loading_state = LoadingState::Failed; - if (on_fail) - on_fail(); - return; - } - - m_loading_state = LoadingState::Loaded; - - if constexpr (IMAGE_LOADER_DEBUG) { - if (!resource()->has_encoded_data()) { - dbgln("ImageLoader: Resource did load, no encoded data. URL: {}", resource()->url()); - } else { - dbgln("ImageLoader: Resource did load, has encoded data. URL: {}", resource()->url()); - } - } - - if (resource()->is_animated() && resource()->frame_count() > 1) { - m_timer->set_interval(resource()->frame_duration(0)); - m_timer->on_timeout = [this] { animate(); }; - m_timer->start(); - } - - if (on_load) - on_load(); -} - -void ImageLoader::animate() -{ - if (!m_visible_in_viewport) - return; - - m_current_frame_index = (m_current_frame_index + 1) % resource()->frame_count(); - auto current_frame_duration = resource()->frame_duration(m_current_frame_index); - - if (current_frame_duration != m_timer->interval()) { - m_timer->restart(current_frame_duration); - } - - if (m_current_frame_index == resource()->frame_count() - 1) { - ++m_loops_completed; - if (m_loops_completed > 0 && m_loops_completed == resource()->loop_count()) { - m_timer->stop(); - } - } - - if (on_animate) - on_animate(); -} - -void ImageLoader::resource_did_fail() -{ - dbgln("ImageLoader: Resource did fail. URL: {}", resource()->url()); - m_loading_state = LoadingState::Failed; - if (on_fail) - on_fail(); -} - -bool ImageLoader::has_image() const -{ - if (!resource()) - return false; - return bitmap(0); -} - -unsigned ImageLoader::width() const -{ - if (!resource()) - return 0; - return bitmap(0) ? bitmap(0)->width() : 0; -} - -unsigned ImageLoader::height() const -{ - if (!resource()) - return 0; - return bitmap(0) ? bitmap(0)->height() : 0; -} - -Gfx::Bitmap const* ImageLoader::bitmap(size_t frame_index) const -{ - if (!resource()) - return nullptr; - return resource()->bitmap(frame_index); -} - -} diff --git a/Userland/Libraries/LibWeb/Loader/ImageLoader.h b/Userland/Libraries/LibWeb/Loader/ImageLoader.h deleted file mode 100644 index 8c2d75b8c5..0000000000 --- a/Userland/Libraries/LibWeb/Loader/ImageLoader.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include - -namespace Web { - -class ImageLoader : public ImageResourceClient { -public: - ImageLoader(DOM::Element& owner_element); - - void adopt_object_resource(Badge, Resource&); - - void load(const AK::URL&); - - Gfx::Bitmap const* bitmap(size_t index) const; - size_t current_frame_index() const { return m_current_frame_index; } - - bool has_image() const; - - bool has_loaded_or_failed() const { return m_loading_state != LoadingState::Loading; } - - void set_visible_in_viewport(bool) const; - - unsigned width() const; - unsigned height() const; - - Function on_load; - Function on_fail; - Function on_animate; - -private: - void load_without_resetting_redirect_counter(AK::URL const&); - - // ^ImageResourceClient - virtual void resource_did_load() override; - virtual void resource_did_fail() override; - virtual bool is_visible_in_viewport() const override { return m_visible_in_viewport; } - - void animate(); - - enum class LoadingState { - None, - Loading, - Loaded, - Failed, - }; - - JS::NonnullGCPtr m_owner_element; - - mutable bool m_visible_in_viewport { false }; - - size_t m_current_frame_index { 0 }; - size_t m_loops_completed { 0 }; - LoadingState m_loading_state { LoadingState::Loading }; - NonnullRefPtr m_timer; - size_t m_redirects_count { 0 }; -}; - -} diff --git a/Userland/Libraries/LibWeb/Loader/ImageResource.cpp b/Userland/Libraries/LibWeb/Loader/ImageResource.cpp deleted file mode 100644 index d4da3bbd9e..0000000000 --- a/Userland/Libraries/LibWeb/Loader/ImageResource.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace Web { - -NonnullRefPtr ImageResource::convert_from_resource(Resource& resource) -{ - return adopt_ref(*new ImageResource(resource)); -} - -ImageResource::ImageResource(LoadRequest const& request) - : Resource(Type::Image, request) -{ -} - -ImageResource::ImageResource(Resource& resource) - : Resource(Type::Image, resource) -{ -} - -ImageResource::~ImageResource() = default; - -int ImageResource::frame_duration(size_t frame_index) const -{ - decode_if_needed(); - if (frame_index >= m_decoded_frames.size()) - return 0; - return m_decoded_frames[frame_index].duration; -} - -void ImageResource::decode_if_needed() const -{ - if (!has_encoded_data()) - return; - - if (m_has_attempted_decode) - return; - - if (!m_decoded_frames.is_empty()) - return; - - bool is_svg_image = mime_type().starts_with("image/svg+xml"sv) || url().basename().ends_with(".svg"sv); - if (is_svg_image) { - decode_svg_image(); - } else { - decode_image(); - } - - m_has_attempted_decode = true; -} - -void ImageResource::decode_svg_image() const -{ - auto page = request().page(); - if (!page.has_value()) - return; - - auto svg_or_error = SVG::SVGDecodedImageData::create(page.value(), url(), encoded_data()); - if (svg_or_error.is_error()) { - dbgln("Could not decode svg image resource {}", url()); - return; - } - - auto svg = svg_or_error.release_value(); - m_loop_count = svg->loop_count(); - m_animated = svg->is_animated(); - m_decoded_frames.resize(svg->frame_count()); - for (size_t i = 0; i < m_decoded_frames.size(); ++i) { - auto& frame = m_decoded_frames[i]; - // FIXME: Decide on what to do when there is no intrinsic width or height - auto width = svg->intrinsic_width(); - auto height = svg->intrinsic_height(); - if (width.has_value() && height.has_value()) { - auto bitmap = svg->bitmap(i, { static_cast(width->value()), static_cast(height->value()) }); - frame.bitmap = bitmap->clone().release_value_but_fixme_should_propagate_errors(); - } - frame.duration = svg->frame_duration(i); - } -} - -void ImageResource::decode_image() const -{ - auto image = Platform::ImageCodecPlugin::the().decode_image(encoded_data()); - if (!image.has_value()) { - dbgln("Could not decode image resource {}", url()); - return; - } - - m_loop_count = image.value().loop_count; - m_animated = image.value().is_animated; - m_decoded_frames.resize(image.value().frames.size()); - for (size_t i = 0; i < m_decoded_frames.size(); ++i) { - auto& frame = m_decoded_frames[i]; - frame.bitmap = image.value().frames[i].bitmap; - frame.duration = image.value().frames[i].duration; - } -} - -Gfx::Bitmap const* ImageResource::bitmap(size_t frame_index) const -{ - decode_if_needed(); - if (frame_index >= m_decoded_frames.size()) - return nullptr; - return m_decoded_frames[frame_index].bitmap; -} - -void ImageResource::update_volatility() -{ - bool visible_in_viewport = false; - for_each_client([&](auto& client) { - if (static_cast(client).is_visible_in_viewport()) - visible_in_viewport = true; - }); - - if (!visible_in_viewport) { - for (auto& frame : m_decoded_frames) { - if (frame.bitmap) - frame.bitmap->set_volatile(); - } - return; - } - - bool still_has_decoded_image = true; - for (auto& frame : m_decoded_frames) { - if (!frame.bitmap) { - still_has_decoded_image = false; - } else { - bool was_purged = false; - bool bitmap_has_memory = frame.bitmap->set_nonvolatile(was_purged); - if (!bitmap_has_memory || was_purged) - still_has_decoded_image = false; - } - } - if (still_has_decoded_image) - return; - - m_decoded_frames.clear(); - m_has_attempted_decode = false; -} - -ImageResourceClient::~ImageResourceClient() = default; - -} diff --git a/Userland/Libraries/LibWeb/Loader/ImageResource.h b/Userland/Libraries/LibWeb/Loader/ImageResource.h deleted file mode 100644 index 75f737a793..0000000000 --- a/Userland/Libraries/LibWeb/Loader/ImageResource.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2020, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace Web { - -class ImageResource final : public Resource { - friend class Resource; - -public: - static NonnullRefPtr convert_from_resource(Resource&); - - virtual ~ImageResource() override; - - struct Frame { - RefPtr bitmap; - size_t duration { 0 }; - }; - - Gfx::Bitmap const* bitmap(size_t frame_index = 0) const; - int frame_duration(size_t frame_index) const; - size_t frame_count() const - { - decode_if_needed(); - return m_decoded_frames.size(); - } - bool is_animated() const - { - decode_if_needed(); - return m_animated; - } - size_t loop_count() const - { - decode_if_needed(); - return m_loop_count; - } - - void update_volatility(); - -private: - explicit ImageResource(LoadRequest const&); - explicit ImageResource(Resource&); - - void decode_if_needed() const; - void decode_svg_image() const; - void decode_image() const; - - mutable bool m_animated { false }; - mutable int m_loop_count { 0 }; - mutable Vector m_decoded_frames; - mutable bool m_has_attempted_decode { false }; -}; - -class ImageResourceClient : public ResourceClient { -public: - virtual ~ImageResourceClient(); - - virtual bool is_visible_in_viewport() const { return false; } - -protected: - ImageResource* resource() { return static_cast(ResourceClient::resource()); } - ImageResource const* resource() const { return static_cast(ResourceClient::resource()); } - -private: - virtual Resource::Type client_type() const override { return Resource::Type::Image; } -}; - -} diff --git a/Userland/Libraries/LibWeb/Loader/Resource.cpp b/Userland/Libraries/LibWeb/Loader/Resource.cpp index 86601c4c22..21b002f039 100644 --- a/Userland/Libraries/LibWeb/Loader/Resource.cpp +++ b/Userland/Libraries/LibWeb/Loader/Resource.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -18,8 +17,6 @@ namespace Web { NonnullRefPtr Resource::create(Badge, Type type, LoadRequest const& request) { - if (type == Type::Image) - return adopt_ref(*new ImageResource(request)); return adopt_ref(*new Resource(type, request)); } diff --git a/Userland/Libraries/LibWeb/Loader/Resource.h b/Userland/Libraries/LibWeb/Loader/Resource.h index a2d0e64f02..8531bbfff1 100644 --- a/Userland/Libraries/LibWeb/Loader/Resource.h +++ b/Userland/Libraries/LibWeb/Loader/Resource.h @@ -29,7 +29,6 @@ class Resource : public RefCounted { public: enum class Type { Generic, - Image, }; static NonnullRefPtr create(Badge, Type, LoadRequest const&);