1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 07:17:35 +00:00

LibWeb: Convert TableFormattingContext to new pixel units

This commit is contained in:
Sam Atkins 2022-12-15 12:57:36 +00:00 committed by Linus Groh
parent ec336c9bc5
commit 700ba0007f
2 changed files with 58 additions and 58 deletions

View file

@ -107,25 +107,25 @@ void TableFormattingContext::compute_table_measures()
auto width_of_containing_block = m_state.get(*cell.box.containing_block()).content_width(); auto width_of_containing_block = m_state.get(*cell.box.containing_block()).content_width();
auto width_of_containing_block_as_length = CSS::Length::make_px(width_of_containing_block); auto width_of_containing_block_as_length = CSS::Length::make_px(width_of_containing_block);
auto& computed_values = cell.box.computed_values(); auto& computed_values = cell.box.computed_values();
float padding_left = computed_values.padding().left().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box); CSSPixels padding_left = computed_values.padding().left().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box);
float padding_right = computed_values.padding().right().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box); CSSPixels padding_right = computed_values.padding().right().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box);
auto is_left_most_cell = cell.column_index == 0; auto is_left_most_cell = cell.column_index == 0;
auto is_right_most_cell = cell.column_index == m_columns.size() - 1; auto is_right_most_cell = cell.column_index == m_columns.size() - 1;
auto should_hide_borders = cell.box.computed_values().border_collapse() == CSS::BorderCollapse::Collapse; auto should_hide_borders = cell.box.computed_values().border_collapse() == CSS::BorderCollapse::Collapse;
float border_left = should_hide_borders && !is_left_most_cell ? 0 : computed_values.border_left().width; CSSPixels border_left = should_hide_borders && !is_left_most_cell ? 0 : computed_values.border_left().width;
float border_right = should_hide_borders && !is_right_most_cell ? 0 : computed_values.border_right().width; CSSPixels border_right = should_hide_borders && !is_right_most_cell ? 0 : computed_values.border_right().width;
float width = computed_values.width().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box); CSSPixels width = computed_values.width().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box);
auto cell_intrinsic_offsets = padding_left + padding_right + border_left + border_right; auto cell_intrinsic_offsets = padding_left + padding_right + border_left + border_right;
auto min_content_width = calculate_min_content_width(cell.box); auto min_content_width = calculate_min_content_width(cell.box);
auto max_content_width = calculate_max_content_width(cell.box); auto max_content_width = calculate_max_content_width(cell.box);
float min_width = min_content_width.value(); CSSPixels min_width = min_content_width.value();
if (!computed_values.min_width().is_auto()) if (!computed_values.min_width().is_auto())
min_width = max(min_width, computed_values.min_width().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box)); min_width = max(min_width, computed_values.min_width().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box));
float max_width = computed_values.width().is_auto() ? max_content_width.value() : width; CSSPixels max_width = computed_values.width().is_auto() ? max_content_width.value() : width;
if (!computed_values.max_width().is_none()) 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)); max_width = min(max_width, computed_values.max_width().resolved(cell.box, width_of_containing_block_as_length).to_px(cell.box));
@ -140,48 +140,48 @@ void TableFormattingContext::compute_table_measures()
} }
} }
void TableFormattingContext::compute_table_width(float& extra_width) void TableFormattingContext::compute_table_width(CSSPixels& extra_width)
{ {
auto const& table_box = context_box(); auto const& table_box = context_box();
auto& table_box_state = m_state.get_mutable(table_box); auto& table_box_state = m_state.get_mutable(table_box);
auto& computed_values = table_box.computed_values(); auto& computed_values = table_box.computed_values();
float width_of_table_containing_block = m_state.get(*table_box.containing_block()).content_width(); CSSPixels width_of_table_containing_block = m_state.get(*table_box.containing_block()).content_width();
// The row/column-grid width minimum (GRIDMIN) width is the sum of the min-content width // The row/column-grid width minimum (GRIDMIN) width is the sum of the min-content width
// of all the columns plus cell spacing or borders. // of all the columns plus cell spacing or borders.
float grid_min = 0.0f; CSSPixels grid_min = 0.0f;
for (auto& column : m_columns) { for (auto& column : m_columns) {
grid_min += column.min_width; grid_min += column.min_width;
} }
// The row/column-grid width maximum (GRIDMAX) width is the sum of the max-content width // The row/column-grid width maximum (GRIDMAX) width is the sum of the max-content width
// of all the columns plus cell spacing or borders. // of all the columns plus cell spacing or borders.
float grid_max = 0.0f; CSSPixels grid_max = 0.0f;
for (auto& column : m_columns) { for (auto& column : m_columns) {
grid_max += column.max_width; grid_max += column.max_width;
} }
// The used min-width of a table is the greater of the resolved min-width, CAPMIN, and GRIDMIN. // The used min-width of a table is the greater of the resolved min-width, CAPMIN, and GRIDMIN.
float used_min_width = grid_min; auto used_min_width = grid_min;
if (!computed_values.min_width().is_auto()) { if (!computed_values.min_width().is_auto()) {
used_min_width = max(used_min_width, computed_values.min_width().resolved(table_box, CSS::Length::make_px(width_of_table_containing_block)).to_px(table_box)); used_min_width = max(used_min_width, computed_values.min_width().resolved(table_box, CSS::Length::make_px(width_of_table_containing_block)).to_px(table_box));
} }
float used_width; CSSPixels used_width;
if (computed_values.width().is_auto()) { if (computed_values.width().is_auto()) {
// If the table-root has 'width: auto', the used width is the greater of // If the table-root has 'width: auto', the used width is the greater of
// min(GRIDMAX, the tables containing block width), the used min-width of the table. // min(GRIDMAX, the tables containing block width), the used min-width of the table.
used_width = max(min(grid_max, width_of_table_containing_block), used_min_width); used_width = max(min(grid_max, width_of_table_containing_block), used_min_width);
table_box_state.set_content_width(used_width); table_box_state.set_content_width(used_width.value());
} else { } else {
// If the table-roots width property has a computed value (resolving to // If the table-roots width property has a computed value (resolving to
// resolved-table-width) other than auto, the used width is the greater // resolved-table-width) other than auto, the used width is the greater
// of resolved-table-width, and the used min-width of the table. // of resolved-table-width, and the used min-width of the table.
float resolved_table_width = computed_values.width().resolved(table_box, CSS::Length::make_px(width_of_table_containing_block)).to_px(table_box); CSSPixels resolved_table_width = computed_values.width().resolved(table_box, CSS::Length::make_px(width_of_table_containing_block)).to_px(table_box);
used_width = max(resolved_table_width, used_min_width); used_width = max(resolved_table_width, used_min_width);
table_box_state.set_content_width(used_width); table_box_state.set_content_width(used_width.value());
} }
if (used_width > grid_min) { if (used_width > grid_min) {
@ -189,9 +189,9 @@ void TableFormattingContext::compute_table_width(float& extra_width)
} }
} }
void TableFormattingContext::distribute_width_to_columns(float extra_width) void TableFormattingContext::distribute_width_to_columns(CSSPixels extra_width)
{ {
float grid_max = 0.0f; CSSPixels grid_max = 0.0f;
for (auto& column : m_columns) for (auto& column : m_columns)
grid_max += column.max_width - column.min_width; grid_max += column.max_width - column.min_width;
@ -209,24 +209,24 @@ void TableFormattingContext::determine_intrisic_size_of_table_container(Availabl
if (available_space.width.is_min_content()) { if (available_space.width.is_min_content()) {
// The min-content width of a table is the width required to fit all of its columns min-content widths and its undistributable spaces. // The min-content width of a table is the width required to fit all of its columns min-content widths and its undistributable spaces.
float grid_min = 0.0f; CSSPixels grid_min = 0.0f;
for (auto& column : m_columns) for (auto& column : m_columns)
grid_min += column.min_width; grid_min += column.min_width;
table_box_state.set_content_width(grid_min); table_box_state.set_content_width(grid_min.value());
} }
if (available_space.width.is_max_content()) { if (available_space.width.is_max_content()) {
// The max-content width of a table is the width required to fit all of its columns max-content widths and its undistributable spaces. // The max-content width of a table is the width required to fit all of its columns max-content widths and its undistributable spaces.
float grid_max = 0.0f; CSSPixels grid_max = 0.0f;
for (auto& column : m_columns) for (auto& column : m_columns)
grid_max += column.max_width; grid_max += column.max_width;
table_box_state.set_content_width(grid_max); table_box_state.set_content_width(grid_max.value());
} }
} }
void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const& available_space) void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace const& available_space)
{ {
float total_content_height = 0; CSSPixels total_content_height = 0;
// Determine the number of rows/columns the table requires. // Determine the number of rows/columns the table requires.
calculate_row_column_grid(box); calculate_row_column_grid(box);
@ -240,13 +240,13 @@ void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace cons
} }
// Compute the width of the table. // Compute the width of the table.
float extra_width = 0; CSSPixels extra_width = 0;
compute_table_width(extra_width); compute_table_width(extra_width);
// Distribute the width of the table among columns. // Distribute the width of the table among columns.
distribute_width_to_columns(extra_width); distribute_width_to_columns(extra_width);
float left_column_offset = 0; CSSPixels left_column_offset = 0;
for (auto& column : m_columns) { for (auto& column : m_columns) {
column.left_offset = left_column_offset; column.left_offset = left_column_offset;
left_column_offset += column.used_width; left_column_offset += column.used_width;
@ -255,7 +255,7 @@ void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace cons
for (auto& cell : m_cells) { for (auto& cell : m_cells) {
auto& cell_state = m_state.get_mutable(cell.box); auto& cell_state = m_state.get_mutable(cell.box);
float span_width = 0; CSSPixels span_width = 0;
for (size_t i = 0; i < cell.column_span; ++i) for (size_t i = 0; i < cell.column_span; ++i)
span_width += m_columns[cell.column_index + i].used_width; span_width += m_columns[cell.column_index + i].used_width;
@ -278,7 +278,7 @@ void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace cons
cell_state.border_left = (should_hide_borders && is_left_most_cell) ? 0 : cell.box.computed_values().border_left().width; cell_state.border_left = (should_hide_borders && is_left_most_cell) ? 0 : cell.box.computed_values().border_left().width;
cell_state.border_right = (should_hide_borders && is_right_most_cell) ? 0 : cell.box.computed_values().border_right().width; cell_state.border_right = (should_hide_borders && is_right_most_cell) ? 0 : cell.box.computed_values().border_right().width;
cell_state.set_content_width(span_width - cell_state.border_box_left() - cell_state.border_box_right()); cell_state.set_content_width((span_width - cell_state.border_box_left() - cell_state.border_box_right()).value());
auto independent_formatting_context = layout_inside(cell.box, LayoutMode::Normal, cell_state.available_inner_space_or_constraints_from(available_space)); auto independent_formatting_context = layout_inside(cell.box, LayoutMode::Normal, cell_state.available_inner_space_or_constraints_from(available_space));
VERIFY(independent_formatting_context); VERIFY(independent_formatting_context);
cell_state.set_content_height(independent_formatting_context->automatic_content_height().value()); cell_state.set_content_height(independent_formatting_context->automatic_content_height().value());
@ -291,33 +291,33 @@ void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace cons
row.baseline = max(row.baseline, cell.baseline); row.baseline = max(row.baseline, cell.baseline);
} }
float row_top_offset = 0.0f; CSSPixels row_top_offset = 0.0f;
for (size_t y = 0; y < m_rows.size(); y++) { for (size_t y = 0; y < m_rows.size(); y++) {
auto& row = m_rows[y]; auto& row = m_rows[y];
auto& row_state = m_state.get_mutable(row.box); auto& row_state = m_state.get_mutable(row.box);
float row_width = 0.0f; CSSPixels row_width = 0.0f;
for (auto& column : m_columns) { for (auto& column : m_columns) {
row_width += column.used_width; row_width += column.used_width;
} }
row_state.set_content_height(row.used_width); row_state.set_content_height(row.used_width.value());
row_state.set_content_width(row_width); row_state.set_content_width(row_width.value());
row_state.set_content_y(row_top_offset); row_state.set_content_y(row_top_offset.value());
row_top_offset += row_state.content_height(); row_top_offset += row_state.content_height();
} }
float row_group_top_offset = 0.0f; CSSPixels row_group_top_offset = 0.0f;
box.for_each_child_of_type<TableRowGroupBox>([&](auto& row_group_box) { box.for_each_child_of_type<TableRowGroupBox>([&](auto& row_group_box) {
float row_group_height = 0.0f; CSSPixels row_group_height = 0.0f;
float row_group_width = 0.0f; CSSPixels row_group_width = 0.0f;
auto& row_group_box_state = m_state.get_mutable(row_group_box); auto& row_group_box_state = m_state.get_mutable(row_group_box);
row_group_box_state.set_content_y(row_group_top_offset); row_group_box_state.set_content_y(row_group_top_offset.value());
float row_top_offset = 0.0f; CSSPixels row_top_offset = 0.0f;
row_group_box.template for_each_child_of_type<TableRowBox>([&](auto& row) { row_group_box.template for_each_child_of_type<TableRowBox>([&](auto& row) {
auto& row_state = m_state.get_mutable(row); auto& row_state = m_state.get_mutable(row);
row_state.set_content_y(row_top_offset); row_state.set_content_y(row_top_offset.value());
row_group_height += row_state.border_box_height(); row_group_height += row_state.border_box_height();
row_group_width = max(row_group_width, row_state.border_box_width()); row_group_width = max(row_group_width, row_state.border_box_width());
row_top_offset += row_state.border_box_height(); row_top_offset += row_state.border_box_height();
@ -325,29 +325,29 @@ void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace cons
row_group_top_offset += row_top_offset; row_group_top_offset += row_top_offset;
row_group_box_state.set_content_height(row_group_height); row_group_box_state.set_content_height(row_group_height.value());
row_group_box_state.set_content_width(row_group_width); row_group_box_state.set_content_width(row_group_width.value());
}); });
for (auto& cell : m_cells) { for (auto& cell : m_cells) {
auto& cell_state = m_state.get_mutable(cell.box); auto& cell_state = m_state.get_mutable(cell.box);
auto& row_state = m_state.get(m_rows[cell.row_index].box); auto& row_state = m_state.get(m_rows[cell.row_index].box);
float const cell_border_box_height = cell_state.content_height() + cell_state.border_box_top() + cell_state.border_box_bottom(); CSSPixels const cell_border_box_height = cell_state.content_height() + cell_state.border_box_top() + cell_state.border_box_bottom();
float const row_content_height = row_state.content_height(); CSSPixels const row_content_height = row_state.content_height();
auto const& vertical_align = cell.box.computed_values().vertical_align(); auto const& vertical_align = cell.box.computed_values().vertical_align();
if (vertical_align.has<CSS::VerticalAlign>()) { if (vertical_align.has<CSS::VerticalAlign>()) {
switch (vertical_align.get<CSS::VerticalAlign>()) { switch (vertical_align.get<CSS::VerticalAlign>()) {
case CSS::VerticalAlign::Middle: { case CSS::VerticalAlign::Middle: {
cell_state.padding_top += (row_content_height - cell_border_box_height) / 2; cell_state.padding_top += ((row_content_height - cell_border_box_height) / 2).value();
cell_state.padding_bottom += (row_content_height - cell_border_box_height) / 2; cell_state.padding_bottom += ((row_content_height - cell_border_box_height) / 2).value();
break; break;
} }
// FIXME: implement actual 'top' and 'bottom' support instead of fall back to 'baseline' // FIXME: implement actual 'top' and 'bottom' support instead of fall back to 'baseline'
case CSS::VerticalAlign::Top: case CSS::VerticalAlign::Top:
case CSS::VerticalAlign::Bottom: case CSS::VerticalAlign::Bottom:
case CSS::VerticalAlign::Baseline: { case CSS::VerticalAlign::Baseline: {
cell_state.padding_top += m_rows[cell.row_index].baseline - cell.baseline; cell_state.padding_top += (m_rows[cell.row_index].baseline - cell.baseline).value();
cell_state.padding_bottom += row_content_height - cell_border_box_height; cell_state.padding_bottom += (row_content_height - cell_border_box_height).value();
break; break;
} }
default: default:
@ -355,10 +355,10 @@ void TableFormattingContext::run(Box const& box, LayoutMode, AvailableSpace cons
} }
} }
cell_state.offset = row_state.offset.translated(cell_state.border_box_left() + m_columns[cell.column_index].left_offset, cell_state.border_box_top()); cell_state.offset = row_state.offset.translated(cell_state.border_box_left() + m_columns[cell.column_index].left_offset.value(), cell_state.border_box_top());
} }
m_state.get_mutable(context_box()).set_content_height(total_content_height); m_state.get_mutable(context_box()).set_content_height(total_content_height.value());
// FIXME: This is a total hack, we should respect the 'height' property. // FIXME: This is a total hack, we should respect the 'height' property.
m_automatic_content_height = total_content_height; m_automatic_content_height = total_content_height;

View file

@ -22,23 +22,23 @@ public:
private: private:
void calculate_row_column_grid(Box const&); void calculate_row_column_grid(Box const&);
void compute_table_measures(); void compute_table_measures();
void compute_table_width(float&); void compute_table_width(CSSPixels&);
void distribute_width_to_columns(float extra_width); void distribute_width_to_columns(CSSPixels extra_width);
void determine_intrisic_size_of_table_container(AvailableSpace const& available_space); void determine_intrisic_size_of_table_container(AvailableSpace const& available_space);
float m_automatic_content_height { 0 }; CSSPixels m_automatic_content_height { 0 };
struct Column { struct Column {
float left_offset { 0 }; CSSPixels left_offset { 0 };
float min_width { 0 }; CSSPixels min_width { 0 };
float max_width { 0 }; CSSPixels max_width { 0 };
float used_width { 0 }; CSSPixels used_width { 0 };
}; };
struct Row { struct Row {
Box& box; Box& box;
float used_width { 0 }; CSSPixels used_width { 0 };
float baseline { 0 }; CSSPixels baseline { 0 };
}; };
struct Cell { struct Cell {
@ -47,7 +47,7 @@ private:
size_t row_index; size_t row_index;
size_t column_span; size_t column_span;
size_t row_span; size_t row_span;
float baseline { 0 }; CSSPixels baseline { 0 };
}; };
Vector<Cell> m_cells; Vector<Cell> m_cells;