From 1c979e0ed7ed6e3dbe64219e0908389cac18269e Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Thu, 8 Jun 2023 02:49:30 +0300 Subject: [PATCH] LibWeb: Resolve percentage padding and margins for grid items in GFC Adds a second pass to resolve percentage paddings and margins of grid items after track sizes are known. If resolving percentage paddings or margins affects tracks sizes then second pass to re-resolve track sizes might also be needed but I cannot come up with an example to reproduce that so we can leave it to improve in the future :) --- .../grid/grid-item-percentage-margins.txt | 10 +++ .../grid/grid-item-percentage-margins.html | 12 ++++ .../LibWeb/Layout/GridFormattingContext.cpp | 62 +++++++++++++------ .../LibWeb/Layout/GridFormattingContext.h | 2 + 4 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 Tests/LibWeb/Layout/expected/grid/grid-item-percentage-margins.txt create mode 100644 Tests/LibWeb/Layout/input/grid/grid-item-percentage-margins.html diff --git a/Tests/LibWeb/Layout/expected/grid/grid-item-percentage-margins.txt b/Tests/LibWeb/Layout/expected/grid/grid-item-percentage-margins.txt new file mode 100644 index 0000000000..cfbdca0692 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/grid-item-percentage-margins.txt @@ -0,0 +1,10 @@ +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 784x17.46875 children: not-inline + BlockContainer
at (8,8) content-size 784x17.46875 children: not-inline + Box at (8,8) content-size 784x17.46875 [GFC] children: not-inline + BlockContainer at (243.2,8) content-size 313.6x17.46875 [BFC] children: inline + line 0 width: 121.0625, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 16, rect: [243.2,8 121.0625x17.46875] + "A filthy t-shirt" + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/grid/grid-item-percentage-margins.html b/Tests/LibWeb/Layout/input/grid/grid-item-percentage-margins.html new file mode 100644 index 0000000000..eb81d1948b --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/grid-item-percentage-margins.html @@ -0,0 +1,12 @@ +
A filthy t-shirt \ No newline at end of file diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp index 969f89ec55..e66168cfd4 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.cpp @@ -1418,6 +1418,38 @@ void GridFormattingContext::resolve_grid_item_heights() } } +void GridFormattingContext::resolve_items_box_metrics(GridDimension const dimension) +{ + for (auto& item : m_grid_items) { + auto& box_state = m_state.get_mutable(item.box()); + auto& computed_values = item.box().computed_values(); + + if (dimension == GridDimension::Column) { + CSSPixels containing_block_width = containing_block_size_for_item(item, GridDimension::Column); + + box_state.padding_right = computed_values.padding().right().to_px(grid_container(), containing_block_width); + box_state.padding_left = computed_values.padding().left().to_px(grid_container(), containing_block_width); + + box_state.margin_right = computed_values.margin().right().to_px(grid_container(), containing_block_width); + box_state.margin_left = computed_values.margin().left().to_px(grid_container(), containing_block_width); + + box_state.border_right = computed_values.border_right().width; + box_state.border_left = computed_values.border_left().width; + } else { + CSSPixels containing_block_height = containing_block_size_for_item(item, GridDimension::Row); + + box_state.padding_top = computed_values.padding().top().to_px(grid_container(), containing_block_height); + box_state.padding_bottom = computed_values.padding().bottom().to_px(grid_container(), containing_block_height); + + box_state.margin_top = computed_values.margin().top().to_px(grid_container(), containing_block_height); + box_state.margin_bottom = computed_values.margin().bottom().to_px(grid_container(), containing_block_height); + + box_state.border_top = computed_values.border_top().width; + box_state.border_bottom = computed_values.border_bottom().width; + } + } +} + void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const& available_space) { m_available_space = available_space; @@ -1447,34 +1479,28 @@ void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const box_state.set_indefinite_content_width(); if (!computed_values.height().is_length()) box_state.set_indefinite_content_height(); - - // NOTE: It is ok to use 0 containing block size to resolve paddings on the first pass when grid areas sizes - // are not known yet. - // FIXME: Do second pass of tracks layout to resolve percentage paddings - box_state.padding_top = computed_values.padding().top().to_px(grid_container(), 0); - box_state.padding_right = computed_values.padding().right().to_px(grid_container(), 0); - box_state.padding_bottom = computed_values.padding().bottom().to_px(grid_container(), 0); - box_state.padding_left = computed_values.padding().left().to_px(grid_container(), 0); - - box_state.margin_top = computed_values.margin().top().to_px(grid_container(), 0); - box_state.margin_right = computed_values.margin().right().to_px(grid_container(), 0); - box_state.margin_bottom = computed_values.margin().bottom().to_px(grid_container(), 0); - box_state.margin_left = computed_values.margin().left().to_px(grid_container(), 0); - - box_state.border_top = computed_values.border_top().width; - box_state.border_right = computed_values.border_right().width; - box_state.border_bottom = computed_values.border_bottom().width; - box_state.border_left = computed_values.border_left().width; } + // Do the first pass of resolving grid items box metrics to compute values that are independent of a track width + resolve_items_box_metrics(GridDimension::Column); + run_track_sizing(available_space, GridDimension::Column); + // Do the second pass of resolving box metrics to compute values that depend on a track width + resolve_items_box_metrics(GridDimension::Column); + // Once the sizes of column tracks, which determine the widths of the grid areas forming the containing blocks // for grid items, ara calculated, it becomes possible to determine the final widths of the grid items. resolve_grid_item_widths(); + // Do the first pass of resolving grid items box metrics to compute values that are independent of a track height + resolve_items_box_metrics(GridDimension::Row); + run_track_sizing(available_space, GridDimension::Row); + // Do the second pass of resolving box metrics to compute values that depend on a track height + resolve_items_box_metrics(GridDimension::Row); + resolve_grid_item_heights(); determine_grid_container_height(); diff --git a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h index 6e316c868e..37c6f364ca 100644 --- a/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h +++ b/Userland/Libraries/LibWeb/Layout/GridFormattingContext.h @@ -124,6 +124,8 @@ public: Box const& grid_container() const { return context_box(); } private: + void resolve_items_box_metrics(GridDimension const dimension); + CSSPixels m_automatic_content_height { 0 }; bool is_auto_positioned_row(CSS::GridTrackPlacement const&, CSS::GridTrackPlacement const&) const; bool is_auto_positioned_column(CSS::GridTrackPlacement const&, CSS::GridTrackPlacement const&) const;