| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <LibWeb/DOM/Node.h>
 | 
					
						
							| 
									
										
										
										
											2021-11-18 15:01:28 +01:00
										 |  |  | #include <LibWeb/HTML/BrowsingContext.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/Box.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | #include <LibWeb/Layout/InlineFormattingContext.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/TableBox.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Layout/TableCellBox.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | #include <LibWeb/Layout/TableFormattingContext.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/TableRowBox.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Layout/TableRowGroupBox.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Web::Layout { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-06 21:53:25 +02:00
										 |  |  | TableFormattingContext::TableFormattingContext(BlockContainer& block_container, FormattingContext* parent) | 
					
						
							|  |  |  |     : BlockFormattingContext(block_container, parent) | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TableFormattingContext::~TableFormattingContext() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 19:48:02 +01:00
										 |  |  | void TableFormattingContext::run(Box& box, LayoutMode) | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-12-06 19:48:02 +01:00
										 |  |  |     compute_width(box); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 14:41:01 +02:00
										 |  |  |     float total_content_width = 0; | 
					
						
							| 
									
										
										
										
											2020-11-29 22:37:15 +01:00
										 |  |  |     float total_content_height = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 19:48:02 +01:00
										 |  |  |     box.for_each_child_of_type<TableRowGroupBox>([&](auto& row_group_box) { | 
					
						
							|  |  |  |         compute_width(row_group_box); | 
					
						
							|  |  |  |         auto column_count = row_group_box.column_count(); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         Vector<float> column_widths; | 
					
						
							|  |  |  |         column_widths.resize(column_count); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 19:48:02 +01:00
										 |  |  |         row_group_box.template for_each_child_of_type<TableRowBox>([&](auto& row) { | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |             calculate_column_widths(row, column_widths); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 14:41:01 +02:00
										 |  |  |         float content_width = 0; | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         float content_height = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 19:48:02 +01:00
										 |  |  |         row_group_box.template for_each_child_of_type<TableRowBox>([&](auto& row) { | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |             row.set_offset(0, content_height); | 
					
						
							|  |  |  |             layout_row(row, column_widths); | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |             content_width = max(content_width, row.content_width()); | 
					
						
							|  |  |  |             content_height += row.content_height(); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-18 15:10:11 +00:00
										 |  |  |         if (row_group_box.computed_values().width().has_value() && row_group_box.computed_values().width()->is_length() && row_group_box.computed_values().width()->length().is_auto()) | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |             row_group_box.set_content_width(content_width); | 
					
						
							|  |  |  |         row_group_box.set_content_height(content_height); | 
					
						
							| 
									
										
										
										
											2020-11-29 22:37:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-18 18:24:23 +01:00
										 |  |  |         row_group_box.set_offset(0, total_content_height); | 
					
						
							| 
									
										
										
										
											2020-11-29 22:37:15 +01:00
										 |  |  |         total_content_height += content_height; | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |         total_content_width = max(total_content_width, row_group_box.content_width()); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-18 15:10:11 +00:00
										 |  |  |     if (box.computed_values().width().has_value() && box.computed_values().width()->is_length() && box.computed_values().width()->length().is_auto()) | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |         box.set_content_width(total_content_width); | 
					
						
							| 
									
										
										
										
											2021-10-28 14:41:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-29 22:37:15 +01:00
										 |  |  |     // FIXME: This is a total hack, we should respect the 'height' property.
 | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |     box.set_content_height(total_content_height); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | void TableFormattingContext::calculate_column_widths(Box& row, Vector<float>& column_widths) | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     size_t column_index = 0; | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |     auto* table = row.first_ancestor_of_type<TableBox>(); | 
					
						
							| 
									
										
										
										
											2022-02-18 15:10:11 +00:00
										 |  |  |     bool use_auto_layout = !table || (!table->computed_values().width().has_value() || (table->computed_values().width()->is_length() && table->computed_values().width()->length().is_undefined_or_auto())); | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |     row.for_each_child_of_type<TableCellBox>([&](auto& cell) { | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         compute_width(cell); | 
					
						
							|  |  |  |         if (use_auto_layout) { | 
					
						
							| 
									
										
										
										
											2021-12-02 12:54:34 +00:00
										 |  |  |             (void)layout_inside(cell, LayoutMode::OnlyRequiredLineBreaks); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-12-02 12:54:34 +00:00
										 |  |  |             (void)layout_inside(cell, LayoutMode::Default); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |         column_widths[column_index] = max(column_widths[column_index], cell.content_width()); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         column_index += cell.colspan(); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | void TableFormattingContext::layout_row(Box& row, Vector<float>& column_widths) | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     size_t column_index = 0; | 
					
						
							|  |  |  |     float tallest_cell_height = 0; | 
					
						
							|  |  |  |     float content_width = 0; | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |     auto* table = row.first_ancestor_of_type<TableBox>(); | 
					
						
							| 
									
										
										
										
											2022-02-18 15:10:11 +00:00
										 |  |  |     bool use_auto_layout = !table || (!table->computed_values().width().has_value() || (table->computed_values().width()->is_length() && table->computed_values().width()->length().is_undefined_or_auto())); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |     row.for_each_child_of_type<TableCellBox>([&](auto& cell) { | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         cell.set_offset(row.effective_offset().translated(content_width, 0)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Layout the cell contents a second time, now that we know its final width.
 | 
					
						
							|  |  |  |         if (use_auto_layout) { | 
					
						
							| 
									
										
										
										
											2021-12-02 12:54:34 +00:00
										 |  |  |             (void)layout_inside(cell, LayoutMode::OnlyRequiredLineBreaks); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-12-02 12:54:34 +00:00
										 |  |  |             (void)layout_inside(cell, LayoutMode::Default); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         size_t cell_colspan = cell.colspan(); | 
					
						
							|  |  |  |         for (size_t i = 0; i < cell_colspan; ++i) | 
					
						
							|  |  |  |             content_width += column_widths[column_index++]; | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |         tallest_cell_height = max(tallest_cell_height, cell.content_height()); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (use_auto_layout) { | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |         row.set_content_width(content_width); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |         row.set_content_width(table->content_width()); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |     row.set_content_height(tallest_cell_height); | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |