| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  | /*
 | 
					
						
							|  |  |  |  |  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | 
					
						
							| 
									
										
										
										
											2021-09-15 12:19:42 +01:00
										 |  |  |  |  * Copyright (c) 2021, Sam Atkins <atkinssj@serenityos.org> | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  |  */ | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-10 08:25:35 +01:00
										 |  |  |  | #include <LibGfx/Painter.h>
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:32:51 +01:00
										 |  |  |  | #include <LibWeb/DOM/Document.h>
 | 
					
						
							| 
									
										
										
										
											2021-11-18 15:01:28 +01:00
										 |  |  |  | #include <LibWeb/HTML/BrowsingContext.h>
 | 
					
						
							| 
									
										
										
										
											2020-07-26 15:08:16 +02:00
										 |  |  |  | #include <LibWeb/HTML/HTMLBodyElement.h>
 | 
					
						
							| 
									
										
										
										
											2021-05-13 09:39:30 -04:00
										 |  |  |  | #include <LibWeb/HTML/HTMLHtmlElement.h>
 | 
					
						
							| 
									
										
										
										
											2021-10-06 20:02:41 +02:00
										 |  |  |  | #include <LibWeb/Layout/BlockContainer.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | #include <LibWeb/Layout/Box.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-15 12:19:42 +01:00
										 |  |  |  | #include <LibWeb/Layout/FormattingContext.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-19 15:58:26 +01:00
										 |  |  |  | #include <LibWeb/Painting/BackgroundPainting.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-04 18:02:21 +01:00
										 |  |  |  | #include <LibWeb/Painting/BorderPainting.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-19 15:00:47 +01:00
										 |  |  |  | #include <LibWeb/Painting/ShadowPainting.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | namespace Web::Layout { | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | void Box::paint(PaintContext& context, PaintPhase phase) | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-15 19:12:12 +02:00
										 |  |  |  |     if (!is_visible()) | 
					
						
							|  |  |  |  |         return; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-13 09:39:30 -04:00
										 |  |  |  |     if (phase == PaintPhase::Background) { | 
					
						
							| 
									
										
										
										
											2021-05-15 20:54:01 +02:00
										 |  |  |  |         paint_background(context); | 
					
						
							| 
									
										
										
										
											2021-07-23 21:31:31 +02:00
										 |  |  |  |         paint_box_shadow(context); | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-18 18:57:35 +02:00
										 |  |  |  |     if (phase == PaintPhase::Border) { | 
					
						
							| 
									
										
										
										
											2021-04-20 13:39:36 +02:00
										 |  |  |  |         paint_border(context); | 
					
						
							| 
									
										
										
										
											2020-06-18 18:57:35 +02:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-15 19:12:12 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 14:46:36 +01:00
										 |  |  |  |     if (phase == PaintPhase::Overlay && dom_node() && document().inspected_node() == dom_node()) { | 
					
						
							| 
									
										
										
										
											2020-06-25 15:15:01 +02:00
										 |  |  |  |         auto content_rect = absolute_rect(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-12 21:02:06 +01:00
										 |  |  |  |         auto margin_box = box_model().margin_box(); | 
					
						
							| 
									
										
										
										
											2020-06-25 15:15:01 +02:00
										 |  |  |  |         Gfx::FloatRect margin_rect; | 
					
						
							|  |  |  |  |         margin_rect.set_x(absolute_x() - margin_box.left); | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |  |         margin_rect.set_width(content_width() + margin_box.left + margin_box.right); | 
					
						
							| 
									
										
										
										
											2020-06-25 15:15:01 +02:00
										 |  |  |  |         margin_rect.set_y(absolute_y() - margin_box.top); | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |  |         margin_rect.set_height(content_height() + margin_box.top + margin_box.bottom); | 
					
						
							| 
									
										
										
										
											2020-06-25 15:15:01 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-26 08:18:14 +01:00
										 |  |  |  |         auto border_rect = absolute_border_box_rect(); | 
					
						
							|  |  |  |  |         auto padding_rect = absolute_padding_box_rect(); | 
					
						
							| 
									
										
										
										
											2022-02-18 00:54:55 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-26 08:18:14 +01:00
										 |  |  |  |         auto paint_inspector_rect = [&](Gfx::FloatRect const& rect, Color color) { | 
					
						
							|  |  |  |  |             context.painter().fill_rect(enclosing_int_rect(rect), Color(color).with_alpha(100)); | 
					
						
							|  |  |  |  |             context.painter().draw_rect(enclosing_int_rect(rect), Color(color)); | 
					
						
							|  |  |  |  |         }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         paint_inspector_rect(margin_rect, Color::Yellow); | 
					
						
							|  |  |  |  |         paint_inspector_rect(padding_rect, Color::Cyan); | 
					
						
							|  |  |  |  |         paint_inspector_rect(border_rect, Color::Green); | 
					
						
							|  |  |  |  |         paint_inspector_rect(content_rect, Color::Magenta); | 
					
						
							| 
									
										
										
										
											2022-02-18 00:54:55 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-26 08:18:14 +01:00
										 |  |  |  |         StringBuilder builder; | 
					
						
							|  |  |  |  |         if (dom_node()) | 
					
						
							|  |  |  |  |             builder.append(dom_node()->debug_description()); | 
					
						
							|  |  |  |  |         else | 
					
						
							|  |  |  |  |             builder.append(debug_description()); | 
					
						
							|  |  |  |  |         builder.appendff(" {}x{} @ {},{}", border_rect.width(), border_rect.height(), border_rect.x(), border_rect.y()); | 
					
						
							|  |  |  |  |         auto size_text = builder.to_string(); | 
					
						
							|  |  |  |  |         auto size_text_rect = border_rect; | 
					
						
							|  |  |  |  |         size_text_rect.set_y(border_rect.y() + border_rect.height()); | 
					
						
							|  |  |  |  |         size_text_rect.set_top(size_text_rect.top()); | 
					
						
							|  |  |  |  |         size_text_rect.set_width((float)context.painter().font().width(size_text) + 4); | 
					
						
							|  |  |  |  |         size_text_rect.set_height(context.painter().font().glyph_height() + 4); | 
					
						
							|  |  |  |  |         context.painter().fill_rect(enclosing_int_rect(size_text_rect), context.palette().color(Gfx::ColorRole::Tooltip)); | 
					
						
							|  |  |  |  |         context.painter().draw_rect(enclosing_int_rect(size_text_rect), context.palette().threed_shadow1()); | 
					
						
							|  |  |  |  |         context.painter().draw_text(enclosing_int_rect(size_text_rect), size_text, Gfx::TextAlignment::Center, context.palette().color(Gfx::ColorRole::TooltipText)); | 
					
						
							| 
									
										
										
										
											2020-06-25 15:15:01 +02:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-14 19:40:37 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-24 19:53:42 +02:00
										 |  |  |  |     if (phase == PaintPhase::FocusOutline && dom_node() && dom_node()->is_element() && verify_cast<DOM::Element>(*dom_node()).is_focused()) { | 
					
						
							| 
									
										
										
										
											2020-08-14 19:40:37 +02:00
										 |  |  |  |         context.painter().draw_rect(enclosing_int_rect(absolute_rect()), context.palette().focus_outline()); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-20 13:39:36 +02:00
										 |  |  |  | void Box::paint_border(PaintContext& context) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-19 20:47:58 +01:00
										 |  |  |  |     auto borders_data = Painting::BordersData { | 
					
						
							|  |  |  |  |         .top = computed_values().border_top(), | 
					
						
							|  |  |  |  |         .right = computed_values().border_right(), | 
					
						
							|  |  |  |  |         .bottom = computed_values().border_bottom(), | 
					
						
							|  |  |  |  |         .left = computed_values().border_left(), | 
					
						
							| 
									
										
										
										
											2021-05-15 00:45:33 +02:00
										 |  |  |  |     }; | 
					
						
							| 
									
										
										
										
											2022-02-11 21:57:56 +01:00
										 |  |  |  |     Painting::paint_all_borders(context, absolute_border_box_rect(), normalized_border_radius_data(), borders_data); | 
					
						
							| 
									
										
										
										
											2021-04-20 13:39:36 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-15 20:54:01 +02:00
										 |  |  |  | void Box::paint_background(PaintContext& context) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     // If the body's background properties were propagated to the root element, do no re-paint the body's background.
 | 
					
						
							|  |  |  |  |     if (is_body() && document().html_element()->should_use_body_background_properties()) | 
					
						
							|  |  |  |  |         return; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-16 20:03:04 +02:00
										 |  |  |  |     Gfx::IntRect background_rect; | 
					
						
							| 
									
										
										
										
											2021-05-15 20:54:01 +02:00
										 |  |  |  |     Color background_color = computed_values().background_color(); | 
					
						
							| 
									
										
										
										
											2021-11-12 12:11:01 +00:00
										 |  |  |  |     auto* background_layers = &computed_values().background_layers(); | 
					
						
							| 
									
										
										
										
											2021-05-15 20:54:01 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  |     if (is_root_element()) { | 
					
						
							|  |  |  |  |         // CSS 2.1 Appendix E.2: If the element is a root element, paint the background over the entire canvas.
 | 
					
						
							|  |  |  |  |         background_rect = context.viewport_rect(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |         // Section 2.11.2: If the computed value of background-image on the root element is none and its background-color is transparent,
 | 
					
						
							|  |  |  |  |         // user agents must instead propagate the computed values of the background properties from that element’s first HTML BODY child element.
 | 
					
						
							|  |  |  |  |         if (document().html_element()->should_use_body_background_properties()) { | 
					
						
							| 
									
										
										
										
											2021-11-12 12:11:01 +00:00
										 |  |  |  |             background_layers = document().background_layers(); | 
					
						
							| 
									
										
										
										
											2021-05-15 20:54:01 +02:00
										 |  |  |  |             background_color = document().background_color(context.palette()); | 
					
						
							|  |  |  |  |         } | 
					
						
							|  |  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-02-11 21:57:56 +01:00
										 |  |  |  |         background_rect = enclosing_int_rect(absolute_padding_box_rect()); | 
					
						
							| 
									
										
										
										
											2021-05-15 20:54:01 +02:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-16 20:03:04 +02:00
										 |  |  |  |     // HACK: If the Box has a border, use the bordered_rect to paint the background.
 | 
					
						
							|  |  |  |  |     //       This way if we have a border-radius there will be no gap between the filling and actual border.
 | 
					
						
							|  |  |  |  |     if (computed_values().border_top().width || computed_values().border_right().width || computed_values().border_bottom().width || computed_values().border_left().width) | 
					
						
							| 
									
										
										
										
											2022-02-11 21:57:56 +01:00
										 |  |  |  |         background_rect = enclosing_int_rect(absolute_border_box_rect()); | 
					
						
							| 
									
										
										
										
											2021-05-16 20:03:04 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-12 20:12:56 +00:00
										 |  |  |  |     Painting::paint_background(context, *this, background_rect, background_color, background_layers, normalized_border_radius_data()); | 
					
						
							| 
									
										
										
										
											2021-04-04 18:04:38 -04:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 21:31:31 +02:00
										 |  |  |  | void Box::paint_box_shadow(PaintContext& context) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     auto box_shadow_data = computed_values().box_shadow(); | 
					
						
							| 
									
										
										
										
											2022-02-08 14:48:37 +00:00
										 |  |  |  |     if (box_shadow_data.is_empty()) | 
					
						
							| 
									
										
										
										
											2021-07-23 21:31:31 +02:00
										 |  |  |  |         return; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-08 14:48:37 +00:00
										 |  |  |  |     Vector<Painting::BoxShadowData> resolved_box_shadow_data; | 
					
						
							|  |  |  |  |     resolved_box_shadow_data.ensure_capacity(box_shadow_data.size()); | 
					
						
							|  |  |  |  |     for (auto const& layer : box_shadow_data) { | 
					
						
							|  |  |  |  |         resolved_box_shadow_data.empend( | 
					
						
							| 
									
										
										
										
											2022-02-08 15:33:27 +00:00
										 |  |  |  |             layer.color, | 
					
						
							| 
									
										
										
										
											2022-02-18 16:27:28 +00:00
										 |  |  |  |             static_cast<int>(layer.offset_x.to_px(*this)), | 
					
						
							|  |  |  |  |             static_cast<int>(layer.offset_y.to_px(*this)), | 
					
						
							|  |  |  |  |             static_cast<int>(layer.blur_radius.to_px(*this)), | 
					
						
							|  |  |  |  |             static_cast<int>(layer.spread_distance.to_px(*this)), | 
					
						
							| 
									
										
										
										
											2022-02-08 15:33:27 +00:00
										 |  |  |  |             layer.placement == CSS::BoxShadowPlacement::Outer ? Painting::BoxShadowPlacement::Outer : Painting::BoxShadowPlacement::Inner); | 
					
						
							| 
									
										
										
										
											2022-02-08 14:48:37 +00:00
										 |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-02-11 21:57:56 +01:00
										 |  |  |  |     Painting::paint_box_shadow(context, enclosing_int_rect(absolute_border_box_rect()), resolved_box_shadow_data); | 
					
						
							| 
									
										
										
										
											2021-07-23 21:31:31 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-19 17:46:28 +01:00
										 |  |  |  | Painting::BorderRadiusData Box::normalized_border_radius_data() | 
					
						
							| 
									
										
										
										
											2021-05-16 00:15:37 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-11 21:57:56 +01:00
										 |  |  |  |     return Painting::normalized_border_radius_data(*this, absolute_border_box_rect(), | 
					
						
							| 
									
										
										
										
											2021-09-19 17:46:28 +01:00
										 |  |  |  |         computed_values().border_top_left_radius(), | 
					
						
							|  |  |  |  |         computed_values().border_top_right_radius(), | 
					
						
							|  |  |  |  |         computed_values().border_bottom_right_radius(), | 
					
						
							|  |  |  |  |         computed_values().border_bottom_left_radius()); | 
					
						
							| 
									
										
										
										
											2021-05-16 00:15:37 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-15 12:19:42 +01:00
										 |  |  |  | // https://www.w3.org/TR/css-display-3/#out-of-flow
 | 
					
						
							|  |  |  |  | bool Box::is_out_of_flow(FormattingContext const& formatting_context) const | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     // A box is out of flow if either:
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 1. It is floated (which requires that floating is not inhibited).
 | 
					
						
							|  |  |  |  |     if (!formatting_context.inhibits_floating() && computed_values().float_() != CSS::Float::None) | 
					
						
							|  |  |  |  |         return true; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     // 2. It is "absolutely positioned".
 | 
					
						
							|  |  |  |  |     switch (computed_values().position()) { | 
					
						
							|  |  |  |  |     case CSS::Position::Absolute: | 
					
						
							|  |  |  |  |     case CSS::Position::Fixed: | 
					
						
							|  |  |  |  |         return true; | 
					
						
							|  |  |  |  |     case CSS::Position::Static: | 
					
						
							|  |  |  |  |     case CSS::Position::Relative: | 
					
						
							|  |  |  |  |     case CSS::Position::Sticky: | 
					
						
							|  |  |  |  |         break; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  |     return false; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | HitTestResult Box::hit_test(const Gfx::IntPoint& position, HitTestType type) const | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |     // FIXME: It would be nice if we could confidently skip over hit testing
 | 
					
						
							|  |  |  |  |     //        parts of the layout tree, but currently we can't just check
 | 
					
						
							|  |  |  |  |     //        m_rect.contains() since inline text rects can't be trusted..
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  |     HitTestResult result { absolute_rect().contains(position.x(), position.y()) ? this : nullptr }; | 
					
						
							| 
									
										
										
										
											2020-12-06 19:59:28 +01:00
										 |  |  |  |     for_each_child_in_paint_order([&](auto& child) { | 
					
						
							| 
									
										
										
										
											2020-08-05 16:55:56 +02:00
										 |  |  |  |         auto child_result = child.hit_test(position, type); | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  |         if (child_result.layout_node) | 
					
						
							|  |  |  |  |             result = child_result; | 
					
						
							|  |  |  |  |     }); | 
					
						
							|  |  |  |  |     return result; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | void Box::set_needs_display() | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |     if (!is_inline()) { | 
					
						
							| 
									
										
										
										
											2021-05-30 12:36:53 +02:00
										 |  |  |  |         browsing_context().set_needs_display(enclosing_int_rect(absolute_rect())); | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  |         return; | 
					
						
							|  |  |  |  |     } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  |     Node::set_needs_display(); | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-19 11:49:46 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | bool Box::is_body() const | 
					
						
							| 
									
										
										
										
											2019-10-19 11:49:46 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-22 14:46:36 +01:00
										 |  |  |  |     return dom_node() && dom_node() == document().body(); | 
					
						
							| 
									
										
										
										
											2019-10-19 11:49:46 +02:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | void Box::set_offset(const Gfx::FloatPoint& offset) | 
					
						
							| 
									
										
										
										
											2020-06-05 19:13:27 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  |     if (m_offset == offset) | 
					
						
							| 
									
										
										
										
											2020-06-05 19:13:27 +02:00
										 |  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  |     m_offset = offset; | 
					
						
							| 
									
										
										
										
											2020-06-05 19:13:27 +02:00
										 |  |  |  |     did_set_rect(); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |  | void Box::set_content_size(Gfx::FloatSize const& size) | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |  |     if (m_content_size == size) | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  |         return; | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |  |     m_content_size = size; | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  |     did_set_rect(); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | Gfx::FloatPoint Box::effective_offset() const | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-27 10:26:38 +01:00
										 |  |  |  |     if (m_containing_line_box_fragment.has_value()) { | 
					
						
							|  |  |  |  |         auto const& fragment = containing_block()->line_boxes()[m_containing_line_box_fragment->line_box_index].fragments()[m_containing_line_box_fragment->fragment_index]; | 
					
						
							|  |  |  |  |         return fragment.offset(); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  |     return m_offset; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | const Gfx::FloatRect Box::absolute_rect() const | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-06 00:49:09 +01:00
										 |  |  |  |     Gfx::FloatRect rect { effective_offset(), content_size() }; | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  |     for (auto* block = containing_block(); block; block = block->containing_block()) { | 
					
						
							| 
									
										
										
										
											2021-04-12 11:47:09 -07:00
										 |  |  |  |         rect.translate_by(block->effective_offset()); | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  |     return rect; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 10:26:38 +01:00
										 |  |  |  | void Box::set_containing_line_box_fragment(LineBoxFragmentCoordinate fragment_coordinate) | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-02-27 10:26:38 +01:00
										 |  |  |  |     m_containing_line_box_fragment = fragment_coordinate; | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |  | StackingContext* Box::enclosing_stacking_context() | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  |     for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  |  |         if (!is<Box>(ancestor)) | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2021-06-24 19:53:42 +02:00
										 |  |  |  |         auto& ancestor_box = verify_cast<Box>(*ancestor); | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  |  |         if (!ancestor_box.establishes_stacking_context()) | 
					
						
							|  |  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |  |         VERIFY(ancestor_box.stacking_context()); | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  |  |         return ancestor_box.stacking_context(); | 
					
						
							|  |  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-09-08 11:27:46 +02:00
										 |  |  |  |     // We should always reach the Layout::InitialContainingBlock stacking context.
 | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |  |     VERIFY_NOT_REACHED(); | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-28 17:08:42 +02:00
										 |  |  |  | void Box::before_children_paint(PaintContext& context, PaintPhase phase) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     NodeWithStyleAndBoxModelMetrics::before_children_paint(context, phase); | 
					
						
							|  |  |  |  |     // FIXME: Support more overflow variations.
 | 
					
						
							|  |  |  |  |     if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden) { | 
					
						
							|  |  |  |  |         context.painter().save(); | 
					
						
							| 
									
										
										
										
											2022-02-11 21:57:56 +01:00
										 |  |  |  |         context.painter().add_clip_rect(enclosing_int_rect(absolute_border_box_rect())); | 
					
						
							| 
									
										
										
										
											2021-10-28 17:08:42 +02:00
										 |  |  |  |     } | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | void Box::after_children_paint(PaintContext& context, PaintPhase phase) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  |     NodeWithStyleAndBoxModelMetrics::after_children_paint(context, phase); | 
					
						
							|  |  |  |  |     // FIXME: Support more overflow variations.
 | 
					
						
							|  |  |  |  |     if (computed_values().overflow_x() == CSS::Overflow::Hidden && computed_values().overflow_y() == CSS::Overflow::Hidden) | 
					
						
							|  |  |  |  |         context.painter().restore(); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  |  | } |