Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
4 * Copyright (c) 2021-2023, Sam Atkins <atkinssj@serenityos.org>
5 * Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 */
9
10#pragma once
11
12#include <AK/Concepts.h>
13#include <AK/DeprecatedString.h>
14#include <AK/Function.h>
15#include <AK/GenericShorthands.h>
16#include <AK/NonnullOwnPtr.h>
17#include <AK/RefCounted.h>
18#include <AK/RefPtr.h>
19#include <AK/String.h>
20#include <AK/StringView.h>
21#include <AK/URL.h>
22#include <AK/Variant.h>
23#include <AK/Vector.h>
24#include <AK/WeakPtr.h>
25#include <LibGfx/Bitmap.h>
26#include <LibGfx/Color.h>
27#include <LibGfx/Painter.h>
28#include <LibWeb/CSS/Angle.h>
29#include <LibWeb/CSS/Display.h>
30#include <LibWeb/CSS/Enums.h>
31#include <LibWeb/CSS/Frequency.h>
32#include <LibWeb/CSS/GridTrackPlacement.h>
33#include <LibWeb/CSS/GridTrackSize.h>
34#include <LibWeb/CSS/Length.h>
35#include <LibWeb/CSS/Number.h>
36#include <LibWeb/CSS/Parser/ComponentValue.h>
37#include <LibWeb/CSS/Percentage.h>
38#include <LibWeb/CSS/PropertyID.h>
39#include <LibWeb/CSS/Resolution.h>
40#include <LibWeb/CSS/Time.h>
41#include <LibWeb/CSS/TransformFunctions.h>
42#include <LibWeb/CSS/ValueID.h>
43#include <LibWeb/Forward.h>
44#include <LibWeb/Loader/ImageResource.h>
45#include <LibWeb/Painting/GradientPainting.h>
46
47namespace Web::CSS {
48
49enum class BackgroundSize {
50 Contain,
51 Cover,
52 LengthPercentage,
53};
54
55enum class ShadowPlacement {
56 Outer,
57 Inner,
58};
59
60enum class FlexBasis {
61 Content,
62 LengthPercentage,
63 Auto,
64};
65
66// Note: The sides must be before the corners in this enum (as this order is used in parsing).
67enum class SideOrCorner {
68 Top,
69 Bottom,
70 Left,
71 Right,
72 TopLeft,
73 TopRight,
74 BottomLeft,
75 BottomRight
76};
77
78template<typename TPosition>
79struct ColorStopListElement {
80 using PositionType = TPosition;
81 struct ColorHint {
82 TPosition value;
83 inline bool operator==(ColorHint const&) const = default;
84 };
85
86 Optional<ColorHint> transition_hint;
87 struct ColorStop {
88 Color color;
89 Optional<TPosition> position;
90 Optional<TPosition> second_position = {};
91 inline bool operator==(ColorStop const&) const = default;
92 } color_stop;
93
94 inline bool operator==(ColorStopListElement const&) const = default;
95};
96
97using LinearColorStopListElement = ColorStopListElement<LengthPercentage>;
98using AngularColorStopListElement = ColorStopListElement<AnglePercentage>;
99
100// FIXME: Named PositionValue to avoid conflicts with enums, but this represents a <position>
101struct PositionValue {
102 enum class HorizontalPreset {
103 Left,
104 Center,
105 Right
106 };
107
108 enum class VerticalPreset {
109 Top,
110 Center,
111 Bottom
112 };
113
114 enum class HorizontalEdge {
115 Left,
116 Right
117 };
118
119 enum class VerticalEdge {
120 Top,
121 Bottom
122 };
123
124 static PositionValue center()
125 {
126 return PositionValue { HorizontalPreset::Center, VerticalPreset::Center };
127 }
128
129 Variant<HorizontalPreset, LengthPercentage> horizontal_position { HorizontalPreset::Left };
130 Variant<VerticalPreset, LengthPercentage> vertical_position { VerticalPreset::Top };
131 HorizontalEdge x_relative_to { HorizontalEdge::Left };
132 VerticalEdge y_relative_to { VerticalEdge::Top };
133
134 CSSPixelPoint resolved(Layout::Node const& node, CSSPixelRect const& rect) const;
135 ErrorOr<void> serialize(StringBuilder&) const;
136 bool operator==(PositionValue const&) const = default;
137};
138
139struct EdgeRect {
140 Length top_edge;
141 Length right_edge;
142 Length bottom_edge;
143 Length left_edge;
144 Gfx::FloatRect resolved(Layout::Node const&, Gfx::FloatRect) const;
145 bool operator==(EdgeRect const&) const = default;
146};
147
148namespace Filter {
149
150struct Blur {
151 Optional<Length> radius {};
152 float resolved_radius(Layout::Node const&) const;
153 bool operator==(Blur const&) const = default;
154};
155
156struct DropShadow {
157 Length offset_x;
158 Length offset_y;
159 Optional<Length> radius {};
160 Optional<Color> color {};
161 struct Resolved {
162 float offset_x;
163 float offset_y;
164 float radius;
165 Color color;
166 };
167 Resolved resolved(Layout::Node const&) const;
168 bool operator==(DropShadow const&) const = default;
169};
170
171struct HueRotate {
172 struct Zero {
173 bool operator==(Zero const&) const = default;
174 };
175 using AngleOrZero = Variant<Angle, Zero>;
176 Optional<AngleOrZero> angle {};
177 float angle_degrees() const;
178 bool operator==(HueRotate const&) const = default;
179};
180
181struct Color {
182 enum class Operation {
183 Brightness,
184 Contrast,
185 Grayscale,
186 Invert,
187 Opacity,
188 Saturate,
189 Sepia
190 } operation;
191 Optional<NumberPercentage> amount {};
192 float resolved_amount() const;
193 bool operator==(Color const&) const = default;
194};
195
196};
197
198using FilterFunction = Variant<Filter::Blur, Filter::DropShadow, Filter::HueRotate, Filter::Color>;
199
200// FIXME: Find a better place for this helper.
201inline Gfx::Painter::ScalingMode to_gfx_scaling_mode(CSS::ImageRendering css_value)
202{
203 switch (css_value) {
204 case CSS::ImageRendering::Auto:
205 case CSS::ImageRendering::HighQuality:
206 case CSS::ImageRendering::Smooth:
207 return Gfx::Painter::ScalingMode::BilinearBlend;
208 case CSS::ImageRendering::CrispEdges:
209 return Gfx::Painter::ScalingMode::NearestNeighbor;
210 case CSS::ImageRendering::Pixelated:
211 return Gfx::Painter::ScalingMode::SmoothPixels;
212 }
213 VERIFY_NOT_REACHED();
214}
215
216template<typename T>
217struct ValueComparingNonnullRefPtr : public NonnullRefPtr<T> {
218 using NonnullRefPtr<T>::NonnullRefPtr;
219
220 ValueComparingNonnullRefPtr(NonnullRefPtr<T> const& other)
221 : NonnullRefPtr<T>(other)
222 {
223 }
224
225 ValueComparingNonnullRefPtr(NonnullRefPtr<T>&& other)
226 : NonnullRefPtr<T>(move(other))
227 {
228 }
229
230 bool operator==(ValueComparingNonnullRefPtr const& other) const
231 {
232 return this->ptr() == other.ptr() || this->ptr()->equals(*other);
233 }
234
235private:
236 using NonnullRefPtr<T>::operator==;
237};
238
239template<typename T>
240struct ValueComparingRefPtr : public RefPtr<T> {
241 using RefPtr<T>::RefPtr;
242
243 ValueComparingRefPtr(RefPtr<T> const& other)
244 : RefPtr<T>(other)
245 {
246 }
247
248 ValueComparingRefPtr(RefPtr<T>&& other)
249 : RefPtr<T>(move(other))
250 {
251 }
252
253 template<typename U>
254 bool operator==(ValueComparingNonnullRefPtr<U> const& other) const
255 {
256 return this->ptr() == other.ptr() || (this->ptr() && this->ptr()->equals(*other));
257 }
258
259 bool operator==(ValueComparingRefPtr const& other) const
260 {
261 return this->ptr() == other.ptr() || (this->ptr() && other.ptr() && this->ptr()->equals(*other));
262 }
263
264private:
265 using RefPtr<T>::operator==;
266};
267
268using StyleValueVector = Vector<ValueComparingNonnullRefPtr<StyleValue const>>;
269
270class StyleValue : public RefCounted<StyleValue> {
271public:
272 virtual ~StyleValue() = default;
273
274 enum class Type {
275 Angle,
276 Background,
277 BackgroundRepeat,
278 BackgroundSize,
279 Border,
280 BorderRadius,
281 BorderRadiusShorthand,
282 Calculated,
283 Color,
284 ConicGradient,
285 Content,
286 FilterValueList,
287 Flex,
288 FlexFlow,
289 Font,
290 Frequency,
291 GridAreaShorthand,
292 GridTemplateArea,
293 GridTrackPlacement,
294 GridTrackPlacementShorthand,
295 GridTrackSizeList,
296 Identifier,
297 Image,
298 Inherit,
299 Initial,
300 Invalid,
301 Length,
302 LinearGradient,
303 ListStyle,
304 Numeric,
305 Overflow,
306 Percentage,
307 Position,
308 RadialGradient,
309 Rect,
310 Resolution,
311 Shadow,
312 String,
313 TextDecoration,
314 Time,
315 Transformation,
316 Unresolved,
317 Unset,
318 ValueList
319 };
320
321 Type type() const { return m_type; }
322
323 bool is_abstract_image() const { return AK::first_is_one_of(type(), Type::Image, Type::LinearGradient, Type::ConicGradient, Type::RadialGradient); }
324 bool is_angle() const { return type() == Type::Angle; }
325 bool is_background() const { return type() == Type::Background; }
326 bool is_background_repeat() const { return type() == Type::BackgroundRepeat; }
327 bool is_background_size() const { return type() == Type::BackgroundSize; }
328 bool is_border() const { return type() == Type::Border; }
329 bool is_border_radius() const { return type() == Type::BorderRadius; }
330 bool is_border_radius_shorthand() const { return type() == Type::BorderRadiusShorthand; }
331 bool is_calculated() const { return type() == Type::Calculated; }
332 bool is_color() const { return type() == Type::Color; }
333 bool is_conic_gradient() const { return type() == Type::ConicGradient; }
334 bool is_content() const { return type() == Type::Content; }
335 bool is_filter_value_list() const { return type() == Type::FilterValueList; }
336 bool is_flex() const { return type() == Type::Flex; }
337 bool is_flex_flow() const { return type() == Type::FlexFlow; }
338 bool is_font() const { return type() == Type::Font; }
339 bool is_frequency() const { return type() == Type::Frequency; }
340 bool is_grid_area_shorthand() const { return type() == Type::GridAreaShorthand; }
341 bool is_grid_template_area() const { return type() == Type::GridTemplateArea; }
342 bool is_grid_track_placement() const { return type() == Type::GridTrackPlacement; }
343 bool is_grid_track_placement_shorthand() const { return type() == Type::GridTrackPlacementShorthand; }
344 bool is_grid_track_size_list() const { return type() == Type::GridTrackSizeList; }
345 bool is_identifier() const { return type() == Type::Identifier; }
346 bool is_image() const { return type() == Type::Image; }
347 bool is_inherit() const { return type() == Type::Inherit; }
348 bool is_initial() const { return type() == Type::Initial; }
349 bool is_length() const { return type() == Type::Length; }
350 bool is_linear_gradient() const { return type() == Type::LinearGradient; }
351 bool is_list_style() const { return type() == Type::ListStyle; }
352 bool is_numeric() const { return type() == Type::Numeric; }
353 bool is_overflow() const { return type() == Type::Overflow; }
354 bool is_percentage() const { return type() == Type::Percentage; }
355 bool is_position() const { return type() == Type::Position; }
356 bool is_radial_gradient() const { return type() == Type::RadialGradient; }
357 bool is_rect() const { return type() == Type::Rect; }
358 bool is_resolution() const { return type() == Type::Resolution; }
359 bool is_shadow() const { return type() == Type::Shadow; }
360 bool is_string() const { return type() == Type::String; }
361 bool is_text_decoration() const { return type() == Type::TextDecoration; }
362 bool is_time() const { return type() == Type::Time; }
363 bool is_transformation() const { return type() == Type::Transformation; }
364 bool is_unresolved() const { return type() == Type::Unresolved; }
365 bool is_unset() const { return type() == Type::Unset; }
366 bool is_value_list() const { return type() == Type::ValueList; }
367
368 bool is_builtin() const { return is_inherit() || is_initial() || is_unset(); }
369
370 AbstractImageStyleValue const& as_abstract_image() const;
371 AngleStyleValue const& as_angle() const;
372 BackgroundStyleValue const& as_background() const;
373 BackgroundRepeatStyleValue const& as_background_repeat() const;
374 BackgroundSizeStyleValue const& as_background_size() const;
375 BorderRadiusStyleValue const& as_border_radius() const;
376 BorderRadiusShorthandStyleValue const& as_border_radius_shorthand() const;
377 BorderStyleValue const& as_border() const;
378 CalculatedStyleValue const& as_calculated() const;
379 ColorStyleValue const& as_color() const;
380 ConicGradientStyleValue const& as_conic_gradient() const;
381 ContentStyleValue const& as_content() const;
382 FilterValueListStyleValue const& as_filter_value_list() const;
383 FlexFlowStyleValue const& as_flex_flow() const;
384 FlexStyleValue const& as_flex() const;
385 FontStyleValue const& as_font() const;
386 FrequencyStyleValue const& as_frequency() const;
387 GridAreaShorthandStyleValue const& as_grid_area_shorthand() const;
388 GridTemplateAreaStyleValue const& as_grid_template_area() const;
389 GridTrackPlacementShorthandStyleValue const& as_grid_track_placement_shorthand() const;
390 GridTrackPlacementStyleValue const& as_grid_track_placement() const;
391 GridTrackSizeStyleValue const& as_grid_track_size_list() const;
392 IdentifierStyleValue const& as_identifier() const;
393 ImageStyleValue const& as_image() const;
394 InheritStyleValue const& as_inherit() const;
395 InitialStyleValue const& as_initial() const;
396 LengthStyleValue const& as_length() const;
397 LinearGradientStyleValue const& as_linear_gradient() const;
398 ListStyleStyleValue const& as_list_style() const;
399 NumericStyleValue const& as_numeric() const;
400 OverflowStyleValue const& as_overflow() const;
401 PercentageStyleValue const& as_percentage() const;
402 PositionStyleValue const& as_position() const;
403 RadialGradientStyleValue const& as_radial_gradient() const;
404 RectStyleValue const& as_rect() const;
405 ResolutionStyleValue const& as_resolution() const;
406 ShadowStyleValue const& as_shadow() const;
407 StringStyleValue const& as_string() const;
408 TextDecorationStyleValue const& as_text_decoration() const;
409 TimeStyleValue const& as_time() const;
410 TransformationStyleValue const& as_transformation() const;
411 UnresolvedStyleValue const& as_unresolved() const;
412 UnsetStyleValue const& as_unset() const;
413 StyleValueList const& as_value_list() const;
414
415 AbstractImageStyleValue& as_abstract_image() { return const_cast<AbstractImageStyleValue&>(const_cast<StyleValue const&>(*this).as_abstract_image()); }
416 AngleStyleValue& as_angle() { return const_cast<AngleStyleValue&>(const_cast<StyleValue const&>(*this).as_angle()); }
417 BackgroundStyleValue& as_background() { return const_cast<BackgroundStyleValue&>(const_cast<StyleValue const&>(*this).as_background()); }
418 BackgroundRepeatStyleValue& as_background_repeat() { return const_cast<BackgroundRepeatStyleValue&>(const_cast<StyleValue const&>(*this).as_background_repeat()); }
419 BackgroundSizeStyleValue& as_background_size() { return const_cast<BackgroundSizeStyleValue&>(const_cast<StyleValue const&>(*this).as_background_size()); }
420 BorderRadiusStyleValue& as_border_radius() { return const_cast<BorderRadiusStyleValue&>(const_cast<StyleValue const&>(*this).as_border_radius()); }
421 BorderRadiusShorthandStyleValue& as_border_radius_shorthand() { return const_cast<BorderRadiusShorthandStyleValue&>(const_cast<StyleValue const&>(*this).as_border_radius_shorthand()); }
422 BorderStyleValue& as_border() { return const_cast<BorderStyleValue&>(const_cast<StyleValue const&>(*this).as_border()); }
423 CalculatedStyleValue& as_calculated() { return const_cast<CalculatedStyleValue&>(const_cast<StyleValue const&>(*this).as_calculated()); }
424 ColorStyleValue& as_color() { return const_cast<ColorStyleValue&>(const_cast<StyleValue const&>(*this).as_color()); }
425 ConicGradientStyleValue& as_conic_gradient() { return const_cast<ConicGradientStyleValue&>(const_cast<StyleValue const&>(*this).as_conic_gradient()); }
426 ContentStyleValue& as_content() { return const_cast<ContentStyleValue&>(const_cast<StyleValue const&>(*this).as_content()); }
427 FilterValueListStyleValue& as_filter_value_list() { return const_cast<FilterValueListStyleValue&>(const_cast<StyleValue const&>(*this).as_filter_value_list()); }
428 FlexFlowStyleValue& as_flex_flow() { return const_cast<FlexFlowStyleValue&>(const_cast<StyleValue const&>(*this).as_flex_flow()); }
429 FlexStyleValue& as_flex() { return const_cast<FlexStyleValue&>(const_cast<StyleValue const&>(*this).as_flex()); }
430 FontStyleValue& as_font() { return const_cast<FontStyleValue&>(const_cast<StyleValue const&>(*this).as_font()); }
431 FrequencyStyleValue& as_frequency() { return const_cast<FrequencyStyleValue&>(const_cast<StyleValue const&>(*this).as_frequency()); }
432 GridAreaShorthandStyleValue& as_grid_area_shorthand() { return const_cast<GridAreaShorthandStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_area_shorthand()); }
433 GridTemplateAreaStyleValue& as_grid_template_area() { return const_cast<GridTemplateAreaStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_template_area()); }
434 GridTrackPlacementShorthandStyleValue& as_grid_track_placement_shorthand() { return const_cast<GridTrackPlacementShorthandStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_placement_shorthand()); }
435 GridTrackPlacementStyleValue& as_grid_track_placement() { return const_cast<GridTrackPlacementStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_placement()); }
436 GridTrackSizeStyleValue& as_grid_track_size_list() { return const_cast<GridTrackSizeStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_size_list()); }
437 IdentifierStyleValue& as_identifier() { return const_cast<IdentifierStyleValue&>(const_cast<StyleValue const&>(*this).as_identifier()); }
438 ImageStyleValue& as_image() { return const_cast<ImageStyleValue&>(const_cast<StyleValue const&>(*this).as_image()); }
439 InheritStyleValue& as_inherit() { return const_cast<InheritStyleValue&>(const_cast<StyleValue const&>(*this).as_inherit()); }
440 InitialStyleValue& as_initial() { return const_cast<InitialStyleValue&>(const_cast<StyleValue const&>(*this).as_initial()); }
441 LengthStyleValue& as_length() { return const_cast<LengthStyleValue&>(const_cast<StyleValue const&>(*this).as_length()); }
442 LinearGradientStyleValue& as_linear_gradient() { return const_cast<LinearGradientStyleValue&>(const_cast<StyleValue const&>(*this).as_linear_gradient()); }
443 ListStyleStyleValue& as_list_style() { return const_cast<ListStyleStyleValue&>(const_cast<StyleValue const&>(*this).as_list_style()); }
444 NumericStyleValue& as_numeric() { return const_cast<NumericStyleValue&>(const_cast<StyleValue const&>(*this).as_numeric()); }
445 OverflowStyleValue& as_overflow() { return const_cast<OverflowStyleValue&>(const_cast<StyleValue const&>(*this).as_overflow()); }
446 PercentageStyleValue& as_percentage() { return const_cast<PercentageStyleValue&>(const_cast<StyleValue const&>(*this).as_percentage()); }
447 PositionStyleValue& as_position() { return const_cast<PositionStyleValue&>(const_cast<StyleValue const&>(*this).as_position()); }
448 RadialGradientStyleValue& as_radial_gradient() { return const_cast<RadialGradientStyleValue&>(const_cast<StyleValue const&>(*this).as_radial_gradient()); }
449 RectStyleValue& as_rect() { return const_cast<RectStyleValue&>(const_cast<StyleValue const&>(*this).as_rect()); }
450 ResolutionStyleValue& as_resolution() { return const_cast<ResolutionStyleValue&>(const_cast<StyleValue const&>(*this).as_resolution()); }
451 ShadowStyleValue& as_shadow() { return const_cast<ShadowStyleValue&>(const_cast<StyleValue const&>(*this).as_shadow()); }
452 StringStyleValue& as_string() { return const_cast<StringStyleValue&>(const_cast<StyleValue const&>(*this).as_string()); }
453 TextDecorationStyleValue& as_text_decoration() { return const_cast<TextDecorationStyleValue&>(const_cast<StyleValue const&>(*this).as_text_decoration()); }
454 TimeStyleValue& as_time() { return const_cast<TimeStyleValue&>(const_cast<StyleValue const&>(*this).as_time()); }
455 TransformationStyleValue& as_transformation() { return const_cast<TransformationStyleValue&>(const_cast<StyleValue const&>(*this).as_transformation()); }
456 UnresolvedStyleValue& as_unresolved() { return const_cast<UnresolvedStyleValue&>(const_cast<StyleValue const&>(*this).as_unresolved()); }
457 UnsetStyleValue& as_unset() { return const_cast<UnsetStyleValue&>(const_cast<StyleValue const&>(*this).as_unset()); }
458 StyleValueList& as_value_list() { return const_cast<StyleValueList&>(const_cast<StyleValue const&>(*this).as_value_list()); }
459
460 virtual bool has_auto() const { return false; }
461 virtual bool has_color() const { return false; }
462 virtual bool has_identifier() const { return false; }
463 virtual bool has_length() const { return false; }
464 virtual bool has_rect() const { return false; }
465 virtual bool has_number() const { return false; }
466 virtual bool has_integer() const { return false; }
467
468 virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const;
469
470 virtual Color to_color(Layout::NodeWithStyle const&) const { return {}; }
471 virtual EdgeRect to_rect() const { VERIFY_NOT_REACHED(); }
472 virtual CSS::ValueID to_identifier() const { return ValueID::Invalid; }
473 virtual Length to_length() const { VERIFY_NOT_REACHED(); }
474 virtual float to_number() const { return 0; }
475 virtual float to_integer() const { return 0; }
476 virtual ErrorOr<String> to_string() const = 0;
477
478 virtual bool equals(StyleValue const& other) const = 0;
479
480 bool operator==(StyleValue const& other) const
481 {
482 return this->equals(other);
483 }
484
485protected:
486 explicit StyleValue(Type);
487
488private:
489 Type m_type { Type::Invalid };
490};
491
492template<typename T>
493struct StyleValueWithDefaultOperators : public StyleValue {
494 using StyleValue::StyleValue;
495
496 virtual bool equals(StyleValue const& other) const override
497 {
498 if (type() != other.type())
499 return false;
500 auto const& typed_other = static_cast<T const&>(other);
501 return static_cast<T const&>(*this).properties_equal(typed_other);
502 }
503};
504
505class AngleStyleValue : public StyleValueWithDefaultOperators<AngleStyleValue> {
506public:
507 static ValueComparingNonnullRefPtr<AngleStyleValue> create(Angle angle)
508 {
509 return adopt_ref(*new AngleStyleValue(move(angle)));
510 }
511 virtual ~AngleStyleValue() override { }
512
513 Angle const& angle() const { return m_angle; }
514
515 virtual ErrorOr<String> to_string() const override { return m_angle.to_string(); }
516
517 bool properties_equal(AngleStyleValue const& other) const { return m_angle == other.m_angle; }
518
519private:
520 explicit AngleStyleValue(Angle angle)
521 : StyleValueWithDefaultOperators(Type::Angle)
522 , m_angle(move(angle))
523 {
524 }
525
526 Angle m_angle;
527};
528
529class BackgroundStyleValue final : public StyleValueWithDefaultOperators<BackgroundStyleValue> {
530public:
531 static ValueComparingNonnullRefPtr<BackgroundStyleValue> create(
532 ValueComparingNonnullRefPtr<StyleValue const> color,
533 ValueComparingNonnullRefPtr<StyleValue const> image,
534 ValueComparingNonnullRefPtr<StyleValue const> position,
535 ValueComparingNonnullRefPtr<StyleValue const> size,
536 ValueComparingNonnullRefPtr<StyleValue const> repeat,
537 ValueComparingNonnullRefPtr<StyleValue const> attachment,
538 ValueComparingNonnullRefPtr<StyleValue const> origin,
539 ValueComparingNonnullRefPtr<StyleValue const> clip)
540 {
541 return adopt_ref(*new BackgroundStyleValue(move(color), move(image), move(position), move(size), move(repeat), move(attachment), move(origin), move(clip)));
542 }
543 virtual ~BackgroundStyleValue() override = default;
544
545 size_t layer_count() const { return m_properties.layer_count; }
546
547 auto attachment() const { return m_properties.attachment; }
548 auto clip() const { return m_properties.clip; }
549 auto color() const { return m_properties.color; }
550 auto image() const { return m_properties.image; }
551 auto origin() const { return m_properties.origin; }
552 auto position() const { return m_properties.position; }
553 auto repeat() const { return m_properties.repeat; }
554 auto size() const { return m_properties.size; }
555
556 virtual ErrorOr<String> to_string() const override;
557
558 bool properties_equal(BackgroundStyleValue const& other) const { return m_properties == other.m_properties; }
559
560private:
561 BackgroundStyleValue(
562 ValueComparingNonnullRefPtr<StyleValue const> color,
563 ValueComparingNonnullRefPtr<StyleValue const> image,
564 ValueComparingNonnullRefPtr<StyleValue const> position,
565 ValueComparingNonnullRefPtr<StyleValue const> size,
566 ValueComparingNonnullRefPtr<StyleValue const> repeat,
567 ValueComparingNonnullRefPtr<StyleValue const> attachment,
568 ValueComparingNonnullRefPtr<StyleValue const> origin,
569 ValueComparingNonnullRefPtr<StyleValue const> clip);
570
571 struct Properties {
572 ValueComparingNonnullRefPtr<StyleValue const> color;
573 ValueComparingNonnullRefPtr<StyleValue const> image;
574 ValueComparingNonnullRefPtr<StyleValue const> position;
575 ValueComparingNonnullRefPtr<StyleValue const> size;
576 ValueComparingNonnullRefPtr<StyleValue const> repeat;
577 ValueComparingNonnullRefPtr<StyleValue const> attachment;
578 ValueComparingNonnullRefPtr<StyleValue const> origin;
579 ValueComparingNonnullRefPtr<StyleValue const> clip;
580 size_t layer_count;
581 bool operator==(Properties const&) const = default;
582 } m_properties;
583};
584
585class BackgroundRepeatStyleValue final : public StyleValueWithDefaultOperators<BackgroundRepeatStyleValue> {
586public:
587 static ValueComparingNonnullRefPtr<BackgroundRepeatStyleValue> create(Repeat repeat_x, Repeat repeat_y)
588 {
589 return adopt_ref(*new BackgroundRepeatStyleValue(repeat_x, repeat_y));
590 }
591 virtual ~BackgroundRepeatStyleValue() override = default;
592
593 Repeat repeat_x() const { return m_properties.repeat_x; }
594 Repeat repeat_y() const { return m_properties.repeat_y; }
595
596 virtual ErrorOr<String> to_string() const override;
597
598 bool properties_equal(BackgroundRepeatStyleValue const& other) const { return m_properties == other.m_properties; }
599
600private:
601 BackgroundRepeatStyleValue(Repeat repeat_x, Repeat repeat_y)
602 : StyleValueWithDefaultOperators(Type::BackgroundRepeat)
603 , m_properties { .repeat_x = repeat_x, .repeat_y = repeat_y }
604 {
605 }
606
607 struct Properties {
608 Repeat repeat_x;
609 Repeat repeat_y;
610 bool operator==(Properties const&) const = default;
611 } m_properties;
612};
613
614// NOTE: This is not used for identifier sizes, like `cover` and `contain`.
615class BackgroundSizeStyleValue final : public StyleValueWithDefaultOperators<BackgroundSizeStyleValue> {
616public:
617 static ValueComparingNonnullRefPtr<BackgroundSizeStyleValue> create(LengthPercentage size_x, LengthPercentage size_y)
618 {
619 return adopt_ref(*new BackgroundSizeStyleValue(size_x, size_y));
620 }
621 virtual ~BackgroundSizeStyleValue() override = default;
622
623 LengthPercentage size_x() const { return m_properties.size_x; }
624 LengthPercentage size_y() const { return m_properties.size_y; }
625
626 virtual ErrorOr<String> to_string() const override;
627
628 bool properties_equal(BackgroundSizeStyleValue const& other) const { return m_properties == other.m_properties; }
629
630private:
631 BackgroundSizeStyleValue(LengthPercentage size_x, LengthPercentage size_y)
632 : StyleValueWithDefaultOperators(Type::BackgroundSize)
633 , m_properties { .size_x = size_x, .size_y = size_y }
634 {
635 }
636
637 struct Properties {
638 LengthPercentage size_x;
639 LengthPercentage size_y;
640 bool operator==(Properties const&) const = default;
641 } m_properties;
642};
643
644class BorderStyleValue final : public StyleValueWithDefaultOperators<BorderStyleValue> {
645public:
646 static ValueComparingNonnullRefPtr<BorderStyleValue> create(
647 ValueComparingNonnullRefPtr<StyleValue> border_width,
648 ValueComparingNonnullRefPtr<StyleValue> border_style,
649 ValueComparingNonnullRefPtr<StyleValue> border_color)
650 {
651 return adopt_ref(*new BorderStyleValue(move(border_width), move(border_style), move(border_color)));
652 }
653 virtual ~BorderStyleValue() override = default;
654
655 ValueComparingNonnullRefPtr<StyleValue> border_width() const { return m_properties.border_width; }
656 ValueComparingNonnullRefPtr<StyleValue> border_style() const { return m_properties.border_style; }
657 ValueComparingNonnullRefPtr<StyleValue> border_color() const { return m_properties.border_color; }
658
659 virtual ErrorOr<String> to_string() const override;
660
661 bool properties_equal(BorderStyleValue const& other) const { return m_properties == other.m_properties; }
662
663private:
664 BorderStyleValue(
665 ValueComparingNonnullRefPtr<StyleValue> border_width,
666 ValueComparingNonnullRefPtr<StyleValue> border_style,
667 ValueComparingNonnullRefPtr<StyleValue> border_color)
668 : StyleValueWithDefaultOperators(Type::Border)
669 , m_properties { .border_width = move(border_width), .border_style = move(border_style), .border_color = move(border_color) }
670 {
671 }
672
673 struct Properties {
674 ValueComparingNonnullRefPtr<StyleValue> border_width;
675 ValueComparingNonnullRefPtr<StyleValue> border_style;
676 ValueComparingNonnullRefPtr<StyleValue> border_color;
677 bool operator==(Properties const&) const = default;
678 } m_properties;
679};
680
681class BorderRadiusStyleValue final : public StyleValueWithDefaultOperators<BorderRadiusStyleValue> {
682public:
683 static ValueComparingNonnullRefPtr<BorderRadiusStyleValue> create(LengthPercentage const& horizontal_radius, LengthPercentage const& vertical_radius)
684 {
685 return adopt_ref(*new BorderRadiusStyleValue(horizontal_radius, vertical_radius));
686 }
687 virtual ~BorderRadiusStyleValue() override = default;
688
689 LengthPercentage const& horizontal_radius() const { return m_properties.horizontal_radius; }
690 LengthPercentage const& vertical_radius() const { return m_properties.vertical_radius; }
691 bool is_elliptical() const { return m_properties.is_elliptical; }
692
693 virtual ErrorOr<String> to_string() const override;
694
695 bool properties_equal(BorderRadiusStyleValue const& other) const { return m_properties == other.m_properties; }
696
697private:
698 BorderRadiusStyleValue(LengthPercentage const& horizontal_radius, LengthPercentage const& vertical_radius)
699 : StyleValueWithDefaultOperators(Type::BorderRadius)
700 , m_properties { .is_elliptical = horizontal_radius != vertical_radius, .horizontal_radius = horizontal_radius, .vertical_radius = vertical_radius }
701 {
702 }
703
704 virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const override;
705
706 struct Properties {
707 bool is_elliptical;
708 LengthPercentage horizontal_radius;
709 LengthPercentage vertical_radius;
710 bool operator==(Properties const&) const = default;
711 } m_properties;
712};
713
714class BorderRadiusShorthandStyleValue final : public StyleValueWithDefaultOperators<BorderRadiusShorthandStyleValue> {
715public:
716 static ValueComparingNonnullRefPtr<BorderRadiusShorthandStyleValue> create(
717 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> top_left,
718 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> top_right,
719 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> bottom_right,
720 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> bottom_left)
721 {
722 return adopt_ref(*new BorderRadiusShorthandStyleValue(move(top_left), move(top_right), move(bottom_right), move(bottom_left)));
723 }
724 virtual ~BorderRadiusShorthandStyleValue() override = default;
725
726 auto top_left() const { return m_properties.top_left; }
727 auto top_right() const { return m_properties.top_right; }
728 auto bottom_right() const { return m_properties.bottom_right; }
729 auto bottom_left() const { return m_properties.bottom_left; }
730
731 virtual ErrorOr<String> to_string() const override;
732
733 bool properties_equal(BorderRadiusShorthandStyleValue const& other) const { return m_properties == other.m_properties; }
734
735private:
736 BorderRadiusShorthandStyleValue(
737 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> top_left,
738 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> top_right,
739 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> bottom_right,
740 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> bottom_left)
741 : StyleValueWithDefaultOperators(Type::BorderRadiusShorthand)
742 , m_properties { .top_left = move(top_left), .top_right = move(top_right), .bottom_right = move(bottom_right), .bottom_left = move(bottom_left) }
743 {
744 }
745
746 struct Properties {
747 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> top_left;
748 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> top_right;
749 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> bottom_right;
750 ValueComparingNonnullRefPtr<BorderRadiusStyleValue const> bottom_left;
751 bool operator==(Properties const&) const = default;
752 } m_properties;
753};
754
755class CalculatedStyleValue : public StyleValue {
756public:
757 enum class ResolvedType {
758 Angle,
759 Frequency,
760 Integer,
761 Length,
762 Number,
763 Percentage,
764 Time,
765 };
766
767 enum class SumOperation {
768 Add,
769 Subtract,
770 };
771 enum class ProductOperation {
772 Multiply,
773 Divide,
774 };
775
776 using PercentageBasis = Variant<Empty, Angle, Frequency, Length, Time>;
777
778 class CalculationResult {
779 public:
780 using Value = Variant<Number, Angle, Frequency, Length, Percentage, Time>;
781 CalculationResult(Value value)
782 : m_value(move(value))
783 {
784 }
785 void add(CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis);
786 void subtract(CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis);
787 void multiply_by(CalculationResult const& other, Layout::Node const*);
788 void divide_by(CalculationResult const& other, Layout::Node const*);
789
790 Value const& value() const { return m_value; }
791
792 private:
793 void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis);
794 Value m_value;
795 };
796
797 struct CalcSum;
798 struct CalcSumPartWithOperator;
799 struct CalcProduct;
800 struct CalcProductPartWithOperator;
801 struct CalcNumberSum;
802 struct CalcNumberSumPartWithOperator;
803 struct CalcNumberProduct;
804 struct CalcNumberProductPartWithOperator;
805
806 struct CalcNumberValue {
807 Variant<Number, NonnullOwnPtr<CalcNumberSum>> value;
808 ErrorOr<String> to_string() const;
809 Optional<ResolvedType> resolved_type() const;
810 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
811 };
812
813 struct CalcValue {
814 Variant<Number, Angle, Frequency, Length, Percentage, Time, NonnullOwnPtr<CalcSum>> value;
815 ErrorOr<String> to_string() const;
816 Optional<ResolvedType> resolved_type() const;
817 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
818 bool contains_percentage() const;
819 };
820
821 // This represents that: https://www.w3.org/TR/css-values-3/#calc-syntax
822 struct CalcSum {
823 CalcSum(NonnullOwnPtr<CalcProduct> first_calc_product, Vector<NonnullOwnPtr<CalcSumPartWithOperator>> additional)
824 : first_calc_product(move(first_calc_product))
825 , zero_or_more_additional_calc_products(move(additional)) {};
826
827 NonnullOwnPtr<CalcProduct> first_calc_product;
828 Vector<NonnullOwnPtr<CalcSumPartWithOperator>> zero_or_more_additional_calc_products;
829
830 ErrorOr<String> to_string() const;
831 Optional<ResolvedType> resolved_type() const;
832 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
833
834 bool contains_percentage() const;
835 };
836
837 struct CalcNumberSum {
838 CalcNumberSum(NonnullOwnPtr<CalcNumberProduct> first_calc_number_product, Vector<NonnullOwnPtr<CalcNumberSumPartWithOperator>> additional)
839 : first_calc_number_product(move(first_calc_number_product))
840 , zero_or_more_additional_calc_number_products(move(additional)) {};
841
842 NonnullOwnPtr<CalcNumberProduct> first_calc_number_product;
843 Vector<NonnullOwnPtr<CalcNumberSumPartWithOperator>> zero_or_more_additional_calc_number_products;
844
845 ErrorOr<String> to_string() const;
846 Optional<ResolvedType> resolved_type() const;
847 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
848 };
849
850 struct CalcProduct {
851 CalcValue first_calc_value;
852 Vector<NonnullOwnPtr<CalcProductPartWithOperator>> zero_or_more_additional_calc_values;
853
854 ErrorOr<String> to_string() const;
855 Optional<ResolvedType> resolved_type() const;
856 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
857 bool contains_percentage() const;
858 };
859
860 struct CalcSumPartWithOperator {
861 CalcSumPartWithOperator(SumOperation op, NonnullOwnPtr<CalcProduct> calc_product)
862 : op(op)
863 , value(move(calc_product)) {};
864
865 SumOperation op;
866 NonnullOwnPtr<CalcProduct> value;
867
868 ErrorOr<String> to_string() const;
869 Optional<ResolvedType> resolved_type() const;
870 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
871 bool contains_percentage() const;
872 };
873
874 struct CalcProductPartWithOperator {
875 ProductOperation op;
876 Variant<CalcValue, CalcNumberValue> value;
877
878 ErrorOr<String> to_string() const;
879 Optional<ResolvedType> resolved_type() const;
880 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
881
882 bool contains_percentage() const;
883 };
884
885 struct CalcNumberProduct {
886 CalcNumberValue first_calc_number_value;
887 Vector<NonnullOwnPtr<CalcNumberProductPartWithOperator>> zero_or_more_additional_calc_number_values;
888
889 ErrorOr<String> to_string() const;
890 Optional<ResolvedType> resolved_type() const;
891 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
892 };
893
894 struct CalcNumberProductPartWithOperator {
895 ProductOperation op;
896 CalcNumberValue value;
897
898 ErrorOr<String> to_string() const;
899 Optional<ResolvedType> resolved_type() const;
900 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
901 };
902
903 struct CalcNumberSumPartWithOperator {
904 CalcNumberSumPartWithOperator(SumOperation op, NonnullOwnPtr<CalcNumberProduct> calc_number_product)
905 : op(op)
906 , value(move(calc_number_product)) {};
907
908 SumOperation op;
909 NonnullOwnPtr<CalcNumberProduct> value;
910
911 ErrorOr<String> to_string() const;
912 Optional<ResolvedType> resolved_type() const;
913 CalculationResult resolve(Layout::Node const*, PercentageBasis const& percentage_basis) const;
914 };
915
916 static ValueComparingNonnullRefPtr<CalculatedStyleValue> create(NonnullOwnPtr<CalcSum> calc_sum, ResolvedType resolved_type)
917 {
918 return adopt_ref(*new CalculatedStyleValue(move(calc_sum), resolved_type));
919 }
920
921 ErrorOr<String> to_string() const override;
922 virtual bool equals(StyleValue const& other) const override;
923 ResolvedType resolved_type() const { return m_resolved_type; }
924 NonnullOwnPtr<CalcSum> const& expression() const { return m_expression; }
925
926 bool resolves_to_angle() const { return m_resolved_type == ResolvedType::Angle; }
927 Optional<Angle> resolve_angle() const;
928 Optional<Angle> resolve_angle_percentage(Angle const& percentage_basis) const;
929
930 bool resolves_to_frequency() const { return m_resolved_type == ResolvedType::Frequency; }
931 Optional<Frequency> resolve_frequency() const;
932 Optional<Frequency> resolve_frequency_percentage(Frequency const& percentage_basis) const;
933
934 bool resolves_to_length() const { return m_resolved_type == ResolvedType::Length; }
935 Optional<Length> resolve_length(Layout::Node const& layout_node) const;
936 Optional<Length> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
937
938 bool resolves_to_percentage() const { return m_resolved_type == ResolvedType::Percentage; }
939 Optional<Percentage> resolve_percentage() const;
940
941 bool resolves_to_time() const { return m_resolved_type == ResolvedType::Time; }
942 Optional<Time> resolve_time() const;
943 Optional<Time> resolve_time_percentage(Time const& percentage_basis) const;
944
945 bool resolves_to_integer() const { return m_resolved_type == ResolvedType::Integer; }
946 bool resolves_to_number() const { return resolves_to_integer() || m_resolved_type == ResolvedType::Number; }
947 Optional<float> resolve_number();
948 Optional<i64> resolve_integer();
949
950 bool contains_percentage() const;
951
952private:
953 explicit CalculatedStyleValue(NonnullOwnPtr<CalcSum> calc_sum, ResolvedType resolved_type)
954 : StyleValue(Type::Calculated)
955 , m_resolved_type(resolved_type)
956 , m_expression(move(calc_sum))
957 {
958 }
959
960 ResolvedType m_resolved_type;
961 NonnullOwnPtr<CalcSum> m_expression;
962};
963
964class ColorStyleValue : public StyleValueWithDefaultOperators<ColorStyleValue> {
965public:
966 static ValueComparingNonnullRefPtr<ColorStyleValue> create(Color color);
967 virtual ~ColorStyleValue() override = default;
968
969 Color color() const { return m_color; }
970 virtual ErrorOr<String> to_string() const override;
971 virtual bool has_color() const override { return true; }
972 virtual Color to_color(Layout::NodeWithStyle const&) const override { return m_color; }
973
974 bool properties_equal(ColorStyleValue const& other) const { return m_color == other.m_color; };
975
976private:
977 explicit ColorStyleValue(Color color)
978 : StyleValueWithDefaultOperators(Type::Color)
979 , m_color(color)
980 {
981 }
982
983 Color m_color;
984};
985
986class ContentStyleValue final : public StyleValueWithDefaultOperators<ContentStyleValue> {
987public:
988 static ValueComparingNonnullRefPtr<ContentStyleValue> create(ValueComparingNonnullRefPtr<StyleValueList> content, ValueComparingRefPtr<StyleValueList> alt_text)
989 {
990 return adopt_ref(*new ContentStyleValue(move(content), move(alt_text)));
991 }
992
993 StyleValueList const& content() const { return *m_properties.content; }
994 bool has_alt_text() const { return !m_properties.alt_text.is_null(); }
995 StyleValueList const* alt_text() const { return m_properties.alt_text; }
996
997 virtual ErrorOr<String> to_string() const override;
998
999 bool properties_equal(ContentStyleValue const& other) const { return m_properties == other.m_properties; };
1000
1001private:
1002 ContentStyleValue(ValueComparingNonnullRefPtr<StyleValueList> content, ValueComparingRefPtr<StyleValueList> alt_text)
1003 : StyleValueWithDefaultOperators(Type::Content)
1004 , m_properties { .content = move(content), .alt_text = move(alt_text) }
1005 {
1006 }
1007
1008 struct Properties {
1009 ValueComparingNonnullRefPtr<StyleValueList> content;
1010 ValueComparingRefPtr<StyleValueList> alt_text;
1011 bool operator==(Properties const&) const = default;
1012 } m_properties;
1013};
1014
1015class FilterValueListStyleValue final : public StyleValueWithDefaultOperators<FilterValueListStyleValue> {
1016public:
1017 static ValueComparingNonnullRefPtr<FilterValueListStyleValue> create(
1018 Vector<FilterFunction> filter_value_list)
1019 {
1020 VERIFY(filter_value_list.size() >= 1);
1021 return adopt_ref(*new FilterValueListStyleValue(move(filter_value_list)));
1022 }
1023
1024 Vector<FilterFunction> const& filter_value_list() const { return m_filter_value_list; }
1025
1026 virtual ErrorOr<String> to_string() const override;
1027
1028 virtual ~FilterValueListStyleValue() override = default;
1029
1030 bool properties_equal(FilterValueListStyleValue const& other) const { return m_filter_value_list == other.m_filter_value_list; };
1031
1032private:
1033 FilterValueListStyleValue(Vector<FilterFunction> filter_value_list)
1034 : StyleValueWithDefaultOperators(Type::FilterValueList)
1035 , m_filter_value_list(move(filter_value_list))
1036 {
1037 }
1038
1039 // FIXME: No support for SVG filters yet
1040 Vector<FilterFunction> m_filter_value_list;
1041};
1042
1043class FlexStyleValue final : public StyleValueWithDefaultOperators<FlexStyleValue> {
1044public:
1045 static ValueComparingNonnullRefPtr<FlexStyleValue> create(
1046 ValueComparingNonnullRefPtr<StyleValue> grow,
1047 ValueComparingNonnullRefPtr<StyleValue> shrink,
1048 ValueComparingNonnullRefPtr<StyleValue> basis)
1049 {
1050 return adopt_ref(*new FlexStyleValue(move(grow), move(shrink), move(basis)));
1051 }
1052 virtual ~FlexStyleValue() override = default;
1053
1054 ValueComparingNonnullRefPtr<StyleValue> grow() const { return m_properties.grow; }
1055 ValueComparingNonnullRefPtr<StyleValue> shrink() const { return m_properties.shrink; }
1056 ValueComparingNonnullRefPtr<StyleValue> basis() const { return m_properties.basis; }
1057
1058 virtual ErrorOr<String> to_string() const override;
1059
1060 bool properties_equal(FlexStyleValue const& other) const { return m_properties == other.m_properties; };
1061
1062private:
1063 FlexStyleValue(
1064 ValueComparingNonnullRefPtr<StyleValue> grow,
1065 ValueComparingNonnullRefPtr<StyleValue> shrink,
1066 ValueComparingNonnullRefPtr<StyleValue> basis)
1067 : StyleValueWithDefaultOperators(Type::Flex)
1068 , m_properties { .grow = move(grow), .shrink = move(shrink), .basis = move(basis) }
1069 {
1070 }
1071
1072 struct Properties {
1073 ValueComparingNonnullRefPtr<StyleValue> grow;
1074 ValueComparingNonnullRefPtr<StyleValue> shrink;
1075 ValueComparingNonnullRefPtr<StyleValue> basis;
1076 bool operator==(Properties const&) const = default;
1077 } m_properties;
1078};
1079
1080class FlexFlowStyleValue final : public StyleValueWithDefaultOperators<FlexFlowStyleValue> {
1081public:
1082 static ValueComparingNonnullRefPtr<FlexFlowStyleValue> create(ValueComparingNonnullRefPtr<StyleValue> flex_direction, ValueComparingNonnullRefPtr<StyleValue> flex_wrap)
1083 {
1084 return adopt_ref(*new FlexFlowStyleValue(move(flex_direction), move(flex_wrap)));
1085 }
1086 virtual ~FlexFlowStyleValue() override = default;
1087
1088 ValueComparingNonnullRefPtr<StyleValue> flex_direction() const { return m_properties.flex_direction; }
1089 ValueComparingNonnullRefPtr<StyleValue> flex_wrap() const { return m_properties.flex_wrap; }
1090
1091 virtual ErrorOr<String> to_string() const override;
1092
1093 bool properties_equal(FlexFlowStyleValue const& other) const { return m_properties == other.m_properties; };
1094
1095private:
1096 FlexFlowStyleValue(ValueComparingNonnullRefPtr<StyleValue> flex_direction, ValueComparingNonnullRefPtr<StyleValue> flex_wrap)
1097 : StyleValueWithDefaultOperators(Type::FlexFlow)
1098 , m_properties { .flex_direction = move(flex_direction), .flex_wrap = move(flex_wrap) }
1099 {
1100 }
1101
1102 struct Properties {
1103 ValueComparingNonnullRefPtr<StyleValue> flex_direction;
1104 ValueComparingNonnullRefPtr<StyleValue> flex_wrap;
1105 bool operator==(Properties const&) const = default;
1106 } m_properties;
1107};
1108
1109class FontStyleValue final : public StyleValueWithDefaultOperators<FontStyleValue> {
1110public:
1111 static ValueComparingNonnullRefPtr<FontStyleValue> create(ValueComparingNonnullRefPtr<StyleValue> font_stretch, ValueComparingNonnullRefPtr<StyleValue> font_style, ValueComparingNonnullRefPtr<StyleValue> font_weight, ValueComparingNonnullRefPtr<StyleValue> font_size, ValueComparingNonnullRefPtr<StyleValue> line_height, ValueComparingNonnullRefPtr<StyleValue> font_families)
1112 {
1113 return adopt_ref(*new FontStyleValue(move(font_stretch), move(font_style), move(font_weight), move(font_size), move(line_height), move(font_families)));
1114 }
1115 virtual ~FontStyleValue() override = default;
1116
1117 ValueComparingNonnullRefPtr<StyleValue> font_stretch() const { return m_properties.font_stretch; }
1118 ValueComparingNonnullRefPtr<StyleValue> font_style() const { return m_properties.font_style; }
1119 ValueComparingNonnullRefPtr<StyleValue> font_weight() const { return m_properties.font_weight; }
1120 ValueComparingNonnullRefPtr<StyleValue> font_size() const { return m_properties.font_size; }
1121 ValueComparingNonnullRefPtr<StyleValue> line_height() const { return m_properties.line_height; }
1122 ValueComparingNonnullRefPtr<StyleValue> font_families() const { return m_properties.font_families; }
1123
1124 virtual ErrorOr<String> to_string() const override;
1125
1126 bool properties_equal(FontStyleValue const& other) const { return m_properties == other.m_properties; };
1127
1128private:
1129 FontStyleValue(ValueComparingNonnullRefPtr<StyleValue> font_stretch, ValueComparingNonnullRefPtr<StyleValue> font_style, ValueComparingNonnullRefPtr<StyleValue> font_weight, ValueComparingNonnullRefPtr<StyleValue> font_size, ValueComparingNonnullRefPtr<StyleValue> line_height, ValueComparingNonnullRefPtr<StyleValue> font_families)
1130 : StyleValueWithDefaultOperators(Type::Font)
1131 , m_properties { .font_stretch = move(font_stretch), .font_style = move(font_style), .font_weight = move(font_weight), .font_size = move(font_size), .line_height = move(line_height), .font_families = move(font_families) }
1132 {
1133 }
1134
1135 struct Properties {
1136 ValueComparingNonnullRefPtr<StyleValue> font_stretch;
1137 ValueComparingNonnullRefPtr<StyleValue> font_style;
1138 ValueComparingNonnullRefPtr<StyleValue> font_weight;
1139 ValueComparingNonnullRefPtr<StyleValue> font_size;
1140 ValueComparingNonnullRefPtr<StyleValue> line_height;
1141 ValueComparingNonnullRefPtr<StyleValue> font_families;
1142 // FIXME: Implement font-variant.
1143 bool operator==(Properties const&) const = default;
1144 } m_properties;
1145};
1146
1147class FrequencyStyleValue : public StyleValueWithDefaultOperators<FrequencyStyleValue> {
1148public:
1149 static ValueComparingNonnullRefPtr<FrequencyStyleValue> create(Frequency frequency)
1150 {
1151 return adopt_ref(*new FrequencyStyleValue(move(frequency)));
1152 }
1153 virtual ~FrequencyStyleValue() override { }
1154
1155 Frequency const& frequency() const { return m_frequency; }
1156
1157 virtual ErrorOr<String> to_string() const override { return m_frequency.to_string(); }
1158
1159 bool properties_equal(FrequencyStyleValue const& other) const { return m_frequency == other.m_frequency; };
1160
1161private:
1162 explicit FrequencyStyleValue(Frequency frequency)
1163 : StyleValueWithDefaultOperators(Type::Frequency)
1164 , m_frequency(move(frequency))
1165 {
1166 }
1167
1168 Frequency m_frequency;
1169};
1170
1171class GridTemplateAreaStyleValue final : public StyleValueWithDefaultOperators<GridTemplateAreaStyleValue> {
1172public:
1173 static ValueComparingNonnullRefPtr<GridTemplateAreaStyleValue> create(Vector<Vector<String>> grid_template_area);
1174 virtual ~GridTemplateAreaStyleValue() override = default;
1175
1176 Vector<Vector<String>> const& grid_template_area() const { return m_grid_template_area; }
1177 virtual ErrorOr<String> to_string() const override;
1178
1179 bool properties_equal(GridTemplateAreaStyleValue const& other) const { return m_grid_template_area == other.m_grid_template_area; };
1180
1181private:
1182 explicit GridTemplateAreaStyleValue(Vector<Vector<String>> grid_template_area)
1183 : StyleValueWithDefaultOperators(Type::GridTemplateArea)
1184 , m_grid_template_area(grid_template_area)
1185 {
1186 }
1187
1188 Vector<Vector<String>> m_grid_template_area;
1189};
1190
1191class GridTrackPlacementStyleValue final : public StyleValueWithDefaultOperators<GridTrackPlacementStyleValue> {
1192public:
1193 static ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue> create(CSS::GridTrackPlacement grid_track_placement);
1194 virtual ~GridTrackPlacementStyleValue() override = default;
1195
1196 CSS::GridTrackPlacement const& grid_track_placement() const { return m_grid_track_placement; }
1197 virtual ErrorOr<String> to_string() const override;
1198
1199 bool properties_equal(GridTrackPlacementStyleValue const& other) const { return m_grid_track_placement == other.m_grid_track_placement; };
1200
1201private:
1202 explicit GridTrackPlacementStyleValue(CSS::GridTrackPlacement grid_track_placement)
1203 : StyleValueWithDefaultOperators(Type::GridTrackPlacement)
1204 , m_grid_track_placement(grid_track_placement)
1205 {
1206 }
1207
1208 CSS::GridTrackPlacement m_grid_track_placement;
1209};
1210
1211class GridTrackPlacementShorthandStyleValue final : public StyleValueWithDefaultOperators<GridTrackPlacementShorthandStyleValue> {
1212public:
1213 static ValueComparingNonnullRefPtr<GridTrackPlacementShorthandStyleValue> create(ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> start, ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> end)
1214 {
1215 return adopt_ref(*new GridTrackPlacementShorthandStyleValue(move(start), move(end)));
1216 }
1217 static ValueComparingNonnullRefPtr<GridTrackPlacementShorthandStyleValue> create(GridTrackPlacement start)
1218 {
1219 return adopt_ref(*new GridTrackPlacementShorthandStyleValue(GridTrackPlacementStyleValue::create(start), GridTrackPlacementStyleValue::create(GridTrackPlacement::make_auto())));
1220 }
1221 virtual ~GridTrackPlacementShorthandStyleValue() override = default;
1222
1223 auto start() const { return m_properties.start; }
1224 auto end() const { return m_properties.end; }
1225
1226 virtual ErrorOr<String> to_string() const override;
1227
1228 bool properties_equal(GridTrackPlacementShorthandStyleValue const& other) const { return m_properties == other.m_properties; };
1229
1230private:
1231 GridTrackPlacementShorthandStyleValue(ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> start, ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> end)
1232 : StyleValueWithDefaultOperators(Type::GridTrackPlacementShorthand)
1233 , m_properties { .start = move(start), .end = move(end) }
1234 {
1235 }
1236
1237 struct Properties {
1238 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> start;
1239 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> end;
1240 bool operator==(Properties const&) const = default;
1241 } m_properties;
1242};
1243
1244class GridAreaShorthandStyleValue final : public StyleValueWithDefaultOperators<GridAreaShorthandStyleValue> {
1245public:
1246 static ValueComparingNonnullRefPtr<GridAreaShorthandStyleValue> create(
1247 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> row_start,
1248 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> column_start,
1249 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> row_end,
1250 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> column_end)
1251 {
1252 return adopt_ref(*new GridAreaShorthandStyleValue(row_start, column_start, row_end, column_end));
1253 }
1254 static ValueComparingNonnullRefPtr<GridAreaShorthandStyleValue> create(GridTrackPlacement row_start, GridTrackPlacement column_start, GridTrackPlacement row_end, GridTrackPlacement column_end)
1255 {
1256 return adopt_ref(*new GridAreaShorthandStyleValue(GridTrackPlacementStyleValue::create(row_start), GridTrackPlacementStyleValue::create(column_start), GridTrackPlacementStyleValue::create(row_end), GridTrackPlacementStyleValue::create(column_end)));
1257 }
1258 virtual ~GridAreaShorthandStyleValue() override = default;
1259
1260 auto row_start() const { return m_properties.row_start; }
1261 auto column_start() const { return m_properties.column_start; }
1262 auto row_end() const { return m_properties.row_end; }
1263 auto column_end() const { return m_properties.column_end; }
1264
1265 virtual ErrorOr<String> to_string() const override;
1266
1267 bool properties_equal(GridAreaShorthandStyleValue const& other) const { return m_properties == other.m_properties; }
1268
1269private:
1270 GridAreaShorthandStyleValue(ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> row_start, ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> column_start, ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> row_end, ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> column_end)
1271 : StyleValueWithDefaultOperators(Type::GridAreaShorthand)
1272 , m_properties { .row_start = move(row_start), .column_start = move(column_start), .row_end = move(row_end), .column_end = move(column_end) }
1273 {
1274 }
1275
1276 struct Properties {
1277 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> row_start;
1278 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> column_start;
1279 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> row_end;
1280 ValueComparingNonnullRefPtr<GridTrackPlacementStyleValue const> column_end;
1281 bool operator==(Properties const&) const = default;
1282 } m_properties;
1283};
1284
1285class GridTrackSizeStyleValue final : public StyleValueWithDefaultOperators<GridTrackSizeStyleValue> {
1286public:
1287 static ValueComparingNonnullRefPtr<GridTrackSizeStyleValue> create(CSS::GridTrackSizeList grid_track_size_list);
1288 virtual ~GridTrackSizeStyleValue() override = default;
1289
1290 static ValueComparingNonnullRefPtr<GridTrackSizeStyleValue> make_auto();
1291
1292 CSS::GridTrackSizeList grid_track_size_list() const { return m_grid_track_size_list; }
1293
1294 virtual ErrorOr<String> to_string() const override;
1295
1296 bool properties_equal(GridTrackSizeStyleValue const& other) const { return m_grid_track_size_list == other.m_grid_track_size_list; }
1297
1298private:
1299 explicit GridTrackSizeStyleValue(CSS::GridTrackSizeList grid_track_size_list)
1300 : StyleValueWithDefaultOperators(Type::GridTrackSizeList)
1301 , m_grid_track_size_list(grid_track_size_list)
1302 {
1303 }
1304
1305 CSS::GridTrackSizeList m_grid_track_size_list;
1306};
1307
1308class IdentifierStyleValue final : public StyleValueWithDefaultOperators<IdentifierStyleValue> {
1309public:
1310 static ValueComparingNonnullRefPtr<IdentifierStyleValue> create(CSS::ValueID id)
1311 {
1312 return adopt_ref(*new IdentifierStyleValue(id));
1313 }
1314 virtual ~IdentifierStyleValue() override = default;
1315
1316 CSS::ValueID id() const { return m_id; }
1317
1318 virtual bool has_auto() const override { return m_id == ValueID::Auto; }
1319 virtual bool has_identifier() const override { return true; }
1320 virtual CSS::ValueID to_identifier() const override { return m_id; }
1321 virtual bool has_color() const override;
1322 virtual Color to_color(Layout::NodeWithStyle const& node) const override;
1323 virtual ErrorOr<String> to_string() const override;
1324
1325 bool properties_equal(IdentifierStyleValue const& other) const { return m_id == other.m_id; }
1326
1327private:
1328 explicit IdentifierStyleValue(CSS::ValueID id)
1329 : StyleValueWithDefaultOperators(Type::Identifier)
1330 , m_id(id)
1331 {
1332 }
1333
1334 CSS::ValueID m_id { CSS::ValueID::Invalid };
1335};
1336
1337class AbstractImageStyleValue : public StyleValue {
1338public:
1339 using StyleValue::StyleValue;
1340
1341 virtual Optional<CSSPixels> natural_width() const { return {}; }
1342 virtual Optional<CSSPixels> natural_height() const { return {}; }
1343
1344 virtual void load_any_resources(DOM::Document&) {};
1345 virtual void resolve_for_size(Layout::Node const&, CSSPixelSize) const {};
1346
1347 virtual bool is_paintable() const = 0;
1348 virtual void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const = 0;
1349};
1350
1351class ImageStyleValue final
1352 : public AbstractImageStyleValue
1353 , public ImageResourceClient {
1354public:
1355 static ValueComparingNonnullRefPtr<ImageStyleValue> create(AK::URL const& url) { return adopt_ref(*new ImageStyleValue(url)); }
1356 virtual ~ImageStyleValue() override = default;
1357
1358 virtual ErrorOr<String> to_string() const override;
1359 virtual bool equals(StyleValue const& other) const override;
1360
1361 virtual void load_any_resources(DOM::Document&) override;
1362
1363 Optional<CSSPixels> natural_width() const override;
1364 Optional<CSSPixels> natural_height() const override;
1365
1366 bool is_paintable() const override { return bitmap(0) != nullptr; }
1367 void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const override;
1368
1369 Function<void()> on_animate;
1370
1371private:
1372 ImageStyleValue(AK::URL const&);
1373
1374 // ^ResourceClient
1375 virtual void resource_did_load() override;
1376
1377 void animate();
1378 Gfx::Bitmap const* bitmap(size_t index) const;
1379
1380 AK::URL m_url;
1381 WeakPtr<DOM::Document> m_document;
1382
1383 size_t m_current_frame_index { 0 };
1384 size_t m_loops_completed { 0 };
1385 RefPtr<Platform::Timer> m_timer;
1386};
1387
1388enum class GradientRepeating {
1389 Yes,
1390 No
1391};
1392
1393class RadialGradientStyleValue final : public AbstractImageStyleValue {
1394public:
1395 enum class EndingShape {
1396 Circle,
1397 Ellipse
1398 };
1399
1400 enum class Extent {
1401 ClosestCorner,
1402 ClosestSide,
1403 FarthestCorner,
1404 FarthestSide
1405 };
1406
1407 struct CircleSize {
1408 Length radius;
1409 bool operator==(CircleSize const&) const = default;
1410 };
1411
1412 struct EllipseSize {
1413 LengthPercentage radius_a;
1414 LengthPercentage radius_b;
1415 bool operator==(EllipseSize const&) const = default;
1416 };
1417
1418 using Size = Variant<Extent, CircleSize, EllipseSize>;
1419
1420 static ValueComparingNonnullRefPtr<RadialGradientStyleValue> create(EndingShape ending_shape, Size size, PositionValue position, Vector<LinearColorStopListElement> color_stop_list, GradientRepeating repeating)
1421 {
1422 VERIFY(color_stop_list.size() >= 2);
1423 return adopt_ref(*new RadialGradientStyleValue(ending_shape, size, position, move(color_stop_list), repeating));
1424 }
1425
1426 virtual ErrorOr<String> to_string() const override;
1427
1428 void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override;
1429
1430 virtual bool equals(StyleValue const& other) const override;
1431
1432 Vector<LinearColorStopListElement> const& color_stop_list() const
1433 {
1434 return m_properties.color_stop_list;
1435 }
1436
1437 bool is_paintable() const override { return true; }
1438
1439 void resolve_for_size(Layout::Node const&, CSSPixelSize) const override;
1440
1441 Gfx::FloatSize resolve_size(Layout::Node const&, Gfx::FloatPoint, Gfx::FloatRect const&) const;
1442
1443 bool is_repeating() const { return m_properties.repeating == GradientRepeating::Yes; }
1444
1445 virtual ~RadialGradientStyleValue() override = default;
1446
1447private:
1448 RadialGradientStyleValue(EndingShape ending_shape, Size size, PositionValue position, Vector<LinearColorStopListElement> color_stop_list, GradientRepeating repeating)
1449 : AbstractImageStyleValue(Type::RadialGradient)
1450 , m_properties { .ending_shape = ending_shape, .size = size, .position = position, .color_stop_list = move(color_stop_list), .repeating = repeating }
1451 {
1452 }
1453
1454 struct Properties {
1455 EndingShape ending_shape;
1456 Size size;
1457 PositionValue position;
1458 Vector<LinearColorStopListElement> color_stop_list;
1459 GradientRepeating repeating;
1460 bool operator==(Properties const&) const = default;
1461 } m_properties;
1462
1463 struct ResolvedData {
1464 Painting::RadialGradientData data;
1465 Gfx::FloatSize gradient_size;
1466 Gfx::FloatPoint center;
1467 };
1468
1469 mutable Optional<ResolvedData> m_resolved;
1470};
1471
1472class ConicGradientStyleValue final : public AbstractImageStyleValue {
1473public:
1474 static ValueComparingNonnullRefPtr<ConicGradientStyleValue> create(Angle from_angle, PositionValue position, Vector<AngularColorStopListElement> color_stop_list, GradientRepeating repeating)
1475 {
1476 VERIFY(color_stop_list.size() >= 2);
1477 return adopt_ref(*new ConicGradientStyleValue(from_angle, position, move(color_stop_list), repeating));
1478 }
1479
1480 virtual ErrorOr<String> to_string() const override;
1481
1482 void paint(PaintContext&, DevicePixelRect const& dest_rect, CSS::ImageRendering) const override;
1483
1484 virtual bool equals(StyleValue const& other) const override;
1485
1486 Vector<AngularColorStopListElement> const& color_stop_list() const
1487 {
1488 return m_properties.color_stop_list;
1489 }
1490
1491 float angle_degrees() const;
1492
1493 bool is_paintable() const override { return true; }
1494
1495 void resolve_for_size(Layout::Node const&, CSSPixelSize) const override;
1496
1497 virtual ~ConicGradientStyleValue() override = default;
1498
1499 bool is_repeating() const { return m_properties.repeating == GradientRepeating::Yes; }
1500
1501private:
1502 ConicGradientStyleValue(Angle from_angle, PositionValue position, Vector<AngularColorStopListElement> color_stop_list, GradientRepeating repeating)
1503 : AbstractImageStyleValue(Type::ConicGradient)
1504 , m_properties { .from_angle = from_angle, .position = position, .color_stop_list = move(color_stop_list), .repeating = repeating }
1505 {
1506 }
1507
1508 struct Properties {
1509 // FIXME: Support <color-interpolation-method>
1510 Angle from_angle;
1511 PositionValue position;
1512 Vector<AngularColorStopListElement> color_stop_list;
1513 GradientRepeating repeating;
1514 bool operator==(Properties const&) const = default;
1515 } m_properties;
1516
1517 struct ResolvedData {
1518 Painting::ConicGradientData data;
1519 CSSPixelPoint position;
1520 };
1521
1522 mutable Optional<ResolvedData> m_resolved;
1523};
1524
1525class LinearGradientStyleValue final : public AbstractImageStyleValue {
1526public:
1527 using GradientDirection = Variant<Angle, SideOrCorner>;
1528
1529 enum class GradientType {
1530 Standard,
1531 WebKit
1532 };
1533
1534 static ValueComparingNonnullRefPtr<LinearGradientStyleValue> create(GradientDirection direction, Vector<LinearColorStopListElement> color_stop_list, GradientType type, GradientRepeating repeating)
1535 {
1536 VERIFY(color_stop_list.size() >= 2);
1537 return adopt_ref(*new LinearGradientStyleValue(direction, move(color_stop_list), type, repeating));
1538 }
1539
1540 virtual ErrorOr<String> to_string() const override;
1541 virtual ~LinearGradientStyleValue() override = default;
1542 virtual bool equals(StyleValue const& other) const override;
1543
1544 Vector<LinearColorStopListElement> const& color_stop_list() const
1545 {
1546 return m_properties.color_stop_list;
1547 }
1548
1549 bool is_repeating() const { return m_properties.repeating == GradientRepeating::Yes; }
1550
1551 float angle_degrees(CSSPixelSize gradient_size) const;
1552
1553 void resolve_for_size(Layout::Node const&, CSSPixelSize) const override;
1554
1555 bool is_paintable() const override { return true; }
1556 void paint(PaintContext& context, DevicePixelRect const& dest_rect, CSS::ImageRendering image_rendering) const override;
1557
1558private:
1559 LinearGradientStyleValue(GradientDirection direction, Vector<LinearColorStopListElement> color_stop_list, GradientType type, GradientRepeating repeating)
1560 : AbstractImageStyleValue(Type::LinearGradient)
1561 , m_properties { .direction = direction, .color_stop_list = move(color_stop_list), .gradient_type = type, .repeating = repeating }
1562 {
1563 }
1564
1565 struct Properties {
1566 GradientDirection direction;
1567 Vector<LinearColorStopListElement> color_stop_list;
1568 GradientType gradient_type;
1569 GradientRepeating repeating;
1570 bool operator==(Properties const&) const = default;
1571 } m_properties;
1572
1573 struct ResolvedData {
1574 Painting::LinearGradientData data;
1575 CSSPixelSize size;
1576 };
1577
1578 mutable Optional<ResolvedData> m_resolved;
1579};
1580
1581class InheritStyleValue final : public StyleValueWithDefaultOperators<InheritStyleValue> {
1582public:
1583 static ValueComparingNonnullRefPtr<InheritStyleValue> the()
1584 {
1585 static ValueComparingNonnullRefPtr<InheritStyleValue> instance = adopt_ref(*new InheritStyleValue);
1586 return instance;
1587 }
1588 virtual ~InheritStyleValue() override = default;
1589
1590 ErrorOr<String> to_string() const override { return "inherit"_string; }
1591
1592 bool properties_equal(InheritStyleValue const&) const { return true; }
1593
1594private:
1595 InheritStyleValue()
1596 : StyleValueWithDefaultOperators(Type::Inherit)
1597 {
1598 }
1599};
1600
1601class InitialStyleValue final : public StyleValueWithDefaultOperators<InitialStyleValue> {
1602public:
1603 static ValueComparingNonnullRefPtr<InitialStyleValue> the()
1604 {
1605 static ValueComparingNonnullRefPtr<InitialStyleValue> instance = adopt_ref(*new InitialStyleValue);
1606 return instance;
1607 }
1608 virtual ~InitialStyleValue() override = default;
1609
1610 ErrorOr<String> to_string() const override { return "initial"_string; }
1611
1612 bool properties_equal(InitialStyleValue const&) const { return true; }
1613
1614private:
1615 InitialStyleValue()
1616 : StyleValueWithDefaultOperators(Type::Initial)
1617 {
1618 }
1619};
1620
1621class LengthStyleValue : public StyleValueWithDefaultOperators<LengthStyleValue> {
1622public:
1623 static ValueComparingNonnullRefPtr<LengthStyleValue> create(Length const&);
1624 virtual ~LengthStyleValue() override = default;
1625
1626 Length const& length() const { return m_length; }
1627
1628 virtual bool has_auto() const override { return m_length.is_auto(); }
1629 virtual bool has_length() const override { return true; }
1630 virtual bool has_identifier() const override { return has_auto(); }
1631 virtual ErrorOr<String> to_string() const override { return m_length.to_string(); }
1632 virtual Length to_length() const override { return m_length; }
1633 virtual ValueID to_identifier() const override { return has_auto() ? ValueID::Auto : ValueID::Invalid; }
1634 virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const override;
1635
1636 bool properties_equal(LengthStyleValue const& other) const { return m_length == other.m_length; }
1637
1638private:
1639 explicit LengthStyleValue(Length const& length)
1640 : StyleValueWithDefaultOperators(Type::Length)
1641 , m_length(length)
1642 {
1643 }
1644
1645 Length m_length;
1646};
1647
1648class ListStyleStyleValue final : public StyleValueWithDefaultOperators<ListStyleStyleValue> {
1649public:
1650 static ValueComparingNonnullRefPtr<ListStyleStyleValue> create(
1651 ValueComparingNonnullRefPtr<StyleValue> position,
1652 ValueComparingNonnullRefPtr<StyleValue> image,
1653 ValueComparingNonnullRefPtr<StyleValue> style_type)
1654 {
1655 return adopt_ref(*new ListStyleStyleValue(move(position), move(image), move(style_type)));
1656 }
1657 virtual ~ListStyleStyleValue() override = default;
1658
1659 ValueComparingNonnullRefPtr<StyleValue> position() const { return m_properties.position; }
1660 ValueComparingNonnullRefPtr<StyleValue> image() const { return m_properties.image; }
1661 ValueComparingNonnullRefPtr<StyleValue> style_type() const { return m_properties.style_type; }
1662
1663 virtual ErrorOr<String> to_string() const override;
1664
1665 bool properties_equal(ListStyleStyleValue const& other) const { return m_properties == other.m_properties; }
1666
1667private:
1668 ListStyleStyleValue(
1669 ValueComparingNonnullRefPtr<StyleValue> position,
1670 ValueComparingNonnullRefPtr<StyleValue> image,
1671 ValueComparingNonnullRefPtr<StyleValue> style_type)
1672 : StyleValueWithDefaultOperators(Type::ListStyle)
1673 , m_properties { .position = move(position), .image = move(image), .style_type = move(style_type) }
1674 {
1675 }
1676
1677 struct Properties {
1678 ValueComparingNonnullRefPtr<StyleValue> position;
1679 ValueComparingNonnullRefPtr<StyleValue> image;
1680 ValueComparingNonnullRefPtr<StyleValue> style_type;
1681 bool operator==(Properties const&) const = default;
1682 } m_properties;
1683};
1684
1685class NumericStyleValue : public StyleValueWithDefaultOperators<NumericStyleValue> {
1686public:
1687 static ValueComparingNonnullRefPtr<NumericStyleValue> create_float(float value)
1688 {
1689 return adopt_ref(*new NumericStyleValue(value));
1690 }
1691
1692 static ValueComparingNonnullRefPtr<NumericStyleValue> create_integer(i64 value)
1693 {
1694 return adopt_ref(*new NumericStyleValue(value));
1695 }
1696
1697 virtual bool has_length() const override { return to_number() == 0; }
1698 virtual Length to_length() const override { return Length::make_px(0); }
1699
1700 virtual bool has_number() const override { return true; }
1701 virtual float to_number() const override
1702 {
1703 return m_value.visit(
1704 [](float value) { return value; },
1705 [](i64 value) { return (float)value; });
1706 }
1707
1708 virtual bool has_integer() const override { return m_value.has<i64>(); }
1709 virtual float to_integer() const override { return m_value.get<i64>(); }
1710
1711 virtual ErrorOr<String> to_string() const override;
1712
1713 bool properties_equal(NumericStyleValue const& other) const { return m_value == other.m_value; }
1714
1715private:
1716 explicit NumericStyleValue(Variant<float, i64> value)
1717 : StyleValueWithDefaultOperators(Type::Numeric)
1718 , m_value(move(value))
1719 {
1720 }
1721
1722 Variant<float, i64> m_value { (i64)0 };
1723};
1724
1725class OverflowStyleValue final : public StyleValueWithDefaultOperators<OverflowStyleValue> {
1726public:
1727 static ValueComparingNonnullRefPtr<OverflowStyleValue> create(ValueComparingNonnullRefPtr<StyleValue> overflow_x, ValueComparingNonnullRefPtr<StyleValue> overflow_y)
1728 {
1729 return adopt_ref(*new OverflowStyleValue(move(overflow_x), move(overflow_y)));
1730 }
1731 virtual ~OverflowStyleValue() override = default;
1732
1733 ValueComparingNonnullRefPtr<StyleValue> overflow_x() const { return m_properties.overflow_x; }
1734 ValueComparingNonnullRefPtr<StyleValue> overflow_y() const { return m_properties.overflow_y; }
1735
1736 virtual ErrorOr<String> to_string() const override;
1737
1738 bool properties_equal(OverflowStyleValue const& other) const { return m_properties == other.m_properties; }
1739
1740private:
1741 OverflowStyleValue(ValueComparingNonnullRefPtr<StyleValue> overflow_x, ValueComparingNonnullRefPtr<StyleValue> overflow_y)
1742 : StyleValueWithDefaultOperators(Type::Overflow)
1743 , m_properties { .overflow_x = move(overflow_x), .overflow_y = move(overflow_y) }
1744 {
1745 }
1746
1747 struct Properties {
1748 ValueComparingNonnullRefPtr<StyleValue> overflow_x;
1749 ValueComparingNonnullRefPtr<StyleValue> overflow_y;
1750 bool operator==(Properties const&) const = default;
1751 } m_properties;
1752};
1753
1754class PercentageStyleValue final : public StyleValueWithDefaultOperators<PercentageStyleValue> {
1755public:
1756 static ValueComparingNonnullRefPtr<PercentageStyleValue> create(Percentage percentage)
1757 {
1758 return adopt_ref(*new PercentageStyleValue(move(percentage)));
1759 }
1760 virtual ~PercentageStyleValue() override = default;
1761
1762 Percentage const& percentage() const { return m_percentage; }
1763 Percentage& percentage() { return m_percentage; }
1764
1765 virtual ErrorOr<String> to_string() const override;
1766
1767 bool properties_equal(PercentageStyleValue const& other) const { return m_percentage == other.m_percentage; }
1768
1769private:
1770 PercentageStyleValue(Percentage&& percentage)
1771 : StyleValueWithDefaultOperators(Type::Percentage)
1772 , m_percentage(percentage)
1773 {
1774 }
1775
1776 Percentage m_percentage;
1777};
1778
1779class PositionStyleValue final : public StyleValueWithDefaultOperators<PositionStyleValue> {
1780public:
1781 static ValueComparingNonnullRefPtr<PositionStyleValue> create(PositionEdge edge_x, LengthPercentage const& offset_x, PositionEdge edge_y, LengthPercentage const& offset_y)
1782 {
1783 return adopt_ref(*new PositionStyleValue(edge_x, offset_x, edge_y, offset_y));
1784 }
1785 virtual ~PositionStyleValue() override = default;
1786
1787 PositionEdge edge_x() const { return m_properties.edge_x; }
1788 LengthPercentage const& offset_x() const { return m_properties.offset_x; }
1789 PositionEdge edge_y() const { return m_properties.edge_y; }
1790 LengthPercentage const& offset_y() const { return m_properties.offset_y; }
1791
1792 virtual ErrorOr<String> to_string() const override;
1793
1794 bool properties_equal(PositionStyleValue const& other) const { return m_properties == other.m_properties; }
1795
1796private:
1797 PositionStyleValue(PositionEdge edge_x, LengthPercentage const& offset_x, PositionEdge edge_y, LengthPercentage const& offset_y)
1798 : StyleValueWithDefaultOperators(Type::Position)
1799 , m_properties { .edge_x = edge_x, .offset_x = offset_x, .edge_y = edge_y, .offset_y = offset_y }
1800 {
1801 }
1802
1803 struct Properties {
1804 PositionEdge edge_x;
1805 LengthPercentage offset_x;
1806 PositionEdge edge_y;
1807 LengthPercentage offset_y;
1808 bool operator==(Properties const&) const = default;
1809 } m_properties;
1810};
1811
1812class ResolutionStyleValue : public StyleValueWithDefaultOperators<ResolutionStyleValue> {
1813public:
1814 static ValueComparingNonnullRefPtr<ResolutionStyleValue> create(Resolution resolution)
1815 {
1816 return adopt_ref(*new ResolutionStyleValue(move(resolution)));
1817 }
1818 virtual ~ResolutionStyleValue() override { }
1819
1820 Resolution const& resolution() const { return m_resolution; }
1821
1822 virtual ErrorOr<String> to_string() const override { return m_resolution.to_string(); }
1823
1824 bool properties_equal(ResolutionStyleValue const& other) const { return m_resolution == other.m_resolution; }
1825
1826private:
1827 explicit ResolutionStyleValue(Resolution resolution)
1828 : StyleValueWithDefaultOperators(Type::Resolution)
1829 , m_resolution(move(resolution))
1830 {
1831 }
1832
1833 Resolution m_resolution;
1834};
1835
1836class ShadowStyleValue final : public StyleValueWithDefaultOperators<ShadowStyleValue> {
1837public:
1838 static ValueComparingNonnullRefPtr<ShadowStyleValue>
1839 create(Color color, Length const& offset_x, Length const& offset_y, Length const& blur_radius, Length const& spread_distance, ShadowPlacement placement)
1840 {
1841 return adopt_ref(*new ShadowStyleValue(color, offset_x, offset_y, blur_radius, spread_distance, placement));
1842 }
1843 virtual ~ShadowStyleValue() override = default;
1844
1845 Color color() const { return m_properties.color; }
1846 Length const& offset_x() const { return m_properties.offset_x; }
1847 Length const& offset_y() const { return m_properties.offset_y; }
1848 Length const& blur_radius() const { return m_properties.blur_radius; }
1849 Length const& spread_distance() const { return m_properties.spread_distance; }
1850 ShadowPlacement placement() const { return m_properties.placement; }
1851
1852 virtual ErrorOr<String> to_string() const override;
1853
1854 bool properties_equal(ShadowStyleValue const& other) const { return m_properties == other.m_properties; }
1855
1856private:
1857 explicit ShadowStyleValue(Color color, Length const& offset_x, Length const& offset_y, Length const& blur_radius, Length const& spread_distance, ShadowPlacement placement)
1858 : StyleValueWithDefaultOperators(Type::Shadow)
1859 , m_properties { .color = color, .offset_x = offset_x, .offset_y = offset_y, .blur_radius = blur_radius, .spread_distance = spread_distance, .placement = placement }
1860 {
1861 }
1862
1863 virtual ValueComparingNonnullRefPtr<StyleValue const> absolutized(CSSPixelRect const& viewport_rect, Gfx::FontPixelMetrics const& font_metrics, CSSPixels font_size, CSSPixels root_font_size) const override;
1864
1865 struct Properties {
1866 Color color;
1867 Length offset_x;
1868 Length offset_y;
1869 Length blur_radius;
1870 Length spread_distance;
1871 ShadowPlacement placement;
1872 bool operator==(Properties const&) const = default;
1873 } m_properties;
1874};
1875
1876class StringStyleValue : public StyleValueWithDefaultOperators<StringStyleValue> {
1877public:
1878 static ValueComparingNonnullRefPtr<StringStyleValue> create(String const& string)
1879 {
1880 return adopt_ref(*new StringStyleValue(string));
1881 }
1882 virtual ~StringStyleValue() override = default;
1883
1884 ErrorOr<String> to_string() const override { return m_string; }
1885
1886 bool properties_equal(StringStyleValue const& other) const { return m_string == other.m_string; }
1887
1888private:
1889 explicit StringStyleValue(String const& string)
1890 : StyleValueWithDefaultOperators(Type::String)
1891 , m_string(string)
1892 {
1893 }
1894
1895 String m_string;
1896};
1897
1898class TextDecorationStyleValue final : public StyleValueWithDefaultOperators<TextDecorationStyleValue> {
1899public:
1900 static ValueComparingNonnullRefPtr<TextDecorationStyleValue> create(
1901 ValueComparingNonnullRefPtr<StyleValue> line,
1902 ValueComparingNonnullRefPtr<StyleValue> thickness,
1903 ValueComparingNonnullRefPtr<StyleValue> style,
1904 ValueComparingNonnullRefPtr<StyleValue> color)
1905 {
1906 return adopt_ref(*new TextDecorationStyleValue(move(line), move(thickness), move(style), move(color)));
1907 }
1908 virtual ~TextDecorationStyleValue() override = default;
1909
1910 ValueComparingNonnullRefPtr<StyleValue> line() const { return m_properties.line; }
1911 ValueComparingNonnullRefPtr<StyleValue> thickness() const { return m_properties.thickness; }
1912 ValueComparingNonnullRefPtr<StyleValue> style() const { return m_properties.style; }
1913 ValueComparingNonnullRefPtr<StyleValue> color() const { return m_properties.color; }
1914
1915 virtual ErrorOr<String> to_string() const override;
1916
1917 bool properties_equal(TextDecorationStyleValue const& other) const { return m_properties == other.m_properties; }
1918
1919private:
1920 TextDecorationStyleValue(
1921 ValueComparingNonnullRefPtr<StyleValue> line,
1922 ValueComparingNonnullRefPtr<StyleValue> thickness,
1923 ValueComparingNonnullRefPtr<StyleValue> style,
1924 ValueComparingNonnullRefPtr<StyleValue> color)
1925 : StyleValueWithDefaultOperators(Type::TextDecoration)
1926 , m_properties { .line = move(line), .thickness = move(thickness), .style = move(style), .color = move(color) }
1927 {
1928 }
1929
1930 struct Properties {
1931 ValueComparingNonnullRefPtr<StyleValue> line;
1932 ValueComparingNonnullRefPtr<StyleValue> thickness;
1933 ValueComparingNonnullRefPtr<StyleValue> style;
1934 ValueComparingNonnullRefPtr<StyleValue> color;
1935 bool operator==(Properties const&) const = default;
1936 } m_properties;
1937};
1938
1939class TimeStyleValue : public StyleValueWithDefaultOperators<TimeStyleValue> {
1940public:
1941 static ValueComparingNonnullRefPtr<TimeStyleValue> create(Time time)
1942 {
1943 return adopt_ref(*new TimeStyleValue(move(time)));
1944 }
1945 virtual ~TimeStyleValue() override { }
1946
1947 Time const& time() const { return m_time; }
1948
1949 virtual ErrorOr<String> to_string() const override { return m_time.to_string(); }
1950
1951 bool properties_equal(TimeStyleValue const& other) const { return m_time == other.m_time; }
1952
1953private:
1954 explicit TimeStyleValue(Time time)
1955 : StyleValueWithDefaultOperators(Type::Time)
1956 , m_time(move(time))
1957 {
1958 }
1959
1960 Time m_time;
1961};
1962
1963class TransformationStyleValue final : public StyleValueWithDefaultOperators<TransformationStyleValue> {
1964public:
1965 static ValueComparingNonnullRefPtr<TransformationStyleValue> create(CSS::TransformFunction transform_function, StyleValueVector&& values)
1966 {
1967 return adopt_ref(*new TransformationStyleValue(transform_function, move(values)));
1968 }
1969 virtual ~TransformationStyleValue() override = default;
1970
1971 CSS::TransformFunction transform_function() const { return m_properties.transform_function; }
1972 StyleValueVector values() const { return m_properties.values; }
1973
1974 virtual ErrorOr<String> to_string() const override;
1975
1976 bool properties_equal(TransformationStyleValue const& other) const { return m_properties == other.m_properties; }
1977
1978private:
1979 TransformationStyleValue(CSS::TransformFunction transform_function, StyleValueVector&& values)
1980 : StyleValueWithDefaultOperators(Type::Transformation)
1981 , m_properties { .transform_function = transform_function, .values = move(values) }
1982 {
1983 }
1984
1985 struct Properties {
1986 CSS::TransformFunction transform_function;
1987 StyleValueVector values;
1988 bool operator==(Properties const& other) const;
1989 } m_properties;
1990};
1991
1992class UnresolvedStyleValue final : public StyleValue {
1993public:
1994 static ValueComparingNonnullRefPtr<UnresolvedStyleValue> create(Vector<Parser::ComponentValue>&& values, bool contains_var_or_attr)
1995 {
1996 return adopt_ref(*new UnresolvedStyleValue(move(values), contains_var_or_attr));
1997 }
1998 virtual ~UnresolvedStyleValue() override = default;
1999
2000 virtual ErrorOr<String> to_string() const override;
2001
2002 Vector<Parser::ComponentValue> const& values() const { return m_values; }
2003 bool contains_var_or_attr() const { return m_contains_var_or_attr; }
2004
2005 virtual bool equals(StyleValue const& other) const override;
2006
2007private:
2008 UnresolvedStyleValue(Vector<Parser::ComponentValue>&& values, bool contains_var_or_attr)
2009 : StyleValue(Type::Unresolved)
2010 , m_values(move(values))
2011 , m_contains_var_or_attr(contains_var_or_attr)
2012 {
2013 }
2014
2015 Vector<Parser::ComponentValue> m_values;
2016 bool m_contains_var_or_attr { false };
2017};
2018
2019class UnsetStyleValue final : public StyleValueWithDefaultOperators<UnsetStyleValue> {
2020public:
2021 static ValueComparingNonnullRefPtr<UnsetStyleValue> the()
2022 {
2023 static ValueComparingNonnullRefPtr<UnsetStyleValue> instance = adopt_ref(*new UnsetStyleValue);
2024 return instance;
2025 }
2026 virtual ~UnsetStyleValue() override = default;
2027
2028 ErrorOr<String> to_string() const override { return "unset"_string; }
2029
2030 bool properties_equal(UnsetStyleValue const&) const { return true; }
2031
2032private:
2033 UnsetStyleValue()
2034 : StyleValueWithDefaultOperators(Type::Unset)
2035 {
2036 }
2037};
2038
2039class StyleValueList final : public StyleValueWithDefaultOperators<StyleValueList> {
2040public:
2041 enum class Separator {
2042 Space,
2043 Comma,
2044 };
2045 static ValueComparingNonnullRefPtr<StyleValueList> create(StyleValueVector&& values, Separator separator) { return adopt_ref(*new StyleValueList(move(values), separator)); }
2046
2047 size_t size() const { return m_properties.values.size(); }
2048 StyleValueVector const& values() const { return m_properties.values; }
2049 ValueComparingNonnullRefPtr<StyleValue const> value_at(size_t i, bool allow_loop) const
2050 {
2051 if (allow_loop)
2052 return m_properties.values[i % size()];
2053 return m_properties.values[i];
2054 }
2055
2056 virtual ErrorOr<String> to_string() const override;
2057
2058 bool properties_equal(StyleValueList const& other) const { return m_properties == other.m_properties; }
2059
2060private:
2061 StyleValueList(StyleValueVector&& values, Separator separator)
2062 : StyleValueWithDefaultOperators(Type::ValueList)
2063 , m_properties { .separator = separator, .values = move(values) }
2064 {
2065 }
2066
2067 struct Properties {
2068 Separator separator;
2069 StyleValueVector values;
2070 bool operator==(Properties const&) const;
2071 } m_properties;
2072};
2073
2074class RectStyleValue : public StyleValueWithDefaultOperators<RectStyleValue> {
2075public:
2076 static ValueComparingNonnullRefPtr<RectStyleValue> create(EdgeRect rect);
2077 virtual ~RectStyleValue() override = default;
2078
2079 EdgeRect rect() const { return m_rect; }
2080 virtual ErrorOr<String> to_string() const override;
2081 virtual bool has_rect() const override { return true; }
2082 virtual EdgeRect to_rect() const override { return m_rect; }
2083
2084 bool properties_equal(RectStyleValue const& other) const { return m_rect == other.m_rect; }
2085
2086private:
2087 explicit RectStyleValue(EdgeRect rect)
2088 : StyleValueWithDefaultOperators(Type::Rect)
2089 , m_rect(rect)
2090 {
2091 }
2092
2093 EdgeRect m_rect;
2094};
2095
2096}
2097
2098template<>
2099struct AK::Formatter<Web::CSS::StyleValue> : Formatter<StringView> {
2100 ErrorOr<void> format(FormatBuilder& builder, Web::CSS::StyleValue const& style_value)
2101 {
2102 return Formatter<StringView>::format(builder, TRY(style_value.to_string()));
2103 }
2104};