Serenity Operating System
at master 2104 lines 88 kB view raw
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};