mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 09:07:44 +00:00
LibWeb: Treat unresolvable percentages as auto to resolve sizes in GFC
Fixes the bug that currently we always consider tracks with percentage size as ones with "fixed" length even when available size is not definite. With this change tracks with percentage size when available size is not definite will be considered as "intrinsic" sized.
This commit is contained in:
parent
30feb95d53
commit
537256fae2
6 changed files with 73 additions and 58 deletions
|
@ -0,0 +1,10 @@
|
||||||
|
Viewport <#document> at (0,0) content-size 800x600 children: not-inline
|
||||||
|
BlockContainer <html> at (0,0) content-size 800x600 [BFC] children: not-inline
|
||||||
|
BlockContainer <body> at (8,8) content-size 784x17.46875 children: not-inline
|
||||||
|
Box <div.ipc-page-grid> at (8,8) content-size 784x17.46875 flex-container(row) [FFC] children: not-inline
|
||||||
|
Box <div.ipc-sub-grid> at (8,8) content-size 36.84375x17.46875 flex-item [GFC] children: not-inline
|
||||||
|
BlockContainer <div> at (8,8) content-size 36.84375x17.46875 [BFC] children: inline
|
||||||
|
line 0 width: 36.84375, height: 17.46875, bottom: 17.46875, baseline: 13.53125
|
||||||
|
frag 0 from TextNode start: 0, length: 5, rect: [8,8 36.84375x17.46875]
|
||||||
|
"hello"
|
||||||
|
TextNode <#text>
|
|
@ -0,0 +1,11 @@
|
||||||
|
<style>
|
||||||
|
.ipc-page-grid {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ipc-sub-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="ipc-page-grid"><div class="ipc-sub-grid"><div>hello</div></div></div>
|
|
@ -36,6 +36,33 @@ GridSize::GridSize()
|
||||||
|
|
||||||
GridSize::~GridSize() = default;
|
GridSize::~GridSize() = default;
|
||||||
|
|
||||||
|
bool GridSize::is_auto(Layout::AvailableSize const& available_size) const
|
||||||
|
{
|
||||||
|
if (m_type == Type::LengthPercentage) {
|
||||||
|
if (m_length_percentage.is_percentage())
|
||||||
|
return !available_size.is_definite();
|
||||||
|
return m_length_percentage.is_auto();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GridSize::is_fixed(Layout::AvailableSize const& available_size) const
|
||||||
|
{
|
||||||
|
if (m_type == Type::LengthPercentage) {
|
||||||
|
if (m_length_percentage.is_percentage())
|
||||||
|
return available_size.is_definite();
|
||||||
|
return !m_length_percentage.is_auto();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GridSize::is_intrinsic(Layout::AvailableSize const& available_size) const
|
||||||
|
{
|
||||||
|
return is_auto(available_size) || is_max_content() || is_min_content();
|
||||||
|
}
|
||||||
|
|
||||||
GridSize GridSize::make_auto()
|
GridSize GridSize::make_auto()
|
||||||
{
|
{
|
||||||
return GridSize(CSS::Length::make_auto());
|
return GridSize(CSS::Length::make_auto());
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibWeb/CSS/PercentageOr.h>
|
#include <LibWeb/CSS/PercentageOr.h>
|
||||||
|
#include <LibWeb/Layout/AvailableSpace.h>
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
@ -30,8 +31,8 @@ public:
|
||||||
|
|
||||||
Type type() const { return m_type; }
|
Type type() const { return m_type; }
|
||||||
|
|
||||||
bool is_auto() const { return m_type == Type::LengthPercentage && m_length_percentage.is_auto(); }
|
bool is_auto(Layout::AvailableSize const&) const;
|
||||||
bool is_length_percentage() const { return m_type == Type::LengthPercentage; }
|
bool is_fixed(Layout::AvailableSize const&) const;
|
||||||
bool is_flexible_length() const { return m_type == Type::FlexibleLength; }
|
bool is_flexible_length() const { return m_type == Type::FlexibleLength; }
|
||||||
bool is_max_content() const { return m_type == Type::MaxContent; }
|
bool is_max_content() const { return m_type == Type::MaxContent; }
|
||||||
bool is_min_content() const { return m_type == Type::MinContent; }
|
bool is_min_content() const { return m_type == Type::MinContent; }
|
||||||
|
@ -42,10 +43,7 @@ public:
|
||||||
// https://www.w3.org/TR/css-grid-2/#layout-algorithm
|
// https://www.w3.org/TR/css-grid-2/#layout-algorithm
|
||||||
// An intrinsic sizing function (min-content, max-content, auto, fit-content()).
|
// An intrinsic sizing function (min-content, max-content, auto, fit-content()).
|
||||||
// FIXME: Add missing properties once implemented.
|
// FIXME: Add missing properties once implemented.
|
||||||
bool is_intrinsic_track_sizing() const
|
bool is_intrinsic(Layout::AvailableSize const&) const;
|
||||||
{
|
|
||||||
return is_auto() || is_max_content() || is_min_content();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_definite() const
|
bool is_definite() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -630,59 +630,23 @@ void GridFormattingContext::initialize_track_sizes(AvailableSpace const& availab
|
||||||
auto& tracks_and_gaps = dimension == GridDimension::Column ? m_grid_columns_and_gaps : m_grid_rows_and_gaps;
|
auto& tracks_and_gaps = dimension == GridDimension::Column ? m_grid_columns_and_gaps : m_grid_rows_and_gaps;
|
||||||
auto& available_size = dimension == GridDimension::Column ? available_space.width : available_space.height;
|
auto& available_size = dimension == GridDimension::Column ? available_space.width : available_space.height;
|
||||||
|
|
||||||
// For each track, if the track’s min track sizing function is:
|
|
||||||
for (auto& track : tracks_and_gaps) {
|
for (auto& track : tracks_and_gaps) {
|
||||||
if (track.is_gap)
|
if (track.is_gap)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (track.min_track_sizing_function.type()) {
|
if (track.min_track_sizing_function.is_fixed(available_size)) {
|
||||||
// - A fixed sizing function
|
track.base_size = track.min_track_sizing_function.css_size().to_px(grid_container(), available_size.to_px());
|
||||||
// Resolve to an absolute length and use that size as the track’s initial base size.
|
} else if (track.min_track_sizing_function.is_intrinsic(available_size)) {
|
||||||
case CSS::GridSize::Type::LengthPercentage: {
|
|
||||||
if (!track.min_track_sizing_function.is_auto()) {
|
|
||||||
track.base_size = track.min_track_sizing_function.css_size().to_px(grid_container(), available_size.to_px());
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// - An intrinsic sizing function
|
|
||||||
// Use an initial base size of zero.
|
|
||||||
case CSS::GridSize::Type::FlexibleLength:
|
|
||||||
case CSS::GridSize::Type::MaxContent:
|
|
||||||
case CSS::GridSize::Type::MinContent: {
|
|
||||||
track.base_size = 0;
|
track.base_size = 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each track, if the track’s max track sizing function is:
|
if (track.max_track_sizing_function.is_fixed(available_size)) {
|
||||||
switch (track.max_track_sizing_function.type()) {
|
track.growth_limit = track.max_track_sizing_function.css_size().to_px(grid_container(), available_size.to_px());
|
||||||
// - A fixed sizing function
|
} else if (track.max_track_sizing_function.is_flexible_length()) {
|
||||||
// Resolve to an absolute length and use that size as the track’s initial growth limit.
|
|
||||||
case CSS::GridSize::Type::LengthPercentage: {
|
|
||||||
if (!track.max_track_sizing_function.is_auto()) {
|
|
||||||
track.growth_limit = track.max_track_sizing_function.css_size().to_px(grid_container(), available_size.to_px());
|
|
||||||
} else {
|
|
||||||
track.growth_limit = INFINITY;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// - A flexible sizing function
|
|
||||||
// Use an initial growth limit of infinity.
|
|
||||||
case CSS::GridSize::Type::FlexibleLength: {
|
|
||||||
track.growth_limit = INFINITY;
|
track.growth_limit = INFINITY;
|
||||||
break;
|
} else if (track.max_track_sizing_function.is_intrinsic(available_size)) {
|
||||||
}
|
|
||||||
// - An intrinsic sizing function
|
|
||||||
// Use an initial growth limit of infinity.
|
|
||||||
case CSS::GridSize::Type::MaxContent:
|
|
||||||
case CSS::GridSize::Type::MinContent: {
|
|
||||||
track.growth_limit = INFINITY;
|
track.growth_limit = INFINITY;
|
||||||
break;
|
} else {
|
||||||
}
|
|
||||||
default:
|
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -891,7 +855,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
|
||||||
// function by distributing extra space as needed to accommodate these items’ minimum contributions.
|
// function by distributing extra space as needed to accommodate these items’ minimum contributions.
|
||||||
Vector<TemporaryTrack&> intrinsic_minimum_spanned_tracks;
|
Vector<TemporaryTrack&> intrinsic_minimum_spanned_tracks;
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
if (track.min_track_sizing_function.is_intrinsic_track_sizing())
|
if (track.min_track_sizing_function.is_intrinsic(available_size))
|
||||||
intrinsic_minimum_spanned_tracks.append(track);
|
intrinsic_minimum_spanned_tracks.append(track);
|
||||||
}
|
}
|
||||||
auto item_size_contribution = [&] {
|
auto item_size_contribution = [&] {
|
||||||
|
@ -929,7 +893,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
|
||||||
if (available_size.is_max_content()) {
|
if (available_size.is_max_content()) {
|
||||||
Vector<TemporaryTrack&> max_content_minimum_tracks;
|
Vector<TemporaryTrack&> max_content_minimum_tracks;
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
if (track.min_track_sizing_function.is_auto() || track.min_track_sizing_function.is_max_content()) {
|
if (track.min_track_sizing_function.is_auto(available_size) || track.min_track_sizing_function.is_max_content()) {
|
||||||
max_content_minimum_tracks.append(track);
|
max_content_minimum_tracks.append(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -951,7 +915,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
|
||||||
// 5. For intrinsic maximums: Next increase the growth limit of tracks with an intrinsic max track sizing
|
// 5. For intrinsic maximums: Next increase the growth limit of tracks with an intrinsic max track sizing
|
||||||
Vector<TemporaryTrack&> intrinsic_maximum_tracks;
|
Vector<TemporaryTrack&> intrinsic_maximum_tracks;
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
if (track.max_track_sizing_function.is_intrinsic_track_sizing()) {
|
if (track.max_track_sizing_function.is_intrinsic(available_size)) {
|
||||||
intrinsic_maximum_tracks.append(track);
|
intrinsic_maximum_tracks.append(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -974,7 +938,7 @@ void GridFormattingContext::increase_sizes_to_accommodate_spanning_items_crossin
|
||||||
// content contributions.
|
// content contributions.
|
||||||
Vector<TemporaryTrack&> max_content_maximum_tracks;
|
Vector<TemporaryTrack&> max_content_maximum_tracks;
|
||||||
for (auto& track : spanned_tracks) {
|
for (auto& track : spanned_tracks) {
|
||||||
if (track.max_track_sizing_function.is_max_content() || track.max_track_sizing_function.is_auto()) {
|
if (track.max_track_sizing_function.is_max_content() || track.max_track_sizing_function.is_auto(available_size)) {
|
||||||
max_content_maximum_tracks.append(track);
|
max_content_maximum_tracks.append(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1183,19 +1147,19 @@ void GridFormattingContext::stretch_auto_tracks(AvailableSpace const& available_
|
||||||
// step instead.
|
// step instead.
|
||||||
CSSPixels used_space = 0;
|
CSSPixels used_space = 0;
|
||||||
for (auto& track : tracks_and_gaps) {
|
for (auto& track : tracks_and_gaps) {
|
||||||
if (!track.max_track_sizing_function.is_auto())
|
if (!track.max_track_sizing_function.is_auto(available_size))
|
||||||
used_space += track.base_size;
|
used_space += track.base_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSSPixels remaining_space = available_size.is_definite() ? available_size.to_px() - used_space : 0;
|
CSSPixels remaining_space = available_size.is_definite() ? available_size.to_px() - used_space : 0;
|
||||||
auto count_of_auto_max_sizing_tracks = 0;
|
auto count_of_auto_max_sizing_tracks = 0;
|
||||||
for (auto& track : tracks_and_gaps) {
|
for (auto& track : tracks_and_gaps) {
|
||||||
if (track.max_track_sizing_function.is_auto())
|
if (track.max_track_sizing_function.is_auto(available_size))
|
||||||
count_of_auto_max_sizing_tracks++;
|
count_of_auto_max_sizing_tracks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& track : tracks_and_gaps) {
|
for (auto& track : tracks_and_gaps) {
|
||||||
if (track.max_track_sizing_function.is_auto())
|
if (track.max_track_sizing_function.is_auto(available_size))
|
||||||
track.base_size = max(track.base_size, remaining_space / count_of_auto_max_sizing_tracks);
|
track.base_size = max(track.base_size, remaining_space / count_of_auto_max_sizing_tracks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1424,6 +1388,8 @@ void GridFormattingContext::resolve_grid_item_heights()
|
||||||
|
|
||||||
void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const& available_space)
|
void GridFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const& available_space)
|
||||||
{
|
{
|
||||||
|
m_available_space = available_space;
|
||||||
|
|
||||||
place_grid_items(available_space);
|
place_grid_items(available_space);
|
||||||
|
|
||||||
initialize_grid_tracks_for_columns_and_rows(available_space);
|
initialize_grid_tracks_for_columns_and_rows(available_space);
|
||||||
|
@ -1812,7 +1778,8 @@ CSSPixels GridFormattingContext::automatic_minimum_size(GridItem const& item, Gr
|
||||||
auto item_track_index = item.raw_position(dimension);
|
auto item_track_index = item.raw_position(dimension);
|
||||||
|
|
||||||
// FIXME: Check all tracks spanned by an item
|
// FIXME: Check all tracks spanned by an item
|
||||||
auto item_spans_auto_tracks = tracks[item_track_index].min_track_sizing_function.is_auto();
|
AvailableSize const& available_size = dimension == GridDimension::Column ? m_available_space->width : m_available_space->height;
|
||||||
|
auto item_spans_auto_tracks = tracks[item_track_index].min_track_sizing_function.is_auto(available_size);
|
||||||
if (item_spans_auto_tracks && !item.box().is_scroll_container()) {
|
if (item_spans_auto_tracks && !item.box().is_scroll_container()) {
|
||||||
return item.add_border_box_sizes(content_based_minimum_size(item, dimension), dimension, m_state);
|
return item.add_border_box_sizes(content_based_minimum_size(item, dimension), dimension, m_state);
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,8 @@ private:
|
||||||
Vector<GridItem> m_grid_items;
|
Vector<GridItem> m_grid_items;
|
||||||
Vector<JS::NonnullGCPtr<Box const>> m_boxes_to_place;
|
Vector<JS::NonnullGCPtr<Box const>> m_boxes_to_place;
|
||||||
|
|
||||||
|
Optional<AvailableSpace> m_available_space;
|
||||||
|
|
||||||
void determine_grid_container_height();
|
void determine_grid_container_height();
|
||||||
void determine_intrinsic_size_of_grid_container(AvailableSpace const& available_space);
|
void determine_intrinsic_size_of_grid_container(AvailableSpace const& available_space);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue