| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <LibWeb/Layout/LineBuilder.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Layout/TextNode.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Web::Layout { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 14:39:07 +01:00
										 |  |  | LineBuilder::LineBuilder(InlineFormattingContext& context, FormattingState& formatting_state, LayoutMode layout_mode) | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  |     : m_context(context) | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     , m_formatting_state(formatting_state) | 
					
						
							| 
									
										
										
										
											2022-02-21 17:42:09 +01:00
										 |  |  |     , m_containing_block_state(formatting_state.get_mutable(context.containing_block())) | 
					
						
							| 
									
										
										
										
											2022-03-18 14:39:07 +01:00
										 |  |  |     , m_layout_mode(layout_mode) | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-23 01:34:26 +01:00
										 |  |  |     begin_new_line(false); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | LineBuilder::~LineBuilder() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-22 10:32:49 +01:00
										 |  |  |     if (m_last_line_needs_update) | 
					
						
							|  |  |  |         update_last_line(); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void LineBuilder::break_line() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     update_last_line(); | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     m_containing_block_state.line_boxes.append(LineBox()); | 
					
						
							| 
									
										
										
										
											2022-01-23 01:34:26 +01:00
										 |  |  |     begin_new_line(true); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-23 01:34:26 +01:00
										 |  |  | void LineBuilder::begin_new_line(bool increment_y) | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-23 01:34:26 +01:00
										 |  |  |     if (increment_y) | 
					
						
							|  |  |  |         m_current_y += max(m_max_height_on_current_line, m_context.containing_block().line_height()); | 
					
						
							| 
									
										
										
										
											2022-03-18 14:44:36 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (m_layout_mode) { | 
					
						
							| 
									
										
										
										
											2022-03-19 15:44:02 +01:00
										 |  |  |     case LayoutMode::Normal: | 
					
						
							| 
									
										
										
										
											2022-03-18 14:44:36 +01:00
										 |  |  |         m_available_width_for_current_line = m_context.available_space_for_line(m_current_y); | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2022-03-19 15:44:02 +01:00
										 |  |  |     case LayoutMode::MinContent: | 
					
						
							| 
									
										
										
										
											2022-03-18 14:44:36 +01:00
										 |  |  |         m_available_width_for_current_line = 0; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2022-03-19 15:44:02 +01:00
										 |  |  |     case LayoutMode::MaxContent: | 
					
						
							| 
									
										
										
										
											2022-03-18 14:44:36 +01:00
										 |  |  |         m_available_width_for_current_line = INFINITY; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  |     m_max_height_on_current_line = 0; | 
					
						
							| 
									
										
										
										
											2022-01-22 10:32:49 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     m_last_line_needs_update = true; | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  | LineBox& LineBuilder::ensure_last_line_box() | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     auto& line_boxes = m_containing_block_state.line_boxes; | 
					
						
							|  |  |  |     if (line_boxes.is_empty()) | 
					
						
							|  |  |  |         line_boxes.append(LineBox {}); | 
					
						
							|  |  |  |     return line_boxes.last(); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 18:46:07 +01:00
										 |  |  | void LineBuilder::append_box(Box const& box, float leading_size, float trailing_size, float leading_margin, float trailing_margin) | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-28 12:41:23 +01:00
										 |  |  |     auto& box_state = m_formatting_state.get_mutable(box); | 
					
						
							| 
									
										
										
										
											2022-02-27 10:26:38 +01:00
										 |  |  |     auto& line_box = ensure_last_line_box(); | 
					
						
							| 
									
										
										
										
											2022-03-09 18:46:07 +01:00
										 |  |  |     line_box.add_fragment(box, 0, 0, leading_size, trailing_size, leading_margin, trailing_margin, box_state.content_width, box_state.content_height, box_state.border_box_top(), box_state.border_box_bottom()); | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |     m_max_height_on_current_line = max(m_max_height_on_current_line, box_state.border_box_height()); | 
					
						
							| 
									
										
										
										
											2022-02-27 10:26:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-28 12:41:23 +01:00
										 |  |  |     box_state.containing_line_box_fragment = LineBoxFragmentCoordinate { | 
					
						
							| 
									
										
										
										
											2022-02-27 10:26:38 +01:00
										 |  |  |         .line_box_index = m_containing_block_state.line_boxes.size() - 1, | 
					
						
							|  |  |  |         .fragment_index = line_box.fragments().size() - 1, | 
					
						
							| 
									
										
										
										
											2022-02-28 12:41:23 +01:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 18:46:07 +01:00
										 |  |  | void LineBuilder::append_text_chunk(TextNode const& text_node, size_t offset_in_node, size_t length_in_node, float leading_size, float trailing_size, float leading_margin, float trailing_margin, float content_width, float content_height) | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-09 18:46:07 +01:00
										 |  |  |     ensure_last_line_box().add_fragment(text_node, offset_in_node, length_in_node, leading_size, trailing_size, leading_margin, trailing_margin, content_width, content_height, 0, 0); | 
					
						
							| 
									
										
										
										
											2022-02-14 15:52:29 +01:00
										 |  |  |     m_max_height_on_current_line = max(m_max_height_on_current_line, content_height); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 18:59:54 +01:00
										 |  |  | bool LineBuilder::should_break(LayoutMode layout_mode, float next_item_width) | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-19 15:44:02 +01:00
										 |  |  |     if (layout_mode == LayoutMode::MinContent) | 
					
						
							| 
									
										
										
										
											2022-01-20 16:19:05 +01:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2022-03-19 15:44:02 +01:00
										 |  |  |     if (layout_mode == LayoutMode::MaxContent) | 
					
						
							| 
									
										
										
										
											2022-01-20 16:19:05 +01:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     auto const& line_boxes = m_containing_block_state.line_boxes; | 
					
						
							| 
									
										
										
										
											2022-01-22 10:32:49 +01:00
										 |  |  |     if (line_boxes.is_empty() || line_boxes.last().is_empty()) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     auto current_line_width = line_boxes.last().width(); | 
					
						
							| 
									
										
										
										
											2022-01-20 16:19:05 +01:00
										 |  |  |     return (current_line_width + next_item_width) > m_available_width_for_current_line; | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  | static float box_baseline(FormattingState const& state, Box const& box) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto const& box_state = state.get(box); | 
					
						
							| 
									
										
										
										
											2022-03-24 22:56:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto const& vertical_align = box.computed_values().vertical_align(); | 
					
						
							|  |  |  |     if (vertical_align.has<CSS::VerticalAlign>()) { | 
					
						
							|  |  |  |         switch (vertical_align.get<CSS::VerticalAlign>()) { | 
					
						
							|  |  |  |         case CSS::VerticalAlign::Top: | 
					
						
							|  |  |  |             return box_state.border_box_top(); | 
					
						
							|  |  |  |         case CSS::VerticalAlign::Bottom: | 
					
						
							|  |  |  |             return box_state.content_height + box_state.border_box_bottom(); | 
					
						
							|  |  |  |         default: | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |     if (!box_state.line_boxes.is_empty()) | 
					
						
							| 
									
										
										
										
											2022-03-24 12:36:16 +01:00
										 |  |  |         return box_state.border_box_top() + box_state.offset.y() + box_state.line_boxes.last().baseline(); | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |     if (box.has_children() && !box.children_are_inline()) { | 
					
						
							|  |  |  |         auto const* child_box = box.last_child_of_type<Box>(); | 
					
						
							|  |  |  |         VERIFY(child_box); | 
					
						
							|  |  |  |         return box_baseline(state, *child_box); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return box_state.border_box_height(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | void LineBuilder::update_last_line() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-01-22 10:32:49 +01:00
										 |  |  |     m_last_line_needs_update = false; | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     auto& line_boxes = m_containing_block_state.line_boxes; | 
					
						
							| 
									
										
										
										
											2022-01-22 10:32:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     if (line_boxes.is_empty()) | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     auto& line_box = line_boxes.last(); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto text_align = m_context.containing_block().computed_values().text_align(); | 
					
						
							| 
									
										
										
										
											2022-03-18 14:44:36 +01:00
										 |  |  |     float x_offset = m_context.leftmost_x_offset_at(m_current_y); | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     float excess_horizontal_space = m_containing_block_state.content_width - line_box.width(); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     switch (text_align) { | 
					
						
							|  |  |  |     case CSS::TextAlign::Center: | 
					
						
							|  |  |  |     case CSS::TextAlign::LibwebCenter: | 
					
						
							|  |  |  |         x_offset += excess_horizontal_space / 2; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case CSS::TextAlign::Right: | 
					
						
							|  |  |  |         x_offset += excess_horizontal_space; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     case CSS::TextAlign::Left: | 
					
						
							|  |  |  |     case CSS::TextAlign::Justify: | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |     auto fragment_baseline = [&](auto const& fragment) -> float { | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  |         float fragment_baseline = 0; | 
					
						
							|  |  |  |         if (fragment.layout_node().is_text_node()) { | 
					
						
							|  |  |  |             fragment_baseline = fragment.layout_node().font().baseline(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             auto const& box = verify_cast<Layout::Box>(fragment.layout_node()); | 
					
						
							|  |  |  |             fragment_baseline = box_baseline(m_formatting_state, box); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return fragment_baseline; | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2022-02-26 09:29:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |     auto line_box_baseline = [&] { | 
					
						
							|  |  |  |         float line_box_baseline = 0; | 
					
						
							|  |  |  |         for (auto const& fragment : line_box.fragments()) { | 
					
						
							|  |  |  |             auto baseline = fragment_baseline(fragment); | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  |             if (fragment.height() < m_context.containing_block().line_height()) | 
					
						
							|  |  |  |                 baseline += (m_context.containing_block().line_height() - fragment.height()) / 2; | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |             // NOTE: For fragments with a <length> vertical-align, shift the fragment baseline down by the length.
 | 
					
						
							|  |  |  |             //       This ensures that we make enough vertical space on the line for any manually-aligned fragments.
 | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  |             if (auto length_percentage = fragment.layout_node().computed_values().vertical_align().template get_pointer<CSS::LengthPercentage>(); length_percentage && length_percentage->is_length()) | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |                 baseline += length_percentage->length().to_px(fragment.layout_node()); | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |             line_box_baseline = max(line_box_baseline, baseline); | 
					
						
							| 
									
										
										
										
											2022-02-26 09:29:51 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |         return line_box_baseline; | 
					
						
							|  |  |  |     }(); | 
					
						
							| 
									
										
										
										
											2022-01-21 13:19:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  |     // Start with the "strut", an imaginary zero-width box at the start of each line box.
 | 
					
						
							|  |  |  |     auto strut_top = m_current_y; | 
					
						
							|  |  |  |     auto strut_bottom = m_current_y + m_context.containing_block().line_height(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     float uppermost_box_top = strut_top; | 
					
						
							|  |  |  |     float lowermost_box_bottom = strut_bottom; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  |     for (size_t i = 0; i < line_box.fragments().size(); ++i) { | 
					
						
							|  |  |  |         auto& fragment = line_box.fragments()[i]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-25 11:34:11 +01:00
										 |  |  |         float new_fragment_x = roundf(x_offset + fragment.offset().x()); | 
					
						
							| 
									
										
										
										
											2022-02-26 09:29:51 +01:00
										 |  |  |         float new_fragment_y = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |         auto y_value_for_alignment = [&](CSS::VerticalAlign vertical_align) { | 
					
						
							|  |  |  |             switch (vertical_align) { | 
					
						
							|  |  |  |             case CSS::VerticalAlign::Baseline: | 
					
						
							| 
									
										
										
										
											2022-03-24 22:56:06 +01:00
										 |  |  |                 return m_current_y + line_box_baseline - fragment_baseline(fragment) + fragment.border_box_top(); | 
					
						
							|  |  |  |             case CSS::VerticalAlign::Top: | 
					
						
							|  |  |  |                 return m_current_y + fragment.border_box_top(); | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |             case CSS::VerticalAlign::Middle: | 
					
						
							| 
									
										
										
										
											2022-03-24 22:56:06 +01:00
										 |  |  |             case CSS::VerticalAlign::Bottom: | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |             case CSS::VerticalAlign::Sub: | 
					
						
							|  |  |  |             case CSS::VerticalAlign::Super: | 
					
						
							|  |  |  |             case CSS::VerticalAlign::TextBottom: | 
					
						
							|  |  |  |             case CSS::VerticalAlign::TextTop: | 
					
						
							|  |  |  |                 // FIXME: These are all 'baseline'
 | 
					
						
							|  |  |  |                 return m_current_y + line_box_baseline - fragment_baseline(fragment) + fragment.border_box_top(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             VERIFY_NOT_REACHED(); | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         auto const& vertical_align = fragment.layout_node().computed_values().vertical_align(); | 
					
						
							|  |  |  |         if (vertical_align.has<CSS::VerticalAlign>()) { | 
					
						
							|  |  |  |             new_fragment_y = y_value_for_alignment(vertical_align.get<CSS::VerticalAlign>()); | 
					
						
							| 
									
										
										
										
											2022-02-26 09:29:51 +01:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |             if (auto length_percentage = vertical_align.get_pointer<CSS::LengthPercentage>(); length_percentage && length_percentage->is_length()) { | 
					
						
							|  |  |  |                 auto vertical_align_amount = length_percentage->length().to_px(fragment.layout_node()); | 
					
						
							|  |  |  |                 new_fragment_y = y_value_for_alignment(CSS::VerticalAlign::Baseline) - vertical_align_amount; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-02-26 09:29:51 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-25 11:34:11 +01:00
										 |  |  |         fragment.set_offset({ new_fragment_x, new_fragment_y }); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  |         uppermost_box_top = min(uppermost_box_top, fragment.top_of_inline_level_box(m_formatting_state)); | 
					
						
							|  |  |  |         lowermost_box_bottom = max(lowermost_box_bottom, fragment.bottom_of_inline_level_box(m_formatting_state)); | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-24 22:45:51 +01:00
										 |  |  |     // 3. The line box height is the distance between the uppermost box top and the lowermost box bottom.
 | 
					
						
							|  |  |  |     line_box.m_height = max(m_context.containing_block().line_height(), lowermost_box_bottom - uppermost_box_top); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     line_box.m_bottom = m_current_y + line_box.m_height; | 
					
						
							| 
									
										
										
										
											2022-03-03 10:09:10 +01:00
										 |  |  |     line_box.m_baseline = line_box_baseline; | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-22 10:32:49 +01:00
										 |  |  | void LineBuilder::remove_last_line_if_empty() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // If there's an empty line box at the bottom, just remove it instead of giving it height.
 | 
					
						
							| 
									
										
										
										
											2022-02-20 15:51:24 +01:00
										 |  |  |     auto& line_boxes = m_containing_block_state.line_boxes; | 
					
						
							| 
									
										
										
										
											2022-01-22 10:32:49 +01:00
										 |  |  |     if (!line_boxes.is_empty() && line_boxes.last().fragments().is_empty()) { | 
					
						
							|  |  |  |         line_boxes.take_last(); | 
					
						
							|  |  |  |         m_last_line_needs_update = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-03-22 19:18:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | void LineBuilder::adjust_last_line_after_inserting_floating_box(Badge<BlockFormattingContext>, CSS::Float float_, float space_used_by_float) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // NOTE: LineBuilder generates lines from left-to-right, so if we've just added a left-side float,
 | 
					
						
							|  |  |  |     //       that means every fragment already on this line has to move towards the right.
 | 
					
						
							|  |  |  |     if (float_ == CSS::Float::Left && !m_containing_block_state.line_boxes.is_empty()) { | 
					
						
							|  |  |  |         for (auto& fragment : m_containing_block_state.line_boxes.last().fragments()) | 
					
						
							|  |  |  |             fragment.set_offset(fragment.offset().translated(space_used_by_float, 0)); | 
					
						
							|  |  |  |         m_containing_block_state.line_boxes.last().m_width += space_used_by_float; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     m_available_width_for_current_line -= space_used_by_float; | 
					
						
							|  |  |  |     if (m_available_width_for_current_line < 0) | 
					
						
							|  |  |  |         m_available_width_for_current_line = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 11:57:58 +01:00
										 |  |  | } |