Serenity Operating System
1/*
2 * Copyright (c) 2022-2023, Martin Falisse <mfalisse@outlook.com>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <LibWeb/CSS/Length.h>
10#include <LibWeb/Layout/FormattingContext.h>
11
12namespace Web::Layout {
13
14class OccupationGrid {
15public:
16 OccupationGrid(int column_count, int row_count);
17 OccupationGrid();
18
19 void maybe_add_column(int needed_number_of_columns);
20 void maybe_add_row(int needed_number_of_rows);
21 void set_occupied(int column_start, int column_end, int row_start, int row_end);
22 void set_occupied(int column_index, int row_index);
23
24 int column_count() { return static_cast<int>(m_occupation_grid[0].size()); }
25 int row_count() { return static_cast<int>(m_occupation_grid.size()); }
26 bool is_occupied(int column_index, int row_index);
27
28private:
29 Vector<Vector<bool>> m_occupation_grid;
30};
31
32class PositionedBox {
33public:
34 PositionedBox(Box const& box, int row, int row_span, int column, int column_span)
35 : m_box(box)
36 , m_row(row)
37 , m_row_span(row_span)
38 , m_column(column)
39 , m_column_span(column_span)
40 {
41 }
42
43 Box const& box() { return m_box; }
44
45 int raw_row_span() { return m_row_span; }
46 int raw_column_span() { return m_column_span; }
47
48 int gap_adjusted_row(Box const& parent_box);
49 int gap_adjusted_column(Box const& parent_box);
50
51private:
52 Box const& m_box;
53 int m_row { 0 };
54 int m_row_span { 1 };
55 int m_column { 0 };
56 int m_column_span { 1 };
57};
58
59class GridFormattingContext final : public FormattingContext {
60public:
61 explicit GridFormattingContext(LayoutState&, Box const& grid_container, FormattingContext* parent);
62 ~GridFormattingContext();
63
64 virtual void run(Box const&, LayoutMode, AvailableSpace const& available_space) override;
65 virtual CSSPixels automatic_content_height() const override;
66
67private:
68 CSSPixels m_automatic_content_height { 0 };
69 bool is_auto_positioned_row(CSS::GridTrackPlacement const&, CSS::GridTrackPlacement const&) const;
70 bool is_auto_positioned_column(CSS::GridTrackPlacement const&, CSS::GridTrackPlacement const&) const;
71 bool is_auto_positioned_track(CSS::GridTrackPlacement const&, CSS::GridTrackPlacement const&) const;
72
73 struct TemporaryTrack {
74 CSS::GridSize min_track_sizing_function;
75 CSS::GridSize max_track_sizing_function;
76 CSSPixels base_size { 0 };
77 CSSPixels growth_limit { 0 };
78 CSSPixels space_to_distribute { 0 };
79 CSSPixels planned_increase { 0 };
80 bool is_gap { false };
81
82 TemporaryTrack(CSS::GridSize min_track_sizing_function, CSS::GridSize max_track_sizing_function)
83 : min_track_sizing_function(min_track_sizing_function)
84 , max_track_sizing_function(max_track_sizing_function)
85 {
86 }
87
88 TemporaryTrack(CSS::GridSize track_sizing_function)
89 : min_track_sizing_function(track_sizing_function)
90 , max_track_sizing_function(track_sizing_function)
91 {
92 }
93
94 TemporaryTrack(CSSPixels size, bool is_gap)
95 : min_track_sizing_function(CSS::GridSize(CSS::Length::make_px(size)))
96 , max_track_sizing_function(CSS::GridSize(CSS::Length::make_px(size)))
97 , base_size(size)
98 , is_gap(is_gap)
99 {
100 }
101
102 TemporaryTrack()
103 : min_track_sizing_function(CSS::GridSize::make_auto())
104 , max_track_sizing_function(CSS::GridSize::make_auto())
105 {
106 }
107 };
108
109 struct GridArea {
110 String name;
111 int row_start { 0 };
112 int row_end { 1 };
113 int column_start { 0 };
114 int column_end { 1 };
115 };
116 Vector<GridArea> m_valid_grid_areas;
117
118 Vector<TemporaryTrack> m_grid_rows;
119 Vector<TemporaryTrack> m_grid_columns;
120
121 OccupationGrid m_occupation_grid;
122 Vector<PositionedBox> m_positioned_boxes;
123 Vector<Box const&> m_boxes_to_place;
124
125 CSSPixels get_free_space_x(AvailableSpace const& available_space);
126 CSSPixels get_free_space_y(Box const&);
127
128 int get_line_index_by_line_name(String const& line_name, CSS::GridTrackSizeList);
129 CSSPixels resolve_definite_track_size(CSS::GridSize const&, AvailableSpace const&, Box const&);
130 size_t count_of_gap_columns();
131 size_t count_of_gap_rows();
132 CSSPixels resolve_size(CSS::Size const&, AvailableSize const&, Box const&);
133 int count_of_repeated_auto_fill_or_fit_tracks(Vector<CSS::ExplicitGridTrack> const& track_list, AvailableSpace const&, Box const&);
134 int get_count_of_tracks(Vector<CSS::ExplicitGridTrack> const&, AvailableSpace const&, Box const&);
135
136 void build_valid_grid_areas(Box const&);
137 int find_valid_grid_area(String const& needle);
138
139 void place_item_with_row_and_column_position(Box const& box, Box const& child_box);
140 void place_item_with_row_position(Box const& box, Box const& child_box);
141 void place_item_with_column_position(Box const& box, Box const& child_box, int& auto_placement_cursor_x, int& auto_placement_cursor_y);
142 void place_item_with_no_declared_position(Box const& child_box, int& auto_placement_cursor_x, int& auto_placement_cursor_y);
143
144 void initialize_grid_tracks(Box const&, AvailableSpace const&, int column_count, int row_count);
145 void calculate_sizes_of_columns(Box const&, AvailableSpace const&);
146 void calculate_sizes_of_rows(Box const&);
147};
148
149}