mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 13:36:13 +03:00
LibWeb: Consider percent and fixed widths in table column distribution
Change column distribution to take in account is_length() and is_percentage() width values instead of treating all cells like they have auto width by implementing it in the way described in CSS Tables 3 spec: https://www.w3.org/TR/css-tables-3/#width-distribution-algorithm distribute_width_to_column() is structured to follow schema: w3.org/TR/css-tables-3/images/CSS-Tables-Column-Width-Assignment.svg
This commit is contained in:
parent
21d89a2153
commit
b2a04ff48a
Notes:
sideshowbarker
2024-07-17 07:31:31 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/SerenityOS/serenity/commit/b2a04ff48a Pull-request: https://github.com/SerenityOS/serenity/pull/16836 Reviewed-by: https://github.com/MacDue
@ -129,18 +129,22 @@ void TableFormattingContext::compute_table_measures()
|
||||
if (!computed_values.max_width().is_none())
|
||||
max_width = min(max_width, computed_values.max_width().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box));
|
||||
|
||||
auto computed_width = computed_values.width();
|
||||
if (computed_width.is_percentage()) {
|
||||
m_columns[cell.column_index].type = ColumnType::Percent;
|
||||
m_columns[cell.column_index].percentage_width = max(m_columns[cell.column_index].percentage_width, computed_width.percentage().value());
|
||||
} else if (computed_width.is_length()) {
|
||||
m_columns[cell.column_index].type = ColumnType::Pixel;
|
||||
}
|
||||
|
||||
auto cell_outer_min_content_width = min_width + cell_intrinsic_offsets;
|
||||
auto cell_outer_max_content_width = max(max(width, min_width), max_width) + cell_intrinsic_offsets;
|
||||
m_columns[cell.column_index].min_width = max(m_columns[cell.column_index].min_width, cell_outer_min_content_width);
|
||||
m_columns[cell.column_index].max_width = max(m_columns[cell.column_index].max_width, cell_outer_max_content_width);
|
||||
}
|
||||
|
||||
for (auto& column : m_columns) {
|
||||
column.used_width = column.min_width;
|
||||
}
|
||||
}
|
||||
|
||||
void TableFormattingContext::compute_table_width(CSSPixels& extra_width)
|
||||
void TableFormattingContext::compute_table_width()
|
||||
{
|
||||
auto const& table_box = context_box();
|
||||
auto& table_box_state = m_state.get_mutable(table_box);
|
||||
@ -183,23 +187,101 @@ void TableFormattingContext::compute_table_width(CSSPixels& extra_width)
|
||||
used_width = max(resolved_table_width, used_min_width);
|
||||
table_box_state.set_content_width(used_width);
|
||||
}
|
||||
|
||||
if (used_width > grid_min) {
|
||||
extra_width = used_width - grid_min;
|
||||
}
|
||||
}
|
||||
|
||||
void TableFormattingContext::distribute_width_to_columns(CSSPixels extra_width)
|
||||
void TableFormattingContext::distribute_width_to_columns()
|
||||
{
|
||||
CSSPixels grid_max = 0.0f;
|
||||
for (auto& column : m_columns)
|
||||
grid_max += column.max_width - column.min_width;
|
||||
// Implements https://www.w3.org/TR/css-tables-3/#width-distribution-algorithm
|
||||
|
||||
if (grid_max == 0)
|
||||
CSSPixels available_width = m_state.get(context_box()).content_width();
|
||||
|
||||
auto columns_total_used_width = [&]() {
|
||||
CSSPixels total_used_width = 0;
|
||||
for (auto& column : m_columns) {
|
||||
total_used_width += column.used_width;
|
||||
}
|
||||
return total_used_width;
|
||||
};
|
||||
|
||||
auto column_preferred_width = [&](Column& column) {
|
||||
switch (column.type) {
|
||||
case ColumnType::Percent: {
|
||||
return max(column.min_width, column.percentage_width / 100 * available_width);
|
||||
}
|
||||
case ColumnType::Pixel:
|
||||
case ColumnType::Auto: {
|
||||
return column.max_width;
|
||||
}
|
||||
default: {
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto expand_columns_to_fill_available_width = [&](ColumnType column_type) {
|
||||
CSSPixels remaining_available_width = available_width;
|
||||
CSSPixels total_preferred_width_increment = 0;
|
||||
for (auto& column : m_columns) {
|
||||
remaining_available_width -= column.used_width;
|
||||
if (column.type == column_type) {
|
||||
total_preferred_width_increment += column_preferred_width(column) - column.min_width;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& column : m_columns) {
|
||||
if (column.type == column_type) {
|
||||
CSSPixels preferred_width_increment = column_preferred_width(column) - column.min_width;
|
||||
column.used_width += preferred_width_increment * remaining_available_width / total_preferred_width_increment;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto shrink_columns_to_fit_available_width = [&](ColumnType column_type) {
|
||||
for (auto& column : m_columns) {
|
||||
if (column.type == column_type)
|
||||
column.used_width = column.min_width;
|
||||
}
|
||||
|
||||
expand_columns_to_fill_available_width(column_type);
|
||||
};
|
||||
|
||||
for (auto& column : m_columns) {
|
||||
column.used_width = column.min_width;
|
||||
}
|
||||
|
||||
for (auto& column : m_columns) {
|
||||
if (column.type == ColumnType::Percent) {
|
||||
column.used_width = max(column.min_width, column.percentage_width / 100 * available_width);
|
||||
}
|
||||
}
|
||||
|
||||
if (columns_total_used_width() > available_width) {
|
||||
shrink_columns_to_fit_available_width(ColumnType::Percent);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto& column : m_columns)
|
||||
column.used_width += ((column.max_width - column.min_width) / grid_max) * extra_width;
|
||||
for (auto& column : m_columns) {
|
||||
if (column.type == ColumnType::Pixel) {
|
||||
column.used_width = column.max_width;
|
||||
}
|
||||
}
|
||||
|
||||
if (columns_total_used_width() > available_width) {
|
||||
shrink_columns_to_fit_available_width(ColumnType::Pixel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (columns_total_used_width() < available_width) {
|
||||
expand_columns_to_fill_available_width(ColumnType::Auto);
|
||||
}
|
||||
|
||||
if (columns_total_used_width() < available_width) {
|
||||
expand_columns_to_fill_available_width(ColumnType::Pixel);
|
||||
}
|
||||
|
||||
if (columns_total_used_width() < available_width) {
|
||||
expand_columns_to_fill_available_width(ColumnType::Percent);
|
||||
}
|
||||
}
|
||||
|
||||
void TableFormattingContext::determine_intrisic_size_of_table_container(AvailableSpace const& available_space)
|
||||
@ -242,11 +324,10 @@ void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace cons
|
||||
}
|
||||
|
||||
// Compute the width of the table.
|
||||
CSSPixels extra_width = 0;
|
||||
compute_table_width(extra_width);
|
||||
compute_table_width();
|
||||
|
||||
// Distribute the width of the table among columns.
|
||||
distribute_width_to_columns(extra_width);
|
||||
distribute_width_to_columns();
|
||||
|
||||
CSSPixels left_column_offset = 0;
|
||||
for (auto& column : m_columns) {
|
||||
|
@ -22,19 +22,27 @@ public:
|
||||
private:
|
||||
void calculate_row_column_grid(Box const&);
|
||||
void compute_table_measures();
|
||||
void compute_table_width(CSSPixels&);
|
||||
void distribute_width_to_columns(CSSPixels extra_width);
|
||||
void compute_table_width();
|
||||
void distribute_width_to_columns();
|
||||
void determine_intrisic_size_of_table_container(AvailableSpace const& available_space);
|
||||
|
||||
CSSPixels m_automatic_content_height { 0 };
|
||||
|
||||
Optional<AvailableSpace> m_available_space;
|
||||
|
||||
enum class ColumnType {
|
||||
Percent,
|
||||
Pixel,
|
||||
Auto
|
||||
};
|
||||
|
||||
struct Column {
|
||||
ColumnType type { ColumnType::Auto };
|
||||
CSSPixels left_offset { 0 };
|
||||
CSSPixels min_width { 0 };
|
||||
CSSPixels max_width { 0 };
|
||||
CSSPixels used_width { 0 };
|
||||
float percentage_width { 0 };
|
||||
};
|
||||
|
||||
struct Row {
|
||||
|
Loading…
Reference in New Issue
Block a user