/src/serenity/Userland/Libraries/LibWeb/CSS/StyleProperties.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2018-2024, Andreas Kling <andreas@ladybird.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #pragma once |
8 | | |
9 | | #include <AK/HashMap.h> |
10 | | #include <AK/NonnullRefPtr.h> |
11 | | #include <LibGfx/Font/Font.h> |
12 | | #include <LibGfx/FontCascadeList.h> |
13 | | #include <LibGfx/Forward.h> |
14 | | #include <LibJS/Heap/GCPtr.h> |
15 | | #include <LibWeb/CSS/ComputedValues.h> |
16 | | #include <LibWeb/CSS/LengthBox.h> |
17 | | #include <LibWeb/CSS/PropertyID.h> |
18 | | #include <LibWeb/CSS/StyleProperty.h> |
19 | | |
20 | | namespace Web::CSS { |
21 | | |
22 | | class StyleProperties : public RefCounted<StyleProperties> { |
23 | | public: |
24 | | static constexpr size_t number_of_properties = to_underlying(CSS::last_property_id) + 1; |
25 | | |
26 | | private: |
27 | | struct Data : public RefCounted<Data> { |
28 | | friend class StyleComputer; |
29 | | |
30 | | NonnullRefPtr<Data> clone() const; |
31 | | |
32 | | // FIXME: These need protection from GC! |
33 | | JS::GCPtr<CSS::CSSStyleDeclaration const> m_animation_name_source; |
34 | | JS::GCPtr<CSS::CSSStyleDeclaration const> m_transition_property_source; |
35 | | |
36 | | Array<RefPtr<CSSStyleValue const>, number_of_properties> m_property_values; |
37 | | Array<u8, ceil_div(number_of_properties, 8uz)> m_property_important {}; |
38 | | Array<u8, ceil_div(number_of_properties, 8uz)> m_property_inherited {}; |
39 | | |
40 | | HashMap<CSS::PropertyID, NonnullRefPtr<CSSStyleValue const>> m_animated_property_values; |
41 | | |
42 | | int m_math_depth { InitialValues::math_depth() }; |
43 | | mutable RefPtr<Gfx::FontCascadeList> m_font_list; |
44 | | |
45 | | Optional<CSSPixels> m_line_height; |
46 | | }; |
47 | | |
48 | | public: |
49 | 0 | StyleProperties() = default; |
50 | | |
51 | 0 | static NonnullRefPtr<StyleProperties> create() { return adopt_ref(*new StyleProperties); } |
52 | | NonnullRefPtr<StyleProperties> clone() const; |
53 | | |
54 | | template<typename Callback> |
55 | | inline void for_each_property(Callback callback) const |
56 | 0 | { |
57 | 0 | for (size_t i = 0; i < m_data->m_property_values.size(); ++i) { |
58 | 0 | if (m_data->m_property_values[i]) |
59 | 0 | callback((CSS::PropertyID)i, *m_data->m_property_values[i]); |
60 | 0 | } |
61 | 0 | } |
62 | | |
63 | | enum class Inherited { |
64 | | No, |
65 | | Yes |
66 | | }; |
67 | | |
68 | 0 | HashMap<CSS::PropertyID, NonnullRefPtr<CSSStyleValue const>> const& animated_property_values() const { return m_data->m_animated_property_values; } |
69 | | void reset_animated_properties(); |
70 | | |
71 | | bool is_property_important(CSS::PropertyID property_id) const; |
72 | | bool is_property_inherited(CSS::PropertyID property_id) const; |
73 | | void set_property_important(CSS::PropertyID, Important); |
74 | | void set_property_inherited(CSS::PropertyID, Inherited); |
75 | | |
76 | | void set_property(CSS::PropertyID, NonnullRefPtr<CSSStyleValue const> value, Inherited = Inherited::No, Important = Important::No); |
77 | | void set_animated_property(CSS::PropertyID, NonnullRefPtr<CSSStyleValue const> value); |
78 | | enum class WithAnimationsApplied { |
79 | | No, |
80 | | Yes, |
81 | | }; |
82 | | NonnullRefPtr<CSSStyleValue const> property(CSS::PropertyID, WithAnimationsApplied = WithAnimationsApplied::Yes) const; |
83 | | RefPtr<CSSStyleValue const> maybe_null_property(CSS::PropertyID) const; |
84 | | void revert_property(CSS::PropertyID, StyleProperties const& style_for_revert); |
85 | | |
86 | 0 | JS::GCPtr<CSS::CSSStyleDeclaration const> animation_name_source() const { return m_data->m_animation_name_source; } |
87 | 0 | void set_animation_name_source(JS::GCPtr<CSS::CSSStyleDeclaration const> declaration) { m_data->m_animation_name_source = declaration; } |
88 | | |
89 | 0 | JS::GCPtr<CSS::CSSStyleDeclaration const> transition_property_source() const { return m_data->m_transition_property_source; } |
90 | 0 | void set_transition_property_source(JS::GCPtr<CSS::CSSStyleDeclaration const> declaration) { m_data->m_transition_property_source = declaration; } |
91 | | |
92 | | CSS::Size size_value(CSS::PropertyID) const; |
93 | | LengthPercentage length_percentage_or_fallback(CSS::PropertyID, LengthPercentage const& fallback) const; |
94 | | Optional<LengthPercentage> length_percentage(CSS::PropertyID) const; |
95 | | LengthBox length_box(CSS::PropertyID left_id, CSS::PropertyID top_id, CSS::PropertyID right_id, CSS::PropertyID bottom_id, const CSS::Length& default_value) const; |
96 | | Color color_or_fallback(CSS::PropertyID, Layout::NodeWithStyle const&, Color fallback) const; |
97 | | Optional<CSS::TextAnchor> text_anchor() const; |
98 | | Optional<CSS::TextAlign> text_align() const; |
99 | | Optional<CSS::TextJustify> text_justify() const; |
100 | | Optional<CSS::TextOverflow> text_overflow() const; |
101 | | CSS::Length border_spacing_horizontal(Layout::Node const&) const; |
102 | | CSS::Length border_spacing_vertical(Layout::Node const&) const; |
103 | | Optional<CSS::CaptionSide> caption_side() const; |
104 | | CSS::Clip clip() const; |
105 | | CSS::Display display() const; |
106 | | Optional<CSS::Float> float_() const; |
107 | | Optional<CSS::Clear> clear() const; |
108 | | Optional<CSS::ColumnSpan> column_span() const; |
109 | | struct ContentDataAndQuoteNestingLevel { |
110 | | CSS::ContentData content_data; |
111 | | u32 final_quote_nesting_level { 0 }; |
112 | | }; |
113 | | ContentDataAndQuoteNestingLevel content(DOM::Element&, u32 initial_quote_nesting_level) const; |
114 | | Optional<CSS::ContentVisibility> content_visibility() const; |
115 | | Optional<CSS::Cursor> cursor() const; |
116 | | Variant<LengthOrCalculated, NumberOrCalculated> tab_size() const; |
117 | | Optional<CSS::WhiteSpace> white_space() const; |
118 | | Optional<CSS::WordBreak> word_break() const; |
119 | | Optional<CSS::LengthOrCalculated> word_spacing() const; |
120 | | Optional<LengthOrCalculated> letter_spacing() const; |
121 | | Optional<CSS::LineStyle> line_style(CSS::PropertyID) const; |
122 | | Optional<CSS::OutlineStyle> outline_style() const; |
123 | | Vector<CSS::TextDecorationLine> text_decoration_line() const; |
124 | | Optional<CSS::TextDecorationStyle> text_decoration_style() const; |
125 | | Optional<CSS::TextTransform> text_transform() const; |
126 | | Vector<CSS::ShadowData> text_shadow(Layout::Node const&) const; |
127 | | Optional<CSS::ListStyleType> list_style_type() const; |
128 | | Optional<CSS::ListStylePosition> list_style_position() const; |
129 | | Optional<CSS::FlexDirection> flex_direction() const; |
130 | | Optional<CSS::FlexWrap> flex_wrap() const; |
131 | | Optional<CSS::FlexBasis> flex_basis() const; |
132 | | float flex_grow() const; |
133 | | float flex_shrink() const; |
134 | | int order() const; |
135 | | Optional<Color> accent_color(Layout::NodeWithStyle const&) const; |
136 | | Optional<CSS::AlignContent> align_content() const; |
137 | | Optional<CSS::AlignItems> align_items() const; |
138 | | Optional<CSS::AlignSelf> align_self() const; |
139 | | Optional<CSS::Appearance> appearance() const; |
140 | | CSS::Filter backdrop_filter() const; |
141 | | CSS::Filter filter() const; |
142 | | float opacity() const; |
143 | | Optional<CSS::Visibility> visibility() const; |
144 | | Optional<CSS::ImageRendering> image_rendering() const; |
145 | | Optional<CSS::JustifyContent> justify_content() const; |
146 | | Optional<CSS::JustifyItems> justify_items() const; |
147 | | Optional<CSS::JustifySelf> justify_self() const; |
148 | | Optional<CSS::Overflow> overflow_x() const; |
149 | | Optional<CSS::Overflow> overflow_y() const; |
150 | | Vector<CSS::ShadowData> box_shadow(Layout::Node const&) const; |
151 | | Optional<CSS::BoxSizing> box_sizing() const; |
152 | | Optional<CSS::PointerEvents> pointer_events() const; |
153 | | Variant<CSS::VerticalAlign, CSS::LengthPercentage> vertical_align() const; |
154 | | Optional<CSS::FontVariant> font_variant() const; |
155 | | Optional<FlyString> font_language_override() const; |
156 | | Optional<HashMap<FlyString, IntegerOrCalculated>> font_feature_settings() const; |
157 | | Optional<HashMap<FlyString, NumberOrCalculated>> font_variation_settings() const; |
158 | | CSS::GridTrackSizeList grid_auto_columns() const; |
159 | | CSS::GridTrackSizeList grid_auto_rows() const; |
160 | | CSS::GridTrackSizeList grid_template_columns() const; |
161 | | CSS::GridTrackSizeList grid_template_rows() const; |
162 | | [[nodiscard]] CSS::GridAutoFlow grid_auto_flow() const; |
163 | | CSS::GridTrackPlacement grid_column_end() const; |
164 | | CSS::GridTrackPlacement grid_column_start() const; |
165 | | CSS::GridTrackPlacement grid_row_end() const; |
166 | | CSS::GridTrackPlacement grid_row_start() const; |
167 | | Optional<CSS::BorderCollapse> border_collapse() const; |
168 | | Vector<Vector<String>> grid_template_areas() const; |
169 | | Optional<CSS::ObjectFit> object_fit() const; |
170 | | CSS::ObjectPosition object_position() const; |
171 | | Optional<CSS::TableLayout> table_layout() const; |
172 | | Optional<CSS::Direction> direction() const; |
173 | | Optional<CSS::UnicodeBidi> unicode_bidi() const; |
174 | | Optional<CSS::WritingMode> writing_mode() const; |
175 | | |
176 | | static Vector<CSS::Transformation> transformations_for_style_value(CSSStyleValue const& value); |
177 | | Vector<CSS::Transformation> transformations() const; |
178 | | Optional<CSS::TransformBox> transform_box() const; |
179 | | CSS::TransformOrigin transform_origin() const; |
180 | | Optional<CSS::Transformation> rotate(Layout::Node const&) const; |
181 | | |
182 | | Optional<CSS::MaskType> mask_type() const; |
183 | | Color stop_color() const; |
184 | | float stop_opacity() const; |
185 | | float fill_opacity() const; |
186 | | Optional<CSS::StrokeLinecap> stroke_linecap() const; |
187 | | Optional<CSS::StrokeLinejoin> stroke_linejoin() const; |
188 | | NumberOrCalculated stroke_miterlimit() const; |
189 | | float stroke_opacity() const; |
190 | | Optional<CSS::FillRule> fill_rule() const; |
191 | | Optional<CSS::ClipRule> clip_rule() const; |
192 | | |
193 | 0 | Gfx::Font const& first_available_computed_font() const { return m_data->m_font_list->first(); } |
194 | | |
195 | | Gfx::FontCascadeList const& computed_font_list() const |
196 | 0 | { |
197 | 0 | VERIFY(m_data->m_font_list); |
198 | 0 | return *m_data->m_font_list; |
199 | 0 | } |
200 | | |
201 | | void set_computed_font_list(NonnullRefPtr<Gfx::FontCascadeList> font_list) const |
202 | 0 | { |
203 | 0 | m_data->m_font_list = move(font_list); |
204 | 0 | } |
205 | | |
206 | | [[nodiscard]] CSSPixels compute_line_height(CSSPixelRect const& viewport_rect, Length::FontMetrics const& font_metrics, Length::FontMetrics const& root_font_metrics) const; |
207 | | |
208 | 0 | [[nodiscard]] CSSPixels line_height() const { return *m_data->m_line_height; } |
209 | 0 | void set_line_height(Badge<StyleComputer> const&, CSSPixels line_height) { m_data->m_line_height = line_height; } |
210 | | |
211 | | bool operator==(StyleProperties const&) const; |
212 | | |
213 | | Optional<CSS::Positioning> position() const; |
214 | | Optional<int> z_index() const; |
215 | | |
216 | | void set_math_depth(int math_depth); |
217 | 0 | int math_depth() const { return m_data->m_math_depth; } |
218 | | |
219 | | QuotesData quotes() const; |
220 | | Vector<CounterData> counter_data(PropertyID) const; |
221 | | |
222 | | Optional<CSS::ScrollbarWidth> scrollbar_width() const; |
223 | | |
224 | | static NonnullRefPtr<Gfx::Font const> font_fallback(bool monospace, bool bold); |
225 | | |
226 | | static float resolve_opacity_value(CSSStyleValue const& value); |
227 | | |
228 | | private: |
229 | | friend class StyleComputer; |
230 | | |
231 | | Optional<CSS::Overflow> overflow(CSS::PropertyID) const; |
232 | | Vector<CSS::ShadowData> shadow(CSS::PropertyID, Layout::Node const&) const; |
233 | | |
234 | | AK::CopyOnWrite<StyleProperties::Data> m_data; |
235 | | }; |
236 | | |
237 | | } |