Serenity Operating System
1/*
2 * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/OwnPtr.h>
10#include <LibWeb/Forward.h>
11#include <LibWeb/Layout/AvailableSpace.h>
12#include <LibWeb/Layout/LayoutState.h>
13
14namespace Web::Layout {
15
16class FormattingContext {
17public:
18 virtual ~FormattingContext();
19
20 enum class Type {
21 Block,
22 Inline,
23 Flex,
24 Grid,
25 Table,
26 SVG,
27 };
28
29 virtual void run(Box const&, LayoutMode, AvailableSpace const&) = 0;
30
31 // This function returns the automatic content height of the context's root box.
32 virtual CSSPixels automatic_content_width() const { return 0; }
33
34 // This function returns the automatic content height of the context's root box.
35 virtual CSSPixels automatic_content_height() const = 0;
36
37 Box const& context_box() const { return m_context_box; }
38
39 FormattingContext* parent() { return m_parent; }
40 FormattingContext const* parent() const { return m_parent; }
41
42 Type type() const { return m_type; }
43 bool is_block_formatting_context() const { return type() == Type::Block; }
44
45 virtual bool inhibits_floating() const { return false; }
46
47 static bool creates_block_formatting_context(Box const&);
48
49 static CSSPixels compute_width_for_replaced_element(LayoutState const&, ReplacedBox const&, AvailableSpace const&);
50 static CSSPixels compute_height_for_replaced_element(LayoutState const&, ReplacedBox const&, AvailableSpace const&);
51
52 OwnPtr<FormattingContext> create_independent_formatting_context_if_needed(LayoutState&, Box const& child_box);
53
54 virtual void parent_context_did_dimension_child_root_box() { }
55
56 CSSPixels calculate_min_content_width(Layout::Box const&) const;
57 CSSPixels calculate_max_content_width(Layout::Box const&) const;
58 CSSPixels calculate_min_content_height(Layout::Box const&, AvailableSize const& available_width) const;
59 CSSPixels calculate_max_content_height(Layout::Box const&, AvailableSize const& available_width) const;
60
61 CSSPixels calculate_fit_content_height(Layout::Box const&, AvailableSpace const&) const;
62 CSSPixels calculate_fit_content_width(Layout::Box const&, AvailableSpace const&) const;
63
64 CSS::Length calculate_inner_width(Layout::Box const&, AvailableSize const&, CSS::Size const& width) const;
65 CSS::Length calculate_inner_height(Layout::Box const&, AvailableSize const&, CSS::Size const& height) const;
66
67 virtual CSSPixels greatest_child_width(Box const&);
68
69 CSSPixels containing_block_width_for(Box const& box) const { return containing_block_width_for(box, m_state); }
70 CSSPixels containing_block_height_for(Box const& box) const { return containing_block_height_for(box, m_state); }
71
72 static CSSPixels containing_block_width_for(Box const&, LayoutState const&);
73 static CSSPixels containing_block_height_for(Box const&, LayoutState const&);
74
75 [[nodiscard]] CSSPixels calculate_stretch_fit_width(Box const&, AvailableSize const&) const;
76 [[nodiscard]] CSSPixels calculate_stretch_fit_height(Box const&, AvailableSize const&) const;
77
78 virtual bool can_determine_size_of_child() const { return false; }
79 virtual void determine_width_of_child(Box const&, AvailableSpace const&) { }
80 virtual void determine_height_of_child(Box const&, AvailableSpace const&) { }
81
82 virtual CSSPixelPoint calculate_static_position(Box const&) const;
83 bool can_skip_is_anonymous_text_run(Box&);
84
85protected:
86 FormattingContext(Type, LayoutState&, Box const&, FormattingContext* parent = nullptr);
87
88 static bool should_treat_width_as_auto(Box const&, AvailableSpace const&);
89 static bool should_treat_height_as_auto(Box const&, AvailableSpace const&);
90
91 OwnPtr<FormattingContext> layout_inside(Box const&, LayoutMode, AvailableSpace const&);
92 void compute_inset(Box const& box);
93
94 struct SpaceUsedByFloats {
95 CSSPixels left { 0 };
96 CSSPixels right { 0 };
97 };
98
99 struct ShrinkToFitResult {
100 CSSPixels preferred_width { 0 };
101 CSSPixels preferred_minimum_width { 0 };
102 };
103
104 static CSSPixels tentative_width_for_replaced_element(LayoutState const&, ReplacedBox const&, CSS::Size const& computed_width, AvailableSpace const&);
105 static CSSPixels tentative_height_for_replaced_element(LayoutState const&, ReplacedBox const&, CSS::Size const& computed_height, AvailableSpace const&);
106 CSSPixels compute_auto_height_for_block_formatting_context_root(Box const&) const;
107
108 ShrinkToFitResult calculate_shrink_to_fit_widths(Box const&);
109
110 void layout_absolutely_positioned_element(Box const&, AvailableSpace const&);
111 void compute_width_for_absolutely_positioned_element(Box const&, AvailableSpace const&);
112 void compute_width_for_absolutely_positioned_non_replaced_element(Box const&, AvailableSpace const&);
113 void compute_width_for_absolutely_positioned_replaced_element(ReplacedBox const&, AvailableSpace const&);
114
115 enum class BeforeOrAfterInsideLayout {
116 Before,
117 After,
118 };
119 void compute_height_for_absolutely_positioned_element(Box const&, AvailableSpace const&, BeforeOrAfterInsideLayout);
120 void compute_height_for_absolutely_positioned_non_replaced_element(Box const&, AvailableSpace const&, BeforeOrAfterInsideLayout);
121 void compute_height_for_absolutely_positioned_replaced_element(ReplacedBox const&, AvailableSpace const&, BeforeOrAfterInsideLayout);
122
123 Type m_type {};
124
125 FormattingContext* m_parent { nullptr };
126 Box const& m_context_box;
127
128 LayoutState& m_state;
129};
130
131}