| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2021-04-22 01:24:48 -07:00
										 |  |  |  * SPDX-License-Identifier: BSD-2-Clause | 
					
						
							| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-01 16:42:44 +01:00
										 |  |  | #include <AK/Demangle.h>
 | 
					
						
							| 
									
										
										
										
											2021-01-06 14:27:40 +01:00
										 |  |  | #include <LibGfx/FontDatabase.h>
 | 
					
						
							| 
									
										
										
										
											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>
 | 
					
						
							| 
									
										
										
										
											2020-11-26 21:18:34 +01:00
										 |  |  | #include <LibWeb/Dump.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-05 20:10:02 +01:00
										 |  |  | #include <LibWeb/HTML/HTMLHtmlElement.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/BlockBox.h>
 | 
					
						
							| 
									
										
										
										
											2020-12-05 20:10:39 +01:00
										 |  |  | #include <LibWeb/Layout/FormattingContext.h>
 | 
					
						
							| 
									
										
										
										
											2021-09-08 11:27:46 +02:00
										 |  |  | #include <LibWeb/Layout/InitialContainingBlock.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/Node.h>
 | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  | #include <LibWeb/Layout/TextNode.h>
 | 
					
						
							| 
									
										
										
										
											2021-05-30 12:36:53 +02:00
										 |  |  | #include <LibWeb/Page/BrowsingContext.h>
 | 
					
						
							| 
									
										
										
										
											2021-08-01 08:58:23 +02:00
										 |  |  | #include <typeinfo>
 | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +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
										 |  |  | Node::Node(DOM::Document& document, DOM::Node* node) | 
					
						
							| 
									
										
										
										
											2020-06-24 19:41:12 +02:00
										 |  |  |     : m_document(document) | 
					
						
							| 
									
										
										
										
											2020-11-22 14:46:36 +01:00
										 |  |  |     , m_dom_node(node) | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-22 14:46:36 +01:00
										 |  |  |     if (m_dom_node) | 
					
						
							|  |  |  |         m_dom_node->set_layout_node({}, this); | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | Node::~Node() | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-22 14:46:36 +01:00
										 |  |  |     if (m_dom_node && m_dom_node->layout_node() == this) | 
					
						
							|  |  |  |         m_dom_node->set_layout_node({}, nullptr); | 
					
						
							| 
									
										
										
										
											2019-06-15 22:49:44 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | bool Node::can_contain_boxes_with_position_absolute() const | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-08 11:27:46 +02:00
										 |  |  |     return computed_values().position() != CSS::Position::Static || is<InitialContainingBlock>(*this); | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | const BlockBox* Node::containing_block() const | 
					
						
							| 
									
										
										
										
											2019-07-01 07:28:37 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-05 19:13:27 +02:00
										 |  |  |     auto nearest_block_ancestor = [this] { | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  |         auto* ancestor = parent(); | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |         while (ancestor && !is<BlockBox>(*ancestor)) | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  |             ancestor = ancestor->parent(); | 
					
						
							| 
									
										
										
										
											2021-01-17 09:34:01 +01:00
										 |  |  |         return static_cast<const BlockBox*>(ancestor); | 
					
						
							| 
									
										
										
										
											2020-06-05 19:13:27 +02:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  |     if (is<TextNode>(*this)) | 
					
						
							| 
									
										
										
										
											2020-06-05 19:13:27 +02:00
										 |  |  |         return nearest_block_ancestor(); | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 11:07:02 +01:00
										 |  |  |     auto position = computed_values().position(); | 
					
						
							| 
									
										
										
										
											2020-06-12 14:19:03 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (position == CSS::Position::Absolute) { | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  |         auto* ancestor = parent(); | 
					
						
							|  |  |  |         while (ancestor && !ancestor->can_contain_boxes_with_position_absolute()) | 
					
						
							|  |  |  |             ancestor = ancestor->parent(); | 
					
						
							| 
									
										
										
										
											2021-01-17 09:34:01 +01:00
										 |  |  |         while (ancestor && (!is<BlockBox>(*ancestor) || ancestor->is_anonymous())) | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  |             ancestor = ancestor->containing_block(); | 
					
						
							| 
									
										
										
										
											2021-01-17 09:34:01 +01:00
										 |  |  |         return static_cast<const BlockBox*>(ancestor); | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 14:19:03 +02:00
										 |  |  |     if (position == CSS::Position::Fixed) | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  |         return &root(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-05 19:13:27 +02:00
										 |  |  |     return nearest_block_ancestor(); | 
					
						
							| 
									
										
										
										
											2019-07-01 07:28:37 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-09-25 12:40:37 +03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-07 19:03:25 +03:00
										 |  |  | bool Node::establishes_stacking_context() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!has_style()) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-09-02 19:27:42 +01:00
										 |  |  |     if (dom_node() == &document().root()) | 
					
						
							| 
									
										
										
										
											2021-05-07 19:03:25 +03:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     auto position = computed_values().position(); | 
					
						
							|  |  |  |     if (position == CSS::Position::Absolute || position == CSS::Position::Relative || position == CSS::Position::Fixed || position == CSS::Position::Sticky) | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2021-07-23 13:19:16 +03:00
										 |  |  |     auto opacity = computed_values().opacity(); | 
					
						
							|  |  |  |     if (opacity.has_value() && opacity.value() != 1.0f) | 
					
						
							|  |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2021-05-07 19:03:25 +03:00
										 |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | void Node::paint(PaintContext& context, PaintPhase phase) | 
					
						
							| 
									
										
										
										
											2019-09-25 12:40:37 +03:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-09 21:25:29 +02:00
										 |  |  |     if (!is_visible()) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-05 16:11:33 -07:00
										 |  |  |     before_children_paint(context, phase); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 19:59:28 +01:00
										 |  |  |     for_each_child_in_paint_order([&](auto& child) { | 
					
						
							| 
									
										
										
										
											2020-06-18 21:35:44 +02:00
										 |  |  |         child.paint(context, phase); | 
					
						
							| 
									
										
										
										
											2019-09-25 12:40:37 +03:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2020-10-05 16:11:33 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     after_children_paint(context, phase); | 
					
						
							| 
									
										
										
										
											2019-09-25 12:40:37 +03:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-09-28 23:02:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | HitTestResult Node::hit_test(const Gfx::IntPoint& position, HitTestType type) const | 
					
						
							| 
									
										
										
										
											2019-09-28 23:02:22 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |     HitTestResult result; | 
					
						
							| 
									
										
										
										
											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-09-28 23:02:22 +02:00
										 |  |  |         if (child_result.layout_node) | 
					
						
							|  |  |  |             result = child_result; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-09-29 11:43:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 12:36:53 +02:00
										 |  |  | const BrowsingContext& Node::browsing_context() const | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-05-30 12:36:53 +02:00
										 |  |  |     VERIFY(document().browsing_context()); | 
					
						
							|  |  |  |     return *document().browsing_context(); | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 12:36:53 +02:00
										 |  |  | BrowsingContext& Node::browsing_context() | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-05-30 12:36:53 +02:00
										 |  |  |     VERIFY(document().browsing_context()); | 
					
						
							|  |  |  |     return *document().browsing_context(); | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-08 11:27:46 +02:00
										 |  |  | const InitialContainingBlock& Node::root() const | 
					
						
							| 
									
										
										
										
											2019-11-04 19:37:52 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(document().layout_node()); | 
					
						
							| 
									
										
										
										
											2019-11-04 19:37:52 +01:00
										 |  |  |     return *document().layout_node(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-08 11:27:46 +02:00
										 |  |  | InitialContainingBlock& Node::root() | 
					
						
							| 
									
										
										
										
											2019-11-04 19:37:52 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(document().layout_node()); | 
					
						
							| 
									
										
										
										
											2019-11-04 19:37:52 +01:00
										 |  |  |     return *document().layout_node(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 20:10:39 +01:00
										 |  |  | void Node::split_into_lines(InlineFormattingContext& context, LayoutMode layout_mode) | 
					
						
							| 
									
										
										
										
											2019-10-05 23:20:35 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     for_each_child([&](auto& child) { | 
					
						
							| 
									
										
										
										
											2020-12-05 20:10:39 +01:00
										 |  |  |         child.split_into_lines(context, layout_mode); | 
					
						
							| 
									
										
										
										
											2019-10-05 23:20:35 +02:00
										 |  |  |     }); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-09 21:25:29 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | void Node::set_needs_display() | 
					
						
							| 
									
										
										
										
											2019-10-09 21:25:29 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-20 09:14:12 +02:00
										 |  |  |     if (auto* block = containing_block()) { | 
					
						
							|  |  |  |         block->for_each_fragment([&](auto& fragment) { | 
					
						
							|  |  |  |             if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) { | 
					
						
							| 
									
										
										
										
											2021-05-30 12:36:53 +02:00
										 |  |  |                 browsing_context().set_needs_display(enclosing_int_rect(fragment.absolute_rect())); | 
					
						
							| 
									
										
										
										
											2019-10-20 09:14:12 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             return IterationDecision::Continue; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | Gfx::FloatPoint Node::box_type_agnostic_position() const | 
					
						
							| 
									
										
										
										
											2019-10-20 09:14:12 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  |     if (is<Box>(*this)) | 
					
						
							| 
									
										
										
										
											2021-06-24 19:53:42 +02:00
										 |  |  |         return verify_cast<Box>(*this).absolute_position(); | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(is_inline()); | 
					
						
							| 
									
										
										
										
											2020-02-06 14:35:54 +01:00
										 |  |  |     Gfx::FloatPoint position; | 
					
						
							| 
									
										
										
										
											2019-10-20 09:14:12 +02:00
										 |  |  |     if (auto* block = containing_block()) { | 
					
						
							|  |  |  |         block->for_each_fragment([&](auto& fragment) { | 
					
						
							|  |  |  |             if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) { | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |                 position = fragment.absolute_rect().location(); | 
					
						
							| 
									
										
										
										
											2019-10-20 09:14:12 +02:00
										 |  |  |                 return IterationDecision::Break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return IterationDecision::Continue; | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return position; | 
					
						
							| 
									
										
										
										
											2019-10-09 21:25:29 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | bool Node::is_floating() const | 
					
						
							| 
									
										
										
										
											2020-06-26 15:08:42 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!has_style()) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-05-29 23:03:05 +02:00
										 |  |  |     // flex-items don't float.
 | 
					
						
							|  |  |  |     if (is_flex_item()) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-01-06 11:07:02 +01:00
										 |  |  |     return computed_values().float_() != CSS::Float::None; | 
					
						
							| 
									
										
										
										
											2020-06-26 15:08:42 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 19:54:23 +01:00
										 |  |  | bool Node::is_positioned() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-06 11:07:02 +01:00
										 |  |  |     return has_style() && computed_values().position() != CSS::Position::Static; | 
					
						
							| 
									
										
										
										
											2020-12-06 19:54:23 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | bool Node::is_absolutely_positioned() const | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-15 12:57:43 +02:00
										 |  |  |     if (!has_style()) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-01-06 11:07:02 +01:00
										 |  |  |     auto position = computed_values().position(); | 
					
						
							| 
									
										
										
										
											2020-06-12 14:19:03 +02:00
										 |  |  |     return position == CSS::Position::Absolute || position == CSS::Position::Fixed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | bool Node::is_fixed_position() const | 
					
						
							| 
									
										
										
										
											2020-06-12 14:19:03 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-06-15 12:57:43 +02:00
										 |  |  |     if (!has_style()) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2021-01-06 11:07:02 +01:00
										 |  |  |     auto position = computed_values().position(); | 
					
						
							| 
									
										
										
										
											2020-06-23 23:15:23 +02:00
										 |  |  |     return position == CSS::Position::Fixed; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | NodeWithStyle::NodeWithStyle(DOM::Document& document, DOM::Node* node, NonnullRefPtr<CSS::StyleProperties> specified_style) | 
					
						
							|  |  |  |     : Node(document, node) | 
					
						
							| 
									
										
										
										
											2020-06-23 23:15:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     m_has_style = true; | 
					
						
							| 
									
										
										
										
											2021-01-06 14:10:53 +01:00
										 |  |  |     apply_style(*specified_style); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | NodeWithStyle::NodeWithStyle(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values) | 
					
						
							|  |  |  |     : Node(document, node) | 
					
						
							|  |  |  |     , m_computed_values(move(computed_values)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     m_has_style = true; | 
					
						
							| 
									
										
										
										
											2021-01-06 14:27:40 +01:00
										 |  |  |     m_font = Gfx::FontDatabase::default_font(); | 
					
						
							| 
									
										
										
										
											2020-06-24 14:17:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style) | 
					
						
							| 
									
										
										
										
											2020-06-24 14:17:05 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |     auto& computed_values = static_cast<CSS::MutableComputedValues&>(m_computed_values); | 
					
						
							| 
									
										
										
										
											2020-06-24 14:17:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-12 16:41:09 +01:00
										 |  |  |     m_font = specified_style.font(*this); | 
					
						
							| 
									
										
										
										
											2021-01-06 11:31:19 +01:00
										 |  |  |     m_line_height = specified_style.line_height(*this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2021-08-16 21:12:48 +01:00
										 |  |  |         constexpr int default_font_size = 10; | 
					
						
							|  |  |  |         auto parent_font_size = parent() == nullptr ? default_font_size : parent()->font_size(); | 
					
						
							|  |  |  |         auto length = specified_style.length_or_fallback(CSS::PropertyID::FontSize, CSS::Length(default_font_size, CSS::Length::Type::Px)); | 
					
						
							|  |  |  |         // FIXME: em sizes return 0 here, for some reason
 | 
					
						
							|  |  |  |         m_font_size = length.resolved_or_zero(*this, parent_font_size).to_px(*this); | 
					
						
							|  |  |  |         if (m_font_size == 0) | 
					
						
							|  |  |  |             m_font_size = default_font_size; | 
					
						
							| 
									
										
										
										
											2021-01-06 11:31:19 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto bgimage = specified_style.property(CSS::PropertyID::BackgroundImage); | 
					
						
							|  |  |  |     if (bgimage.has_value() && bgimage.value()->is_image()) { | 
					
						
							|  |  |  |         m_background_image = static_ptr_cast<CSS::ImageStyleValue>(bgimage.value()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-01-06 11:05:23 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-06 16:55:08 +01:00
										 |  |  |     // FIXME: BorderXRadius properties are now BorderRadiusStyleValues, so make use of that.
 | 
					
						
							| 
									
										
										
										
											2021-05-14 22:31:03 +02:00
										 |  |  |     auto border_bottom_left_radius = specified_style.property(CSS::PropertyID::BorderBottomLeftRadius); | 
					
						
							|  |  |  |     if (border_bottom_left_radius.has_value()) | 
					
						
							|  |  |  |         computed_values.set_border_bottom_left_radius(border_bottom_left_radius.value()->to_length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto border_bottom_right_radius = specified_style.property(CSS::PropertyID::BorderBottomRightRadius); | 
					
						
							|  |  |  |     if (border_bottom_right_radius.has_value()) | 
					
						
							|  |  |  |         computed_values.set_border_bottom_right_radius(border_bottom_right_radius.value()->to_length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto border_top_left_radius = specified_style.property(CSS::PropertyID::BorderTopLeftRadius); | 
					
						
							|  |  |  |     if (border_top_left_radius.has_value()) | 
					
						
							|  |  |  |         computed_values.set_border_top_left_radius(border_top_left_radius.value()->to_length()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto border_top_right_radius = specified_style.property(CSS::PropertyID::BorderTopRightRadius); | 
					
						
							|  |  |  |     if (border_top_right_radius.has_value()) | 
					
						
							|  |  |  |         computed_values.set_border_top_right_radius(border_top_right_radius.value()->to_length()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 12:05:35 -04:00
										 |  |  |     auto background_repeat_x = specified_style.background_repeat_x(); | 
					
						
							|  |  |  |     if (background_repeat_x.has_value()) | 
					
						
							|  |  |  |         computed_values.set_background_repeat_x(background_repeat_x.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto background_repeat_y = specified_style.background_repeat_y(); | 
					
						
							|  |  |  |     if (background_repeat_y.has_value()) | 
					
						
							|  |  |  |         computed_values.set_background_repeat_y(background_repeat_y.value()); | 
					
						
							| 
									
										
										
										
											2021-04-02 15:41:29 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-07 14:41:50 +01:00
										 |  |  |     computed_values.set_display(specified_style.display()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-18 17:41:57 +01:00
										 |  |  |     auto flex_direction = specified_style.flex_direction(); | 
					
						
							|  |  |  |     if (flex_direction.has_value()) | 
					
						
							|  |  |  |         computed_values.set_flex_direction(flex_direction.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 12:11:32 +02:00
										 |  |  |     auto flex_wrap = specified_style.flex_wrap(); | 
					
						
							|  |  |  |     if (flex_wrap.has_value()) | 
					
						
							|  |  |  |         computed_values.set_flex_wrap(flex_wrap.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 14:23:43 +02:00
										 |  |  |     auto flex_basis = specified_style.flex_basis(); | 
					
						
							|  |  |  |     if (flex_basis.has_value()) | 
					
						
							|  |  |  |         computed_values.set_flex_basis(flex_basis.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-30 20:22:25 +02:00
										 |  |  |     computed_values.set_flex_grow_factor(specified_style.flex_grow_factor()); | 
					
						
							|  |  |  |     computed_values.set_flex_shrink_factor(specified_style.flex_shrink_factor()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-16 18:38:26 +02:00
										 |  |  |     auto justify_content = specified_style.justify_content(); | 
					
						
							|  |  |  |     if (justify_content.has_value()) | 
					
						
							|  |  |  |         computed_values.set_justify_content(justify_content.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 18:47:00 +01:00
										 |  |  |     auto position = specified_style.position(); | 
					
						
							| 
									
										
										
										
											2021-05-30 13:43:47 +02:00
										 |  |  |     if (position.has_value()) { | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_position(position.value()); | 
					
						
							| 
									
										
										
										
											2021-05-30 13:43:47 +02:00
										 |  |  |         if (position.value() == CSS::Position::Absolute) { | 
					
						
							|  |  |  |             m_has_definite_width = true; | 
					
						
							|  |  |  |             m_has_definite_height = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-12-14 18:38:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto text_align = specified_style.text_align(); | 
					
						
							|  |  |  |     if (text_align.has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_text_align(text_align.value()); | 
					
						
							| 
									
										
										
										
											2020-06-24 16:37:44 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     auto white_space = specified_style.white_space(); | 
					
						
							|  |  |  |     if (white_space.has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_white_space(white_space.value()); | 
					
						
							| 
									
										
										
										
											2020-06-24 16:37:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-26 15:08:42 +02:00
										 |  |  |     auto float_ = specified_style.float_(); | 
					
						
							|  |  |  |     if (float_.has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_float(float_.value()); | 
					
						
							| 
									
										
										
										
											2020-06-26 15:08:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-06 01:45:51 +01:00
										 |  |  |     auto clear = specified_style.clear(); | 
					
						
							|  |  |  |     if (clear.has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_clear(clear.value()); | 
					
						
							| 
									
										
										
										
											2020-12-06 01:45:51 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 15:20:31 +01:00
										 |  |  |     auto overflow_x = specified_style.overflow_x(); | 
					
						
							|  |  |  |     if (overflow_x.has_value()) | 
					
						
							|  |  |  |         computed_values.set_overflow_x(overflow_x.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     auto overflow_y = specified_style.overflow_y(); | 
					
						
							|  |  |  |     if (overflow_y.has_value()) | 
					
						
							|  |  |  |         computed_values.set_overflow_y(overflow_y.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-21 17:41:00 +00:00
										 |  |  |     auto cursor = specified_style.cursor(); | 
					
						
							|  |  |  |     if (cursor.has_value()) | 
					
						
							|  |  |  |         computed_values.set_cursor(cursor.value()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-15 13:36:27 +01:00
										 |  |  |     auto text_decoration_line = specified_style.text_decoration_line(); | 
					
						
							|  |  |  |     if (text_decoration_line.has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_text_decoration_line(text_decoration_line.value()); | 
					
						
							| 
									
										
										
										
											2020-12-15 13:36:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-15 14:15:49 +01:00
										 |  |  |     auto text_transform = specified_style.text_transform(); | 
					
						
							|  |  |  |     if (text_transform.has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_text_transform(text_transform.value()); | 
					
						
							| 
									
										
										
										
											2020-12-15 14:15:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-15 16:50:39 +01:00
										 |  |  |     if (auto list_style_type = specified_style.list_style_type(); list_style_type.has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_list_style_type(list_style_type.value()); | 
					
						
							| 
									
										
										
										
											2020-12-15 16:50:39 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |     computed_values.set_color(specified_style.color_or_fallback(CSS::PropertyID::Color, document(), Color::Black)); | 
					
						
							|  |  |  |     computed_values.set_background_color(specified_style.color_or_fallback(CSS::PropertyID::BackgroundColor, document(), Color::Transparent)); | 
					
						
							| 
									
										
										
										
											2020-12-15 16:13:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |     computed_values.set_z_index(specified_style.z_index()); | 
					
						
							| 
									
										
										
										
											2021-07-23 13:18:09 +03:00
										 |  |  |     computed_values.set_opacity(specified_style.opacity()); | 
					
						
							|  |  |  |     if (computed_values.opacity() == 0) | 
					
						
							|  |  |  |         m_visible = false; | 
					
						
							| 
									
										
										
										
											2021-05-30 13:43:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (auto width = specified_style.property(CSS::PropertyID::Width); width.has_value()) | 
					
						
							|  |  |  |         m_has_definite_width = true; | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |     computed_values.set_width(specified_style.length_or_fallback(CSS::PropertyID::Width, {})); | 
					
						
							|  |  |  |     computed_values.set_min_width(specified_style.length_or_fallback(CSS::PropertyID::MinWidth, {})); | 
					
						
							|  |  |  |     computed_values.set_max_width(specified_style.length_or_fallback(CSS::PropertyID::MaxWidth, {})); | 
					
						
							| 
									
										
										
										
											2021-05-30 13:43:47 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (auto height = specified_style.property(CSS::PropertyID::Height); height.has_value()) | 
					
						
							|  |  |  |         m_has_definite_height = true; | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |     computed_values.set_height(specified_style.length_or_fallback(CSS::PropertyID::Height, {})); | 
					
						
							|  |  |  |     computed_values.set_min_height(specified_style.length_or_fallback(CSS::PropertyID::MinHeight, {})); | 
					
						
							|  |  |  |     computed_values.set_max_height(specified_style.length_or_fallback(CSS::PropertyID::MaxHeight, {})); | 
					
						
							| 
									
										
										
										
											2020-06-24 17:45:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |     computed_values.set_offset(specified_style.length_box(CSS::PropertyID::Left, CSS::PropertyID::Top, CSS::PropertyID::Right, CSS::PropertyID::Bottom, CSS::Length::make_auto())); | 
					
						
							|  |  |  |     computed_values.set_margin(specified_style.length_box(CSS::PropertyID::MarginLeft, CSS::PropertyID::MarginTop, CSS::PropertyID::MarginRight, CSS::PropertyID::MarginBottom, CSS::Length::make_px(0))); | 
					
						
							|  |  |  |     computed_values.set_padding(specified_style.length_box(CSS::PropertyID::PaddingLeft, CSS::PropertyID::PaddingTop, CSS::PropertyID::PaddingRight, CSS::PropertyID::PaddingBottom, CSS::Length::make_px(0))); | 
					
						
							| 
									
										
										
										
											2020-06-24 19:41:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-23 21:22:31 +02:00
										 |  |  |     computed_values.set_box_shadow(specified_style.box_shadow()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |     auto do_border_style = [&](CSS::BorderData& border, CSS::PropertyID width_property, CSS::PropertyID color_property, CSS::PropertyID style_property) { | 
					
						
							| 
									
										
										
										
											2020-12-04 16:11:55 +01:00
										 |  |  |         border.color = specified_style.color_or_fallback(color_property, document(), Color::Transparent); | 
					
						
							|  |  |  |         border.line_style = specified_style.line_style(style_property).value_or(CSS::LineStyle::None); | 
					
						
							| 
									
										
										
										
											2021-04-12 17:23:17 +03:00
										 |  |  |         if (border.line_style == CSS::LineStyle::None) | 
					
						
							|  |  |  |             border.width = 0; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             border.width = specified_style.length_or_fallback(width_property, {}).resolved_or_zero(*this, 0).to_px(*this); | 
					
						
							| 
									
										
										
										
											2020-12-04 16:11:55 +01:00
										 |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |     do_border_style(computed_values.border_left(), CSS::PropertyID::BorderLeftWidth, CSS::PropertyID::BorderLeftColor, CSS::PropertyID::BorderLeftStyle); | 
					
						
							|  |  |  |     do_border_style(computed_values.border_top(), CSS::PropertyID::BorderTopWidth, CSS::PropertyID::BorderTopColor, CSS::PropertyID::BorderTopStyle); | 
					
						
							|  |  |  |     do_border_style(computed_values.border_right(), CSS::PropertyID::BorderRightWidth, CSS::PropertyID::BorderRightColor, CSS::PropertyID::BorderRightStyle); | 
					
						
							|  |  |  |     do_border_style(computed_values.border_bottom(), CSS::PropertyID::BorderBottomWidth, CSS::PropertyID::BorderBottomColor, CSS::PropertyID::BorderBottomStyle); | 
					
						
							| 
									
										
										
										
											2020-06-05 16:54:28 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | void Node::handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned) | 
					
						
							| 
									
										
										
										
											2020-09-11 18:15:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | void Node::handle_mouseup(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned) | 
					
						
							| 
									
										
										
										
											2020-09-11 18:15:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | void Node::handle_mousemove(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned) | 
					
						
							| 
									
										
										
										
											2020-09-11 18:15:47 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-02 08:36:58 +11:00
										 |  |  | bool Node::handle_mousewheel(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned, int wheel_delta) | 
					
						
							| 
									
										
										
										
											2021-02-22 19:48:24 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (auto* containing_block = this->containing_block()) { | 
					
						
							| 
									
										
										
										
											2021-02-22 23:44:51 +01:00
										 |  |  |         if (!containing_block->is_scrollable()) | 
					
						
							| 
									
										
										
										
											2021-03-02 08:36:58 +11:00
										 |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2021-02-22 19:48:24 +01:00
										 |  |  |         auto new_offset = containing_block->scroll_offset(); | 
					
						
							| 
									
										
										
										
											2021-04-12 11:47:09 -07:00
										 |  |  |         new_offset.translate_by(0, wheel_delta); | 
					
						
							| 
									
										
										
										
											2021-02-22 19:48:24 +01:00
										 |  |  |         containing_block->set_scroll_offset(new_offset); | 
					
						
							| 
									
										
										
										
											2021-03-02 08:36:58 +11:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2021-02-22 19:48:24 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-03-02 08:36:58 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2021-02-22 19:48:24 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-05 20:10:02 +01:00
										 |  |  | bool Node::is_root_element() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (is_anonymous()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     return is<HTML::HTMLHtmlElement>(*dom_node()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-01 16:42:44 +01:00
										 |  |  | String Node::class_name() const | 
					
						
							| 
									
										
										
										
											2021-01-01 16:08:19 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-01-01 16:42:44 +01:00
										 |  |  |     return demangle(typeid(*this).name()); | 
					
						
							| 
									
										
										
										
											2021-01-01 16:08:19 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  | bool Node::is_inline_block() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return is_inline() && is<BlockBox>(*this); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-01-06 14:10:53 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | NonnullRefPtr<NodeWithStyle> NodeWithStyle::create_anonymous_wrapper() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-04-23 16:46:57 +02:00
										 |  |  |     auto wrapper = adopt_ref(*new BlockBox(const_cast<DOM::Document&>(document()), nullptr, m_computed_values.clone_inherited_values())); | 
					
						
							| 
									
										
										
										
											2021-01-06 14:10:53 +01:00
										 |  |  |     wrapper->m_font = m_font; | 
					
						
							|  |  |  |     wrapper->m_font_size = m_font_size; | 
					
						
							|  |  |  |     wrapper->m_line_height = m_line_height; | 
					
						
							|  |  |  |     wrapper->m_background_image = m_background_image; | 
					
						
							|  |  |  |     return wrapper; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | } |