| 
									
										
										
										
											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
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  | #pragma once
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  | #include <AK/OwnPtr.h>
 | 
					
						
							| 
									
										
										
										
											2020-07-25 21:31:47 -07:00
										 |  |  | #include <LibGfx/Rect.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  | #include <LibWeb/Layout/LineBox.h>
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | #include <LibWeb/Layout/Node.h>
 | 
					
						
							| 
									
										
										
										
											2020-06-18 21:39:27 +02:00
										 |  |  | #include <LibWeb/Painting/StackingContext.h>
 | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | namespace Web::Layout { | 
					
						
							| 
									
										
										
										
											2020-03-07 10:27:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  | class Box : public NodeWithStyleAndBoxModelMetrics { | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |     const Gfx::FloatRect absolute_rect() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Gfx::FloatPoint effective_offset() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void set_offset(const Gfx::FloatPoint& offset); | 
					
						
							|  |  |  |     void set_offset(float x, float y) { set_offset({ x, y }); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const Gfx::FloatSize& size() const { return m_size; } | 
					
						
							|  |  |  |     void set_size(const Gfx::FloatSize&); | 
					
						
							|  |  |  |     void set_size(float width, float height) { set_size({ width, height }); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void set_width(float width) { set_size(width, height()); } | 
					
						
							|  |  |  |     void set_height(float height) { set_size(width(), height); } | 
					
						
							|  |  |  |     float width() const { return m_size.width(); } | 
					
						
							|  |  |  |     float height() const { return m_size.height(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-22 18:52:58 +01:00
										 |  |  |     Gfx::FloatRect padded_rect() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Gfx::FloatRect rect; | 
					
						
							|  |  |  |         rect.set_x(absolute_x() - box_model().padding.left); | 
					
						
							|  |  |  |         rect.set_width(width() + box_model().padding.left + box_model().padding.right); | 
					
						
							|  |  |  |         rect.set_y(absolute_y() - box_model().padding.top); | 
					
						
							|  |  |  |         rect.set_height(height() + box_model().padding.top + box_model().padding.bottom); | 
					
						
							|  |  |  |         return rect; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Gfx::FloatRect bordered_rect() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto padded_rect = this->padded_rect(); | 
					
						
							|  |  |  |         Gfx::FloatRect rect; | 
					
						
							|  |  |  |         rect.set_x(padded_rect.x() - box_model().border.left); | 
					
						
							|  |  |  |         rect.set_width(padded_rect.width() + box_model().border.left + box_model().border.right); | 
					
						
							|  |  |  |         rect.set_y(padded_rect.y() - box_model().border.top); | 
					
						
							|  |  |  |         rect.set_height(padded_rect.height() + box_model().border.top + box_model().border.bottom); | 
					
						
							|  |  |  |         return rect; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-18 17:33:16 +01:00
										 |  |  |     float margin_box_width() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto margin_box = box_model().margin_box(); | 
					
						
							|  |  |  |         return width() + margin_box.left + margin_box.right; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-18 17:53:49 +01:00
										 |  |  |     float margin_box_height() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto margin_box = box_model().margin_box(); | 
					
						
							|  |  |  |         return height() + margin_box.top + margin_box.bottom; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-07 21:13:41 +01:00
										 |  |  |     float border_box_width() const | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-12-12 21:02:06 +01:00
										 |  |  |         auto border_box = box_model().border_box(); | 
					
						
							| 
									
										
										
										
											2020-12-07 21:13:41 +01:00
										 |  |  |         return width() + border_box.left + border_box.right; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-02 03:46:26 +01:00
										 |  |  |     float border_box_height() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto border_box = box_model().border_box(); | 
					
						
							|  |  |  |         return height() + border_box.top + border_box.bottom; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-12 19:58:23 +01:00
										 |  |  |     Gfx::FloatRect content_box_as_relative_rect() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return { m_offset, m_size }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Gfx::FloatRect margin_box_as_relative_rect() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         auto rect = content_box_as_relative_rect(); | 
					
						
							| 
									
										
										
										
											2020-12-12 21:02:06 +01:00
										 |  |  |         auto margin_box = box_model().margin_box(); | 
					
						
							| 
									
										
										
										
											2020-12-12 19:58:23 +01:00
										 |  |  |         rect.set_x(rect.x() - margin_box.left); | 
					
						
							|  |  |  |         rect.set_width(rect.width() + margin_box.left + margin_box.right); | 
					
						
							|  |  |  |         rect.set_y(rect.y() - margin_box.top); | 
					
						
							|  |  |  |         rect.set_height(rect.height() + margin_box.top + margin_box.bottom); | 
					
						
							|  |  |  |         return rect; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |     float absolute_x() const { return absolute_rect().x(); } | 
					
						
							|  |  |  |     float absolute_y() const { return absolute_rect().y(); } | 
					
						
							|  |  |  |     Gfx::FloatPoint absolute_position() const { return absolute_rect().location(); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-05 16:55:56 +02:00
										 |  |  |     virtual HitTestResult hit_test(const Gfx::IntPoint&, HitTestType) const override; | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |     virtual void set_needs_display() override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-19 11:49:46 +02:00
										 |  |  |     bool is_body() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |     void set_containing_line_box_fragment(LineBoxFragment&); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  |     StackingContext* stacking_context() { return m_stacking_context; } | 
					
						
							| 
									
										
										
										
											2020-07-01 19:02:28 +02:00
										 |  |  |     const StackingContext* stacking_context() const { return m_stacking_context; } | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  |     void set_stacking_context(NonnullOwnPtr<StackingContext> context) { m_stacking_context = move(context); } | 
					
						
							|  |  |  |     StackingContext* enclosing_stacking_context(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-18 21:35:44 +02:00
										 |  |  |     virtual void paint(PaintContext&, PaintPhase) override; | 
					
						
							| 
									
										
										
										
											2021-04-20 13:39:36 +02:00
										 |  |  |     virtual void paint_border(PaintContext& context); | 
					
						
							| 
									
										
										
										
											2021-07-23 21:31:31 +02:00
										 |  |  |     virtual void paint_box_shadow(PaintContext& context); | 
					
						
							| 
									
										
										
										
											2021-05-15 20:54:01 +02:00
										 |  |  |     virtual void paint_background(PaintContext& context); | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |     Vector<LineBox>& line_boxes() { return m_line_boxes; } | 
					
						
							|  |  |  |     const Vector<LineBox>& line_boxes() const { return m_line_boxes; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     LineBox& ensure_last_line_box(); | 
					
						
							|  |  |  |     LineBox& add_line_box(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual float width_of_logical_containing_block() const; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-16 00:15:37 +02:00
										 |  |  |     struct BorderRadiusData { | 
					
						
							|  |  |  |         // FIXME: Use floats here
 | 
					
						
							|  |  |  |         int top_left { 0 }; | 
					
						
							|  |  |  |         int top_right { 0 }; | 
					
						
							|  |  |  |         int bottom_right { 0 }; | 
					
						
							|  |  |  |         int bottom_left { 0 }; | 
					
						
							|  |  |  |     }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BorderRadiusData normalized_border_radius_data(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  | protected: | 
					
						
							| 
									
										
										
										
											2020-11-22 15:53:01 +01:00
										 |  |  |     Box(DOM::Document& document, DOM::Node* node, NonnullRefPtr<CSS::StyleProperties> style) | 
					
						
							|  |  |  |         : NodeWithStyleAndBoxModelMetrics(document, node, move(style)) | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-06 14:10:53 +01:00
										 |  |  |     Box(DOM::Document& document, DOM::Node* node, CSS::ComputedValues computed_values) | 
					
						
							|  |  |  |         : NodeWithStyleAndBoxModelMetrics(document, node, move(computed_values)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |     virtual void did_set_rect() { } | 
					
						
							| 
									
										
										
										
											2020-06-05 19:13:27 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-05 12:05:35 -04:00
										 |  |  |     void paint_background_image(PaintContext&, const Gfx::Bitmap&, CSS::Repeat, CSS::Repeat, Gfx::IntRect); | 
					
						
							| 
									
										
										
										
											2021-04-04 18:04:38 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-22 13:38:18 +01:00
										 |  |  |     Vector<LineBox> m_line_boxes; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  | private: | 
					
						
							| 
									
										
										
										
											2021-01-07 17:31:26 +01:00
										 |  |  |     virtual bool is_box() const final { return true; } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-10 10:42:29 +02:00
										 |  |  |     Gfx::FloatPoint m_offset; | 
					
						
							|  |  |  |     Gfx::FloatSize m_size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Some boxes hang off of line box fragments. (inline-block, inline-table, replaced, etc)
 | 
					
						
							|  |  |  |     WeakPtr<LineBoxFragment> m_containing_line_box_fragment; | 
					
						
							| 
									
										
										
										
											2020-06-15 17:29:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     OwnPtr<StackingContext> m_stacking_context; | 
					
						
							| 
									
										
										
										
											2019-10-15 16:48:38 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-07 17:31:26 +01:00
										 |  |  | template<> | 
					
						
							| 
									
										
										
										
											2021-01-17 09:34:01 +01:00
										 |  |  | inline bool Node::fast_is<Box>() const { return is_box(); } | 
					
						
							| 
									
										
										
										
											2021-01-07 17:31:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | } |