From da2cd73bcf094c89c9a6d3afbb8fe1bc57fd74d2 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Fri, 4 Aug 2023 14:04:05 +0200 Subject: [PATCH] LibWeb: Add place-self css property support --- .../Layout/expected/grid/place-self.txt | 61 +++++++++++++++++++ .../LibWeb/Layout/input/grid/place-self.html | 11 ++++ Userland/Libraries/LibWeb/CMakeLists.txt | 1 + .../Libraries/LibWeb/CSS/Parser/Parser.cpp | 24 ++++++++ Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 1 + Userland/Libraries/LibWeb/CSS/Properties.json | 8 +++ .../Libraries/LibWeb/CSS/StyleComputer.cpp | 14 +++++ Userland/Libraries/LibWeb/CSS/StyleValue.cpp | 7 +++ Userland/Libraries/LibWeb/CSS/StyleValue.h | 4 ++ .../CSS/StyleValues/PlaceSelfStyleValue.cpp | 16 +++++ .../CSS/StyleValues/PlaceSelfStyleValue.h | 42 +++++++++++++ Userland/Libraries/LibWeb/Forward.h | 1 + 12 files changed, 190 insertions(+) create mode 100644 Tests/LibWeb/Layout/expected/grid/place-self.txt create mode 100644 Tests/LibWeb/Layout/input/grid/place-self.html create mode 100644 Userland/Libraries/LibWeb/CSS/StyleValues/PlaceSelfStyleValue.cpp create mode 100644 Userland/Libraries/LibWeb/CSS/StyleValues/PlaceSelfStyleValue.h diff --git a/Tests/LibWeb/Layout/expected/grid/place-self.txt b/Tests/LibWeb/Layout/expected/grid/place-self.txt new file mode 100644 index 0000000000..6cf79b9c11 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/place-self.txt @@ -0,0 +1,61 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x262.40625 [BFC] children: not-inline + BlockContainer at (10,10) content-size 780x244.40625 children: not-inline + Box at (31,31) content-size 738x39.46875 [GFC] children: not-inline + BlockContainer at (32,32) content-size 50.203125x17.46875 [BFC] children: inline + line 0 width: 50.203125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 6, rect: [32,32 50.203125x17.46875] + "Start1" + TextNode <#text> + BlockContainer at (411,42) content-size 347x17.46875 [BFC] children: inline + line 0 width: 52.671875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 6, rect: [411,42 52.671875x17.46875] + "Start2" + TextNode <#text> + BlockContainer <(anonymous)> at (10,91.46875) content-size 780x0 children: inline + TextNode <#text> + Box at (31,112.46875) content-size 738x39.46875 [GFC] children: not-inline + BlockContainer at (185.796875,123.46875) content-size 59.390625x17.46875 [BFC] children: inline + line 0 width: 59.390625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 7, rect: [185.796875,123.46875 59.390625x17.46875] + "Center1" + TextNode <#text> + BlockContainer at (411,123.46875) content-size 347x17.46875 [BFC] children: inline + line 0 width: 61.859375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 7, rect: [411,123.46875 61.859375x17.46875] + "Center2" + TextNode <#text> + BlockContainer <(anonymous)> at (10,172.9375) content-size 780x0 children: inline + TextNode <#text> + Box at (31,193.9375) content-size 738x39.46875 [GFC] children: not-inline + BlockContainer at (363.328125,214.9375) content-size 35.671875x17.46875 [BFC] children: inline + line 0 width: 35.671875, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 4, rect: [363.328125,214.9375 35.671875x17.46875] + "End1" + TextNode <#text> + BlockContainer at (411,204.9375) content-size 347x17.46875 [BFC] children: inline + line 0 width: 38.140625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 4, rect: [411,204.9375 38.140625x17.46875] + "End2" + TextNode <#text> + +PaintableWithLines (Viewport<#document>) [0,0 800x600] + PaintableWithLines (BlockContainer) [0,0 800x264.40625] + PaintableWithLines (BlockContainer) [9,9 782x246.40625] + PaintableBox (Box
.grid) [10,10 780x81.46875] + PaintableWithLines (BlockContainer
.start) [31,31 52.203125x19.46875] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.item-padding) [400,31 369x39.46875] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer(anonymous)) [10,91.46875 780x0] + PaintableBox (Box
.grid) [10,91.46875 780x81.46875] + PaintableWithLines (BlockContainer
.center) [184.796875,122.46875 61.390625x19.46875] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.item-padding) [400,112.46875 369x39.46875] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer(anonymous)) [10,172.9375 780x0] + PaintableBox (Box
.grid) [10,172.9375 780x81.46875] + PaintableWithLines (BlockContainer
.end) [362.328125,213.9375 37.671875x19.46875] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.item-padding) [400,193.9375 369x39.46875] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/input/grid/place-self.html b/Tests/LibWeb/Layout/input/grid/place-self.html new file mode 100644 index 0000000000..ca51e6417a --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/place-self.html @@ -0,0 +1,11 @@ + +
Start1
Start2
+
Center1
Center2
+
End1
End2
\ No newline at end of file diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index b8fe79275e..af43003b01 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -111,6 +111,7 @@ set(SOURCES CSS/StyleValues/OverflowStyleValue.cpp CSS/StyleValues/PlaceContentStyleValue.cpp CSS/StyleValues/PlaceItemsStyleValue.cpp + CSS/StyleValues/PlaceSelfStyleValue.cpp CSS/StyleValues/PositionStyleValue.cpp CSS/StyleValues/RadialGradientStyleValue.cpp CSS/StyleValues/RectStyleValue.cpp diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index e4102dd9e6..38b8a00069 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -6314,6 +6315,25 @@ ErrorOr> Parser::parse_place_items_value(Vector> Parser::parse_place_self_value(Vector const& component_values) +{ + auto tokens = TokenStream { component_values }; + auto maybe_align_self_value = TRY(parse_css_value_for_property(PropertyID::AlignSelf, tokens)); + if (!maybe_align_self_value) + return nullptr; + + if (component_values.size() == 1) { + if (!property_accepts_identifier(PropertyID::JustifySelf, maybe_align_self_value->to_identifier())) + return nullptr; + return PlaceSelfStyleValue::create(*maybe_align_self_value, *maybe_align_self_value); + } + + auto maybe_justify_self_value = TRY(parse_css_value_for_property(PropertyID::JustifySelf, tokens)); + if (!maybe_justify_self_value) + return nullptr; + return PlaceItemsStyleValue::create(*maybe_align_self_value, *maybe_justify_self_value); +} + ErrorOr> Parser::parse_text_decoration_value(Vector const& component_values) { RefPtr decoration_line; @@ -7555,6 +7575,10 @@ Parser::ParseErrorOr> Parser::parse_css_value(Property if (auto parsed_value = FIXME_TRY(parse_place_items_value(component_values))) return parsed_value.release_nonnull(); return ParseError::SyntaxError; + case PropertyID::PlaceSelf: + if (auto parsed_value = FIXME_TRY(parse_place_self_value(component_values))) + return parsed_value.release_nonnull(); + return ParseError::SyntaxError; case PropertyID::TextDecoration: if (auto parsed_value = FIXME_TRY(parse_text_decoration_value(component_values))) return parsed_value.release_nonnull(); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 8c09746bc5..7404c14a19 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -323,6 +323,7 @@ private: ErrorOr> parse_overflow_value(Vector const&); ErrorOr> parse_place_content_value(Vector const&); ErrorOr> parse_place_items_value(Vector const&); + ErrorOr> parse_place_self_value(Vector const&); enum class AllowInsetKeyword { No, Yes, diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index 47b6712d45..d269303d10 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -1785,6 +1785,14 @@ "justify-items" ] }, + "place-self": { + "inherited": false, + "initial": "normal", + "longhands": [ + "align-self", + "justify-self" + ] + }, "pointer-events": { "affects-layout": false, "inherited": true, diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index 0a16fd66bd..8f12b15924 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -473,6 +474,19 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope return; } + if (property_id == CSS::PropertyID::PlaceSelf) { + if (value.is_place_self()) { + auto const& place_self = value.as_place_self(); + set_longhand_property(CSS::PropertyID::AlignSelf, place_self.align_self()); + set_longhand_property(CSS::PropertyID::JustifySelf, place_self.justify_self()); + return; + } + + set_longhand_property(CSS::PropertyID::AlignSelf, value); + set_longhand_property(CSS::PropertyID::JustifySelf, value); + return; + } + if (property_id == CSS::PropertyID::Border) { set_property_expanding_shorthands(style, CSS::PropertyID::BorderTop, value, document, declaration, properties_for_revert); set_property_expanding_shorthands(style, CSS::PropertyID::BorderRight, value, document, declaration, properties_for_revert); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index 64849832ff..2b722b343c 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,12 @@ PlaceItemsStyleValue const& StyleValue::as_place_items() const return static_cast(*this); } +PlaceSelfStyleValue const& StyleValue::as_place_self() const +{ + VERIFY(is_place_self()); + return static_cast(*this); +} + PositionStyleValue const& StyleValue::as_position() const { VERIFY(is_position()); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 30069f7d10..fb9b540356 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -127,6 +127,7 @@ public: Percentage, PlaceContent, PlaceItems, + PlaceSelf, Position, RadialGradient, Ratio, @@ -187,6 +188,7 @@ public: bool is_percentage() const { return type() == Type::Percentage; } bool is_place_content() const { return type() == Type::PlaceContent; } bool is_place_items() const { return type() == Type::PlaceItems; } + bool is_place_self() const { return type() == Type::PlaceSelf; } bool is_position() const { return type() == Type::Position; } bool is_radial_gradient() const { return type() == Type::RadialGradient; } bool is_ratio() const { return type() == Type::Ratio; } @@ -246,6 +248,7 @@ public: PercentageStyleValue const& as_percentage() const; PlaceContentStyleValue const& as_place_content() const; PlaceItemsStyleValue const& as_place_items() const; + PlaceSelfStyleValue const& as_place_self() const; PositionStyleValue const& as_position() const; RadialGradientStyleValue const& as_radial_gradient() const; RatioStyleValue const& as_ratio() const; @@ -301,6 +304,7 @@ public: PercentageStyleValue& as_percentage() { return const_cast(const_cast(*this).as_percentage()); } PlaceContentStyleValue& as_place_content() { return const_cast(const_cast(*this).as_place_content()); } PlaceItemsStyleValue& as_place_items() { return const_cast(const_cast(*this).as_place_items()); } + PlaceSelfStyleValue& as_place_self() { return const_cast(const_cast(*this).as_place_self()); } PositionStyleValue& as_position() { return const_cast(const_cast(*this).as_position()); } RadialGradientStyleValue& as_radial_gradient() { return const_cast(const_cast(*this).as_radial_gradient()); } RatioStyleValue& as_ratio() { return const_cast(const_cast(*this).as_ratio()); } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceSelfStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceSelfStyleValue.cpp new file mode 100644 index 0000000000..e00e29dd63 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceSelfStyleValue.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "PlaceSelfStyleValue.h" + +namespace Web::CSS { + +ErrorOr PlaceSelfStyleValue::to_string() const +{ + return String::formatted("{} {}", TRY(m_properties.align_self->to_string()), TRY(m_properties.justify_self->to_string())); +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceSelfStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceSelfStyleValue.h new file mode 100644 index 0000000000..8c0c908b6f --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceSelfStyleValue.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::CSS { + +class PlaceSelfStyleValue final : public StyleValueWithDefaultOperators { +public: + static ErrorOr> create(ValueComparingNonnullRefPtr align_self, ValueComparingNonnullRefPtr justify_self) + { + return adopt_nonnull_ref_or_enomem(new (nothrow) PlaceSelfStyleValue(move(align_self), move(justify_self))); + } + virtual ~PlaceSelfStyleValue() override = default; + + ValueComparingNonnullRefPtr align_self() const { return m_properties.align_self; } + ValueComparingNonnullRefPtr justify_self() const { return m_properties.justify_self; } + + virtual ErrorOr to_string() const override; + + bool properties_equal(PlaceSelfStyleValue const& other) const { return m_properties == other.m_properties; } + +private: + PlaceSelfStyleValue(ValueComparingNonnullRefPtr align_self, ValueComparingNonnullRefPtr justify_self) + : StyleValueWithDefaultOperators(Type::PlaceSelf) + , m_properties { .align_self = move(align_self), .justify_self = move(justify_self) } + { + } + + struct Properties { + ValueComparingNonnullRefPtr align_self; + ValueComparingNonnullRefPtr justify_self; + bool operator==(Properties const&) const = default; + } m_properties; +}; + +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 039eced5f5..926c6efd61 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -149,6 +149,7 @@ class PercentageOrCalculated; class PercentageStyleValue; class PlaceContentStyleValue; class PlaceItemsStyleValue; +class PlaceSelfStyleValue; class PositionStyleValue; class PropertyOwningCSSStyleDeclaration; class RadialGradientStyleValue;