2020-01-18 09:38:21 +01:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
2022-11-08 16:31:01 +00:00
* Copyright ( c ) 2021 - 2023 , Sam Atkins < atkinssj @ serenityos . org >
2022-01-24 17:38:29 +00:00
* Copyright ( c ) 2021 , Tobias Christiansen < tobyase @ serenityos . org >
2023-01-13 23:44:44 +00:00
* Copyright ( c ) 2022 - 2023 , MacDue < macdue @ dueutil . tech >
2020-01-18 09:38:21 +01:00
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 09:38:21 +01:00
*/
2020-02-14 21:41:10 +01:00
# include <AK/ByteBuffer.h>
2020-05-25 14:54:27 -04:00
# include <LibGfx/Palette.h>
2022-02-02 20:39:04 +00:00
# include <LibWeb/CSS/Serialize.h>
2020-03-07 10:32:51 +01:00
# include <LibWeb/CSS/StyleValue.h>
2023-03-23 17:26:13 +00:00
# include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
2023-03-23 17:44:13 +00:00
# include <LibWeb/CSS/StyleValues/BackgroundRepeatStyleValue.h>
2023-03-23 17:54:05 +00:00
# include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
2023-03-23 17:35:44 +00:00
# include <LibWeb/CSS/StyleValues/BackgroundStyleValue.h>
2023-03-25 00:29:33 +00:00
# include <LibWeb/CSS/StyleValues/BorderRadiusShorthandStyleValue.h>
2023-03-25 00:33:20 +00:00
# include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h>
2023-03-23 20:56:30 +00:00
# include <LibWeb/CSS/StyleValues/BorderStyleValue.h>
2023-03-23 21:12:15 +00:00
# include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
2023-03-23 21:17:43 +00:00
# include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
2023-03-23 21:26:03 +00:00
# include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h>
2023-03-23 21:39:08 +00:00
# include <LibWeb/CSS/StyleValues/FlexFlowStyleValue.h>
2023-03-23 21:33:13 +00:00
# include <LibWeb/CSS/StyleValues/FlexStyleValue.h>
2023-03-23 21:44:40 +00:00
# include <LibWeb/CSS/StyleValues/FontStyleValue.h>
2023-03-23 21:50:24 +00:00
# include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
2020-03-07 10:32:51 +01:00
# include <LibWeb/DOM/Document.h>
2021-11-18 15:01:28 +01:00
# include <LibWeb/HTML/BrowsingContext.h>
2020-06-02 13:51:30 +02:00
# include <LibWeb/Loader/LoadRequest.h>
2020-06-01 20:42:50 +02:00
# include <LibWeb/Loader/ResourceLoader.h>
2021-08-24 16:28:08 +02:00
# include <LibWeb/Page/Page.h>
2022-07-31 01:11:59 +01:00
# include <LibWeb/Painting/GradientPainting.h>
2022-10-30 15:43:42 +00:00
# include <LibWeb/Platform/Timer.h>
2019-06-22 21:48:21 +02:00
2020-07-26 20:01:35 +02:00
namespace Web : : CSS {
2020-03-07 10:27:02 +01:00
2019-06-22 21:48:21 +02:00
StyleValue : : StyleValue ( Type type )
: m_type ( type )
{
}
2022-07-31 01:11:59 +01:00
AbstractImageStyleValue const & StyleValue : : as_abstract_image ( ) const
{
VERIFY ( is_abstract_image ( ) ) ;
return static_cast < AbstractImageStyleValue const & > ( * this ) ;
}
2022-02-21 17:43:30 +00:00
AngleStyleValue const & StyleValue : : as_angle ( ) const
{
VERIFY ( is_angle ( ) ) ;
return static_cast < AngleStyleValue const & > ( * this ) ;
}
2021-09-23 19:54:19 +01:00
BackgroundStyleValue const & StyleValue : : as_background ( ) const
2021-09-22 12:42:54 +01:00
{
2021-09-23 19:54:19 +01:00
VERIFY ( is_background ( ) ) ;
return static_cast < BackgroundStyleValue const & > ( * this ) ;
}
BackgroundRepeatStyleValue const & StyleValue : : as_background_repeat ( ) const
{
VERIFY ( is_background_repeat ( ) ) ;
return static_cast < BackgroundRepeatStyleValue const & > ( * this ) ;
}
2021-11-05 12:18:23 +00:00
BackgroundSizeStyleValue const & StyleValue : : as_background_size ( ) const
{
VERIFY ( is_background_size ( ) ) ;
return static_cast < BackgroundSizeStyleValue const & > ( * this ) ;
}
2021-09-23 19:54:19 +01:00
BorderStyleValue const & StyleValue : : as_border ( ) const
{
VERIFY ( is_border ( ) ) ;
return static_cast < BorderStyleValue const & > ( * this ) ;
}
BorderRadiusStyleValue const & StyleValue : : as_border_radius ( ) const
{
VERIFY ( is_border_radius ( ) ) ;
return static_cast < BorderRadiusStyleValue const & > ( * this ) ;
}
2022-04-18 17:04:38 +01:00
BorderRadiusShorthandStyleValue const & StyleValue : : as_border_radius_shorthand ( ) const
{
VERIFY ( is_border_radius_shorthand ( ) ) ;
return static_cast < BorderRadiusShorthandStyleValue const & > ( * this ) ;
}
2022-03-23 16:55:22 +00:00
ShadowStyleValue const & StyleValue : : as_shadow ( ) const
2021-09-23 19:54:19 +01:00
{
2022-03-23 16:55:22 +00:00
VERIFY ( is_shadow ( ) ) ;
return static_cast < ShadowStyleValue const & > ( * this ) ;
2021-09-23 19:54:19 +01:00
}
CalculatedStyleValue const & StyleValue : : as_calculated ( ) const
{
VERIFY ( is_calculated ( ) ) ;
return static_cast < CalculatedStyleValue const & > ( * this ) ;
}
ColorStyleValue const & StyleValue : : as_color ( ) const
{
VERIFY ( is_color ( ) ) ;
return static_cast < ColorStyleValue const & > ( * this ) ;
}
2022-10-28 20:44:00 +01:00
ConicGradientStyleValue const & StyleValue : : as_conic_gradient ( ) const
{
VERIFY ( is_conic_gradient ( ) ) ;
return static_cast < ConicGradientStyleValue const & > ( * this ) ;
}
2022-02-23 19:56:25 +00:00
ContentStyleValue const & StyleValue : : as_content ( ) const
{
VERIFY ( is_content ( ) ) ;
return static_cast < ContentStyleValue const & > ( * this ) ;
}
2022-09-15 08:31:14 +01:00
FilterValueListStyleValue const & StyleValue : : as_filter_value_list ( ) const
{
VERIFY ( is_filter_value_list ( ) ) ;
return static_cast < FilterValueListStyleValue const & > ( * this ) ;
}
2021-09-23 19:54:19 +01:00
FlexStyleValue const & StyleValue : : as_flex ( ) const
{
VERIFY ( is_flex ( ) ) ;
return static_cast < FlexStyleValue const & > ( * this ) ;
}
FlexFlowStyleValue const & StyleValue : : as_flex_flow ( ) const
{
VERIFY ( is_flex_flow ( ) ) ;
return static_cast < FlexFlowStyleValue const & > ( * this ) ;
}
FontStyleValue const & StyleValue : : as_font ( ) const
{
VERIFY ( is_font ( ) ) ;
return static_cast < FontStyleValue const & > ( * this ) ;
}
2021-09-22 12:42:54 +01:00
2022-02-21 17:49:47 +00:00
FrequencyStyleValue const & StyleValue : : as_frequency ( ) const
{
VERIFY ( is_frequency ( ) ) ;
return static_cast < FrequencyStyleValue const & > ( * this ) ;
}
2022-08-24 12:25:56 +02:00
GridTrackPlacementShorthandStyleValue const & StyleValue : : as_grid_track_placement_shorthand ( ) const
{
VERIFY ( is_grid_track_placement_shorthand ( ) ) ;
return static_cast < GridTrackPlacementShorthandStyleValue const & > ( * this ) ;
}
2023-01-16 19:02:39 +01:00
GridAreaShorthandStyleValue const & StyleValue : : as_grid_area_shorthand ( ) const
{
VERIFY ( is_grid_area_shorthand ( ) ) ;
return static_cast < GridAreaShorthandStyleValue const & > ( * this ) ;
}
2023-01-16 18:17:05 +01:00
GridTemplateAreaStyleValue const & StyleValue : : as_grid_template_area ( ) const
{
VERIFY ( is_grid_template_area ( ) ) ;
return static_cast < GridTemplateAreaStyleValue const & > ( * this ) ;
}
2022-08-24 12:31:00 +02:00
GridTrackPlacementStyleValue const & StyleValue : : as_grid_track_placement ( ) const
{
VERIFY ( is_grid_track_placement ( ) ) ;
return static_cast < GridTrackPlacementStyleValue const & > ( * this ) ;
}
2021-09-23 19:54:19 +01:00
IdentifierStyleValue const & StyleValue : : as_identifier ( ) const
{
VERIFY ( is_identifier ( ) ) ;
return static_cast < IdentifierStyleValue const & > ( * this ) ;
}
ImageStyleValue const & StyleValue : : as_image ( ) const
{
VERIFY ( is_image ( ) ) ;
return static_cast < ImageStyleValue const & > ( * this ) ;
}
InheritStyleValue const & StyleValue : : as_inherit ( ) const
{
VERIFY ( is_inherit ( ) ) ;
return static_cast < InheritStyleValue const & > ( * this ) ;
}
InitialStyleValue const & StyleValue : : as_initial ( ) const
{
VERIFY ( is_initial ( ) ) ;
return static_cast < InitialStyleValue const & > ( * this ) ;
}
LengthStyleValue const & StyleValue : : as_length ( ) const
{
VERIFY ( is_length ( ) ) ;
return static_cast < LengthStyleValue const & > ( * this ) ;
}
2022-10-30 13:27:57 +01:00
GridTrackSizeStyleValue const & StyleValue : : as_grid_track_size_list ( ) const
2022-08-24 12:27:56 +02:00
{
2022-10-30 13:27:57 +01:00
VERIFY ( is_grid_track_size_list ( ) ) ;
2022-08-24 12:27:56 +02:00
return static_cast < GridTrackSizeStyleValue const & > ( * this ) ;
}
2022-07-12 00:09:29 +01:00
LinearGradientStyleValue const & StyleValue : : as_linear_gradient ( ) const
{
VERIFY ( is_linear_gradient ( ) ) ;
return static_cast < LinearGradientStyleValue const & > ( * this ) ;
}
2021-09-23 19:54:19 +01:00
ListStyleStyleValue const & StyleValue : : as_list_style ( ) const
{
VERIFY ( is_list_style ( ) ) ;
return static_cast < ListStyleStyleValue const & > ( * this ) ;
}
NumericStyleValue const & StyleValue : : as_numeric ( ) const
{
VERIFY ( is_numeric ( ) ) ;
return static_cast < NumericStyleValue const & > ( * this ) ;
}
OverflowStyleValue const & StyleValue : : as_overflow ( ) const
{
VERIFY ( is_overflow ( ) ) ;
return static_cast < OverflowStyleValue const & > ( * this ) ;
}
2022-01-14 17:09:02 +00:00
PercentageStyleValue const & StyleValue : : as_percentage ( ) const
{
VERIFY ( is_percentage ( ) ) ;
return static_cast < PercentageStyleValue const & > ( * this ) ;
}
2021-10-31 16:02:29 +00:00
PositionStyleValue const & StyleValue : : as_position ( ) const
{
VERIFY ( is_position ( ) ) ;
return static_cast < PositionStyleValue const & > ( * this ) ;
}
2022-11-11 18:13:00 +01:00
RadialGradientStyleValue const & StyleValue : : as_radial_gradient ( ) const
{
VERIFY ( is_radial_gradient ( ) ) ;
return static_cast < RadialGradientStyleValue const & > ( * this ) ;
}
2022-07-31 18:46:35 +02:00
RectStyleValue const & StyleValue : : as_rect ( ) const
{
VERIFY ( is_rect ( ) ) ;
return static_cast < RectStyleValue const & > ( * this ) ;
}
2022-02-21 17:51:01 +00:00
ResolutionStyleValue const & StyleValue : : as_resolution ( ) const
{
VERIFY ( is_resolution ( ) ) ;
return static_cast < ResolutionStyleValue const & > ( * this ) ;
}
2021-09-23 19:54:19 +01:00
StringStyleValue const & StyleValue : : as_string ( ) const
{
VERIFY ( is_string ( ) ) ;
return static_cast < StringStyleValue const & > ( * this ) ;
}
TextDecorationStyleValue const & StyleValue : : as_text_decoration ( ) const
{
VERIFY ( is_text_decoration ( ) ) ;
return static_cast < TextDecorationStyleValue const & > ( * this ) ;
}
2022-02-21 19:29:43 +00:00
TimeStyleValue const & StyleValue : : as_time ( ) const
{
VERIFY ( is_time ( ) ) ;
return static_cast < TimeStyleValue const & > ( * this ) ;
}
2021-09-23 19:54:19 +01:00
TransformationStyleValue const & StyleValue : : as_transformation ( ) const
{
VERIFY ( is_transformation ( ) ) ;
return static_cast < TransformationStyleValue const & > ( * this ) ;
}
2021-12-03 12:28:14 +00:00
UnresolvedStyleValue const & StyleValue : : as_unresolved ( ) const
{
VERIFY ( is_unresolved ( ) ) ;
return static_cast < UnresolvedStyleValue const & > ( * this ) ;
}
2021-09-23 19:54:19 +01:00
UnsetStyleValue const & StyleValue : : as_unset ( ) const
{
VERIFY ( is_unset ( ) ) ;
return static_cast < UnsetStyleValue const & > ( * this ) ;
}
StyleValueList const & StyleValue : : as_value_list ( ) const
{
VERIFY ( is_value_list ( ) ) ;
return static_cast < StyleValueList const & > ( * this ) ;
}
2022-02-18 12:07:09 +00:00
void CalculatedStyleValue : : CalculationResult : : add ( CalculationResult const & other , Layout : : Node const * layout_node , PercentageBasis const & percentage_basis )
2022-01-27 14:50:31 +00:00
{
add_or_subtract_internal ( SumOperation : : Add , other , layout_node , percentage_basis ) ;
}
2022-02-18 12:07:09 +00:00
void CalculatedStyleValue : : CalculationResult : : subtract ( CalculationResult const & other , Layout : : Node const * layout_node , PercentageBasis const & percentage_basis )
2022-01-27 14:50:31 +00:00
{
add_or_subtract_internal ( SumOperation : : Subtract , other , layout_node , percentage_basis ) ;
}
2022-02-18 12:07:09 +00:00
void CalculatedStyleValue : : CalculationResult : : add_or_subtract_internal ( SumOperation op , CalculationResult const & other , Layout : : Node const * layout_node , PercentageBasis const & percentage_basis )
2022-01-27 14:50:31 +00:00
{
// We know from validation when resolving the type, that "both sides have the same type, or that one side is a <number> and the other is an <integer>".
// Though, having the same type may mean that one side is a <dimension> and the other a <percentage>.
// Note: This is almost identical to ::add()
m_value . visit (
2022-02-02 12:34:32 +00:00
[ & ] ( Number const & number ) {
auto other_number = other . m_value . get < Number > ( ) ;
if ( op = = SumOperation : : Add ) {
2022-03-21 21:03:17 +00:00
m_value = number + other_number ;
2022-02-02 12:34:32 +00:00
} else {
2022-03-21 21:03:17 +00:00
m_value = number - other_number ;
2022-02-02 12:34:32 +00:00
}
2022-01-27 14:50:31 +00:00
} ,
2022-02-21 17:43:30 +00:00
[ & ] ( Angle const & angle ) {
auto this_degrees = angle . to_degrees ( ) ;
if ( other . m_value . has < Angle > ( ) ) {
auto other_degrees = other . m_value . get < Angle > ( ) . to_degrees ( ) ;
if ( op = = SumOperation : : Add )
m_value = Angle : : make_degrees ( this_degrees + other_degrees ) ;
else
m_value = Angle : : make_degrees ( this_degrees - other_degrees ) ;
} else {
VERIFY ( percentage_basis . has < Angle > ( ) ) ;
auto other_degrees = percentage_basis . get < Angle > ( ) . percentage_of ( other . m_value . get < Percentage > ( ) ) . to_degrees ( ) ;
if ( op = = SumOperation : : Add )
m_value = Angle : : make_degrees ( this_degrees + other_degrees ) ;
else
m_value = Angle : : make_degrees ( this_degrees - other_degrees ) ;
}
} ,
2022-02-21 17:49:47 +00:00
[ & ] ( Frequency const & frequency ) {
auto this_hertz = frequency . to_hertz ( ) ;
if ( other . m_value . has < Frequency > ( ) ) {
auto other_hertz = other . m_value . get < Frequency > ( ) . to_hertz ( ) ;
if ( op = = SumOperation : : Add )
m_value = Frequency : : make_hertz ( this_hertz + other_hertz ) ;
else
m_value = Frequency : : make_hertz ( this_hertz - other_hertz ) ;
} else {
VERIFY ( percentage_basis . has < Frequency > ( ) ) ;
auto other_hertz = percentage_basis . get < Frequency > ( ) . percentage_of ( other . m_value . get < Percentage > ( ) ) . to_hertz ( ) ;
if ( op = = SumOperation : : Add )
m_value = Frequency : : make_hertz ( this_hertz + other_hertz ) ;
else
m_value = Frequency : : make_hertz ( this_hertz - other_hertz ) ;
}
} ,
2022-01-27 14:50:31 +00:00
[ & ] ( Length const & length ) {
auto this_px = length . to_px ( * layout_node ) ;
if ( other . m_value . has < Length > ( ) ) {
auto other_px = other . m_value . get < Length > ( ) . to_px ( * layout_node ) ;
if ( op = = SumOperation : : Add )
m_value = Length : : make_px ( this_px + other_px ) ;
else
m_value = Length : : make_px ( this_px - other_px ) ;
} else {
2022-02-18 12:07:09 +00:00
VERIFY ( percentage_basis . has < Length > ( ) ) ;
2022-01-27 14:50:31 +00:00
2022-02-18 12:07:09 +00:00
auto other_px = percentage_basis . get < Length > ( ) . percentage_of ( other . m_value . get < Percentage > ( ) ) . to_px ( * layout_node ) ;
2022-01-27 14:50:31 +00:00
if ( op = = SumOperation : : Add )
m_value = Length : : make_px ( this_px + other_px ) ;
else
m_value = Length : : make_px ( this_px - other_px ) ;
}
} ,
2022-02-21 19:29:43 +00:00
[ & ] ( Time const & time ) {
auto this_seconds = time . to_seconds ( ) ;
if ( other . m_value . has < Time > ( ) ) {
auto other_seconds = other . m_value . get < Time > ( ) . to_seconds ( ) ;
if ( op = = SumOperation : : Add )
m_value = Time : : make_seconds ( this_seconds + other_seconds ) ;
else
m_value = Time : : make_seconds ( this_seconds - other_seconds ) ;
} else {
VERIFY ( percentage_basis . has < Time > ( ) ) ;
auto other_seconds = percentage_basis . get < Time > ( ) . percentage_of ( other . m_value . get < Percentage > ( ) ) . to_seconds ( ) ;
if ( op = = SumOperation : : Add )
m_value = Time : : make_seconds ( this_seconds + other_seconds ) ;
else
m_value = Time : : make_seconds ( this_seconds - other_seconds ) ;
}
} ,
2022-01-27 14:50:31 +00:00
[ & ] ( Percentage const & percentage ) {
if ( other . m_value . has < Percentage > ( ) ) {
if ( op = = SumOperation : : Add )
m_value = Percentage { percentage . value ( ) + other . m_value . get < Percentage > ( ) . value ( ) } ;
else
m_value = Percentage { percentage . value ( ) - other . m_value . get < Percentage > ( ) . value ( ) } ;
return ;
}
// Other side isn't a percentage, so the easiest way to handle it without duplicating all the logic, is just to swap `this` and `other`.
CalculationResult new_value = other ;
2022-06-29 23:32:05 +01:00
if ( op = = SumOperation : : Add ) {
new_value . add ( * this , layout_node , percentage_basis ) ;
} else {
// Turn 'this - other' into '-other + this', as 'A + B == B + A', but 'A - B != B - A'
new_value . multiply_by ( { Number { Number : : Type : : Integer , - 1.0f } } , layout_node ) ;
2022-01-27 14:50:31 +00:00
new_value . add ( * this , layout_node , percentage_basis ) ;
2022-06-29 23:32:05 +01:00
}
2022-01-27 14:50:31 +00:00
* this = new_value ;
} ) ;
}
void CalculatedStyleValue : : CalculationResult : : multiply_by ( CalculationResult const & other , Layout : : Node const * layout_node )
{
// We know from validation when resolving the type, that at least one side must be a <number> or <integer>.
// Both of these are represented as a float.
2022-02-02 12:34:32 +00:00
VERIFY ( m_value . has < Number > ( ) | | other . m_value . has < Number > ( ) ) ;
bool other_is_number = other . m_value . has < Number > ( ) ;
2022-01-27 14:50:31 +00:00
m_value . visit (
2022-02-02 12:34:32 +00:00
[ & ] ( Number const & number ) {
2022-01-27 14:50:31 +00:00
if ( other_is_number ) {
2022-03-21 21:03:17 +00:00
m_value = number * other . m_value . get < Number > ( ) ;
2022-01-27 14:50:31 +00:00
} else {
// Avoid duplicating all the logic by swapping `this` and `other`.
CalculationResult new_value = other ;
new_value . multiply_by ( * this , layout_node ) ;
* this = new_value ;
}
} ,
2022-02-21 17:43:30 +00:00
[ & ] ( Angle const & angle ) {
2022-03-21 21:03:17 +00:00
m_value = Angle : : make_degrees ( angle . to_degrees ( ) * other . m_value . get < Number > ( ) . value ( ) ) ;
2022-02-21 17:43:30 +00:00
} ,
2022-02-21 17:49:47 +00:00
[ & ] ( Frequency const & frequency ) {
2022-03-21 21:03:17 +00:00
m_value = Frequency : : make_hertz ( frequency . to_hertz ( ) * other . m_value . get < Number > ( ) . value ( ) ) ;
2022-02-21 17:49:47 +00:00
} ,
2022-01-27 14:50:31 +00:00
[ & ] ( Length const & length ) {
2022-01-27 14:51:51 +00:00
VERIFY ( layout_node ) ;
2022-03-21 21:03:17 +00:00
m_value = Length : : make_px ( length . to_px ( * layout_node ) * other . m_value . get < Number > ( ) . value ( ) ) ;
2022-01-27 14:50:31 +00:00
} ,
2022-02-21 19:29:43 +00:00
[ & ] ( Time const & time ) {
2022-03-21 21:03:17 +00:00
m_value = Time : : make_seconds ( time . to_seconds ( ) * other . m_value . get < Number > ( ) . value ( ) ) ;
2022-02-21 19:29:43 +00:00
} ,
2022-01-27 14:50:31 +00:00
[ & ] ( Percentage const & percentage ) {
2022-03-21 21:03:17 +00:00
m_value = Percentage { percentage . value ( ) * other . m_value . get < Number > ( ) . value ( ) } ;
2022-01-27 14:50:31 +00:00
} ) ;
}
void CalculatedStyleValue : : CalculationResult : : divide_by ( CalculationResult const & other , Layout : : Node const * layout_node )
{
// We know from validation when resolving the type, that `other` must be a <number> or <integer>.
2022-02-02 12:34:32 +00:00
// Both of these are represented as a Number.
2022-03-21 21:03:17 +00:00
auto denominator = other . m_value . get < Number > ( ) . value ( ) ;
2022-01-27 14:50:31 +00:00
// FIXME: Dividing by 0 is invalid, and should be caught during parsing.
VERIFY ( denominator ! = 0.0f ) ;
m_value . visit (
2022-02-02 12:34:32 +00:00
[ & ] ( Number const & number ) {
m_value = Number {
2022-03-21 21:03:17 +00:00
Number : : Type : : Number ,
number . value ( ) / denominator
2022-02-02 12:34:32 +00:00
} ;
2022-01-27 14:50:31 +00:00
} ,
2022-02-21 17:43:30 +00:00
[ & ] ( Angle const & angle ) {
m_value = Angle : : make_degrees ( angle . to_degrees ( ) / denominator ) ;
} ,
2022-02-21 17:49:47 +00:00
[ & ] ( Frequency const & frequency ) {
m_value = Frequency : : make_hertz ( frequency . to_hertz ( ) / denominator ) ;
} ,
2022-01-27 14:50:31 +00:00
[ & ] ( Length const & length ) {
2022-01-27 14:51:51 +00:00
VERIFY ( layout_node ) ;
2022-01-27 14:50:31 +00:00
m_value = Length : : make_px ( length . to_px ( * layout_node ) / denominator ) ;
} ,
2022-02-21 19:29:43 +00:00
[ & ] ( Time const & time ) {
m_value = Time : : make_seconds ( time . to_seconds ( ) / denominator ) ;
} ,
2022-01-27 14:50:31 +00:00
[ & ] ( Percentage const & percentage ) {
m_value = Percentage { percentage . value ( ) / denominator } ;
} ) ;
2022-02-02 20:39:04 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
2023-01-06 19:02:26 +01:00
return String : : formatted ( " calc({}) " , TRY ( m_expression - > to_string ( ) ) ) ;
2022-02-02 15:34:13 +00:00
}
2023-02-20 00:41:51 +00:00
bool CalculatedStyleValue : : equals ( StyleValue const & other ) const
2022-04-18 17:42:03 +01:00
{
if ( type ( ) ! = other . type ( ) )
return false ;
// This is a case where comparing the strings actually makes sense.
2023-01-06 19:02:26 +01:00
return to_string ( ) . release_value_but_fixme_should_propagate_errors ( ) = = other . to_string ( ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcNumberValue : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
return value . visit (
2023-01-13 02:22:58 +00:00
[ ] ( Number const & number ) - > ErrorOr < String > { return String : : number ( number . value ( ) ) ; } ,
[ ] ( NonnullOwnPtr < CalcNumberSum > const & sum ) - > ErrorOr < String > { return String : : formatted ( " ({}) " , TRY ( sum - > to_string ( ) ) ) ; } ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcValue : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
return value . visit (
2023-01-13 02:22:58 +00:00
[ ] ( Number const & number ) - > ErrorOr < String > { return String : : number ( number . value ( ) ) ; } ,
[ ] ( NonnullOwnPtr < CalcSum > const & sum ) - > ErrorOr < String > { return String : : formatted ( " ({}) " , TRY ( sum - > to_string ( ) ) ) ; } ,
[ ] ( auto const & v ) - > ErrorOr < String > { return v . to_string ( ) ; } ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcSum : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
StringBuilder builder ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( TRY ( first_calc_product - > to_string ( ) ) ) ) ;
2022-02-02 15:34:13 +00:00
for ( auto const & item : zero_or_more_additional_calc_products )
2023-03-06 17:16:25 +01:00
TRY ( builder . try_append ( TRY ( item - > to_string ( ) ) ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcNumberSum : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
StringBuilder builder ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( TRY ( first_calc_number_product - > to_string ( ) ) ) ) ;
2022-02-02 15:34:13 +00:00
for ( auto const & item : zero_or_more_additional_calc_number_products )
2023-03-06 17:16:25 +01:00
TRY ( builder . try_append ( TRY ( item - > to_string ( ) ) ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcProduct : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
StringBuilder builder ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( TRY ( first_calc_value . to_string ( ) ) ) ) ;
2022-02-02 15:34:13 +00:00
for ( auto const & item : zero_or_more_additional_calc_values )
2023-03-06 17:16:25 +01:00
TRY ( builder . try_append ( TRY ( item - > to_string ( ) ) ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcSumPartWithOperator : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
2023-01-06 19:02:26 +01:00
return String : : formatted ( " {} {} " , op = = SumOperation : : Add ? " + " sv : " - " sv , TRY ( value - > to_string ( ) ) ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcProductPartWithOperator : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
2023-01-13 02:22:58 +00:00
auto value_string = TRY ( value . visit (
2023-01-06 19:02:26 +01:00
[ ] ( CalcValue const & v ) { return v . to_string ( ) ; } ,
2023-01-13 02:22:58 +00:00
[ ] ( CalcNumberValue const & v ) { return v . to_string ( ) ; } ) ) ;
2023-01-06 19:02:26 +01:00
return String : : formatted ( " {} {} " , op = = ProductOperation : : Multiply ? " * " sv : " / " sv , value_string ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcNumberProduct : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
StringBuilder builder ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( TRY ( first_calc_number_value . to_string ( ) ) ) ) ;
2022-02-02 15:34:13 +00:00
for ( auto const & item : zero_or_more_additional_calc_number_values )
2023-03-06 17:16:25 +01:00
TRY ( builder . try_append ( TRY ( item - > to_string ( ) ) ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcNumberProductPartWithOperator : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
2023-01-06 19:02:26 +01:00
return String : : formatted ( " {} {} " , op = = ProductOperation : : Multiply ? " * " sv : " / " sv , TRY ( value . to_string ( ) ) ) ;
2022-02-02 15:34:13 +00:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > CalculatedStyleValue : : CalcNumberSumPartWithOperator : : to_string ( ) const
2022-02-02 15:34:13 +00:00
{
2023-01-06 19:02:26 +01:00
return String : : formatted ( " {} {} " , op = = SumOperation : : Add ? " + " sv : " - " sv , TRY ( value - > to_string ( ) ) ) ;
2022-02-02 15:34:13 +00:00
}
2022-02-21 17:43:30 +00:00
Optional < Angle > CalculatedStyleValue : : resolve_angle ( ) const
2022-01-24 17:38:29 +00:00
{
2022-02-21 17:43:30 +00:00
auto result = m_expression - > resolve ( nullptr , { } ) ;
if ( result . value ( ) . has < Angle > ( ) )
return result . value ( ) . get < Angle > ( ) ;
return { } ;
}
2022-07-20 13:03:30 +01:00
Optional < Angle > CalculatedStyleValue : : resolve_angle_percentage ( Angle const & percentage_basis ) const
2022-02-21 17:43:30 +00:00
{
auto result = m_expression - > resolve ( nullptr , percentage_basis ) ;
2022-01-24 17:38:29 +00:00
2022-01-27 14:51:51 +00:00
return result . value ( ) . visit (
2022-07-20 13:03:30 +01:00
[ & ] ( Angle const & angle ) - > Optional < Angle > {
2022-02-21 17:43:30 +00:00
return angle ;
2022-01-24 17:38:29 +00:00
} ,
2022-07-27 12:20:35 +01:00
[ & ] ( Percentage const & percentage ) - > Optional < Angle > {
return percentage_basis . percentage_of ( percentage ) ;
} ,
2022-07-20 13:03:30 +01:00
[ & ] ( auto const & ) - > Optional < Angle > {
2022-01-27 14:51:51 +00:00
return { } ;
2022-01-24 17:38:29 +00:00
} ) ;
}
2022-02-21 17:49:47 +00:00
Optional < Frequency > CalculatedStyleValue : : resolve_frequency ( ) const
{
auto result = m_expression - > resolve ( nullptr , { } ) ;
if ( result . value ( ) . has < Frequency > ( ) )
return result . value ( ) . get < Frequency > ( ) ;
return { } ;
}
2022-07-20 13:03:30 +01:00
Optional < Frequency > CalculatedStyleValue : : resolve_frequency_percentage ( Frequency const & percentage_basis ) const
2022-02-21 17:49:47 +00:00
{
auto result = m_expression - > resolve ( nullptr , percentage_basis ) ;
return result . value ( ) . visit (
2022-07-20 13:03:30 +01:00
[ & ] ( Frequency const & frequency ) - > Optional < Frequency > {
2022-02-21 17:49:47 +00:00
return frequency ;
} ,
2022-07-27 12:20:35 +01:00
[ & ] ( Percentage const & percentage ) - > Optional < Frequency > {
return percentage_basis . percentage_of ( percentage ) ;
} ,
2022-07-20 13:03:30 +01:00
[ & ] ( auto const & ) - > Optional < Frequency > {
2022-02-21 17:49:47 +00:00
return { } ;
} ) ;
}
2022-02-21 17:43:30 +00:00
Optional < Length > CalculatedStyleValue : : resolve_length ( Layout : : Node const & layout_node ) const
{
auto result = m_expression - > resolve ( & layout_node , { } ) ;
if ( result . value ( ) . has < Length > ( ) )
return result . value ( ) . get < Length > ( ) ;
return { } ;
}
2022-07-20 13:03:30 +01:00
Optional < Length > CalculatedStyleValue : : resolve_length_percentage ( Layout : : Node const & layout_node , Length const & percentage_basis ) const
2022-01-24 17:38:29 +00:00
{
2022-01-27 14:51:51 +00:00
auto result = m_expression - > resolve ( & layout_node , percentage_basis ) ;
2022-01-24 17:38:29 +00:00
2022-01-27 14:51:51 +00:00
return result . value ( ) . visit (
2022-07-20 13:03:30 +01:00
[ & ] ( Length const & length ) - > Optional < Length > {
2022-01-27 14:51:51 +00:00
return length ;
} ,
2022-07-27 12:20:35 +01:00
[ & ] ( Percentage const & percentage ) - > Optional < Length > {
return percentage_basis . percentage_of ( percentage ) ;
} ,
2022-07-20 13:03:30 +01:00
[ & ] ( auto const & ) - > Optional < Length > {
2022-02-21 17:43:30 +00:00
return { } ;
2022-01-24 17:38:29 +00:00
} ) ;
}
2022-01-27 15:46:24 +00:00
Optional < Percentage > CalculatedStyleValue : : resolve_percentage ( ) const
{
auto result = m_expression - > resolve ( nullptr , { } ) ;
if ( result . value ( ) . has < Percentage > ( ) )
return result . value ( ) . get < Percentage > ( ) ;
return { } ;
}
2022-02-21 19:29:43 +00:00
Optional < Time > CalculatedStyleValue : : resolve_time ( ) const
{
auto result = m_expression - > resolve ( nullptr , { } ) ;
if ( result . value ( ) . has < Time > ( ) )
return result . value ( ) . get < Time > ( ) ;
return { } ;
}
2022-07-20 13:03:30 +01:00
Optional < Time > CalculatedStyleValue : : resolve_time_percentage ( Time const & percentage_basis ) const
2022-02-21 19:29:43 +00:00
{
auto result = m_expression - > resolve ( nullptr , percentage_basis ) ;
return result . value ( ) . visit (
2022-07-20 13:03:30 +01:00
[ & ] ( Time const & time ) - > Optional < Time > {
2022-02-21 19:29:43 +00:00
return time ;
} ,
2022-07-20 13:03:30 +01:00
[ & ] ( auto const & ) - > Optional < Time > {
2022-02-21 19:29:43 +00:00
return { } ;
} ) ;
}
2022-01-27 15:46:24 +00:00
Optional < float > CalculatedStyleValue : : resolve_number ( )
{
auto result = m_expression - > resolve ( nullptr , { } ) ;
2022-02-02 12:34:32 +00:00
if ( result . value ( ) . has < Number > ( ) )
2022-03-21 21:03:17 +00:00
return result . value ( ) . get < Number > ( ) . value ( ) ;
2022-01-27 15:46:24 +00:00
return { } ;
}
Optional < i64 > CalculatedStyleValue : : resolve_integer ( )
{
auto result = m_expression - > resolve ( nullptr , { } ) ;
2022-02-02 12:34:32 +00:00
if ( result . value ( ) . has < Number > ( ) )
2022-03-21 21:03:17 +00:00
return result . value ( ) . get < Number > ( ) . integer_value ( ) ;
2022-01-27 15:46:24 +00:00
return { } ;
}
2022-01-25 14:45:08 +00:00
static bool is_number ( CalculatedStyleValue : : ResolvedType type )
{
return type = = CalculatedStyleValue : : ResolvedType : : Number | | type = = CalculatedStyleValue : : ResolvedType : : Integer ;
}
static bool is_dimension ( CalculatedStyleValue : : ResolvedType type )
{
return type ! = CalculatedStyleValue : : ResolvedType : : Number
& & type ! = CalculatedStyleValue : : ResolvedType : : Integer
& & type ! = CalculatedStyleValue : : ResolvedType : : Percentage ;
}
template < typename SumWithOperator >
2023-03-06 17:16:25 +01:00
static Optional < CalculatedStyleValue : : ResolvedType > resolve_sum_type ( CalculatedStyleValue : : ResolvedType first_type , Vector < NonnullOwnPtr < SumWithOperator > > const & zero_or_more_additional_products )
2022-01-25 14:45:08 +00:00
{
auto type = first_type ;
for ( auto const & product : zero_or_more_additional_products ) {
2023-03-06 17:16:25 +01:00
auto maybe_product_type = product - > resolved_type ( ) ;
2022-01-25 14:45:08 +00:00
if ( ! maybe_product_type . has_value ( ) )
return { } ;
auto product_type = maybe_product_type . value ( ) ;
// At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>.
// If both sides are the same type, resolve to that type.
if ( product_type = = type )
continue ;
// If one side is a <number> and the other is an <integer>, resolve to <number>.
if ( is_number ( type ) & & is_number ( product_type ) ) {
type = CalculatedStyleValue : : ResolvedType : : Number ;
continue ;
}
// FIXME: calc() handles <percentage> by allowing them to pretend to be whatever <dimension> type is allowed at this location.
// Since we can't easily check what that type is, we just allow <percentage> to combine with any other <dimension> type.
if ( type = = CalculatedStyleValue : : ResolvedType : : Percentage & & is_dimension ( product_type ) ) {
type = product_type ;
continue ;
}
if ( is_dimension ( type ) & & product_type = = CalculatedStyleValue : : ResolvedType : : Percentage )
continue ;
return { } ;
}
return type ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcSum : : resolved_type ( ) const
{
auto maybe_type = first_calc_product - > resolved_type ( ) ;
if ( ! maybe_type . has_value ( ) )
return { } ;
auto type = maybe_type . value ( ) ;
return resolve_sum_type ( type , zero_or_more_additional_calc_products ) ;
}
2022-08-02 15:08:06 +02:00
// https://www.w3.org/TR/CSS2/visufx.html#value-def-shape
Gfx : : FloatRect EdgeRect : : resolved ( Layout : : Node const & layout_node , Gfx : : FloatRect border_box ) const
{
// In CSS 2.1, the only valid <shape> value is: rect(<top>, <right>, <bottom>, <left>) where
// <top> and <bottom> specify offsets from the top border edge of the box, and <right>, and
// <left> specify offsets from the left border edge of the box.
// The value 'auto' means that a given edge of the clipping region will be the same as the edge
// of the element's generated border box (i.e., 'auto' means the same as '0' for <top> and
// <left>, the same as the used value of the height plus the sum of vertical padding and border
// widths for <bottom>, and the same as the used value of the width plus the sum of the
// horizontal padding and border widths for <right>, such that four 'auto' values result in the
// clipping region being the same as the element's border box).
2022-11-08 17:29:52 +00:00
auto left = border_box . left ( ) + ( left_edge . is_auto ( ) ? 0 : left_edge . to_px ( layout_node ) ) . value ( ) ;
auto top = border_box . top ( ) + ( top_edge . is_auto ( ) ? 0 : top_edge . to_px ( layout_node ) ) . value ( ) ;
auto right = border_box . left ( ) + ( right_edge . is_auto ( ) ? border_box . width ( ) : right_edge . to_px ( layout_node ) ) . value ( ) ;
auto bottom = border_box . top ( ) + ( bottom_edge . is_auto ( ) ? border_box . height ( ) : bottom_edge . to_px ( layout_node ) ) . value ( ) ;
2022-08-02 15:08:06 +02:00
return Gfx : : FloatRect {
2022-08-07 23:28:14 +01:00
left ,
top ,
right - left ,
bottom - top
2022-08-02 15:08:06 +02:00
} ;
}
2022-01-25 14:45:08 +00:00
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcNumberSum : : resolved_type ( ) const
{
auto maybe_type = first_calc_number_product - > resolved_type ( ) ;
if ( ! maybe_type . has_value ( ) )
return { } ;
auto type = maybe_type . value ( ) ;
return resolve_sum_type ( type , zero_or_more_additional_calc_number_products ) ;
}
template < typename ProductWithOperator >
2023-03-06 17:16:25 +01:00
static Optional < CalculatedStyleValue : : ResolvedType > resolve_product_type ( CalculatedStyleValue : : ResolvedType first_type , Vector < NonnullOwnPtr < ProductWithOperator > > const & zero_or_more_additional_values )
2022-01-25 14:45:08 +00:00
{
auto type = first_type ;
for ( auto const & value : zero_or_more_additional_values ) {
2023-03-06 17:16:25 +01:00
auto maybe_value_type = value - > resolved_type ( ) ;
2022-01-25 14:45:08 +00:00
if ( ! maybe_value_type . has_value ( ) )
return { } ;
auto value_type = maybe_value_type . value ( ) ;
2023-03-06 17:16:25 +01:00
if ( value - > op = = CalculatedStyleValue : : ProductOperation : : Multiply ) {
2022-01-25 14:45:08 +00:00
// At *, check that at least one side is <number>.
if ( ! ( is_number ( type ) | | is_number ( value_type ) ) )
return { } ;
// If both sides are <integer>, resolve to <integer>.
if ( type = = CalculatedStyleValue : : ResolvedType : : Integer & & value_type = = CalculatedStyleValue : : ResolvedType : : Integer ) {
type = CalculatedStyleValue : : ResolvedType : : Integer ;
} else {
// Otherwise, resolve to the type of the other side.
if ( is_number ( type ) )
type = value_type ;
}
continue ;
} else {
2023-03-06 17:16:25 +01:00
VERIFY ( value - > op = = CalculatedStyleValue : : ProductOperation : : Divide ) ;
2022-01-25 14:45:08 +00:00
// At /, check that the right side is <number>.
if ( ! is_number ( value_type ) )
return { } ;
// If the left side is <integer>, resolve to <number>.
if ( type = = CalculatedStyleValue : : ResolvedType : : Integer ) {
type = CalculatedStyleValue : : ResolvedType : : Number ;
} else {
// Otherwise, resolve to the type of the left side.
}
// FIXME: Division by zero makes the whole calc() expression invalid.
}
}
return type ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcProduct : : resolved_type ( ) const
{
auto maybe_type = first_calc_value . resolved_type ( ) ;
if ( ! maybe_type . has_value ( ) )
return { } ;
auto type = maybe_type . value ( ) ;
return resolve_product_type ( type , zero_or_more_additional_calc_values ) ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcSumPartWithOperator : : resolved_type ( ) const
{
return value - > resolved_type ( ) ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcNumberProduct : : resolved_type ( ) const
{
auto maybe_type = first_calc_number_value . resolved_type ( ) ;
if ( ! maybe_type . has_value ( ) )
return { } ;
auto type = maybe_type . value ( ) ;
return resolve_product_type ( type , zero_or_more_additional_calc_number_values ) ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcNumberProductPartWithOperator : : resolved_type ( ) const
{
return value . resolved_type ( ) ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcNumberSumPartWithOperator : : resolved_type ( ) const
{
return value - > resolved_type ( ) ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcProductPartWithOperator : : resolved_type ( ) const
{
return value . visit (
[ ] ( CalcValue const & calc_value ) {
return calc_value . resolved_type ( ) ;
} ,
[ ] ( CalcNumberValue const & calc_number_value ) {
return calc_number_value . resolved_type ( ) ;
} ) ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcValue : : resolved_type ( ) const
{
return value . visit (
2022-02-02 12:34:32 +00:00
[ ] ( Number const & number ) - > Optional < CalculatedStyleValue : : ResolvedType > {
2022-03-21 21:03:17 +00:00
return { number . is_integer ( ) ? ResolvedType : : Integer : ResolvedType : : Number } ;
2022-02-02 12:34:32 +00:00
} ,
2022-02-21 17:43:30 +00:00
[ ] ( Angle const & ) - > Optional < CalculatedStyleValue : : ResolvedType > { return { ResolvedType : : Angle } ; } ,
2022-02-21 17:49:47 +00:00
[ ] ( Frequency const & ) - > Optional < CalculatedStyleValue : : ResolvedType > { return { ResolvedType : : Frequency } ; } ,
2022-01-25 14:45:08 +00:00
[ ] ( Length const & ) - > Optional < CalculatedStyleValue : : ResolvedType > { return { ResolvedType : : Length } ; } ,
2022-01-27 14:47:39 +00:00
[ ] ( Percentage const & ) - > Optional < CalculatedStyleValue : : ResolvedType > { return { ResolvedType : : Percentage } ; } ,
2022-02-21 19:29:43 +00:00
[ ] ( Time const & ) - > Optional < CalculatedStyleValue : : ResolvedType > { return { ResolvedType : : Time } ; } ,
2022-01-25 14:45:08 +00:00
[ ] ( NonnullOwnPtr < CalcSum > const & sum ) { return sum - > resolved_type ( ) ; } ) ;
}
Optional < CalculatedStyleValue : : ResolvedType > CalculatedStyleValue : : CalcNumberValue : : resolved_type ( ) const
{
return value . visit (
2022-02-02 12:34:32 +00:00
[ ] ( Number const & number ) - > Optional < CalculatedStyleValue : : ResolvedType > {
2022-03-21 21:03:17 +00:00
return { number . is_integer ( ) ? ResolvedType : : Integer : ResolvedType : : Number } ;
2022-02-02 12:34:32 +00:00
} ,
2022-01-25 14:45:08 +00:00
[ ] ( NonnullOwnPtr < CalcNumberSum > const & sum ) { return sum - > resolved_type ( ) ; } ) ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcNumberValue : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
return value . visit (
2022-02-02 12:34:32 +00:00
[ & ] ( Number const & number ) - > CalculatedStyleValue : : CalculationResult {
return CalculatedStyleValue : : CalculationResult { number } ;
2022-01-27 14:51:51 +00:00
} ,
[ & ] ( NonnullOwnPtr < CalcNumberSum > const & sum ) - > CalculatedStyleValue : : CalculationResult {
return sum - > resolve ( layout_node , percentage_basis ) ;
} ) ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcValue : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
return value . visit (
[ & ] ( NonnullOwnPtr < CalcSum > const & sum ) - > CalculatedStyleValue : : CalculationResult {
return sum - > resolve ( layout_node , percentage_basis ) ;
2022-02-21 17:43:30 +00:00
} ,
[ & ] ( auto const & v ) - > CalculatedStyleValue : : CalculationResult {
return CalculatedStyleValue : : CalculationResult { v } ;
2022-01-27 14:51:51 +00:00
} ) ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcSum : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
auto value = first_calc_product - > resolve ( layout_node , percentage_basis ) ;
for ( auto & additional_product : zero_or_more_additional_calc_products ) {
2023-03-06 17:16:25 +01:00
auto additional_value = additional_product - > resolve ( layout_node , percentage_basis ) ;
2022-01-27 14:51:51 +00:00
2023-03-06 17:16:25 +01:00
if ( additional_product - > op = = CalculatedStyleValue : : SumOperation : : Add )
2022-01-27 14:51:51 +00:00
value . add ( additional_value , layout_node , percentage_basis ) ;
2023-03-06 17:16:25 +01:00
else if ( additional_product - > op = = CalculatedStyleValue : : SumOperation : : Subtract )
2022-01-27 14:51:51 +00:00
value . subtract ( additional_value , layout_node , percentage_basis ) ;
else
VERIFY_NOT_REACHED ( ) ;
}
return value ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcNumberSum : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
auto value = first_calc_number_product - > resolve ( layout_node , percentage_basis ) ;
for ( auto & additional_product : zero_or_more_additional_calc_number_products ) {
2023-03-06 17:16:25 +01:00
auto additional_value = additional_product - > resolve ( layout_node , percentage_basis ) ;
2022-01-27 14:51:51 +00:00
2023-03-06 17:16:25 +01:00
if ( additional_product - > op = = CSS : : CalculatedStyleValue : : SumOperation : : Add )
2022-01-27 14:51:51 +00:00
value . add ( additional_value , layout_node , percentage_basis ) ;
2023-03-06 17:16:25 +01:00
else if ( additional_product - > op = = CalculatedStyleValue : : SumOperation : : Subtract )
2022-01-27 14:51:51 +00:00
value . subtract ( additional_value , layout_node , percentage_basis ) ;
else
VERIFY_NOT_REACHED ( ) ;
}
return value ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcProduct : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
auto value = first_calc_value . resolve ( layout_node , percentage_basis ) ;
for ( auto & additional_value : zero_or_more_additional_calc_values ) {
2023-03-06 17:16:25 +01:00
additional_value - > value . visit (
2022-01-27 14:51:51 +00:00
[ & ] ( CalculatedStyleValue : : CalcValue const & calc_value ) {
2023-03-06 17:16:25 +01:00
VERIFY ( additional_value - > op = = CalculatedStyleValue : : ProductOperation : : Multiply ) ;
2022-01-27 14:51:51 +00:00
auto resolved_value = calc_value . resolve ( layout_node , percentage_basis ) ;
value . multiply_by ( resolved_value , layout_node ) ;
} ,
[ & ] ( CalculatedStyleValue : : CalcNumberValue const & calc_number_value ) {
2023-03-06 17:16:25 +01:00
VERIFY ( additional_value - > op = = CalculatedStyleValue : : ProductOperation : : Divide ) ;
2022-01-27 14:51:51 +00:00
auto resolved_calc_number_value = calc_number_value . resolve ( layout_node , percentage_basis ) ;
2022-02-02 12:34:32 +00:00
// FIXME: Checking for division by 0 should happen during parsing.
2022-03-21 21:03:17 +00:00
VERIFY ( resolved_calc_number_value . value ( ) . get < Number > ( ) . value ( ) ! = 0.0f ) ;
2022-01-27 14:51:51 +00:00
value . divide_by ( resolved_calc_number_value , layout_node ) ;
} ) ;
}
return value ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcNumberProduct : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
auto value = first_calc_number_value . resolve ( layout_node , percentage_basis ) ;
for ( auto & additional_number_value : zero_or_more_additional_calc_number_values ) {
2023-03-06 17:16:25 +01:00
auto additional_value = additional_number_value - > resolve ( layout_node , percentage_basis ) ;
2022-01-27 14:51:51 +00:00
2023-03-06 17:16:25 +01:00
if ( additional_number_value - > op = = CalculatedStyleValue : : ProductOperation : : Multiply )
2022-01-27 14:51:51 +00:00
value . multiply_by ( additional_value , layout_node ) ;
2023-03-06 17:16:25 +01:00
else if ( additional_number_value - > op = = CalculatedStyleValue : : ProductOperation : : Divide )
2022-01-27 14:51:51 +00:00
value . divide_by ( additional_value , layout_node ) ;
else
VERIFY_NOT_REACHED ( ) ;
}
return value ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcProductPartWithOperator : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
return value . visit (
[ & ] ( CalcValue const & calc_value ) {
return calc_value . resolve ( layout_node , percentage_basis ) ;
} ,
[ & ] ( CalcNumberValue const & calc_number_value ) {
return calc_number_value . resolve ( layout_node , percentage_basis ) ;
} ) ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcSumPartWithOperator : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
return value - > resolve ( layout_node , percentage_basis ) ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcNumberProductPartWithOperator : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
return value . resolve ( layout_node , percentage_basis ) ;
}
2022-02-18 12:07:09 +00:00
CalculatedStyleValue : : CalculationResult CalculatedStyleValue : : CalcNumberSumPartWithOperator : : resolve ( Layout : : Node const * layout_node , PercentageBasis const & percentage_basis ) const
2022-01-27 14:51:51 +00:00
{
return value - > resolve ( layout_node , percentage_basis ) ;
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > GridTrackPlacementShorthandStyleValue : : to_string ( ) const
2022-08-24 12:25:56 +02:00
{
2023-02-11 19:12:00 +01:00
if ( m_properties . end - > grid_track_placement ( ) . is_auto ( ) )
return String : : formatted ( " {} " , TRY ( m_properties . start - > grid_track_placement ( ) . to_string ( ) ) ) ;
return String : : formatted ( " {} / {} " , TRY ( m_properties . start - > grid_track_placement ( ) . to_string ( ) ) , TRY ( m_properties . end - > grid_track_placement ( ) . to_string ( ) ) ) ;
2022-08-24 12:25:56 +02:00
}
2023-01-16 19:02:39 +01:00
ErrorOr < String > GridAreaShorthandStyleValue : : to_string ( ) const
{
StringBuilder builder ;
2023-02-11 19:12:00 +01:00
if ( ! m_properties . row_start - > as_grid_track_placement ( ) . grid_track_placement ( ) . is_auto ( ) )
TRY ( builder . try_appendff ( " {} " , TRY ( m_properties . row_start - > as_grid_track_placement ( ) . grid_track_placement ( ) . to_string ( ) ) ) ) ;
if ( ! m_properties . column_start - > as_grid_track_placement ( ) . grid_track_placement ( ) . is_auto ( ) )
TRY ( builder . try_appendff ( " / {} " , TRY ( m_properties . column_start - > as_grid_track_placement ( ) . grid_track_placement ( ) . to_string ( ) ) ) ) ;
if ( ! m_properties . row_end - > as_grid_track_placement ( ) . grid_track_placement ( ) . is_auto ( ) )
TRY ( builder . try_appendff ( " / {} " , TRY ( m_properties . row_end - > as_grid_track_placement ( ) . grid_track_placement ( ) . to_string ( ) ) ) ) ;
if ( ! m_properties . column_end - > as_grid_track_placement ( ) . grid_track_placement ( ) . is_auto ( ) )
TRY ( builder . try_appendff ( " / {} " , TRY ( m_properties . column_end - > as_grid_track_placement ( ) . grid_track_placement ( ) . to_string ( ) ) ) ) ;
2023-01-16 19:02:39 +01:00
return builder . to_string ( ) ;
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > GridTrackPlacementStyleValue : : to_string ( ) const
2022-08-24 12:31:00 +02:00
{
2023-01-06 19:02:26 +01:00
return m_grid_track_placement . to_string ( ) ;
2022-08-24 12:31:00 +02:00
}
2023-01-16 18:17:05 +01:00
ErrorOr < String > GridTemplateAreaStyleValue : : to_string ( ) const
{
StringBuilder builder ;
for ( size_t y = 0 ; y < m_grid_template_area . size ( ) ; + + y ) {
for ( size_t x = 0 ; x < m_grid_template_area [ y ] . size ( ) ; + + x ) {
2023-01-25 19:12:00 +01:00
TRY ( builder . try_appendff ( " {} " , m_grid_template_area [ y ] [ x ] ) ) ;
2023-01-16 18:17:05 +01:00
if ( x < m_grid_template_area [ y ] . size ( ) - 1 )
2023-01-25 19:12:00 +01:00
TRY ( builder . try_append ( " " sv ) ) ;
2023-01-16 18:17:05 +01:00
}
if ( y < m_grid_template_area . size ( ) - 1 )
2023-01-25 19:12:00 +01:00
TRY ( builder . try_append ( " , " sv ) ) ;
2023-01-16 18:17:05 +01:00
}
return builder . to_string ( ) ;
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > GridTrackSizeStyleValue : : to_string ( ) const
2022-08-24 12:27:56 +02:00
{
2023-01-06 19:02:26 +01:00
return m_grid_track_size_list . to_string ( ) ;
2022-08-24 12:27:56 +02:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > IdentifierStyleValue : : to_string ( ) const
2021-09-23 19:54:19 +01:00
{
2023-01-06 19:02:26 +01:00
return String : : from_utf8 ( CSS : : string_from_value_id ( m_id ) ) ;
2021-09-23 19:54:19 +01:00
}
bool IdentifierStyleValue : : has_color ( ) const
{
switch ( m_id ) {
2021-09-22 12:42:54 +01:00
case ValueID : : Currentcolor :
case ValueID : : LibwebLink :
case ValueID : : LibwebPaletteActiveLink :
case ValueID : : LibwebPaletteActiveWindowBorder1 :
case ValueID : : LibwebPaletteActiveWindowBorder2 :
case ValueID : : LibwebPaletteActiveWindowTitle :
case ValueID : : LibwebPaletteBase :
case ValueID : : LibwebPaletteBaseText :
case ValueID : : LibwebPaletteButton :
case ValueID : : LibwebPaletteButtonText :
case ValueID : : LibwebPaletteDesktopBackground :
case ValueID : : LibwebPaletteFocusOutline :
case ValueID : : LibwebPaletteHighlightWindowBorder1 :
case ValueID : : LibwebPaletteHighlightWindowBorder2 :
case ValueID : : LibwebPaletteHighlightWindowTitle :
case ValueID : : LibwebPaletteHoverHighlight :
case ValueID : : LibwebPaletteInactiveSelection :
case ValueID : : LibwebPaletteInactiveSelectionText :
case ValueID : : LibwebPaletteInactiveWindowBorder1 :
case ValueID : : LibwebPaletteInactiveWindowBorder2 :
case ValueID : : LibwebPaletteInactiveWindowTitle :
case ValueID : : LibwebPaletteLink :
case ValueID : : LibwebPaletteMenuBase :
case ValueID : : LibwebPaletteMenuBaseText :
case ValueID : : LibwebPaletteMenuSelection :
case ValueID : : LibwebPaletteMenuSelectionText :
case ValueID : : LibwebPaletteMenuStripe :
case ValueID : : LibwebPaletteMovingWindowBorder1 :
case ValueID : : LibwebPaletteMovingWindowBorder2 :
case ValueID : : LibwebPaletteMovingWindowTitle :
case ValueID : : LibwebPaletteRubberBandBorder :
case ValueID : : LibwebPaletteRubberBandFill :
case ValueID : : LibwebPaletteRuler :
case ValueID : : LibwebPaletteRulerActiveText :
case ValueID : : LibwebPaletteRulerBorder :
case ValueID : : LibwebPaletteRulerInactiveText :
case ValueID : : LibwebPaletteSelection :
case ValueID : : LibwebPaletteSelectionText :
case ValueID : : LibwebPaletteSyntaxComment :
case ValueID : : LibwebPaletteSyntaxControlKeyword :
case ValueID : : LibwebPaletteSyntaxIdentifier :
case ValueID : : LibwebPaletteSyntaxKeyword :
case ValueID : : LibwebPaletteSyntaxNumber :
case ValueID : : LibwebPaletteSyntaxOperator :
case ValueID : : LibwebPaletteSyntaxPreprocessorStatement :
case ValueID : : LibwebPaletteSyntaxPreprocessorValue :
case ValueID : : LibwebPaletteSyntaxPunctuation :
case ValueID : : LibwebPaletteSyntaxString :
case ValueID : : LibwebPaletteSyntaxType :
case ValueID : : LibwebPaletteTextCursor :
case ValueID : : LibwebPaletteThreedHighlight :
case ValueID : : LibwebPaletteThreedShadow1 :
case ValueID : : LibwebPaletteThreedShadow2 :
case ValueID : : LibwebPaletteVisitedLink :
case ValueID : : LibwebPaletteWindow :
case ValueID : : LibwebPaletteWindowText :
return true ;
default :
2021-09-23 19:54:19 +01:00
return false ;
2021-09-22 12:42:54 +01:00
}
2019-10-06 10:25:08 +02:00
}
2021-09-16 19:20:20 +01:00
Color IdentifierStyleValue : : to_color ( Layout : : NodeWithStyle const & node ) const
2019-10-06 10:25:08 +02:00
{
2021-09-16 19:40:56 +01:00
if ( id ( ) = = CSS : : ValueID : : Currentcolor ) {
if ( ! node . has_style ( ) )
return Color : : Black ;
return node . computed_values ( ) . color ( ) ;
}
2021-09-16 19:20:20 +01:00
auto & document = node . document ( ) ;
2020-12-15 20:39:09 +01:00
if ( id ( ) = = CSS : : ValueID : : LibwebLink )
2019-10-06 10:25:08 +02:00
return document . link_color ( ) ;
2020-05-25 14:54:27 -04:00
2022-03-19 18:09:22 +01:00
if ( ! document . page ( ) )
return { } ;
2020-11-12 18:23:05 +01:00
auto palette = document . page ( ) - > palette ( ) ;
2020-05-25 14:54:27 -04:00
switch ( id ( ) ) {
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteDesktopBackground :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : DesktopBackground ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteActiveWindowBorder1 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : ActiveWindowBorder1 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteActiveWindowBorder2 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : ActiveWindowBorder2 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteActiveWindowTitle :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : ActiveWindowTitle ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteInactiveWindowBorder1 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : InactiveWindowBorder1 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteInactiveWindowBorder2 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : InactiveWindowBorder2 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteInactiveWindowTitle :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : InactiveWindowTitle ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteMovingWindowBorder1 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : MovingWindowBorder1 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteMovingWindowBorder2 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : MovingWindowBorder2 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteMovingWindowTitle :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : MovingWindowTitle ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteHighlightWindowBorder1 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : HighlightWindowBorder1 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteHighlightWindowBorder2 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : HighlightWindowBorder2 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteHighlightWindowTitle :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : HighlightWindowTitle ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteMenuStripe :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : MenuStripe ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteMenuBase :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : MenuBase ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteMenuBaseText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : MenuBaseText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteMenuSelection :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : MenuSelection ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteMenuSelectionText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : MenuSelectionText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteWindow :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : Window ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteWindowText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : WindowText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteButton :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : Button ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteButtonText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : ButtonText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteBase :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : Base ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteBaseText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : BaseText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteThreedHighlight :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : ThreedHighlight ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteThreedShadow1 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : ThreedShadow1 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteThreedShadow2 :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : ThreedShadow2 ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteHoverHighlight :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : HoverHighlight ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSelection :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : Selection ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSelectionText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SelectionText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteInactiveSelection :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : InactiveSelection ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteInactiveSelectionText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : InactiveSelectionText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteRubberBandFill :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : RubberBandFill ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteRubberBandBorder :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : RubberBandBorder ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteLink :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : Link ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteActiveLink :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : ActiveLink ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteVisitedLink :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : VisitedLink ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteRuler :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : Ruler ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteRulerBorder :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : RulerBorder ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteRulerActiveText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : RulerActiveText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteRulerInactiveText :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : RulerInactiveText ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteTextCursor :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : TextCursor ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteFocusOutline :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : FocusOutline ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxComment :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxComment ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxNumber :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxNumber ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxString :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxString ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxType :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxType ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxPunctuation :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxPunctuation ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxOperator :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxOperator ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxKeyword :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxKeyword ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxControlKeyword :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxControlKeyword ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxIdentifier :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxIdentifier ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxPreprocessorStatement :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxPreprocessorStatement ) ;
2020-12-15 20:39:09 +01:00
case CSS : : ValueID : : LibwebPaletteSyntaxPreprocessorValue :
2020-05-25 14:54:27 -04:00
return palette . color ( ColorRole : : SyntaxPreprocessorValue ) ;
default :
return { } ;
}
2019-10-06 10:25:08 +02:00
}
2019-10-19 11:49:46 +02:00
2021-10-22 20:55:27 +01:00
ImageStyleValue : : ImageStyleValue ( AK : : URL const & url )
2022-07-31 01:11:59 +01:00
: AbstractImageStyleValue ( Type : : Image )
2019-10-19 11:49:46 +02:00
, m_url ( url )
{
2021-10-22 20:55:27 +01:00
}
2022-07-31 01:11:59 +01:00
void ImageStyleValue : : load_any_resources ( DOM : : Document & document )
2021-10-22 20:55:27 +01:00
{
2022-09-07 17:38:29 +02:00
if ( resource ( ) )
return ;
2021-10-22 20:55:27 +01:00
m_document = & document ;
auto request = LoadRequest : : create_for_url_on_page ( m_url , document . page ( ) ) ;
2020-06-05 23:32:23 +02:00
set_resource ( ResourceLoader : : the ( ) . load_resource ( Resource : : Type : : Image , request ) ) ;
2020-06-02 13:51:30 +02:00
}
void ImageStyleValue : : resource_did_load ( )
{
if ( ! m_document )
return ;
// FIXME: Do less than a full repaint if possible?
2021-09-30 02:18:30 +02:00
if ( m_document & & m_document - > browsing_context ( ) )
2022-06-30 20:03:55 +01:00
m_document - > browsing_context ( ) - > set_needs_display ( ) ;
2022-10-30 15:43:42 +00:00
if ( resource ( ) - > is_animated ( ) & & resource ( ) - > frame_count ( ) > 1 ) {
m_timer = Platform : : Timer : : create ( ) ;
m_timer - > set_interval ( resource ( ) - > frame_duration ( 0 ) ) ;
m_timer - > on_timeout = [ this ] { animate ( ) ; } ;
m_timer - > start ( ) ;
}
}
void ImageStyleValue : : animate ( )
{
m_current_frame_index = ( m_current_frame_index + 1 ) % resource ( ) - > frame_count ( ) ;
auto current_frame_duration = resource ( ) - > frame_duration ( m_current_frame_index ) ;
if ( current_frame_duration ! = m_timer - > interval ( ) )
m_timer - > restart ( current_frame_duration ) ;
if ( m_current_frame_index = = resource ( ) - > frame_count ( ) - 1 ) {
+ + m_loops_completed ;
if ( m_loops_completed > 0 & & m_loops_completed = = resource ( ) - > loop_count ( ) )
m_timer - > stop ( ) ;
}
if ( on_animate )
on_animate ( ) ;
}
Gfx : : Bitmap const * ImageStyleValue : : bitmap ( size_t frame_index ) const
{
if ( ! resource ( ) )
return nullptr ;
return resource ( ) - > bitmap ( frame_index ) ;
2019-10-19 11:49:46 +02:00
}
2021-10-03 17:56:01 +02:00
2023-01-06 19:02:26 +01:00
ErrorOr < String > ImageStyleValue : : to_string ( ) const
2021-10-03 17:56:01 +02:00
{
2023-02-14 20:50:41 +00:00
return serialize_a_url ( m_url . to_deprecated_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
2023-02-20 00:41:51 +00:00
bool ImageStyleValue : : equals ( StyleValue const & other ) const
2022-04-18 17:42:03 +01:00
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_url = = other . as_image ( ) . m_url ;
}
2022-11-08 16:31:01 +00:00
Optional < CSSPixels > ImageStyleValue : : natural_width ( ) const
2022-07-31 01:11:59 +01:00
{
2022-11-16 20:00:49 +01:00
if ( auto * b = bitmap ( 0 ) ; b ! = nullptr )
return b - > width ( ) ;
2022-07-31 01:11:59 +01:00
return { } ;
}
2022-11-08 16:31:01 +00:00
Optional < CSSPixels > ImageStyleValue : : natural_height ( ) const
2022-07-31 01:11:59 +01:00
{
2022-11-16 20:00:49 +01:00
if ( auto * b = bitmap ( 0 ) ; b ! = nullptr )
return b - > height ( ) ;
2022-07-31 01:11:59 +01:00
return { } ;
}
2022-11-08 16:31:01 +00:00
void ImageStyleValue : : paint ( PaintContext & context , DevicePixelRect const & dest_rect , CSS : : ImageRendering image_rendering ) const
2022-07-31 01:11:59 +01:00
{
2022-11-16 20:00:49 +01:00
if ( auto * b = bitmap ( m_current_frame_index ) ; b ! = nullptr )
2022-11-08 16:31:01 +00:00
context . painter ( ) . draw_scaled_bitmap ( dest_rect . to_type < int > ( ) , * b , bitmap ( 0 ) - > rect ( ) , 1.0f , to_gfx_scaling_mode ( image_rendering ) ) ;
2022-07-31 01:11:59 +01:00
}
2023-01-12 22:15:19 +00:00
static ErrorOr < void > serialize_color_stop_list ( StringBuilder & builder , auto const & color_stop_list )
2022-10-28 20:44:00 +01:00
{
bool first = true ;
for ( auto const & element : color_stop_list ) {
if ( ! first )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " , " sv ) ) ;
2022-10-28 20:44:00 +01:00
2023-01-13 23:57:55 +00:00
if ( element . transition_hint . has_value ( ) )
TRY ( builder . try_appendff ( " {}, " sv , TRY ( element . transition_hint - > value . to_string ( ) ) ) ) ;
2022-10-28 20:44:00 +01:00
2023-02-14 20:50:41 +00:00
TRY ( serialize_a_srgb_value ( builder , element . color_stop . color ) ) ;
2022-10-28 20:44:00 +01:00
for ( auto position : Array { & element . color_stop . position , & element . color_stop . second_position } ) {
if ( position - > has_value ( ) )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_appendff ( " {} " sv , TRY ( ( * position ) - > to_string ( ) ) ) ) ;
2022-10-28 20:44:00 +01:00
}
first = false ;
}
2023-01-12 22:15:19 +00:00
return { } ;
2022-10-28 20:44:00 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > LinearGradientStyleValue : : to_string ( ) const
2022-07-12 00:09:29 +01:00
{
StringBuilder builder ;
2023-01-06 19:02:26 +01:00
auto side_or_corner_to_string = [ ] ( SideOrCorner value ) {
2022-07-12 00:09:29 +01:00
switch ( value ) {
case SideOrCorner : : Top :
return " top " sv ;
case SideOrCorner : : Bottom :
return " bottom " sv ;
case SideOrCorner : : Left :
return " left " sv ;
case SideOrCorner : : Right :
return " right " sv ;
case SideOrCorner : : TopLeft :
return " top left " sv ;
case SideOrCorner : : TopRight :
return " top right " sv ;
case SideOrCorner : : BottomLeft :
return " bottom left " sv ;
case SideOrCorner : : BottomRight :
return " bottom right " sv ;
default :
VERIFY_NOT_REACHED ( ) ;
}
} ;
2023-02-11 19:12:00 +01:00
if ( m_properties . gradient_type = = GradientType : : WebKit )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " -webkit- " sv ) ) ;
2022-11-06 14:51:10 +00:00
if ( is_repeating ( ) )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " repeating- " sv ) ) ;
TRY ( builder . try_append ( " linear-gradient( " sv ) ) ;
2023-02-11 19:12:00 +01:00
TRY ( m_properties . direction . visit (
2023-01-12 22:15:19 +00:00
[ & ] ( SideOrCorner side_or_corner ) - > ErrorOr < void > {
2023-02-11 19:12:00 +01:00
return builder . try_appendff ( " {}{}, " sv , m_properties . gradient_type = = GradientType : : Standard ? " to " sv : " " sv , side_or_corner_to_string ( side_or_corner ) ) ;
2022-07-12 00:09:29 +01:00
} ,
2023-01-12 22:15:19 +00:00
[ & ] ( Angle const & angle ) - > ErrorOr < void > {
2023-01-13 23:57:55 +00:00
return builder . try_appendff ( " {}, " sv , TRY ( angle . to_string ( ) ) ) ;
2023-01-12 22:15:19 +00:00
} ) ) ;
2022-07-12 00:09:29 +01:00
2023-02-11 19:12:00 +01:00
TRY ( serialize_color_stop_list ( builder , m_properties . color_stop_list ) ) ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " ) " sv ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-07-12 00:09:29 +01:00
}
2023-02-20 00:41:51 +00:00
bool LinearGradientStyleValue : : equals ( StyleValue const & other_ ) const
2022-07-12 00:09:29 +01:00
{
if ( type ( ) ! = other_ . type ( ) )
return false ;
auto & other = other_ . as_linear_gradient ( ) ;
2023-02-11 19:12:00 +01:00
return m_properties = = other . m_properties ;
2022-07-12 00:09:29 +01:00
}
2022-11-08 16:31:01 +00:00
float LinearGradientStyleValue : : angle_degrees ( CSSPixelSize gradient_size ) const
2022-07-12 00:09:29 +01:00
{
2022-07-17 19:45:38 +01:00
auto corner_angle_degrees = [ & ] {
2022-11-08 16:31:01 +00:00
return static_cast < float > ( atan2 ( gradient_size . height ( ) . value ( ) , gradient_size . width ( ) . value ( ) ) ) * 180 / AK : : Pi < float > ;
2022-07-17 19:45:38 +01:00
} ;
2023-02-11 19:12:00 +01:00
return m_properties . direction . visit (
2022-07-12 00:09:29 +01:00
[ & ] ( SideOrCorner side_or_corner ) {
2022-08-07 12:36:04 +01:00
auto angle = [ & ] {
switch ( side_or_corner ) {
case SideOrCorner : : Top :
return 0.0f ;
case SideOrCorner : : Bottom :
return 180.0f ;
case SideOrCorner : : Left :
return 270.0f ;
case SideOrCorner : : Right :
return 90.0f ;
case SideOrCorner : : TopRight :
return corner_angle_degrees ( ) ;
case SideOrCorner : : BottomLeft :
return corner_angle_degrees ( ) + 180.0f ;
case SideOrCorner : : TopLeft :
return - corner_angle_degrees ( ) ;
case SideOrCorner : : BottomRight :
return - ( corner_angle_degrees ( ) + 180.0f ) ;
default :
VERIFY_NOT_REACHED ( ) ;
}
} ( ) ;
// Note: For unknowable reasons the angles are opposite on the -webkit- version
2023-02-11 19:12:00 +01:00
if ( m_properties . gradient_type = = GradientType : : WebKit )
2022-08-07 12:36:04 +01:00
return angle + 180.0f ;
return angle ;
2022-07-12 00:09:29 +01:00
} ,
[ & ] ( Angle const & angle ) {
return angle . to_degrees ( ) ;
} ) ;
}
2022-11-08 16:31:01 +00:00
void LinearGradientStyleValue : : resolve_for_size ( Layout : : Node const & node , CSSPixelSize size ) const
2022-07-31 01:11:59 +01:00
{
2022-08-22 21:46:09 +01:00
if ( m_resolved . has_value ( ) & & m_resolved - > size = = size )
return ;
2022-11-08 16:31:01 +00:00
m_resolved = ResolvedData { Painting : : resolve_linear_gradient_data ( node , size , * this ) , size } ;
2022-07-31 01:11:59 +01:00
}
2022-11-08 16:31:01 +00:00
void LinearGradientStyleValue : : paint ( PaintContext & context , DevicePixelRect const & dest_rect , CSS : : ImageRendering ) const
2022-07-31 01:11:59 +01:00
{
2022-08-22 21:46:09 +01:00
VERIFY ( m_resolved . has_value ( ) ) ;
2022-11-08 16:31:01 +00:00
Painting : : paint_linear_gradient ( context , dest_rect , m_resolved - > data ) ;
2022-07-31 01:11:59 +01:00
}
2022-11-08 16:31:01 +00:00
CSSPixelPoint PositionValue : : resolved ( Layout : : Node const & node , CSSPixelRect const & rect ) const
2022-10-29 13:11:00 +01:00
{
// Note: A preset + a none default x/y_relative_to is impossible in the syntax (and makes little sense)
2022-11-08 16:31:01 +00:00
CSSPixels x = horizontal_position . visit (
[ & ] ( HorizontalPreset preset ) - > CSSPixels {
2022-10-29 13:11:00 +01:00
return rect . width ( ) * [ & ] {
switch ( preset ) {
case HorizontalPreset : : Left :
return 0.0f ;
case HorizontalPreset : : Center :
return 0.5f ;
case HorizontalPreset : : Right :
return 1.0f ;
default :
VERIFY_NOT_REACHED ( ) ;
}
} ( ) ;
} ,
2022-11-08 16:31:01 +00:00
[ & ] ( LengthPercentage length_percentage ) - > CSSPixels {
2022-10-29 13:11:00 +01:00
return length_percentage . resolved ( node , Length : : make_px ( rect . width ( ) ) ) . to_px ( node ) ;
} ) ;
2022-11-08 16:31:01 +00:00
CSSPixels y = vertical_position . visit (
[ & ] ( VerticalPreset preset ) - > CSSPixels {
2022-10-29 13:11:00 +01:00
return rect . height ( ) * [ & ] {
switch ( preset ) {
case VerticalPreset : : Top :
return 0.0f ;
case VerticalPreset : : Center :
return 0.5f ;
case VerticalPreset : : Bottom :
return 1.0f ;
default :
VERIFY_NOT_REACHED ( ) ;
}
} ( ) ;
} ,
2022-11-08 16:31:01 +00:00
[ & ] ( LengthPercentage length_percentage ) - > CSSPixels {
2022-10-29 13:11:00 +01:00
return length_percentage . resolved ( node , Length : : make_px ( rect . height ( ) ) ) . to_px ( node ) ;
} ) ;
if ( x_relative_to = = HorizontalEdge : : Right )
x = rect . width ( ) - x ;
if ( y_relative_to = = VerticalEdge : : Bottom )
y = rect . height ( ) - y ;
2022-11-08 16:31:01 +00:00
return CSSPixelPoint { rect . x ( ) + x , rect . y ( ) + y } ;
2022-10-29 13:11:00 +01:00
}
2023-01-13 23:44:44 +00:00
ErrorOr < void > PositionValue : : serialize ( StringBuilder & builder ) const
2022-10-29 13:11:00 +01:00
{
// Note: This means our serialization with simplify any with explicit edges that are just `top left`.
bool has_relative_edges = x_relative_to = = HorizontalEdge : : Right | | y_relative_to = = VerticalEdge : : Bottom ;
if ( has_relative_edges )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( x_relative_to = = HorizontalEdge : : Left ? " left " sv : " right " sv ) ) ;
2023-01-13 23:44:44 +00:00
TRY ( horizontal_position . visit (
[ & ] ( HorizontalPreset preset ) - > ErrorOr < void > {
2023-01-13 23:57:55 +00:00
return builder . try_append ( [ & ] {
2022-10-29 13:11:00 +01:00
switch ( preset ) {
case HorizontalPreset : : Left :
return " left " sv ;
case HorizontalPreset : : Center :
return " center " sv ;
case HorizontalPreset : : Right :
return " right " sv ;
default :
VERIFY_NOT_REACHED ( ) ;
}
} ( ) ) ;
} ,
2023-01-13 23:44:44 +00:00
[ & ] ( LengthPercentage length_percentage ) - > ErrorOr < void > {
2023-01-13 23:57:55 +00:00
return builder . try_appendff ( TRY ( length_percentage . to_string ( ) ) ) ;
2023-01-13 23:44:44 +00:00
} ) ) ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( ' ' ) ) ;
2022-10-29 13:11:00 +01:00
if ( has_relative_edges )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( y_relative_to = = VerticalEdge : : Top ? " top " sv : " bottom " sv ) ) ;
2023-01-13 23:44:44 +00:00
TRY ( vertical_position . visit (
[ & ] ( VerticalPreset preset ) - > ErrorOr < void > {
2023-01-13 23:57:55 +00:00
return builder . try_append ( [ & ] {
2022-10-29 13:11:00 +01:00
switch ( preset ) {
case VerticalPreset : : Top :
return " top " sv ;
case VerticalPreset : : Center :
return " center " sv ;
case VerticalPreset : : Bottom :
return " bottom " sv ;
default :
VERIFY_NOT_REACHED ( ) ;
}
} ( ) ) ;
} ,
2023-01-13 23:44:44 +00:00
[ & ] ( LengthPercentage length_percentage ) - > ErrorOr < void > {
2023-01-13 23:57:55 +00:00
return builder . try_append ( TRY ( length_percentage . to_string ( ) ) ) ;
2023-01-13 23:44:44 +00:00
} ) ) ;
return { } ;
2022-10-29 13:11:00 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > RadialGradientStyleValue : : to_string ( ) const
2022-11-11 18:13:00 +01:00
{
StringBuilder builder ;
2022-12-02 19:20:25 +00:00
if ( is_repeating ( ) )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " repeating- " sv ) ) ;
TRY ( builder . try_appendff ( " radial-gradient({} " sv ,
2023-02-11 19:12:00 +01:00
m_properties . ending_shape = = EndingShape : : Circle ? " circle " sv : " ellipse " sv ) ) ;
2022-11-11 18:13:00 +01:00
2023-02-11 19:12:00 +01:00
TRY ( m_properties . size . visit (
2023-01-12 22:15:19 +00:00
[ & ] ( Extent extent ) - > ErrorOr < void > {
2023-01-13 23:57:55 +00:00
return builder . try_append ( [ & ] {
2022-11-11 18:13:00 +01:00
switch ( extent ) {
case Extent : : ClosestCorner :
return " closest-corner " sv ;
case Extent : : ClosestSide :
return " closest-side " sv ;
case Extent : : FarthestCorner :
return " farthest-corner " sv ;
case Extent : : FarthestSide :
return " farthest-side " sv ;
default :
VERIFY_NOT_REACHED ( ) ;
}
} ( ) ) ;
2023-01-12 22:15:19 +00:00
} ,
[ & ] ( CircleSize const & circle_size ) - > ErrorOr < void > {
2023-01-13 23:57:55 +00:00
return builder . try_append ( TRY ( circle_size . radius . to_string ( ) ) ) ;
2022-11-11 18:13:00 +01:00
} ,
2023-01-12 22:15:19 +00:00
[ & ] ( EllipseSize const & ellipse_size ) - > ErrorOr < void > {
2023-01-13 23:57:55 +00:00
return builder . try_appendff ( " {} {} " , TRY ( ellipse_size . radius_a . to_string ( ) ) , TRY ( ellipse_size . radius_b . to_string ( ) ) ) ;
2023-01-12 22:15:19 +00:00
} ) ) ;
2022-11-11 18:13:00 +01:00
2023-02-11 19:12:00 +01:00
if ( m_properties . position ! = PositionValue : : center ( ) ) {
2023-01-13 23:57:55 +00:00
TRY ( builder . try_appendff ( " at " sv ) ) ;
2023-02-11 19:12:00 +01:00
TRY ( m_properties . position . serialize ( builder ) ) ;
2022-11-11 18:13:00 +01:00
}
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " , " sv ) ) ;
2023-02-11 19:12:00 +01:00
TRY ( serialize_color_stop_list ( builder , m_properties . color_stop_list ) ) ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( ' ) ' ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-11-11 18:13:00 +01:00
}
Gfx : : FloatSize RadialGradientStyleValue : : resolve_size ( Layout : : Node const & node , Gfx : : FloatPoint center , Gfx : : FloatRect const & size ) const
{
auto const side_shape = [ & ] ( auto distance_function ) {
auto const distance_from = [ & ] ( float v , float a , float b , auto distance_function ) {
return distance_function ( fabs ( a - v ) , fabs ( b - v ) ) ;
} ;
auto x_dist = distance_from ( center . x ( ) , size . left ( ) , size . right ( ) , distance_function ) ;
auto y_dist = distance_from ( center . y ( ) , size . top ( ) , size . bottom ( ) , distance_function ) ;
2023-02-11 19:12:00 +01:00
if ( m_properties . ending_shape = = EndingShape : : Circle ) {
2022-11-11 18:13:00 +01:00
auto dist = distance_function ( x_dist , y_dist ) ;
return Gfx : : FloatSize { dist , dist } ;
} else {
return Gfx : : FloatSize { x_dist , y_dist } ;
}
} ;
auto const closest_side_shape = [ & ] {
return side_shape ( AK : : min < float > ) ;
} ;
auto const farthest_side_shape = [ & ] {
return side_shape ( AK : : max < float > ) ;
} ;
auto const corner_distance = [ & ] ( auto distance_compare , Gfx : : FloatPoint & corner ) {
auto top_left_distance = size . top_left ( ) . distance_from ( center ) ;
auto top_right_distance = size . top_right ( ) . distance_from ( center ) ;
auto bottom_right_distance = size . bottom_right ( ) . distance_from ( center ) ;
auto bottom_left_distance = size . bottom_left ( ) . distance_from ( center ) ;
auto distance = top_left_distance ;
if ( distance_compare ( top_right_distance , distance ) ) {
corner = size . top_right ( ) ;
distance = top_right_distance ;
}
if ( distance_compare ( bottom_right_distance , distance ) ) {
corner = size . top_right ( ) ;
distance = bottom_right_distance ;
}
if ( distance_compare ( bottom_left_distance , distance ) ) {
corner = size . top_right ( ) ;
distance = bottom_left_distance ;
}
return distance ;
} ;
auto const closest_corner_distance = [ & ] ( Gfx : : FloatPoint & corner ) {
return corner_distance ( [ ] ( float a , float b ) { return a < b ; } , corner ) ;
} ;
auto const farthest_corner_distance = [ & ] ( Gfx : : FloatPoint & corner ) {
return corner_distance ( [ ] ( float a , float b ) { return a > b ; } , corner ) ;
} ;
auto const corner_shape = [ & ] ( auto corner_distance , auto get_shape ) {
Gfx : : FloatPoint corner { } ;
auto distance = corner_distance ( corner ) ;
2023-02-11 19:12:00 +01:00
if ( m_properties . ending_shape = = EndingShape : : Ellipse ) {
2022-11-11 18:13:00 +01:00
auto shape = get_shape ( ) ;
auto aspect_ratio = shape . width ( ) / shape . height ( ) ;
auto p = corner - center ;
auto radius_a = AK : : sqrt ( p . y ( ) * p . y ( ) * aspect_ratio * aspect_ratio + p . x ( ) * p . x ( ) ) ;
auto radius_b = radius_a / aspect_ratio ;
return Gfx : : FloatSize { radius_a , radius_b } ;
}
return Gfx : : FloatSize { distance , distance } ;
} ;
// https://w3c.github.io/csswg-drafts/css-images/#radial-gradient-syntax
2023-02-11 19:12:00 +01:00
auto resolved_size = m_properties . size . visit (
2022-11-11 18:13:00 +01:00
[ & ] ( Extent extent ) {
switch ( extent ) {
case Extent : : ClosestSide :
// The ending shape is sized so that it exactly meets the side of the gradient box closest to the gradient’ s center.
// If the shape is an ellipse, it exactly meets the closest side in each dimension.
return closest_side_shape ( ) ;
case Extent : : ClosestCorner :
// The ending shape is sized so that it passes through the corner of the gradient box closest to the gradient’ s center.
// If the shape is an ellipse, the ending shape is given the same aspect-ratio it would have if closest-side were specified
return corner_shape ( closest_corner_distance , closest_side_shape ) ;
case Extent : : FarthestCorner :
// Same as closest-corner, except the ending shape is sized based on the farthest corner.
// If the shape is an ellipse, the ending shape is given the same aspect ratio it would have if farthest-side were specified.
return corner_shape ( farthest_corner_distance , farthest_side_shape ) ;
case Extent : : FarthestSide :
// Same as closest-side, except the ending shape is sized based on the farthest side(s).
return farthest_side_shape ( ) ;
default :
VERIFY_NOT_REACHED ( ) ;
}
} ,
[ & ] ( CircleSize const & circle_size ) {
auto radius = circle_size . radius . to_px ( node ) ;
return Gfx : : FloatSize { radius , radius } ;
} ,
[ & ] ( EllipseSize const & ellipse_size ) {
auto radius_a = ellipse_size . radius_a . resolved ( node , CSS : : Length : : make_px ( size . width ( ) ) ) . to_px ( node ) ;
auto radius_b = ellipse_size . radius_b . resolved ( node , CSS : : Length : : make_px ( size . height ( ) ) ) . to_px ( node ) ;
return Gfx : : FloatSize { radius_a , radius_b } ;
} ) ;
2022-11-13 15:30:36 +00:00
// Handle degenerate cases
// https://w3c.github.io/csswg-drafts/css-images/#degenerate-radials
constexpr auto arbitrary_small_number = 1e-10 ;
constexpr auto arbitrary_large_number = 1e10 ;
// If the ending shape is a circle with zero radius:
2023-02-11 19:12:00 +01:00
if ( m_properties . ending_shape = = EndingShape : : Circle & & resolved_size . is_empty ( ) ) {
2022-11-13 15:30:36 +00:00
// Render as if the ending shape was a circle whose radius was an arbitrary very small number greater than zero.
// This will make the gradient continue to look like a circle.
return Gfx : : FloatSize { arbitrary_small_number , arbitrary_small_number } ;
}
// If the ending shape has zero width (regardless of the height):
if ( resolved_size . width ( ) < = 0 ) {
// Render as if the ending shape was an ellipse whose height was an arbitrary very large number
// and whose width was an arbitrary very small number greater than zero.
// This will make the gradient look similar to a horizontal linear gradient that is mirrored across the center of the ellipse.
// It also means that all color-stop positions specified with a percentage resolve to 0px.
return Gfx : : FloatSize { arbitrary_small_number , arbitrary_large_number } ;
}
// Otherwise, if the ending shape has zero height:
if ( resolved_size . height ( ) < = 0 ) {
// Render as if the ending shape was an ellipse whose width was an arbitrary very large number and whose height
// was an arbitrary very small number greater than zero. This will make the gradient look like a solid-color image equal
// to the color of the last color-stop, or equal to the average color of the gradient if it’ s repeating.
return Gfx : : FloatSize { arbitrary_large_number , arbitrary_small_number } ;
}
return resolved_size ;
2022-11-11 18:13:00 +01:00
}
2022-11-08 16:31:01 +00:00
void RadialGradientStyleValue : : resolve_for_size ( Layout : : Node const & node , CSSPixelSize paint_size ) const
2022-11-11 18:13:00 +01:00
{
2022-11-08 16:31:01 +00:00
CSSPixelRect gradient_box { { 0 , 0 } , paint_size } ;
2023-02-11 19:12:00 +01:00
auto center = m_properties . position . resolved ( node , gradient_box ) . to_type < float > ( ) ;
2022-11-08 16:31:01 +00:00
auto gradient_size = resolve_size ( node , center , gradient_box . to_type < float > ( ) ) ;
2022-11-13 00:33:42 +00:00
if ( m_resolved . has_value ( ) & & m_resolved - > gradient_size = = gradient_size )
return ;
m_resolved = ResolvedData {
2022-11-25 17:11:09 +00:00
Painting : : resolve_radial_gradient_data ( node , gradient_size . to_type < CSSPixels > ( ) , * this ) ,
2022-11-13 00:33:42 +00:00
gradient_size ,
center ,
} ;
2022-11-11 18:13:00 +01:00
}
2023-02-20 00:41:51 +00:00
bool RadialGradientStyleValue : : equals ( StyleValue const & other ) const
2022-11-11 18:13:00 +01:00
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto & other_gradient = other . as_radial_gradient ( ) ;
2023-02-11 19:12:00 +01:00
return m_properties = = other_gradient . m_properties ;
2022-11-11 18:13:00 +01:00
}
2022-11-08 16:31:01 +00:00
void RadialGradientStyleValue : : paint ( PaintContext & context , DevicePixelRect const & dest_rect , CSS : : ImageRendering ) const
2022-11-11 18:13:00 +01:00
{
2022-11-13 00:33:42 +00:00
VERIFY ( m_resolved . has_value ( ) ) ;
2022-11-08 16:31:01 +00:00
Painting : : paint_radial_gradient ( context , dest_rect , m_resolved - > data ,
2022-12-17 20:04:39 +00:00
context . rounded_device_point ( m_resolved - > center . to_type < CSSPixels > ( ) ) ,
context . rounded_device_size ( m_resolved - > gradient_size . to_type < CSSPixels > ( ) ) ) ;
2022-11-11 18:13:00 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > ConicGradientStyleValue : : to_string ( ) const
2022-10-28 20:44:00 +01:00
{
StringBuilder builder ;
2022-11-06 14:51:10 +00:00
if ( is_repeating ( ) )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " repeating- " sv ) ) ;
TRY ( builder . try_append ( " conic-gradient( " sv ) ) ;
2022-10-28 20:44:00 +01:00
bool has_from_angle = false ;
bool has_at_position = false ;
2023-02-11 19:12:00 +01:00
if ( ( has_from_angle = m_properties . from_angle . to_degrees ( ) ! = 0 ) )
TRY ( builder . try_appendff ( " from {} " , TRY ( m_properties . from_angle . to_string ( ) ) ) ) ;
if ( ( has_at_position = m_properties . position ! = PositionValue : : center ( ) ) ) {
2022-10-28 20:44:00 +01:00
if ( has_from_angle )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( ' ' ) ) ;
TRY ( builder . try_appendff ( " at " sv ) ) ;
2023-02-11 19:12:00 +01:00
TRY ( m_properties . position . serialize ( builder ) ) ;
2022-10-28 20:44:00 +01:00
}
if ( has_from_angle | | has_at_position )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " , " sv ) ) ;
2023-02-11 19:12:00 +01:00
TRY ( serialize_color_stop_list ( builder , m_properties . color_stop_list ) ) ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( ' ) ' ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-10-28 20:44:00 +01:00
}
2022-11-08 16:31:01 +00:00
void ConicGradientStyleValue : : resolve_for_size ( Layout : : Node const & node , CSSPixelSize size ) const
2022-10-28 20:44:00 +01:00
{
2022-10-30 19:28:00 +01:00
if ( ! m_resolved . has_value ( ) )
m_resolved = ResolvedData { Painting : : resolve_conic_gradient_data ( node , * this ) , { } } ;
2023-02-11 19:12:00 +01:00
m_resolved - > position = m_properties . position . resolved ( node , CSSPixelRect { { 0 , 0 } , size } ) ;
2022-10-28 20:44:00 +01:00
}
2022-11-08 16:31:01 +00:00
void ConicGradientStyleValue : : paint ( PaintContext & context , DevicePixelRect const & dest_rect , CSS : : ImageRendering ) const
2022-10-28 20:44:00 +01:00
{
2022-10-30 19:28:00 +01:00
VERIFY ( m_resolved . has_value ( ) ) ;
2022-11-08 16:31:01 +00:00
Painting : : paint_conic_gradient ( context , dest_rect , m_resolved - > data , context . rounded_device_point ( m_resolved - > position ) ) ;
2022-10-28 20:44:00 +01:00
}
2023-02-20 00:41:51 +00:00
bool ConicGradientStyleValue : : equals ( StyleValue const & other ) const
2022-10-28 20:44:00 +01:00
{
2022-11-07 19:02:00 +01:00
if ( type ( ) ! = other . type ( ) )
return false ;
auto & other_gradient = other . as_conic_gradient ( ) ;
2023-02-11 19:12:00 +01:00
return m_properties = = other_gradient . m_properties ;
2022-10-28 20:44:00 +01:00
}
float ConicGradientStyleValue : : angle_degrees ( ) const
{
2023-02-11 19:12:00 +01:00
return m_properties . from_angle . to_degrees ( ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > ListStyleStyleValue : : to_string ( ) const
2022-02-02 20:39:04 +00:00
{
2023-02-11 19:12:00 +01:00
return String : : formatted ( " {} {} {} " , TRY ( m_properties . position - > to_string ( ) ) , TRY ( m_properties . image - > to_string ( ) ) , TRY ( m_properties . style_type - > to_string ( ) ) ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > NumericStyleValue : : to_string ( ) const
2022-02-02 20:39:04 +00:00
{
return m_value . visit (
2023-02-11 19:12:00 +01:00
[ ] ( auto value ) {
2023-01-06 19:02:26 +01:00
return String : : formatted ( " {} " , value ) ;
2022-02-02 20:39:04 +00:00
} ) ;
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > OverflowStyleValue : : to_string ( ) const
2022-02-02 20:39:04 +00:00
{
2023-02-11 19:12:00 +01:00
return String : : formatted ( " {} {} " , TRY ( m_properties . overflow_x - > to_string ( ) ) , TRY ( m_properties . overflow_y - > to_string ( ) ) ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > PercentageStyleValue : : to_string ( ) const
2022-02-02 20:39:04 +00:00
{
2023-01-06 19:02:26 +01:00
return m_percentage . to_string ( ) ;
2021-10-03 17:56:01 +02:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > PositionStyleValue : : to_string ( ) const
2021-10-31 16:02:29 +00:00
{
2023-01-06 19:02:26 +01:00
auto to_string = [ ] ( PositionEdge edge ) {
2021-10-31 16:02:29 +00:00
switch ( edge ) {
case PositionEdge : : Left :
return " left " ;
case PositionEdge : : Right :
return " right " ;
case PositionEdge : : Top :
return " top " ;
case PositionEdge : : Bottom :
return " bottom " ;
}
VERIFY_NOT_REACHED ( ) ;
} ;
2023-02-11 19:12:00 +01:00
return String : : formatted ( " {} {} {} {} " , to_string ( m_properties . edge_x ) , TRY ( m_properties . offset_x . to_string ( ) ) , to_string ( m_properties . edge_y ) , TRY ( m_properties . offset_y . to_string ( ) ) ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > RectStyleValue : : to_string ( ) const
2022-07-31 18:46:35 +02:00
{
2023-01-06 19:02:26 +01:00
return String : : formatted ( " rect({} {} {} {}) " , m_rect . top_edge , m_rect . right_edge , m_rect . bottom_edge , m_rect . left_edge ) ;
2022-07-31 18:46:35 +02:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > ShadowStyleValue : : to_string ( ) const
2022-04-18 17:42:03 +01:00
{
StringBuilder builder ;
2023-02-11 19:12:00 +01:00
TRY ( builder . try_appendff ( " {} {} {} {} {} " , m_properties . color . to_deprecated_string ( ) , TRY ( m_properties . offset_x . to_string ( ) ) , TRY ( m_properties . offset_y . to_string ( ) ) , TRY ( m_properties . blur_radius . to_string ( ) ) , TRY ( m_properties . spread_distance . to_string ( ) ) ) ) ;
if ( m_properties . placement = = ShadowPlacement : : Inner )
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( " inset " sv ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > TextDecorationStyleValue : : to_string ( ) const
2022-02-02 20:39:04 +00:00
{
2023-02-11 19:12:00 +01:00
return String : : formatted ( " {} {} {} {} " , TRY ( m_properties . line - > to_string ( ) ) , TRY ( m_properties . thickness - > to_string ( ) ) , TRY ( m_properties . style - > to_string ( ) ) , TRY ( m_properties . color - > to_string ( ) ) ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > TransformationStyleValue : : to_string ( ) const
2022-02-02 20:39:04 +00:00
{
2022-02-02 21:19:43 +00:00
StringBuilder builder ;
2023-02-11 19:12:00 +01:00
TRY ( builder . try_append ( CSS : : to_string ( m_properties . transform_function ) ) ) ;
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( ' ( ' ) ) ;
2023-03-06 14:33:11 +01:00
for ( size_t i = 0 ; i < m_properties . values . size ( ) ; + + i ) {
TRY ( builder . try_append ( TRY ( m_properties . values [ i ] - > to_string ( ) ) ) ) ;
if ( i ! = m_properties . values . size ( ) - 1 )
TRY ( builder . try_append ( " , " sv ) ) ;
}
2023-01-13 23:57:55 +00:00
TRY ( builder . try_append ( ' ) ' ) ) ;
2022-02-02 21:19:43 +00:00
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2022-02-02 20:39:04 +00:00
}
2023-02-11 19:12:00 +01:00
bool TransformationStyleValue : : Properties : : operator = = ( Properties const & other ) const
2022-04-18 17:42:03 +01:00
{
2023-02-11 19:12:00 +01:00
return transform_function = = other . transform_function & & values . span ( ) = = other . values . span ( ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > UnresolvedStyleValue : : to_string ( ) const
2021-12-03 12:28:14 +00:00
{
StringBuilder builder ;
for ( auto & value : m_values )
2023-02-14 19:04:12 +00:00
TRY ( builder . try_append ( TRY ( value . to_string ( ) ) ) ) ;
2023-01-06 19:02:26 +01:00
return builder . to_string ( ) ;
2021-12-03 12:28:14 +00:00
}
2023-02-20 00:41:51 +00:00
bool UnresolvedStyleValue : : equals ( StyleValue const & other ) const
2022-04-18 17:42:03 +01:00
{
if ( type ( ) ! = other . type ( ) )
return false ;
// This is a case where comparing the strings actually makes sense.
2023-01-06 19:02:26 +01:00
return to_string ( ) . release_value_but_fixme_should_propagate_errors ( ) = = other . to_string ( ) . release_value_but_fixme_should_propagate_errors ( ) ;
2022-04-18 17:42:03 +01:00
}
2023-02-11 19:12:00 +01:00
bool StyleValueList : : Properties : : operator = = ( Properties const & other ) const
2022-04-18 17:42:03 +01:00
{
2023-02-11 19:12:00 +01:00
return separator = = other . separator & & values . span ( ) = = other . values . span ( ) ;
2022-04-18 17:42:03 +01:00
}
2023-01-06 19:02:26 +01:00
ErrorOr < String > StyleValueList : : to_string ( ) const
2022-02-02 20:39:04 +00:00
{
2023-01-06 19:02:26 +01:00
auto separator = " " sv ;
2023-02-11 19:12:00 +01:00
switch ( m_properties . separator ) {
2022-02-02 20:53:55 +00:00
case Separator : : Space :
2023-01-06 19:02:26 +01:00
separator = " " sv ;
2022-02-02 20:53:55 +00:00
break ;
case Separator : : Comma :
2023-01-06 19:02:26 +01:00
separator = " , " sv ;
2022-02-02 20:53:55 +00:00
break ;
default :
VERIFY_NOT_REACHED ( ) ;
2022-02-02 20:39:04 +00:00
}
2022-02-02 20:53:55 +00:00
2023-03-06 14:33:11 +01:00
StringBuilder builder ;
for ( size_t i = 0 ; i < m_properties . values . size ( ) ; + + i ) {
TRY ( builder . try_append ( TRY ( m_properties . values [ i ] - > to_string ( ) ) ) ) ;
if ( i ! = m_properties . values . size ( ) - 1 )
TRY ( builder . try_append ( separator ) ) ;
}
return builder . to_string ( ) ;
2022-04-18 17:42:03 +01:00
}
2023-02-20 00:41:51 +00:00
ValueComparingNonnullRefPtr < GridTemplateAreaStyleValue > GridTemplateAreaStyleValue : : create ( Vector < Vector < String > > grid_template_area )
2023-01-16 18:17:05 +01:00
{
return adopt_ref ( * new GridTemplateAreaStyleValue ( grid_template_area ) ) ;
}
2023-02-20 00:41:51 +00:00
ValueComparingNonnullRefPtr < GridTrackPlacementStyleValue > GridTrackPlacementStyleValue : : create ( CSS : : GridTrackPlacement grid_track_placement )
2022-08-24 12:31:00 +02:00
{
return adopt_ref ( * new GridTrackPlacementStyleValue ( grid_track_placement ) ) ;
}
2023-02-20 00:41:51 +00:00
ValueComparingNonnullRefPtr < GridTrackSizeStyleValue > GridTrackSizeStyleValue : : create ( CSS : : GridTrackSizeList grid_track_size_list )
2022-08-24 12:27:56 +02:00
{
2022-10-30 13:27:57 +01:00
return adopt_ref ( * new GridTrackSizeStyleValue ( grid_track_size_list ) ) ;
}
2023-02-20 00:41:51 +00:00
ValueComparingNonnullRefPtr < GridTrackSizeStyleValue > GridTrackSizeStyleValue : : make_auto ( )
2022-10-30 13:27:57 +01:00
{
return adopt_ref ( * new GridTrackSizeStyleValue ( CSS : : GridTrackSizeList ( ) ) ) ;
2022-08-24 12:27:56 +02:00
}
2023-02-20 00:41:51 +00:00
ValueComparingNonnullRefPtr < RectStyleValue > RectStyleValue : : create ( EdgeRect rect )
2022-07-31 18:46:35 +02:00
{
return adopt_ref ( * new RectStyleValue ( rect ) ) ;
}
2023-02-20 00:41:51 +00:00
ValueComparingNonnullRefPtr < LengthStyleValue > LengthStyleValue : : create ( Length const & length )
2022-02-18 20:26:09 +01:00
{
if ( length . is_auto ( ) ) {
static auto value = adopt_ref ( * new LengthStyleValue ( CSS : : Length : : make_auto ( ) ) ) ;
return value ;
}
if ( length . is_px ( ) ) {
if ( length . raw_value ( ) = = 0 ) {
static auto value = adopt_ref ( * new LengthStyleValue ( CSS : : Length : : make_px ( 0 ) ) ) ;
return value ;
}
if ( length . raw_value ( ) = = 1 ) {
static auto value = adopt_ref ( * new LengthStyleValue ( CSS : : Length : : make_px ( 1 ) ) ) ;
return value ;
}
}
return adopt_ref ( * new LengthStyleValue ( length ) ) ;
}
2023-03-25 00:33:20 +00:00
Optional < CSS : : Length > absolutized_length ( CSS : : Length const & length , CSSPixelRect const & viewport_rect , Gfx : : FontPixelMetrics const & font_metrics , CSSPixels font_size , CSSPixels root_font_size , CSSPixels line_height , CSSPixels root_line_height )
2022-02-26 01:35:25 +01:00
{
if ( length . is_px ( ) )
return { } ;
if ( length . is_absolute ( ) | | length . is_relative ( ) ) {
2023-03-17 23:08:45 +01:00
auto px = length . to_px ( viewport_rect , font_metrics , font_size , root_font_size , line_height , root_line_height ) ;
2022-02-26 01:35:25 +01:00
return CSS : : Length : : make_px ( px ) ;
}
return { } ;
}
2023-03-17 23:08:45 +01:00
ValueComparingNonnullRefPtr < StyleValue const > StyleValue : : absolutized ( CSSPixelRect const & , Gfx : : FontPixelMetrics const & , CSSPixels , CSSPixels , CSSPixels , CSSPixels ) const
2022-02-26 01:35:25 +01:00
{
return * this ;
}
2023-03-17 23:08:45 +01:00
ValueComparingNonnullRefPtr < StyleValue const > LengthStyleValue : : absolutized ( CSSPixelRect const & viewport_rect , Gfx : : FontPixelMetrics const & font_metrics , CSSPixels font_size , CSSPixels root_font_size , CSSPixels line_height , CSSPixels root_line_height ) const
2022-02-26 01:35:25 +01:00
{
2023-03-17 23:08:45 +01:00
if ( auto length = absolutized_length ( m_length , viewport_rect , font_metrics , font_size , root_font_size , line_height , root_line_height ) ; length . has_value ( ) )
2022-02-26 01:35:25 +01:00
return LengthStyleValue : : create ( length . release_value ( ) ) ;
return * this ;
}
2023-03-17 23:08:45 +01:00
ValueComparingNonnullRefPtr < StyleValue const > ShadowStyleValue : : absolutized ( CSSPixelRect const & viewport_rect , Gfx : : FontPixelMetrics const & font_metrics , CSSPixels font_size , CSSPixels root_font_size , CSSPixels line_height , CSSPixels root_line_height ) const
2022-02-26 01:35:25 +01:00
{
2023-03-17 23:08:45 +01:00
auto absolutized_offset_x = absolutized_length ( m_properties . offset_x , viewport_rect , font_metrics , font_size , root_font_size , line_height , root_line_height ) . value_or ( m_properties . offset_x ) ;
auto absolutized_offset_y = absolutized_length ( m_properties . offset_y , viewport_rect , font_metrics , font_size , root_font_size , line_height , root_line_height ) . value_or ( m_properties . offset_y ) ;
auto absolutized_blur_radius = absolutized_length ( m_properties . blur_radius , viewport_rect , font_metrics , font_size , root_font_size , line_height , root_line_height ) . value_or ( m_properties . blur_radius ) ;
auto absolutized_spread_distance = absolutized_length ( m_properties . spread_distance , viewport_rect , font_metrics , font_size , root_font_size , line_height , root_line_height ) . value_or ( m_properties . spread_distance ) ;
2023-02-11 19:12:00 +01:00
return ShadowStyleValue : : create ( m_properties . color , absolutized_offset_x , absolutized_offset_y , absolutized_blur_radius , absolutized_spread_distance , m_properties . placement ) ;
2022-02-26 01:35:25 +01:00
}
2022-09-14 11:28:15 +02:00
bool CalculatedStyleValue : : contains_percentage ( ) const
{
return m_expression - > contains_percentage ( ) ;
}
bool CalculatedStyleValue : : CalcSum : : contains_percentage ( ) const
{
if ( first_calc_product - > contains_percentage ( ) )
return true ;
for ( auto & part : zero_or_more_additional_calc_products ) {
2023-03-06 17:16:25 +01:00
if ( part - > contains_percentage ( ) )
2022-09-14 11:28:15 +02:00
return true ;
}
return false ;
}
bool CalculatedStyleValue : : CalcSumPartWithOperator : : contains_percentage ( ) const
{
return value - > contains_percentage ( ) ;
}
bool CalculatedStyleValue : : CalcProduct : : contains_percentage ( ) const
{
if ( first_calc_value . contains_percentage ( ) )
return true ;
for ( auto & part : zero_or_more_additional_calc_values ) {
2023-03-06 17:16:25 +01:00
if ( part - > contains_percentage ( ) )
2022-09-14 11:28:15 +02:00
return true ;
}
return false ;
}
bool CalculatedStyleValue : : CalcProductPartWithOperator : : contains_percentage ( ) const
{
return value . visit (
[ ] ( CalcValue const & value ) { return value . contains_percentage ( ) ; } ,
[ ] ( CalcNumberValue const & ) { return false ; } ) ;
}
bool CalculatedStyleValue : : CalcValue : : contains_percentage ( ) const
{
return value . visit (
[ ] ( Percentage const & ) { return true ; } ,
[ ] ( NonnullOwnPtr < CalcSum > const & sum ) { return sum - > contains_percentage ( ) ; } ,
[ ] ( auto const & ) { return false ; } ) ;
}
2022-09-27 18:12:54 +02:00
bool calculated_style_value_contains_percentage ( CalculatedStyleValue const & value )
{
return value . contains_percentage ( ) ;
}
2020-03-07 10:27:02 +01:00
}