.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