diff options
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/BackdropFilter.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleComputer.cpp | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleValue.cpp | 112 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleValue.h | 80 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.cpp | 127 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.h | 100 |
8 files changed, 232 insertions, 191 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 1d35524eb9..450c8b59ac 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -73,6 +73,7 @@ set(SOURCES CSS/StyleValues/BorderStyleValue.cpp CSS/StyleValues/ColorStyleValue.cpp CSS/StyleValues/ContentStyleValue.cpp + CSS/StyleValues/FilterValueListStyleValue.cpp CSS/Supports.cpp CSS/SyntaxHighlighter/SyntaxHighlighter.cpp CSS/Time.cpp diff --git a/Userland/Libraries/LibWeb/CSS/BackdropFilter.h b/Userland/Libraries/LibWeb/CSS/BackdropFilter.h index bdceb36ee1..5dd1e5be8d 100644 --- a/Userland/Libraries/LibWeb/CSS/BackdropFilter.h +++ b/Userland/Libraries/LibWeb/CSS/BackdropFilter.h @@ -8,6 +8,7 @@ #include <AK/Variant.h> #include <LibWeb/CSS/StyleValue.h> +#include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h> namespace Web::CSS { diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 84b48ed75b..1a2883164a 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -38,6 +38,7 @@ #include <LibWeb/CSS/StyleValues/BorderStyleValue.h> #include <LibWeb/CSS/StyleValues/ColorStyleValue.h> #include <LibWeb/CSS/StyleValues/ContentStyleValue.h> +#include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/Dump.h> #include <LibWeb/Infra/Strings.h> diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index c04837ee15..61d8a4b754 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -30,6 +30,7 @@ #include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h> #include <LibWeb/CSS/StyleValues/BorderStyleValue.h> #include <LibWeb/CSS/StyleValues/ColorStyleValue.h> +#include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/DOM/Element.h> #include <LibWeb/FontCache.h> diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index 0e9bca9cb5..f13b0db3a2 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -20,6 +20,7 @@ #include <LibWeb/CSS/StyleValues/BorderStyleValue.h> #include <LibWeb/CSS/StyleValues/ColorStyleValue.h> #include <LibWeb/CSS/StyleValues/ContentStyleValue.h> +#include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h> #include <LibWeb/DOM/Document.h> #include <LibWeb/HTML/BrowsingContext.h> #include <LibWeb/Loader/LoadRequest.h> @@ -1022,117 +1023,6 @@ CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalcNumberSumPartW return value->resolve(layout_node, percentage_basis); } -float Filter::Blur::resolved_radius(Layout::Node const& node) const -{ - // Default value when omitted is 0px. - auto sigma = 0; - if (radius.has_value()) - sigma = radius->resolved(node).to_px(node).value(); - // Note: The radius/sigma of the blur needs to be doubled for LibGfx's blur functions. - return sigma * 2; -} - -Filter::DropShadow::Resolved Filter::DropShadow::resolved(Layout::Node const& node) const -{ - // The default value for omitted values is missing length values set to 0 - // and the missing used color is taken from the color property. - return Resolved { - offset_x.resolved(node).to_px(node).value(), - offset_y.resolved(node).to_px(node).value(), - radius.has_value() ? radius->resolved(node).to_px(node).value() : 0.0f, - color.has_value() ? *color : node.computed_values().color() - }; -} - -float Filter::HueRotate::angle_degrees() const -{ - // Default value when omitted is 0deg. - if (!angle.has_value()) - return 0.0f; - return angle->visit([&](Angle const& angle) { return angle.to_degrees(); }, [&](auto) { return 0.0f; }); -} - -float Filter::Color::resolved_amount() const -{ - if (amount.has_value()) { - if (amount->is_percentage()) - return amount->percentage().as_fraction(); - return amount->number().value(); - } - // All color filters (brightness, sepia, etc) have a default amount of 1. - return 1.0f; -} - -ErrorOr<String> FilterValueListStyleValue::to_string() const -{ - StringBuilder builder {}; - bool first = true; - for (auto& filter_function : filter_value_list()) { - if (!first) - TRY(builder.try_append(' ')); - TRY(filter_function.visit( - [&](Filter::Blur const& blur) -> ErrorOr<void> { - TRY(builder.try_append("blur("sv)); - if (blur.radius.has_value()) - TRY(builder.try_append(TRY(blur.radius->to_string()))); - return {}; - }, - [&](Filter::DropShadow const& drop_shadow) -> ErrorOr<void> { - TRY(builder.try_appendff("drop-shadow({} {}"sv, - drop_shadow.offset_x, drop_shadow.offset_y)); - if (drop_shadow.radius.has_value()) - TRY(builder.try_appendff(" {}", TRY(drop_shadow.radius->to_string()))); - if (drop_shadow.color.has_value()) { - TRY(builder.try_append(' ')); - TRY(serialize_a_srgb_value(builder, *drop_shadow.color)); - } - return {}; - }, - [&](Filter::HueRotate const& hue_rotate) -> ErrorOr<void> { - TRY(builder.try_append("hue-rotate("sv)); - if (hue_rotate.angle.has_value()) { - TRY(hue_rotate.angle->visit( - [&](Angle const& angle) -> ErrorOr<void> { - return builder.try_append(TRY(angle.to_string())); - }, - [&](auto&) -> ErrorOr<void> { - return builder.try_append('0'); - })); - } - return {}; - }, - [&](Filter::Color const& color) -> ErrorOr<void> { - TRY(builder.try_appendff("{}(", - [&] { - switch (color.operation) { - case Filter::Color::Operation::Brightness: - return "brightness"sv; - case Filter::Color::Operation::Contrast: - return "contrast"sv; - case Filter::Color::Operation::Grayscale: - return "grayscale"sv; - case Filter::Color::Operation::Invert: - return "invert"sv; - case Filter::Color::Operation::Opacity: - return "opacity"sv; - case Filter::Color::Operation::Saturate: - return "saturate"sv; - case Filter::Color::Operation::Sepia: - return "sepia"sv; - default: - VERIFY_NOT_REACHED(); - } - }())); - if (color.amount.has_value()) - TRY(builder.try_append(TRY(color.amount->to_string()))); - return {}; - })); - TRY(builder.try_append(')')); - first = false; - } - return builder.to_string(); -} - ErrorOr<String> FlexStyleValue::to_string() const { return String::formatted("{} {} {}", TRY(m_properties.grow->to_string()), TRY(m_properties.shrink->to_string()), TRY(m_properties.basis->to_string())); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 0719cc91a5..1a40817745 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -145,58 +145,6 @@ struct EdgeRect { bool operator==(EdgeRect const&) const = default; }; -namespace Filter { - -struct Blur { - Optional<Length> radius {}; - float resolved_radius(Layout::Node const&) const; - bool operator==(Blur const&) const = default; -}; - -struct DropShadow { - Length offset_x; - Length offset_y; - Optional<Length> radius {}; - Optional<Color> color {}; - struct Resolved { - float offset_x; - float offset_y; - float radius; - Color color; - }; - Resolved resolved(Layout::Node const&) const; - bool operator==(DropShadow const&) const = default; -}; - -struct HueRotate { - struct Zero { - bool operator==(Zero const&) const = default; - }; - using AngleOrZero = Variant<Angle, Zero>; - Optional<AngleOrZero> angle {}; - float angle_degrees() const; - bool operator==(HueRotate const&) const = default; -}; - -struct Color { - enum class Operation { - Brightness, - Contrast, - Grayscale, - Invert, - Opacity, - Saturate, - Sepia - } operation; - Optional<NumberPercentage> amount {}; - float resolved_amount() const; - bool operator==(Color const&) const = default; -}; - -}; - -using FilterFunction = Variant<Filter::Blur, Filter::DropShadow, Filter::HueRotate, Filter::Color>; - // FIXME: Find a better place for this helper. inline Gfx::Painter::ScalingMode to_gfx_scaling_mode(CSS::ImageRendering css_value) { @@ -713,34 +661,6 @@ private: NonnullOwnPtr<CalcSum> m_expression; }; -class FilterValueListStyleValue final : public StyleValueWithDefaultOperators<FilterValueListStyleValue> { -public: - static ValueComparingNonnullRefPtr<FilterValueListStyleValue> create( - Vector<FilterFunction> filter_value_list) - { - VERIFY(filter_value_list.size() >= 1); - return adopt_ref(*new FilterValueListStyleValue(move(filter_value_list))); - } - - Vector<FilterFunction> const& filter_value_list() const { return m_filter_value_list; } - - virtual ErrorOr<String> to_string() const override; - - virtual ~FilterValueListStyleValue() override = default; - - bool properties_equal(FilterValueListStyleValue const& other) const { return m_filter_value_list == other.m_filter_value_list; }; - -private: - FilterValueListStyleValue(Vector<FilterFunction> filter_value_list) - : StyleValueWithDefaultOperators(Type::FilterValueList) - , m_filter_value_list(move(filter_value_list)) - { - } - - // FIXME: No support for SVG filters yet - Vector<FilterFunction> m_filter_value_list; -}; - class FlexStyleValue final : public StyleValueWithDefaultOperators<FlexStyleValue> { public: static ValueComparingNonnullRefPtr<FlexStyleValue> create( diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.cpp new file mode 100644 index 0000000000..a106fd1001 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> + * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org> + * Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "FilterValueListStyleValue.h" +#include <LibWeb/CSS/Serialize.h> +#include <LibWeb/Layout/Node.h> + +namespace Web::CSS { + +float Filter::Blur::resolved_radius(Layout::Node const& node) const +{ + // Default value when omitted is 0px. + auto sigma = 0; + if (radius.has_value()) + sigma = radius->resolved(node).to_px(node).value(); + // Note: The radius/sigma of the blur needs to be doubled for LibGfx's blur functions. + return sigma * 2; +} + +Filter::DropShadow::Resolved Filter::DropShadow::resolved(Layout::Node const& node) const +{ + // The default value for omitted values is missing length values set to 0 + // and the missing used color is taken from the color property. + return Resolved { + offset_x.resolved(node).to_px(node).value(), + offset_y.resolved(node).to_px(node).value(), + radius.has_value() ? radius->resolved(node).to_px(node).value() : 0.0f, + color.has_value() ? *color : node.computed_values().color() + }; +} + +float Filter::HueRotate::angle_degrees() const +{ + // Default value when omitted is 0deg. + if (!angle.has_value()) + return 0.0f; + return angle->visit([&](Angle const& a) { return a.to_degrees(); }, [&](auto) { return 0.0f; }); +} + +float Filter::Color::resolved_amount() const +{ + if (amount.has_value()) { + if (amount->is_percentage()) + return amount->percentage().as_fraction(); + return amount->number().value(); + } + // All color filters (brightness, sepia, etc) have a default amount of 1. + return 1.0f; +} + +ErrorOr<String> FilterValueListStyleValue::to_string() const +{ + StringBuilder builder {}; + bool first = true; + for (auto& filter_function : filter_value_list()) { + if (!first) + TRY(builder.try_append(' ')); + TRY(filter_function.visit( + [&](Filter::Blur const& blur) -> ErrorOr<void> { + TRY(builder.try_append("blur("sv)); + if (blur.radius.has_value()) + TRY(builder.try_append(TRY(blur.radius->to_string()))); + return {}; + }, + [&](Filter::DropShadow const& drop_shadow) -> ErrorOr<void> { + TRY(builder.try_appendff("drop-shadow({} {}"sv, + drop_shadow.offset_x, drop_shadow.offset_y)); + if (drop_shadow.radius.has_value()) + TRY(builder.try_appendff(" {}", TRY(drop_shadow.radius->to_string()))); + if (drop_shadow.color.has_value()) { + TRY(builder.try_append(' ')); + TRY(serialize_a_srgb_value(builder, *drop_shadow.color)); + } + return {}; + }, + [&](Filter::HueRotate const& hue_rotate) -> ErrorOr<void> { + TRY(builder.try_append("hue-rotate("sv)); + if (hue_rotate.angle.has_value()) { + TRY(hue_rotate.angle->visit( + [&](Angle const& angle) -> ErrorOr<void> { + return builder.try_append(TRY(angle.to_string())); + }, + [&](auto&) -> ErrorOr<void> { + return builder.try_append('0'); + })); + } + return {}; + }, + [&](Filter::Color const& color) -> ErrorOr<void> { + TRY(builder.try_appendff("{}(", + [&] { + switch (color.operation) { + case Filter::Color::Operation::Brightness: + return "brightness"sv; + case Filter::Color::Operation::Contrast: + return "contrast"sv; + case Filter::Color::Operation::Grayscale: + return "grayscale"sv; + case Filter::Color::Operation::Invert: + return "invert"sv; + case Filter::Color::Operation::Opacity: + return "opacity"sv; + case Filter::Color::Operation::Saturate: + return "saturate"sv; + case Filter::Color::Operation::Sepia: + return "sepia"sv; + default: + VERIFY_NOT_REACHED(); + } + }())); + if (color.amount.has_value()) + TRY(builder.try_append(TRY(color.amount->to_string()))); + return {}; + })); + TRY(builder.try_append(')')); + first = false; + } + return builder.to_string(); +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.h new file mode 100644 index 0000000000..2275d04dcc --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/FilterValueListStyleValue.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> + * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org> + * Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibWeb/CSS/Angle.h> +#include <LibWeb/CSS/Length.h> +#include <LibWeb/CSS/Number.h> +#include <LibWeb/CSS/Percentage.h> +#include <LibWeb/CSS/StyleValue.h> + +namespace Web::CSS { + +namespace Filter { + +struct Blur { + Optional<Length> radius {}; + float resolved_radius(Layout::Node const&) const; + bool operator==(Blur const&) const = default; +}; + +struct DropShadow { + Length offset_x; + Length offset_y; + Optional<Length> radius {}; + Optional<Color> color {}; + struct Resolved { + float offset_x; + float offset_y; + float radius; + Color color; + }; + Resolved resolved(Layout::Node const&) const; + bool operator==(DropShadow const&) const = default; +}; + +struct HueRotate { + struct Zero { + bool operator==(Zero const&) const = default; + }; + using AngleOrZero = Variant<Angle, Zero>; + Optional<AngleOrZero> angle {}; + float angle_degrees() const; + bool operator==(HueRotate const&) const = default; +}; + +struct Color { + enum class Operation { + Brightness, + Contrast, + Grayscale, + Invert, + Opacity, + Saturate, + Sepia + } operation; + Optional<NumberPercentage> amount {}; + float resolved_amount() const; + bool operator==(Color const&) const = default; +}; + +}; + +using FilterFunction = Variant<Filter::Blur, Filter::DropShadow, Filter::HueRotate, Filter::Color>; + +class FilterValueListStyleValue final : public StyleValueWithDefaultOperators<FilterValueListStyleValue> { +public: + static ValueComparingNonnullRefPtr<FilterValueListStyleValue> create( + Vector<FilterFunction> filter_value_list) + { + VERIFY(filter_value_list.size() >= 1); + return adopt_ref(*new FilterValueListStyleValue(move(filter_value_list))); + } + + Vector<FilterFunction> const& filter_value_list() const { return m_filter_value_list; } + + virtual ErrorOr<String> to_string() const override; + + virtual ~FilterValueListStyleValue() override = default; + + bool properties_equal(FilterValueListStyleValue const& other) const { return m_filter_value_list == other.m_filter_value_list; }; + +private: + FilterValueListStyleValue(Vector<FilterFunction> filter_value_list) + : StyleValueWithDefaultOperators(Type::FilterValueList) + , m_filter_value_list(move(filter_value_list)) + { + } + + // FIXME: No support for SVG filters yet + Vector<FilterFunction> m_filter_value_list; +}; + +} |