| 
									
										
										
										
											2020-01-18 09:38:21 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Redistribution and use in source and binary forms, with or without | 
					
						
							|  |  |  |  * modification, are permitted provided that the following conditions are met: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 1. Redistributions of source code must retain the above copyright notice, this | 
					
						
							|  |  |  |  *    list of conditions and the following disclaimer. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | 
					
						
							|  |  |  |  *    this list of conditions and the following disclaimer in the documentation | 
					
						
							|  |  |  |  *    and/or other materials provided with the distribution. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
					
						
							|  |  |  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
					
						
							|  |  |  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
					
						
							|  |  |  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
					
						
							|  |  |  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
					
						
							|  |  |  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
					
						
							|  |  |  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
					
						
							|  |  |  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
					
						
							|  |  |  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
					
						
							|  |  |  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/InitialContainingBlockBox.h>
 | 
					
						
							|  |  |  | #include <LibWeb/Layout/Node.h>
 | 
					
						
							| 
									
										
										
										
											2021-01-01 18:55:47 +01:00
										 |  |  | #include <LibWeb/Layout/TextNode.h>
 | 
					
						
							| 
									
										
										
										
											2020-07-28 19:27:41 +02:00
										 |  |  | #include <LibWeb/Page/Frame.h>
 | 
					
						
							| 
									
										
										
										
											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-01-06 11:07:02 +01:00
										 |  |  |     return computed_values().position() != CSS::Position::Static || is<InitialContainingBlockBox>(*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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | const Frame& Node::frame() const | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(document().frame()); | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  |     return *document().frame(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | Frame& Node::frame() | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-02-23 20:42:32 +01:00
										 |  |  |     VERIFY(document().frame()); | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  |     return *document().frame(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | const InitialContainingBlockBox& 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(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | InitialContainingBlockBox& 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())) { | 
					
						
							| 
									
										
										
										
											2020-06-14 16:45:45 +02:00
										 |  |  |                 frame().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)) | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |         return downcast<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-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-01-06 11:05:23 +01:00
										 |  |  |     m_font = specified_style.font(); | 
					
						
							| 
									
										
										
										
											2021-01-06 11:31:19 +01:00
										 |  |  |     m_line_height = specified_style.line_height(*this); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // FIXME: This doesn't work right for relative font-sizes
 | 
					
						
							|  |  |  |         auto length = specified_style.length_or_fallback(CSS::PropertyID::FontSize, CSS::Length(10, CSS::Length::Type::Px)); | 
					
						
							|  |  |  |         m_font_size = length.raw_value(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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-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()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-14 18:47:00 +01:00
										 |  |  |     auto position = specified_style.position(); | 
					
						
							|  |  |  |     if (position.has_value()) | 
					
						
							| 
									
										
										
										
											2021-01-06 10:34:31 +01:00
										 |  |  |         computed_values.set_position(position.value()); | 
					
						
							| 
									
										
										
										
											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()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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()); | 
					
						
							|  |  |  |     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, {})); | 
					
						
							|  |  |  |     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-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.width = specified_style.length_or_fallback(width_property, {}).resolved_or_zero(*this, 0).to_px(*this); | 
					
						
							|  |  |  |         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-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-02-22 19:48:24 +01:00
										 |  |  | void Node::handle_mousewheel(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned, int wheel_delta) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (auto* containing_block = this->containing_block()) { | 
					
						
							| 
									
										
										
										
											2021-02-22 23:44:51 +01:00
										 |  |  |         if (!containing_block->is_scrollable()) | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2021-02-22 19:48:24 +01:00
										 |  |  |         auto new_offset = containing_block->scroll_offset(); | 
					
						
							|  |  |  |         new_offset.move_by(0, wheel_delta); | 
					
						
							|  |  |  |         containing_block->set_scroll_offset(new_offset); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     auto wrapper = adopt(*new BlockBox(const_cast<DOM::Document&>(document()), nullptr, m_computed_values.clone_inherited_values())); | 
					
						
							|  |  |  |     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
										 |  |  | } |