diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index a6e30bedb7a..7ec4cbffa86 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -158,7 +158,6 @@ set(SOURCES CSS/StyleValues/PositionStyleValue.cpp CSS/StyleValues/RadialGradientStyleValue.cpp CSS/StyleValues/RectStyleValue.cpp - CSS/StyleValues/RotationStyleValue.cpp CSS/StyleValues/ShadowStyleValue.cpp CSS/StyleValues/ShorthandStyleValue.cpp CSS/StyleValues/StyleValueList.cpp diff --git a/Libraries/LibWeb/CSS/CSSStyleValue.cpp b/Libraries/LibWeb/CSS/CSSStyleValue.cpp index df16704267b..78cd08d113c 100644 --- a/Libraries/LibWeb/CSS/CSSStyleValue.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleValue.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include #include #include @@ -295,12 +294,6 @@ ResolutionStyleValue const& CSSStyleValue::as_resolution() const return static_cast(*this); } -RotationStyleValue const& CSSStyleValue::as_rotation() const -{ - VERIFY(is_rotation()); - return static_cast(*this); -} - ScrollbarGutterStyleValue const& CSSStyleValue::as_scrollbar_gutter() const { VERIFY(is_scrollbar_gutter()); diff --git a/Libraries/LibWeb/CSS/CSSStyleValue.h b/Libraries/LibWeb/CSS/CSSStyleValue.h index 9dc4d23e29f..2717bb78eeb 100644 --- a/Libraries/LibWeb/CSS/CSSStyleValue.h +++ b/Libraries/LibWeb/CSS/CSSStyleValue.h @@ -127,7 +127,6 @@ public: Ratio, Rect, Resolution, - Rotation, ScrollbarGutter, Shadow, Shorthand, @@ -297,10 +296,6 @@ public: ResolutionStyleValue const& as_resolution() const; ResolutionStyleValue& as_resolution() { return const_cast(const_cast(*this).as_resolution()); } - bool is_rotation() const { return type() == Type::Rotation; } - RotationStyleValue const& as_rotation() const; - RotationStyleValue& as_rotation() { return const_cast(const_cast(*this).as_rotation()); } - bool is_scrollbar_gutter() const { return type() == Type::ScrollbarGutter; } ScrollbarGutterStyleValue const& as_scrollbar_gutter() const; ScrollbarGutterStyleValue& as_scrollbar_gutter() { return const_cast(const_cast(*this).as_scrollbar_gutter()); } diff --git a/Libraries/LibWeb/CSS/ComputedProperties.cpp b/Libraries/LibWeb/CSS/ComputedProperties.cpp index 43423f99c69..66a73bb432d 100644 --- a/Libraries/LibWeb/CSS/ComputedProperties.cpp +++ b/Libraries/LibWeb/CSS/ComputedProperties.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -558,41 +557,12 @@ Vector ComputedProperties::transformations() const return transformations_for_style_value(property(CSS::PropertyID::Transform)); } -Optional ComputedProperties::rotate(Layout::Node const& layout_node) const +Optional ComputedProperties::rotate() const { - auto const& value = property(CSS::PropertyID::Rotate); - if (!value.is_rotation()) + auto const& value = property(PropertyID::Rotate); + if (!value.is_transformation()) return {}; - auto& rotation = value.as_rotation(); - - auto resolve_angle = [&layout_node](CSSStyleValue const& value) -> Optional { - if (value.is_angle()) - return value.as_angle().angle(); - if (value.is_calculated() && value.as_calculated().resolves_to_angle()) - return value.as_calculated().resolve_angle(layout_node); - return {}; - }; - - auto resolve_number = [&](CSSStyleValue const& value) -> Optional { - if (value.is_number()) - return value.as_number().number(); - if (value.is_calculated() && value.as_calculated().resolves_to_number()) - return value.as_calculated().resolve_number(); - return {}; - }; - - auto x = resolve_number(rotation.rotation_x()).value_or(0); - auto y = resolve_number(rotation.rotation_y()).value_or(0); - auto z = resolve_number(rotation.rotation_z()).value_or(0); - auto angle = resolve_angle(rotation.angle()).value_or(Angle::make_degrees(0)); - - Vector values; - values.append({ Number(Number::Type::Number, x) }); - values.append({ Number(Number::Type::Number, y) }); - values.append({ Number(Number::Type::Number, z) }); - values.append({ angle }); - - return CSS::Transformation(CSS::TransformFunction::Rotate3d, move(values)); + return value.as_transformation().to_transformation(); } Optional ComputedProperties::translate() const diff --git a/Libraries/LibWeb/CSS/ComputedProperties.h b/Libraries/LibWeb/CSS/ComputedProperties.h index 0c21276b265..5c8a745bbb5 100644 --- a/Libraries/LibWeb/CSS/ComputedProperties.h +++ b/Libraries/LibWeb/CSS/ComputedProperties.h @@ -166,7 +166,7 @@ public: Vector transformations() const; Optional transform_box() const; CSS::TransformOrigin transform_origin() const; - Optional rotate(Layout::Node const&) const; + Optional rotate() const; Optional translate() const; Optional scale() const; diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index adcbf68fa50..5a0f9014081 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -69,7 +69,6 @@ #include #include #include -#include #include #include #include @@ -5237,7 +5236,7 @@ RefPtr Parser::parse_rotate_value(TokenStream& to // if (auto angle = parse_angle_value(tokens)) - return RotationStyleValue::create(angle.release_nonnull(), NumberStyleValue::create(0), NumberStyleValue::create(0), NumberStyleValue::create(1)); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::Rotate, { angle.release_nonnull() }); } auto parse_one_of_xyz = [&]() -> Optional { @@ -5258,11 +5257,11 @@ RefPtr Parser::parse_rotate_value(TokenStream& to if (auto axis = parse_one_of_xyz(); axis.has_value()) { if (auto angle = parse_angle_value(tokens); angle) { if (axis->is_ident("x"sv)) - return RotationStyleValue::create(angle.release_nonnull(), NumberStyleValue::create(1), NumberStyleValue::create(0), NumberStyleValue::create(0)); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::RotateX, { angle.release_nonnull() }); if (axis->is_ident("y"sv)) - return RotationStyleValue::create(angle.release_nonnull(), NumberStyleValue::create(0), NumberStyleValue::create(1), NumberStyleValue::create(0)); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::RotateY, { angle.release_nonnull() }); if (axis->is_ident("z"sv)) - return RotationStyleValue::create(angle.release_nonnull(), NumberStyleValue::create(0), NumberStyleValue::create(0), NumberStyleValue::create(1)); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::RotateZ, { angle.release_nonnull() }); } } @@ -5270,11 +5269,11 @@ RefPtr Parser::parse_rotate_value(TokenStream& to if (auto angle = parse_angle_value(tokens); angle) { if (auto axis = parse_one_of_xyz(); axis.has_value()) { if (axis->is_ident("x"sv)) - return RotationStyleValue::create(angle.release_nonnull(), NumberStyleValue::create(1), NumberStyleValue::create(0), NumberStyleValue::create(0)); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::RotateX, { angle.release_nonnull() }); if (axis->is_ident("y"sv)) - return RotationStyleValue::create(angle.release_nonnull(), NumberStyleValue::create(0), NumberStyleValue::create(1), NumberStyleValue::create(0)); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::RotateY, { angle.release_nonnull() }); if (axis->is_ident("z"sv)) - return RotationStyleValue::create(angle.release_nonnull(), NumberStyleValue::create(0), NumberStyleValue::create(0), NumberStyleValue::create(1)); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::RotateZ, { angle.release_nonnull() }); } } } @@ -5299,7 +5298,7 @@ RefPtr Parser::parse_rotate_value(TokenStream& to if (auto maybe_numbers = parse_three_numbers(); maybe_numbers.has_value()) { if (auto angle = parse_angle_value(tokens); angle) { auto numbers = maybe_numbers.release_value(); - return RotationStyleValue::create(angle.release_nonnull(), numbers[0], numbers[1], numbers[2]); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::Rotate3d, { numbers[0], numbers[1], numbers[2], angle.release_nonnull() }); } } @@ -5307,7 +5306,7 @@ RefPtr Parser::parse_rotate_value(TokenStream& to if (auto angle = parse_angle_value(tokens); angle) { if (auto maybe_numbers = parse_three_numbers(); maybe_numbers.has_value()) { auto numbers = maybe_numbers.release_value(); - return RotationStyleValue::create(angle.release_nonnull(), numbers[0], numbers[1], numbers[2]); + return TransformationStyleValue::create(PropertyID::Rotate, TransformFunction::Rotate3d, { numbers[0], numbers[1], numbers[2], angle.release_nonnull() }); } } } diff --git a/Libraries/LibWeb/CSS/StyleValues/RotationStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/RotationStyleValue.cpp deleted file mode 100644 index 4d3ca7d9a5b..00000000000 --- a/Libraries/LibWeb/CSS/StyleValues/RotationStyleValue.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2024, Steffen T. Larssen - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include - -#include "RotationStyleValue.h" - -namespace Web::CSS { - -// https://www.w3.org/TR/2021/WD-css-transforms-2-20211109/#individual-transform-serialization -String RotationStyleValue::to_string(SerializationMode mode) const -{ - auto resolve_to_number = [](ValueComparingNonnullRefPtr const& value) -> Optional { - if (value->is_number()) - return value->as_number().number(); - if (value->is_calculated() && value->as_calculated().resolves_to_number()) - return value->as_calculated().resolve_number(); - - VERIFY_NOT_REACHED(); - }; - - auto x_value = resolve_to_number(m_properties.rotation_x).value_or(0); - auto y_value = resolve_to_number(m_properties.rotation_y).value_or(0); - auto z_value = resolve_to_number(m_properties.rotation_z).value_or(0); - - // If the axis is parallel with the x or y axes, it must serialize as the appropriate keyword. - if (x_value > 0.0 && y_value == 0 && z_value == 0) - return MUST(String::formatted("x {}", m_properties.angle->to_string(mode))); - - if (x_value == 0 && y_value > 0.0 && z_value == 0) - return MUST(String::formatted("y {}", m_properties.angle->to_string(mode))); - - // If a rotation about the z axis (that is, in 2D) is specified, the property must serialize as just an . - if (x_value == 0 && y_value == 0 && z_value > 0.0) - return m_properties.angle->to_string(mode); - - // It must serialize as the keyword none if and only if none was originally specified. - // NOTE: This is handled by returning a keyword from the parser. - - // If any other rotation is specified, the property must serialize with an axis specified. - return MUST(String::formatted("{} {} {} {}", m_properties.rotation_x->to_string(mode), m_properties.rotation_y->to_string(mode), m_properties.rotation_z->to_string(mode), m_properties.angle->to_string(mode))); -} - -} diff --git a/Libraries/LibWeb/CSS/StyleValues/RotationStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/RotationStyleValue.h deleted file mode 100644 index cb08e1d85c9..00000000000 --- a/Libraries/LibWeb/CSS/StyleValues/RotationStyleValue.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2024, Steffen T. Larssen - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace Web::CSS { - -class RotationStyleValue : public StyleValueWithDefaultOperators { -public: - static ValueComparingNonnullRefPtr create(ValueComparingNonnullRefPtr angle, ValueComparingNonnullRefPtr rotation_x, ValueComparingNonnullRefPtr rotation_y, ValueComparingNonnullRefPtr rotation_z) - { - return adopt_ref(*new (nothrow) RotationStyleValue(move(angle), move(rotation_x), move(rotation_y), move(rotation_z))); - } - - virtual ~RotationStyleValue() override = default; - - ValueComparingNonnullRefPtr const& angle() const { return m_properties.angle; } - ValueComparingNonnullRefPtr const& rotation_x() const { return m_properties.rotation_x; } - ValueComparingNonnullRefPtr const& rotation_y() const { return m_properties.rotation_y; } - ValueComparingNonnullRefPtr const& rotation_z() const { return m_properties.rotation_z; } - - virtual String to_string(SerializationMode) const override; - - bool properties_equal(RotationStyleValue const& other) const { return m_properties == other.m_properties; } - -private: - explicit RotationStyleValue( - ValueComparingNonnullRefPtr angle, - ValueComparingNonnullRefPtr rotation_x, - ValueComparingNonnullRefPtr rotation_y, - ValueComparingNonnullRefPtr rotation_z) - : StyleValueWithDefaultOperators(Type::Rotation) - , m_properties { - .angle = move(angle), - .rotation_x = move(rotation_x), - .rotation_y = move(rotation_y), - .rotation_z = move(rotation_z) - } - { - } - - struct Properties { - ValueComparingNonnullRefPtr angle; - ValueComparingNonnullRefPtr rotation_x; - ValueComparingNonnullRefPtr rotation_y; - ValueComparingNonnullRefPtr rotation_z; - bool operator==(Properties const&) const = default; - } m_properties; -}; - -} diff --git a/Libraries/LibWeb/CSS/StyleValues/TransformationStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/TransformationStyleValue.cpp index c38b06d7fd8..9ee475ebb59 100644 --- a/Libraries/LibWeb/CSS/StyleValues/TransformationStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/TransformationStyleValue.cpp @@ -3,6 +3,7 @@ * Copyright (c) 2021, Tobias Christiansen * Copyright (c) 2021-2025, Sam Atkins * Copyright (c) 2022-2023, MacDue + * Copyright (c) 2024, Steffen T. Larssen * * SPDX-License-Identifier: BSD-2-Clause */ @@ -64,6 +65,59 @@ Transformation TransformationStyleValue::to_transformation() const String TransformationStyleValue::to_string(SerializationMode mode) const { // https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization + if (m_properties.property == PropertyID::Rotate) { + auto resolve_to_number = [](ValueComparingNonnullRefPtr const& value) -> Optional { + if (value->is_number()) + return value->as_number().number(); + if (value->is_calculated() && value->as_calculated().resolves_to_number()) + return value->as_calculated().resolve_number(); + + VERIFY_NOT_REACHED(); + }; + + // NOTE: Serialize simple rotations directly. + switch (m_properties.transform_function) { + // If the axis is parallel with the x or y axes, it must serialize as the appropriate keyword. + case TransformFunction::RotateX: + return MUST(String::formatted("x {}", m_properties.values[0]->to_string(mode))); + case TransformFunction::RotateY: + return MUST(String::formatted("y {}", m_properties.values[0]->to_string(mode))); + + // If a rotation about the z axis (that is, in 2D) is specified, the property must serialize as just an . + case TransformFunction::Rotate: + case TransformFunction::RotateZ: + return m_properties.values[0]->to_string(mode); + + default: + break; + } + + auto& rotation_x = m_properties.values[0]; + auto& rotation_y = m_properties.values[1]; + auto& rotation_z = m_properties.values[2]; + auto& angle = m_properties.values[3]; + + auto x_value = resolve_to_number(rotation_x).value_or(0); + auto y_value = resolve_to_number(rotation_y).value_or(0); + auto z_value = resolve_to_number(rotation_z).value_or(0); + + // If the axis is parallel with the x or y axes, it must serialize as the appropriate keyword. + if (x_value > 0.0 && y_value == 0 && z_value == 0) + return MUST(String::formatted("x {}", angle->to_string(mode))); + + if (x_value == 0 && y_value > 0.0 && z_value == 0) + return MUST(String::formatted("y {}", angle->to_string(mode))); + + // If a rotation about the z axis (that is, in 2D) is specified, the property must serialize as just an . + if (x_value == 0 && y_value == 0 && z_value > 0.0) + return angle->to_string(mode); + + // It must serialize as the keyword none if and only if none was originally specified. + // NOTE: This is handled by returning a keyword from the parser. + + // If any other rotation is specified, the property must serialize with an axis specified. + return MUST(String::formatted("{} {} {} {}", rotation_x->to_string(mode), rotation_y->to_string(mode), rotation_z->to_string(mode), angle->to_string(mode))); + } if (m_properties.property == PropertyID::Scale) { auto resolve_to_string = [mode](CSSStyleValue const& value) -> String { if (value.is_number()) { diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 23c874235dc..c1fbfbdbe6b 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -206,7 +206,6 @@ class RectStyleValue; class Resolution; class ResolutionOrCalculated; class ResolutionStyleValue; -class RotationStyleValue; class Screen; class ScreenOrientation; class ScrollbarGutterStyleValue; diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index 90c9ce75617..b92f558de04 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -750,7 +750,7 @@ void NodeWithStyle::apply_style(const CSS::ComputedProperties& computed_style) computed_values.set_box_shadow(computed_style.box_shadow(*this)); - if (auto rotate_value = computed_style.rotate(*this); rotate_value.has_value()) + if (auto rotate_value = computed_style.rotate(); rotate_value.has_value()) computed_values.set_rotate(rotate_value.release_value()); if (auto translate_value = computed_style.translate(); translate_value.has_value()) diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/CSS/StyleValues/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/CSS/StyleValues/BUILD.gn index 47963f511a0..83befee9660 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/CSS/StyleValues/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/CSS/StyleValues/BUILD.gn @@ -38,7 +38,6 @@ source_set("StyleValues") { "PositionStyleValue.cpp", "RadialGradientStyleValue.cpp", "RectStyleValue.cpp", - "RotationStyleValue.cpp", "ShadowStyleValue.cpp", "ShorthandStyleValue.cpp", "StyleValueList.cpp",