diff --git a/Tests/LibWeb/Layout/expected/grid/named-tracks.txt b/Tests/LibWeb/Layout/expected/grid/named-tracks.txt index d2b7c38c93c..7d849511fa2 100644 --- a/Tests/LibWeb/Layout/expected/grid/named-tracks.txt +++ b/Tests/LibWeb/Layout/expected/grid/named-tracks.txt @@ -1,7 +1,7 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline BlockContainer at (0,0) content-size 800x600 [BFC] children: not-inline BlockContainer at (8,8) content-size 784x127.40625 children: not-inline - Box at (8,8) content-size 784x17.46875 [GFC] children: not-inline + Box at (8,8) content-size 784x34.9375 [GFC] children: not-inline BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> BlockContainer at (8,8) content-size 392x17.46875 [BFC] children: inline @@ -11,79 +11,79 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (400,8) content-size 392x17.46875 [BFC] children: inline + BlockContainer at (8,25.46875) content-size 392x17.46875 [BFC] children: inline line 0 width: 8.8125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [400,8 8.8125x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [8,25.46875 8.8125x17.46875] "2" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer <(anonymous)> at (8,25.46875) content-size 784x0 children: inline + BlockContainer <(anonymous)> at (8,42.9375) content-size 784x0 children: inline TextNode <#text> TextNode <#text> TextNode <#text> - Box at (8,25.46875) content-size 784x75 [GFC] children: not-inline + Box at (8,42.9375) content-size 784x75 [GFC] children: not-inline BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (8,25.46875) content-size 261.328125x75 [BFC] children: inline + BlockContainer at (8,42.9375) content-size 261.328125x25 [BFC] children: inline line 0 width: 6.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [8,25.46875 6.34375x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [8,42.9375 6.34375x17.46875] "1" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (530.65625,25.46875) content-size 261.328125x50 [BFC] children: inline + BlockContainer at (8,42.9375) content-size 261.328125x25 [BFC] children: inline line 0 width: 8.8125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [530.65625,25.46875 8.8125x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [8,42.9375 8.8125x17.46875] "2" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (269.328125,25.46875) content-size 261.328125x25 [BFC] children: inline + BlockContainer at (8,42.9375) content-size 261.328125x25 [BFC] children: inline line 0 width: 9.09375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [269.328125,25.46875 9.09375x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [8,42.9375 9.09375x17.46875] "3" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (269.328125,75.46875) content-size 522.65625x25 [BFC] children: inline + BlockContainer at (8,42.9375) content-size 261.328125x25 [BFC] children: inline line 0 width: 7.75, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [269.328125,75.46875 7.75x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [8,42.9375 7.75x17.46875] "4" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer <(anonymous)> at (8,100.46875) content-size 784x0 children: inline + BlockContainer <(anonymous)> at (8,117.9375) content-size 784x0 children: inline TextNode <#text> TextNode <#text> TextNode <#text> - Box at (8,100.46875) content-size 784x34.9375 [GFC] children: not-inline + Box at (8,117.9375) content-size 784x17.46875 [GFC] children: not-inline BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (58,100.46875) content-size 100x17.46875 [BFC] children: inline + BlockContainer at (8,117.9375) content-size 50x17.46875 [BFC] children: inline line 0 width: 6.34375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [58,100.46875 6.34375x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [8,117.9375 6.34375x17.46875] "1" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (158,100.46875) content-size 50x17.46875 [BFC] children: inline + BlockContainer at (58,117.9375) content-size 100x17.46875 [BFC] children: inline line 0 width: 8.8125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [158,100.46875 8.8125x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [58,117.9375 8.8125x17.46875] "2" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (208,100.46875) content-size 100x17.46875 [BFC] children: inline + BlockContainer at (158,117.9375) content-size 50x17.46875 [BFC] children: inline line 0 width: 9.09375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [208,100.46875 9.09375x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [158,117.9375 9.09375x17.46875] "3" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline TextNode <#text> - BlockContainer at (8,117.9375) content-size 50x17.46875 [BFC] children: inline + BlockContainer at (208,117.9375) content-size 100x17.46875 [BFC] children: inline line 0 width: 7.75, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 1, rect: [8,117.9375 7.75x17.46875] + frag 0 from TextNode start: 0, length: 1, rect: [208,117.9375 7.75x17.46875] "4" TextNode <#text> BlockContainer <(anonymous)> (not painted) [BFC] children: inline @@ -92,28 +92,28 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableWithLines (BlockContainer) [0,0 800x600] PaintableWithLines (BlockContainer) [8,8 784x127.40625] - PaintableBox (Box
.grid-container) [8,8 784x17.46875] + PaintableBox (Box
.grid-container) [8,8 784x34.9375] PaintableWithLines (BlockContainer
.grid-item) [8,8 392x17.46875] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.grid-item) [400,8 392x17.46875] + PaintableWithLines (BlockContainer
.grid-item) [8,25.46875 392x17.46875] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer(anonymous)) [8,25.46875 784x0] - PaintableBox (Box
.grid-container) [8,25.46875 784x75] - PaintableWithLines (BlockContainer
.grid-item) [8,25.46875 261.328125x75] + PaintableWithLines (BlockContainer(anonymous)) [8,42.9375 784x0] + PaintableBox (Box
.grid-container) [8,42.9375 784x75] + PaintableWithLines (BlockContainer
.grid-item) [8,42.9375 261.328125x25] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.grid-item) [530.65625,25.46875 261.328125x50] + PaintableWithLines (BlockContainer
.grid-item) [8,42.9375 261.328125x25] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.grid-item) [269.328125,25.46875 261.328125x25] + PaintableWithLines (BlockContainer
.grid-item) [8,42.9375 261.328125x25] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.grid-item) [269.328125,75.46875 522.65625x25] - TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer(anonymous)) [8,100.46875 784x0] - PaintableBox (Box
.grid-container) [8,100.46875 784x34.9375] - PaintableWithLines (BlockContainer
.grid-item) [58,100.46875 100x17.46875] - TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.grid-item) [158,100.46875 50x17.46875] - TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.grid-item) [208,100.46875 100x17.46875] + PaintableWithLines (BlockContainer
.grid-item) [8,42.9375 261.328125x25] TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer(anonymous)) [8,117.9375 784x0] + PaintableBox (Box
.grid-container) [8,117.9375 784x17.46875] PaintableWithLines (BlockContainer
.grid-item) [8,117.9375 50x17.46875] TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.grid-item) [58,117.9375 100x17.46875] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.grid-item) [158,117.9375 50x17.46875] + TextPaintable (TextNode<#text>) + PaintableWithLines (BlockContainer
.grid-item) [208,117.9375 100x17.46875] + TextPaintable (TextNode<#text>) diff --git a/Tests/LibWeb/Layout/expected/grid/template-lines-and-areas.txt b/Tests/LibWeb/Layout/expected/grid/template-lines-and-areas.txt index d45f449a2c0..1cb6c4be033 100644 --- a/Tests/LibWeb/Layout/expected/grid/template-lines-and-areas.txt +++ b/Tests/LibWeb/Layout/expected/grid/template-lines-and-areas.txt @@ -7,9 +7,9 @@ Viewport <#document> at (0,0) content-size 800x600 children: not-inline frag 0 from TextNode start: 0, length: 3, rect: [8,8 21.609375x17.46875] "1fr" TextNode <#text> - BlockContainer at (530.65625,8) content-size 261.328125x17.46875 [BFC] children: inline + BlockContainer at (269.328125,8) content-size 522.65625x17.46875 [BFC] children: inline line 0 width: 21.609375, height: 17.46875, bottom: 17.46875, baseline: 13.53125 - frag 0 from TextNode start: 0, length: 3, rect: [530.65625,8 21.609375x17.46875] + frag 0 from TextNode start: 0, length: 3, rect: [269.328125,8 21.609375x17.46875] "1fr" TextNode <#text> @@ -19,5 +19,5 @@ ViewportPaintable (Viewport<#document>) [0,0 800x600] PaintableBox (Box
.grid) [8,8 784x17.46875] PaintableWithLines (BlockContainer
.item-left) [8,8 261.328125x17.46875] TextPaintable (TextNode<#text>) - PaintableWithLines (BlockContainer
.item-right) [530.65625,8 261.328125x17.46875] + PaintableWithLines (BlockContainer
.item-right) [269.328125,8 522.65625x17.46875] TextPaintable (TextNode<#text>) diff --git a/Userland/Libraries/LibWeb/CSS/GridTrackPlacement.cpp b/Userland/Libraries/LibWeb/CSS/GridTrackPlacement.cpp index 437fc36d6fa..c97e9097619 100644 --- a/Userland/Libraries/LibWeb/CSS/GridTrackPlacement.cpp +++ b/Userland/Libraries/LibWeb/CSS/GridTrackPlacement.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023, Aliaksandr Kalenik * Copyright (c) 2022, Martin Falisse * * SPDX-License-Identifier: BSD-2-Clause @@ -9,48 +10,24 @@ namespace Web::CSS { -GridTrackPlacement::GridTrackPlacement(int span_count_or_position, bool has_span) - : m_type(has_span ? Type::Span : Type::Position) - , m_span_count_or_position(span_count_or_position) -{ -} - -GridTrackPlacement::GridTrackPlacement(String line_name, int span_count_or_position, bool has_span) - : m_type(has_span ? Type::Span : Type::Position) - , m_span_count_or_position(span_count_or_position) - , m_line_name(line_name) -{ -} - -GridTrackPlacement::GridTrackPlacement(String line_name, bool has_span) - : m_type(has_span ? Type::Span : Type::Position) - , m_line_name(line_name) -{ -} - -GridTrackPlacement::GridTrackPlacement() - : m_type(Type::Auto) -{ -} - String GridTrackPlacement::to_string() const { StringBuilder builder; - if (is_auto()) { - builder.append("auto"sv); - return MUST(builder.to_string()); - } - if (is_span()) { - builder.append("span"sv); - builder.append(" "sv); - } - if (m_span_count_or_position != 0) { - builder.append(MUST(String::number(m_span_count_or_position))); - builder.append(" "sv); - } - if (has_line_name()) { - builder.append(m_line_name); - } + m_value.visit( + [&](Auto const&) { + builder.append("auto"sv); + }, + [&](Area const& area) { + builder.append(area.name); + }, + [&](Line const& line) { + builder.appendff("{}", line.value); + if (line.name.has_value()) + builder.appendff(" {}", line.name.value()); + }, + [&](Span const& span) { + builder.appendff("span {}", span.value); + }); return MUST(builder.to_string()); } diff --git a/Userland/Libraries/LibWeb/CSS/GridTrackPlacement.h b/Userland/Libraries/LibWeb/CSS/GridTrackPlacement.h index 103d1c4e4a6..c2a88089154 100644 --- a/Userland/Libraries/LibWeb/CSS/GridTrackPlacement.h +++ b/Userland/Libraries/LibWeb/CSS/GridTrackPlacement.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023, Aliaksandr Kalenik * Copyright (c) 2022, Martin Falisse * * SPDX-License-Identifier: BSD-2-Clause @@ -12,40 +13,79 @@ namespace Web::CSS { class GridTrackPlacement { public: - enum class Type { - Span, - Position, - Auto - }; - - GridTrackPlacement(String line_name, int span_count_or_position, bool has_span = false); - GridTrackPlacement(int span_count_or_position, bool has_span = false); - GridTrackPlacement(String line_name, bool has_span = false); - GridTrackPlacement(); - - static GridTrackPlacement make_auto() { return GridTrackPlacement(); } - - bool is_span() const { return m_type == Type::Span; } - bool is_position() const { return m_type == Type::Position; } - bool is_auto() const { return m_type == Type::Auto; } - bool is_auto_positioned() const { return m_type == Type::Auto || (m_type == Type::Span && !has_line_name()); } - - bool has_line_name() const { return !m_line_name.is_empty(); } - - int raw_value() const { return m_span_count_or_position; } - Type type() const { return m_type; } - String line_name() const { return m_line_name; } - - String to_string() const; - bool operator==(GridTrackPlacement const& other) const + static GridTrackPlacement make_auto() { - return m_type == other.type() && m_span_count_or_position == other.raw_value(); + return GridTrackPlacement(); } + static GridTrackPlacement make_area(String name) + { + return GridTrackPlacement(Area { .name = name }); + } + + static GridTrackPlacement make_line(int value, Optional name) + { + return GridTrackPlacement(Line { .value = value, .name = name }); + } + + static GridTrackPlacement make_span(int value) + { + return GridTrackPlacement(Span { .value = value }); + } + + bool is_auto() const { return m_value.has(); } + bool is_area() const { return m_value.has(); } + bool is_line() const { return m_value.has(); } + bool is_span() const { return m_value.has(); } + + bool is_auto_positioned() const { return is_auto() || is_span(); } + bool is_positioned() const { return !is_auto_positioned(); } + + bool has_line_name() const + { + return is_line() && m_value.get().name.has_value(); + } + + String area_name() const { return m_value.get().name; } + String line_name() const { return m_value.get().name.value(); } + int line_number() const { return m_value.get().value; } + int span() const { return m_value.get().value; } + + String to_string() const; + + bool operator==(GridTrackPlacement const& other) const = default; + private: - Type m_type; - int m_span_count_or_position { 0 }; - String m_line_name; + struct Auto { + bool operator==(Auto const&) const = default; + }; + + struct Area { + String name; + bool operator==(Area const& other) const = default; + }; + + struct Line { + int value; + Optional name; + bool operator==(Line const& other) const = default; + }; + + struct Span { + int value; + bool operator==(Span const& other) const = default; + }; + + GridTrackPlacement() + : m_value(Auto {}) {}; + GridTrackPlacement(Area value) + : m_value(value) {}; + GridTrackPlacement(Line value) + : m_value(value) {}; + GridTrackPlacement(Span value) + : m_value(value) {}; + + Variant m_value; }; } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index c192bd5fdc5..7b731b060b2 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -5350,7 +5350,7 @@ RefPtr Parser::parse_grid_track_placement(Vector con return true; return false; }; - auto is_line_name = [](Token token) -> bool { + auto is_identifier = [](Token token) -> bool { // The additionally excludes the keywords span and auto. if (token.is(Token::Type::Ident) && !token.ident().equals_ignoring_ascii_case("span"sv) && !token.ident().equals_ignoring_ascii_case("auto"sv)) return true; @@ -5363,22 +5363,22 @@ RefPtr Parser::parse_grid_track_placement(Vector con if (!tokens.has_next_token()) { if (is_auto(current_token)) - return GridTrackPlacementStyleValue::create(CSS::GridTrackPlacement()); + return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_auto()); if (is_span(current_token)) - return GridTrackPlacementStyleValue::create(CSS::GridTrackPlacement(1, true)); + return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_span(1)); if (is_valid_integer(current_token)) - return GridTrackPlacementStyleValue::create(CSS::GridTrackPlacement(static_cast(current_token.number_value()))); - if (is_line_name(current_token)) { + return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast(current_token.number_value()), {})); + if (is_identifier(current_token)) { auto maybe_string = String::from_utf8(current_token.ident()); if (!maybe_string.is_error()) - return GridTrackPlacementStyleValue::create(CSS::GridTrackPlacement(maybe_string.value())); + return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_area(maybe_string.value())); } return nullptr; } auto span_value = false; auto span_or_position_value = 0; - String line_name_value; + String identifier_value; while (true) { if (is_auto(current_token)) return nullptr; @@ -5394,12 +5394,12 @@ RefPtr Parser::parse_grid_track_placement(Vector con else return nullptr; } - if (is_line_name(current_token)) { - if (line_name_value.is_empty()) { + if (is_identifier(current_token)) { + if (identifier_value.is_empty()) { auto maybe_string = String::from_utf8(current_token.ident()); if (maybe_string.is_error()) return nullptr; - line_name_value = maybe_string.release_value(); + identifier_value = maybe_string.release_value(); } else { return nullptr; } @@ -5419,9 +5419,9 @@ RefPtr Parser::parse_grid_track_placement(Vector con if (span_or_position_value == 0) span_or_position_value = 1; - if (!line_name_value.is_empty()) - return GridTrackPlacementStyleValue::create(CSS::GridTrackPlacement(line_name_value, span_or_position_value, span_value)); - return GridTrackPlacementStyleValue::create(CSS::GridTrackPlacement(span_or_position_value, span_value)); + if (!identifier_value.is_empty()) + return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(span_or_position_value, identifier_value)); + return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_span(span_or_position_value)); } RefPtr Parser::parse_grid_track_placement_shorthand_value(Vector const& component_values) diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 2c5341e1716..a3c4a7d4c01 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023, Aliaksandr Kalenik * Copyright (c) 2022-2023, Martin Falisse * * SPDX-License-Identifier: BSD-2-Clause @@ -128,10 +129,21 @@ int GridFormattingContext::count_of_repeated_auto_fill_or_fit_tracks(Vectorcolumn_end; - else if (auto line_name_index = get_line_index_by_line_name(child_box.computed_values().grid_column_end().line_name(), grid_container().computed_values().grid_template_columns()); line_name_index > -1) + else + column_end = 1; + column_start = column_end - 1; + } else if (grid_column_end.has_line_name()) { + if (auto line_name_index = get_line_index_by_line_name(grid_column_end.line_name(), grid_container().computed_values().grid_template_columns()); line_name_index > -1) column_end = line_name_index; else column_end = 1; column_start = column_end - 1; } - if (child_box.computed_values().grid_column_start().has_line_name()) { - if (auto maybe_grid_area = m_grid_areas.get(child_box.computed_values().grid_column_end().line_name()); maybe_grid_area.has_value()) + + if (grid_column_start.is_area()) { + if (auto maybe_grid_area = m_grid_areas.get(grid_column_start.area_name()); maybe_grid_area.has_value()) column_start = maybe_grid_area->column_start; - else if (auto line_name_index = get_line_index_by_line_name(child_box.computed_values().grid_column_start().line_name(), grid_container().computed_values().grid_template_columns()); line_name_index > -1) + else + column_start = 0; + } + if (grid_column_start.has_line_name()) { + if (auto line_name_index = get_line_index_by_line_name(grid_column_start.line_name(), grid_container().computed_values().grid_template_columns()); line_name_index > -1) column_start = line_name_index; else column_start = 0; } - if (child_box.computed_values().grid_row_end().has_line_name()) { - if (auto maybe_grid_area = m_grid_areas.get(child_box.computed_values().grid_row_end().line_name()); maybe_grid_area.has_value()) + + if (grid_row_end.is_area()) { + if (auto maybe_grid_area = m_grid_areas.get(grid_row_end.area_name()); maybe_grid_area.has_value()) row_end = maybe_grid_area->row_end; - else if (auto line_name_index = get_line_index_by_line_name(child_box.computed_values().grid_row_end().line_name(), grid_container().computed_values().grid_template_rows()); line_name_index > -1) + else + row_end = 1; + row_start = row_end - 1; + } else if (grid_row_end.has_line_name()) { + if (auto line_name_index = get_line_index_by_line_name(grid_row_end.line_name(), grid_container().computed_values().grid_template_rows()); line_name_index > -1) row_end = line_name_index; else row_end = 1; row_start = row_end - 1; } - if (child_box.computed_values().grid_row_start().has_line_name()) { - if (auto maybe_grid_area = m_grid_areas.get(child_box.computed_values().grid_row_end().line_name()); maybe_grid_area.has_value()) + + if (grid_row_start.is_area()) { + if (auto maybe_grid_area = m_grid_areas.get(grid_row_start.area_name()); maybe_grid_area.has_value()) row_start = maybe_grid_area->row_start; - else if (auto line_name_index = get_line_index_by_line_name(child_box.computed_values().grid_row_start().line_name(), grid_container().computed_values().grid_template_rows()); line_name_index > -1) + else + row_start = 0; + } else if (grid_row_start.has_line_name()) { + if (auto line_name_index = get_line_index_by_line_name(grid_row_start.line_name(), grid_container().computed_values().grid_template_rows()); line_name_index > -1) row_start = line_name_index; else row_start = 0; @@ -231,13 +261,13 @@ void GridFormattingContext::place_item_with_row_and_column_position(Box const& c // If the placement for a grid item contains two lines, and the start line is further end-ward than // the end line, swap the two lines. If the start line is equal to the end line, remove the end // line. - if (child_box.computed_values().grid_row_start().is_position() && child_box.computed_values().grid_row_end().is_position()) { + if (grid_row_start.is_positioned() && grid_row_end.is_positioned()) { if (row_start > row_end) swap(row_start, row_end); if (row_start != row_end) row_span = row_end - row_start; } - if (child_box.computed_values().grid_column_start().is_position() && child_box.computed_values().grid_column_end().is_position()) { + if (grid_column_start.is_positioned() && grid_column_end.is_positioned()) { if (column_start > column_end) swap(column_start, column_end); if (column_start != column_end) @@ -246,10 +276,10 @@ void GridFormattingContext::place_item_with_row_and_column_position(Box const& c // If the placement contains two spans, remove the one contributed by the end grid-placement // property. - if (child_box.computed_values().grid_row_start().is_span() && child_box.computed_values().grid_row_end().is_span()) - row_span = child_box.computed_values().grid_row_start().raw_value(); - if (child_box.computed_values().grid_column_start().is_span() && child_box.computed_values().grid_column_end().is_span()) - column_span = child_box.computed_values().grid_column_start().raw_value(); + if (grid_row_start.is_span() && grid_row_end.is_span()) + row_span = grid_row_start.span(); + if (grid_column_start.is_span() && grid_column_end.is_span()) + column_span = grid_column_start.span(); // FIXME: If the placement contains only a span for a named line, replace it with a span of 1. @@ -265,8 +295,16 @@ void GridFormattingContext::place_item_with_row_and_column_position(Box const& c void GridFormattingContext::place_item_with_row_position(Box const& child_box) { - int row_start = child_box.computed_values().grid_row_start().raw_value() - 1; - int row_end = child_box.computed_values().grid_row_end().raw_value() - 1; + auto const& grid_row_start = child_box.computed_values().grid_row_start(); + auto const& grid_row_end = child_box.computed_values().grid_row_end(); + auto const& grid_column_start = child_box.computed_values().grid_column_start(); + + int row_start = 0, row_end = 0; + + if (grid_row_start.is_line()) + row_start = grid_row_start.line_number() - 1; + if (grid_row_end.is_line()) + row_end = grid_row_end.line_number() - 1; // https://www.w3.org/TR/css-grid-2/#line-placement // 8.3. Line-based Placement: the grid-row-start, grid-column-start, grid-row-end, and grid-column-end properties @@ -294,10 +332,10 @@ void GridFormattingContext::place_item_with_row_position(Box const& child_box) // grid-column-end: span 2 indicates the second grid line in the endward direction from the // grid-column-start line. size_t row_span = 1; - if (child_box.computed_values().grid_row_start().is_position() && child_box.computed_values().grid_row_end().is_span()) - row_span = child_box.computed_values().grid_row_end().raw_value(); - if (child_box.computed_values().grid_row_end().is_position() && child_box.computed_values().grid_row_start().is_span()) { - row_span = child_box.computed_values().grid_row_start().raw_value(); + if (grid_row_start.is_line() && grid_row_end.is_span()) + row_span = grid_row_end.span(); + if (grid_row_end.is_line() && grid_row_start.is_span()) { + row_span = grid_row_start.span(); row_start = row_end - row_span; // FIXME: Remove me once have implemented spans overflowing into negative indexes, e.g., grid-row: span 2 / 1 if (row_start < 0) @@ -317,19 +355,27 @@ void GridFormattingContext::place_item_with_row_position(Box const& child_box) // https://www.w3.org/TR/css-grid-2/#common-uses-named-lines // 8.1.3. Named Lines and Spans // Instead of counting lines by number, lines can be referenced by their line name: - if (child_box.computed_values().grid_row_end().has_line_name()) { - if (auto maybe_grid_area = m_grid_areas.get(child_box.computed_values().grid_row_end().line_name()); maybe_grid_area.has_value()) + if (grid_row_end.is_area()) { + if (auto maybe_grid_area = m_grid_areas.get(grid_row_end.area_name()); maybe_grid_area.has_value()) row_end = maybe_grid_area->row_end; - else if (auto line_name_index = get_line_index_by_line_name(child_box.computed_values().grid_row_end().line_name(), grid_container().computed_values().grid_template_rows()); line_name_index > -1) - row_end = line_name_index; + else + row_end = 1; + row_start = row_end - 1; + } else if (grid_row_end.has_line_name()) { + if (auto line_name_index = get_line_index_by_line_name(grid_row_end.line_name(), grid_container().computed_values().grid_template_rows()); line_name_index > -1) + row_end = line_name_index - 1; else row_end = 1; row_start = row_end - 1; } - if (child_box.computed_values().grid_row_start().has_line_name()) { - if (auto maybe_grid_area = m_grid_areas.get(child_box.computed_values().grid_row_end().line_name()); maybe_grid_area.has_value()) + + if (grid_row_start.is_area()) { + if (auto maybe_grid_area = m_grid_areas.get(grid_row_start.area_name()); maybe_grid_area.has_value()) row_start = maybe_grid_area->row_start; - else if (auto line_name_index = get_line_index_by_line_name(child_box.computed_values().grid_row_start().line_name(), grid_container().computed_values().grid_template_rows()); line_name_index > -1) + else + row_start = 0; + } else if (grid_row_start.has_line_name()) { + if (auto line_name_index = get_line_index_by_line_name(grid_row_start.line_name(), grid_container().computed_values().grid_template_rows()); line_name_index > -1) row_start = line_name_index; else row_start = 0; @@ -343,25 +389,25 @@ void GridFormattingContext::place_item_with_row_position(Box const& child_box) // If the placement for a grid item contains two lines, and the start line is further end-ward than // the end line, swap the two lines. If the start line is equal to the end line, remove the end // line. - if (child_box.computed_values().grid_row_start().is_position() && child_box.computed_values().grid_row_end().is_position()) { + if (grid_row_start.is_positioned() && grid_row_end.is_positioned()) { if (row_start > row_end) swap(row_start, row_end); if (row_start != row_end) row_span = row_end - row_start; } // FIXME: Have yet to find the spec for this. - if (!child_box.computed_values().grid_row_start().is_position() && child_box.computed_values().grid_row_end().is_position() && row_end == 0) + if (!grid_row_start.is_positioned() && grid_row_end.is_positioned() && row_end == 0) row_start = 0; // If the placement contains two spans, remove the one contributed by the end grid-placement // property. - if (child_box.computed_values().grid_row_start().is_span() && child_box.computed_values().grid_row_end().is_span()) - row_span = child_box.computed_values().grid_row_start().raw_value(); + if (grid_row_start.is_span() && grid_row_end.is_span()) + row_span = grid_row_start.span(); // FIXME: If the placement contains only a span for a named line, replace it with a span of 1. int column_start = 0; - size_t column_span = child_box.computed_values().grid_column_start().is_span() ? child_box.computed_values().grid_column_start().raw_value() : 1; + size_t column_span = grid_column_start.is_span() ? grid_column_start.span() : 1; bool found_available_column = false; for (size_t column_index = column_start; column_index < m_occupation_grid.column_count(); column_index++) { if (!m_occupation_grid.is_occupied(column_index, row_start)) { @@ -385,15 +431,21 @@ void GridFormattingContext::place_item_with_row_position(Box const& child_box) void GridFormattingContext::place_item_with_column_position(Box const& child_box, int& auto_placement_cursor_x, int& auto_placement_cursor_y) { - int column_start; - if (child_box.computed_values().grid_column_start().raw_value() > 0) { - column_start = child_box.computed_values().grid_column_start().raw_value() - 1; - } else { + auto const& grid_row_start = child_box.computed_values().grid_row_start(); + auto const& grid_column_start = child_box.computed_values().grid_column_start(); + auto const& grid_column_end = child_box.computed_values().grid_column_end(); + + int column_start = 0; + if (grid_column_start.is_line() && grid_column_start.line_number() > 0) { + column_start = grid_column_start.line_number() - 1; + } else if (grid_column_start.is_line()) { // NOTE: Negative indexes count from the end side of the explicit grid - column_start = m_explicit_columns_line_count + child_box.computed_values().grid_column_start().raw_value(); + column_start = m_explicit_columns_line_count + grid_column_start.line_number(); } - int column_end = child_box.computed_values().grid_column_end().raw_value() - 1; + int column_end = 0; + if (grid_column_end.is_line()) + column_end = grid_column_end.line_number() - 1; // https://www.w3.org/TR/css-grid-2/#line-placement // 8.3. Line-based Placement: the grid-row-start, grid-column-start, grid-row-end, and grid-column-end properties @@ -421,18 +473,18 @@ void GridFormattingContext::place_item_with_column_position(Box const& child_box // grid-column-end: span 2 indicates the second grid line in the endward direction from the // grid-column-start line. size_t column_span = 1; - size_t row_span = child_box.computed_values().grid_row_start().is_span() ? child_box.computed_values().grid_row_start().raw_value() : 1; - if (child_box.computed_values().grid_column_start().is_position() && child_box.computed_values().grid_column_end().is_span()) - column_span = child_box.computed_values().grid_column_end().raw_value(); - if (child_box.computed_values().grid_column_end().is_position() && child_box.computed_values().grid_column_start().is_span()) { - column_span = child_box.computed_values().grid_column_start().raw_value(); + size_t row_span = grid_row_start.is_span() ? grid_row_start.span() : 1; + if (grid_column_start.is_line() && grid_column_end.is_span()) + column_span = grid_column_end.span(); + if (grid_column_end.is_line() && grid_column_start.is_span()) { + column_span = grid_column_start.span(); column_start = column_end - column_span; // FIXME: Remove me once have implemented spans overflowing into negative indexes, e.g., grid-column: span 2 / 1 if (column_start < 0) column_start = 0; } // FIXME: Have yet to find the spec for this. - if (!child_box.computed_values().grid_column_start().is_position() && child_box.computed_values().grid_column_end().is_position() && column_end == 0) + if (!grid_column_start.is_positioned() && grid_column_end.is_positioned() && column_end == 0) column_start = 0; // If a name is given as a , only lines with that name are counted. If not enough @@ -448,19 +500,28 @@ void GridFormattingContext::place_item_with_column_position(Box const& child_box // https://www.w3.org/TR/css-grid-2/#common-uses-named-lines // 8.1.3. Named Lines and Spans // Instead of counting lines by number, lines can be referenced by their line name: - if (child_box.computed_values().grid_column_end().has_line_name()) { - if (auto maybe_grid_area = m_grid_areas.get(child_box.computed_values().grid_column_end().line_name()); maybe_grid_area.has_value()) + if (grid_column_end.is_area()) { + if (auto maybe_grid_area = m_grid_areas.get(grid_column_end.area_name()); maybe_grid_area.has_value()) column_end = maybe_grid_area->column_end; - else if (auto line_name_index = get_line_index_by_line_name(child_box.computed_values().grid_column_end().line_name(), grid_container().computed_values().grid_template_columns()); line_name_index > -1) + else + column_end = 1; + column_start = column_end - 1; + } else if (grid_column_end.has_line_name()) { + if (auto line_name_index = get_line_index_by_line_name(grid_column_end.line_name(), grid_container().computed_values().grid_template_columns()); line_name_index > -1) column_end = line_name_index; else column_end = 1; column_start = column_end - 1; } - if (child_box.computed_values().grid_column_start().has_line_name()) { - if (auto maybe_grid_area = m_grid_areas.get(child_box.computed_values().grid_column_end().line_name()); maybe_grid_area.has_value()) + + if (grid_column_start.is_area()) { + if (auto maybe_grid_area = m_grid_areas.get(grid_column_start.area_name()); maybe_grid_area.has_value()) column_start = maybe_grid_area->column_start; - else if (auto line_name_index = get_line_index_by_line_name(child_box.computed_values().grid_column_start().line_name(), grid_container().computed_values().grid_template_columns()); line_name_index > -1) + else + column_start = 0; + } + if (grid_column_start.has_line_name()) { + if (auto line_name_index = get_line_index_by_line_name(grid_column_start.line_name(), grid_container().computed_values().grid_template_columns()); line_name_index > -1) column_start = line_name_index; else column_start = 0; @@ -474,7 +535,7 @@ void GridFormattingContext::place_item_with_column_position(Box const& child_box // If the placement for a grid item contains two lines, and the start line is further end-ward than // the end line, swap the two lines. If the start line is equal to the end line, remove the end // line. - if (child_box.computed_values().grid_column_start().is_position() && child_box.computed_values().grid_column_end().is_position()) { + if (grid_column_start.is_positioned() && grid_column_end.is_positioned()) { if (column_start > column_end) swap(column_start, column_end); if (column_start != column_end) @@ -483,8 +544,8 @@ void GridFormattingContext::place_item_with_column_position(Box const& child_box // If the placement contains two spans, remove the one contributed by the end grid-placement // property. - if (child_box.computed_values().grid_column_start().is_span() && child_box.computed_values().grid_column_end().is_span()) - column_span = child_box.computed_values().grid_column_start().raw_value(); + if (grid_column_start.is_span() && grid_column_end.is_span()) + column_span = grid_column_start.span(); // FIXME: If the placement contains only a span for a named line, replace it with a span of 1. @@ -516,22 +577,27 @@ void GridFormattingContext::place_item_with_column_position(Box const& child_box void GridFormattingContext::place_item_with_no_declared_position(Box const& child_box, int& auto_placement_cursor_x, int& auto_placement_cursor_y) { + auto const& grid_row_start = child_box.computed_values().grid_row_start(); + auto const& grid_row_end = child_box.computed_values().grid_row_end(); + auto const& grid_column_start = child_box.computed_values().grid_column_start(); + auto const& grid_column_end = child_box.computed_values().grid_column_end(); + // 4.1.2.1. Increment the column position of the auto-placement cursor until either this item's grid // area does not overlap any occupied grid cells, or the cursor's column position, plus the item's // column span, overflow the number of columns in the implicit grid, as determined earlier in this // algorithm. auto column_start = 0; size_t column_span = 1; - if (child_box.computed_values().grid_column_start().is_span()) - column_span = child_box.computed_values().grid_column_start().raw_value(); - else if (child_box.computed_values().grid_column_end().is_span()) - column_span = child_box.computed_values().grid_column_end().raw_value(); + if (grid_column_start.is_span()) + column_span = grid_column_start.span(); + else if (grid_column_end.is_span()) + column_span = grid_column_end.span(); auto row_start = 0; size_t row_span = 1; - if (child_box.computed_values().grid_row_start().is_span()) - row_span = child_box.computed_values().grid_row_start().raw_value(); - else if (child_box.computed_values().grid_row_end().is_span()) - row_span = child_box.computed_values().grid_row_end().raw_value(); + if (grid_row_start.is_span()) + row_span = grid_row_start.span(); + else if (grid_row_end.is_span()) + row_span = grid_row_end.span(); auto found_unoccupied_area = false; auto const& auto_flow = grid_container().computed_values().grid_auto_flow(); @@ -1395,11 +1461,14 @@ void GridFormattingContext::place_grid_items(AvailableSpace const& available_spa for (auto key : keys) { auto& boxes_to_place = order_item_bucket.get(key).value(); for (auto const& child_box : boxes_to_place) { + auto const& grid_column_start = child_box->computed_values().grid_column_start(); + auto const& grid_column_end = child_box->computed_values().grid_column_end(); + int column_span = 1; - if (child_box->computed_values().grid_column_start().is_span()) - column_span = child_box->computed_values().grid_column_start().raw_value(); - else if (child_box->computed_values().grid_column_end().is_span()) - column_span = child_box->computed_values().grid_column_end().raw_value(); + if (grid_column_start.is_span()) + column_span = grid_column_start.span(); + else if (grid_column_end.is_span()) + column_span = grid_column_end.span(); if (column_span - 1 > m_occupation_grid.max_column_index()) m_occupation_grid.set_max_column_index(column_span - 1); diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h index e4ac6d5e57f..a277eb6c6d4 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2023, Aliaksandr Kalenik * Copyright (c) 2022-2023, Martin Falisse * * SPDX-License-Identifier: BSD-2-Clause