diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 3c73271faa..6181bfa419 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -83,6 +83,7 @@ set(SOURCES CSS/StyleValues/GridTrackPlacementShorthandStyleValue.cpp CSS/StyleValues/GridTrackSizeStyleValue.cpp CSS/StyleValues/IdentifierStyleValue.cpp + CSS/StyleValues/ImageStyleValue.cpp CSS/Supports.cpp CSS/SyntaxHighlighter/SyntaxHighlighter.cpp CSS/Time.cpp diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index d669c3a280..a01a65df1e 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index ae117b2c9a..ad48ace59c 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1033,95 +1034,6 @@ CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalcNumberSumPartW return value->resolve(layout_node, percentage_basis); } -ImageStyleValue::ImageStyleValue(AK::URL const& url) - : AbstractImageStyleValue(Type::Image) - , m_url(url) -{ -} - -void ImageStyleValue::load_any_resources(DOM::Document& document) -{ - if (resource()) - return; - - m_document = &document; - auto request = LoadRequest::create_for_url_on_page(m_url, document.page()); - set_resource(ResourceLoader::the().load_resource(Resource::Type::Image, request)); -} - -void ImageStyleValue::resource_did_load() -{ - if (!m_document) - return; - // FIXME: Do less than a full repaint if possible? - if (m_document && m_document->browsing_context()) - m_document->browsing_context()->set_needs_display(); - - if (resource()->is_animated() && resource()->frame_count() > 1) { - m_timer = Platform::Timer::create(); - m_timer->set_interval(resource()->frame_duration(0)); - m_timer->on_timeout = [this] { animate(); }; - m_timer->start(); - } -} - -void ImageStyleValue::animate() -{ - 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(); -} - -Gfx::Bitmap const* ImageStyleValue::bitmap(size_t frame_index) const -{ - if (!resource()) - return nullptr; - return resource()->bitmap(frame_index); -} - -ErrorOr ImageStyleValue::to_string() const -{ - return serialize_a_url(m_url.to_deprecated_string()); -} - -bool ImageStyleValue::equals(StyleValue const& other) const -{ - if (type() != other.type()) - return false; - return m_url == other.as_image().m_url; -} - -Optional ImageStyleValue::natural_width() const -{ - if (auto* b = bitmap(0); b != nullptr) - return b->width(); - return {}; -} - -Optional ImageStyleValue::natural_height() const -{ - if (auto* b = bitmap(0); b != nullptr) - return b->height(); - return {}; -} - -void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const -{ - if (auto* b = bitmap(m_current_frame_index); b != nullptr) - context.painter().draw_scaled_bitmap(dest_rect.to_type(), *b, bitmap(0)->rect(), 1.0f, to_gfx_scaling_mode(image_rendering)); -} - static ErrorOr serialize_color_stop_list(StringBuilder& builder, auto const& color_stop_list) { bool first = true; diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 5c41a54f47..0029f945c0 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -675,43 +675,6 @@ public: virtual void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const = 0; }; -class ImageStyleValue final - : public AbstractImageStyleValue - , public ImageResourceClient { -public: - static ValueComparingNonnullRefPtr create(AK::URL const& url) { return adopt_ref(*new ImageStyleValue(url)); } - virtual ~ImageStyleValue() override = default; - - virtual ErrorOr to_string() const override; - virtual bool equals(StyleValue const& other) const override; - - virtual void load_any_resources(DOM::Document&) override; - - Optional natural_width() const override; - Optional natural_height() const override; - - bool is_paintable() const override { return bitmap(0) != nullptr; } - void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const override; - - Function on_animate; - -private: - ImageStyleValue(AK::URL const&); - - // ^ResourceClient - virtual void resource_did_load() override; - - void animate(); - Gfx::Bitmap const* bitmap(size_t index) const; - - AK::URL m_url; - WeakPtr m_document; - - size_t m_current_frame_index { 0 }; - size_t m_loops_completed { 0 }; - RefPtr m_timer; -}; - enum class GradientRepeating { Yes, No diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp new file mode 100644 index 0000000000..0039031c0a --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Tobias Christiansen + * Copyright (c) 2021-2023, Sam Atkins + * Copyright (c) 2022-2023, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "ImageStyleValue.h" +#include +#include +#include +#include + +namespace Web::CSS { + +ImageStyleValue::ImageStyleValue(AK::URL const& url) + : AbstractImageStyleValue(Type::Image) + , m_url(url) +{ +} + +void ImageStyleValue::load_any_resources(DOM::Document& document) +{ + if (resource()) + return; + + m_document = &document; + auto request = LoadRequest::create_for_url_on_page(m_url, document.page()); + set_resource(ResourceLoader::the().load_resource(Resource::Type::Image, request)); +} + +void ImageStyleValue::resource_did_load() +{ + if (!m_document) + return; + // FIXME: Do less than a full repaint if possible? + if (m_document && m_document->browsing_context()) + m_document->browsing_context()->set_needs_display(); + + if (resource()->is_animated() && resource()->frame_count() > 1) { + m_timer = Platform::Timer::create(); + m_timer->set_interval(resource()->frame_duration(0)); + m_timer->on_timeout = [this] { animate(); }; + m_timer->start(); + } +} + +void ImageStyleValue::animate() +{ + 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(); +} + +Gfx::Bitmap const* ImageStyleValue::bitmap(size_t frame_index) const +{ + if (!resource()) + return nullptr; + return resource()->bitmap(frame_index); +} + +ErrorOr ImageStyleValue::to_string() const +{ + return serialize_a_url(m_url.to_deprecated_string()); +} + +bool ImageStyleValue::equals(StyleValue const& other) const +{ + if (type() != other.type()) + return false; + return m_url == other.as_image().m_url; +} + +Optional ImageStyleValue::natural_width() const +{ + if (auto* b = bitmap(0); b != nullptr) + return b->width(); + return {}; +} + +Optional ImageStyleValue::natural_height() const +{ + if (auto* b = bitmap(0); b != nullptr) + return b->height(); + return {}; +} + +void ImageStyleValue::paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const +{ + if (auto* b = bitmap(m_current_frame_index); b != nullptr) + context.painter().draw_scaled_bitmap(dest_rect.to_type(), *b, bitmap(0)->rect(), 1.0f, to_gfx_scaling_mode(image_rendering)); +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h new file mode 100644 index 0000000000..584461a17b --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Tobias Christiansen + * Copyright (c) 2021-2023, Sam Atkins + * Copyright (c) 2022-2023, MacDue + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::CSS { + +class ImageStyleValue final + : public AbstractImageStyleValue + , public ImageResourceClient { +public: + static ValueComparingNonnullRefPtr create(AK::URL const& url) { return adopt_ref(*new ImageStyleValue(url)); } + virtual ~ImageStyleValue() override = default; + + virtual ErrorOr to_string() const override; + virtual bool equals(StyleValue const& other) const override; + + virtual void load_any_resources(DOM::Document&) override; + + Optional natural_width() const override; + Optional natural_height() const override; + + bool is_paintable() const override { return bitmap(0) != nullptr; } + void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const override; + + Function on_animate; + +private: + ImageStyleValue(AK::URL const&); + + // ^ResourceClient + virtual void resource_did_load() override; + + void animate(); + Gfx::Bitmap const* bitmap(size_t index) const; + + AK::URL m_url; + WeakPtr m_document; + + size_t m_current_frame_index { 0 }; + size_t m_loops_completed { 0 }; + RefPtr m_timer; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp index 0a0be578f1..d2ef464426 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLBodyElement.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include