2020-01-18 09:38:21 +01:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
2022-02-02 20:39:04 +00:00
* Copyright ( c ) 2021 - 2022 , Sam Atkins < atkinssj @ serenityos . org >
2022-01-24 17:38:29 +00:00
* Copyright ( c ) 2021 , Tobias Christiansen < tobyase @ serenityos . org >
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>
# 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>
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-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-02-23 19:56:25 +00:00
ContentStyleValue const & StyleValue : : as_content ( ) const
{
VERIFY ( is_content ( ) ) ;
return static_cast < ContentStyleValue 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 ) ;
}
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 ) ;
}
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-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 ) ;
}
2021-11-11 11:47:31 +00:00
BackgroundStyleValue : : BackgroundStyleValue (
NonnullRefPtr < StyleValue > color ,
NonnullRefPtr < StyleValue > image ,
NonnullRefPtr < StyleValue > position ,
NonnullRefPtr < StyleValue > size ,
NonnullRefPtr < StyleValue > repeat ,
NonnullRefPtr < StyleValue > attachment ,
NonnullRefPtr < StyleValue > origin ,
NonnullRefPtr < StyleValue > clip )
: StyleValue ( Type : : Background )
, m_color ( color )
, m_image ( image )
, m_position ( position )
, m_size ( size )
, m_repeat ( repeat )
, m_attachment ( attachment )
, m_origin ( origin )
, m_clip ( clip )
{
auto layer_count = [ ] ( auto style_value ) - > size_t {
if ( style_value - > is_value_list ( ) )
return style_value - > as_value_list ( ) . size ( ) ;
else
return 1 ;
} ;
m_layer_count = max ( layer_count ( m_image ) , layer_count ( m_position ) ) ;
m_layer_count = max ( m_layer_count , layer_count ( m_size ) ) ;
m_layer_count = max ( m_layer_count , layer_count ( m_repeat ) ) ;
m_layer_count = max ( m_layer_count , layer_count ( m_attachment ) ) ;
m_layer_count = max ( m_layer_count , layer_count ( m_origin ) ) ;
m_layer_count = max ( m_layer_count , layer_count ( m_clip ) ) ;
VERIFY ( ! m_color - > is_value_list ( ) ) ;
}
String BackgroundStyleValue : : to_string ( ) const
{
if ( m_layer_count = = 1 ) {
return String : : formatted ( " {} {} {} {} {} {} {} {} " , m_color - > to_string ( ) , m_image - > to_string ( ) , m_position - > to_string ( ) , m_size - > to_string ( ) , m_repeat - > to_string ( ) , m_attachment - > to_string ( ) , m_origin - > to_string ( ) , m_clip - > to_string ( ) ) ;
}
auto get_layer_value_string = [ ] ( NonnullRefPtr < StyleValue > const & style_value , size_t index ) {
if ( style_value - > is_value_list ( ) )
return style_value - > as_value_list ( ) . value_at ( index , true ) - > to_string ( ) ;
return style_value - > to_string ( ) ;
} ;
StringBuilder builder ;
for ( size_t i = 0 ; i < m_layer_count ; i + + ) {
if ( i )
2022-07-11 17:32:29 +00:00
builder . append ( " , " sv ) ;
2021-11-11 11:47:31 +00:00
if ( i = = m_layer_count - 1 )
builder . appendff ( " {} " , m_color - > to_string ( ) ) ;
builder . appendff ( " {} {} {} {} {} {} {} " , get_layer_value_string ( m_image , i ) , get_layer_value_string ( m_position , i ) , get_layer_value_string ( m_size , i ) , get_layer_value_string ( m_repeat , i ) , get_layer_value_string ( m_attachment , i ) , get_layer_value_string ( m_origin , i ) , get_layer_value_string ( m_clip , i ) ) ;
}
return builder . to_string ( ) ;
}
2022-04-18 17:42:03 +01:00
bool BackgroundStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_background ( ) ;
return m_color - > equals ( typed_other . m_color )
& & m_image - > equals ( typed_other . m_image )
& & m_position - > equals ( typed_other . m_position )
& & m_size - > equals ( typed_other . m_size )
& & m_repeat - > equals ( typed_other . m_repeat )
& & m_attachment - > equals ( typed_other . m_attachment )
& & m_origin - > equals ( typed_other . m_origin )
& & m_clip - > equals ( typed_other . m_clip ) ;
}
2022-02-02 20:39:04 +00:00
String BackgroundRepeatStyleValue : : to_string ( ) const
{
return String : : formatted ( " {} {} " , CSS : : to_string ( m_repeat_x ) , CSS : : to_string ( m_repeat_y ) ) ;
}
2022-04-18 17:42:03 +01:00
bool BackgroundRepeatStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_background_repeat ( ) ;
return m_repeat_x = = typed_other . m_repeat_x & & m_repeat_y = = typed_other . m_repeat_y ;
}
2022-02-02 20:39:04 +00:00
String BackgroundSizeStyleValue : : to_string ( ) const
{
return String : : formatted ( " {} {} " , m_size_x . to_string ( ) , m_size_y . to_string ( ) ) ;
}
2022-04-18 17:42:03 +01:00
bool BackgroundSizeStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_background_size ( ) ;
return m_size_x = = typed_other . m_size_x & & m_size_y = = typed_other . m_size_y ;
}
2022-02-02 20:39:04 +00:00
String BorderStyleValue : : to_string ( ) const
{
2022-02-02 20:40:34 +00:00
return String : : formatted ( " {} {} {} " , m_border_width - > to_string ( ) , m_border_style - > to_string ( ) , m_border_color - > to_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool BorderStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_border ( ) ;
return m_border_width - > equals ( typed_other . m_border_width )
& & m_border_style - > equals ( typed_other . m_border_style )
& & m_border_color - > equals ( typed_other . m_border_color ) ;
}
2022-02-02 20:39:04 +00:00
String BorderRadiusStyleValue : : to_string ( ) const
{
2022-04-03 17:03:32 -03:00
if ( m_horizontal_radius = = m_vertical_radius )
return m_horizontal_radius . to_string ( ) ;
2022-02-02 20:39:04 +00:00
return String : : formatted ( " {} / {} " , m_horizontal_radius . to_string ( ) , m_vertical_radius . to_string ( ) ) ;
}
2022-04-18 17:42:03 +01:00
bool BorderRadiusStyleValue : : equals ( StyleValue const & other ) const
2022-02-02 20:39:04 +00:00
{
2022-04-18 17:42:03 +01:00
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_border_radius ( ) ;
return m_is_elliptical = = typed_other . m_is_elliptical
& & m_horizontal_radius = = typed_other . m_horizontal_radius
& & m_vertical_radius = = typed_other . m_vertical_radius ;
}
String BorderRadiusShorthandStyleValue : : to_string ( ) const
{
return String : : formatted ( " {} {} {} {} / {} {} {} {} " , m_top_left - > horizontal_radius ( ) . to_string ( ) , m_top_right - > horizontal_radius ( ) . to_string ( ) , m_bottom_right - > horizontal_radius ( ) . to_string ( ) , m_bottom_left - > horizontal_radius ( ) . to_string ( ) , m_top_left - > vertical_radius ( ) . to_string ( ) , m_top_right - > vertical_radius ( ) . to_string ( ) , m_bottom_right - > vertical_radius ( ) . to_string ( ) , m_bottom_left - > vertical_radius ( ) . to_string ( ) ) ;
}
bool BorderRadiusShorthandStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_border_radius_shorthand ( ) ;
return m_top_left - > equals ( typed_other . m_top_left )
& & m_top_right - > equals ( typed_other . m_top_right )
& & m_bottom_right - > equals ( typed_other . m_bottom_right )
& & m_bottom_left - > equals ( typed_other . m_bottom_left ) ;
2022-01-27 14:51:51 +00:00
}
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
}
2022-02-02 15:34:13 +00:00
String CalculatedStyleValue : : to_string ( ) const
{
return String : : formatted ( " calc({}) " , m_expression - > to_string ( ) ) ;
}
2022-04-18 17:42:03 +01:00
bool CalculatedStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
// This is a case where comparing the strings actually makes sense.
return to_string ( ) = = other . to_string ( ) ;
}
2022-02-02 15:34:13 +00:00
String CalculatedStyleValue : : CalcNumberValue : : to_string ( ) const
{
return value . visit (
2022-03-21 21:03:17 +00:00
[ ] ( Number const & number ) { return String : : number ( number . value ( ) ) ; } ,
2022-02-02 15:34:13 +00:00
[ ] ( NonnullOwnPtr < CalcNumberSum > const & sum ) { return String : : formatted ( " ({}) " , sum - > to_string ( ) ) ; } ) ;
}
String CalculatedStyleValue : : CalcValue : : to_string ( ) const
{
return value . visit (
2022-03-21 21:03:17 +00:00
[ ] ( Number const & number ) { return String : : number ( number . value ( ) ) ; } ,
2022-02-21 17:43:30 +00:00
[ ] ( NonnullOwnPtr < CalcSum > const & sum ) { return String : : formatted ( " ({}) " , sum - > to_string ( ) ) ; } ,
[ ] ( auto const & v ) { return v . to_string ( ) ; } ) ;
2022-02-02 15:34:13 +00:00
}
String CalculatedStyleValue : : CalcSum : : to_string ( ) const
{
StringBuilder builder ;
builder . append ( first_calc_product - > to_string ( ) ) ;
for ( auto const & item : zero_or_more_additional_calc_products )
builder . append ( item . to_string ( ) ) ;
return builder . to_string ( ) ;
}
String CalculatedStyleValue : : CalcNumberSum : : to_string ( ) const
{
StringBuilder builder ;
builder . append ( first_calc_number_product - > to_string ( ) ) ;
for ( auto const & item : zero_or_more_additional_calc_number_products )
builder . append ( item . to_string ( ) ) ;
return builder . to_string ( ) ;
}
String CalculatedStyleValue : : CalcProduct : : to_string ( ) const
{
StringBuilder builder ;
builder . append ( first_calc_value . to_string ( ) ) ;
for ( auto const & item : zero_or_more_additional_calc_values )
builder . append ( item . to_string ( ) ) ;
return builder . to_string ( ) ;
}
String CalculatedStyleValue : : CalcSumPartWithOperator : : to_string ( ) const
{
return String : : formatted ( " {} {} " , op = = SumOperation : : Add ? " + " sv : " - " sv , value - > to_string ( ) ) ;
}
String CalculatedStyleValue : : CalcProductPartWithOperator : : to_string ( ) const
{
auto value_string = value . visit (
[ ] ( CalcValue const & v ) { return v . to_string ( ) ; } ,
[ ] ( CalcNumberValue const & v ) { return v . to_string ( ) ; } ) ;
return String : : formatted ( " {} {} " , op = = ProductOperation : : Multiply ? " * " sv : " / " sv , value_string ) ;
}
String CalculatedStyleValue : : CalcNumberProduct : : to_string ( ) const
{
StringBuilder builder ;
builder . append ( first_calc_number_value . to_string ( ) ) ;
for ( auto const & item : zero_or_more_additional_calc_number_values )
builder . append ( item . to_string ( ) ) ;
return builder . to_string ( ) ;
}
String CalculatedStyleValue : : CalcNumberProductPartWithOperator : : to_string ( ) const
{
return String : : formatted ( " {} {} " , op = = ProductOperation : : Multiply ? " * " sv : " / " sv , value . to_string ( ) ) ;
}
String CalculatedStyleValue : : CalcNumberSumPartWithOperator : : to_string ( ) const
{
return String : : formatted ( " {} {} " , op = = SumOperation : : Add ? " + " sv : " - " sv , value - > to_string ( ) ) ;
}
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 { } ;
}
Optional < AnglePercentage > CalculatedStyleValue : : resolve_angle_percentage ( Angle const & percentage_basis ) const
{
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-02-21 17:43:30 +00:00
[ & ] ( Angle const & angle ) - > Optional < AnglePercentage > {
return angle ;
2022-01-24 17:38:29 +00:00
} ,
2022-02-21 17:43:30 +00:00
[ & ] ( Percentage const & percentage ) - > Optional < AnglePercentage > {
return percentage ;
2022-01-24 17:38:29 +00:00
} ,
2022-02-21 17:43:30 +00:00
[ & ] ( auto const & ) - > Optional < AnglePercentage > {
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 { } ;
}
Optional < FrequencyPercentage > CalculatedStyleValue : : resolve_frequency_percentage ( Frequency const & percentage_basis ) const
{
auto result = m_expression - > resolve ( nullptr , percentage_basis ) ;
return result . value ( ) . visit (
[ & ] ( Frequency const & frequency ) - > Optional < FrequencyPercentage > {
return frequency ;
} ,
[ & ] ( Percentage const & percentage ) - > Optional < FrequencyPercentage > {
return percentage ;
} ,
[ & ] ( auto const & ) - > Optional < FrequencyPercentage > {
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-01-27 14:51:51 +00:00
Optional < LengthPercentage > 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 (
[ & ] ( Length const & length ) - > Optional < LengthPercentage > {
return length ;
} ,
[ & ] ( Percentage const & percentage ) - > Optional < LengthPercentage > {
return percentage ;
2022-02-21 17:43:30 +00:00
} ,
[ & ] ( auto const & ) - > Optional < LengthPercentage > {
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 { } ;
}
Optional < TimePercentage > CalculatedStyleValue : : resolve_time_percentage ( Time const & percentage_basis ) const
{
auto result = m_expression - > resolve ( nullptr , percentage_basis ) ;
return result . value ( ) . visit (
[ & ] ( Time const & time ) - > Optional < TimePercentage > {
return time ;
} ,
[ & ] ( Percentage const & percentage ) - > Optional < TimePercentage > {
return percentage ;
} ,
[ & ] ( auto const & ) - > Optional < TimePercentage > {
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 >
static Optional < CalculatedStyleValue : : ResolvedType > resolve_sum_type ( CalculatedStyleValue : : ResolvedType first_type , NonnullOwnPtrVector < SumWithOperator > const & zero_or_more_additional_products )
{
auto type = first_type ;
for ( auto const & product : zero_or_more_additional_products ) {
auto maybe_product_type = product . resolved_type ( ) ;
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 ) ;
}
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 >
static Optional < CalculatedStyleValue : : ResolvedType > resolve_product_type ( CalculatedStyleValue : : ResolvedType first_type , NonnullOwnPtrVector < ProductWithOperator > const & zero_or_more_additional_values )
{
auto type = first_type ;
for ( auto const & value : zero_or_more_additional_values ) {
auto maybe_value_type = value . resolved_type ( ) ;
if ( ! maybe_value_type . has_value ( ) )
return { } ;
auto value_type = maybe_value_type . value ( ) ;
if ( value . op = = CalculatedStyleValue : : ProductOperation : : Multiply ) {
// 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 {
VERIFY ( value . op = = CalculatedStyleValue : : ProductOperation : : Divide ) ;
// 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 ) {
auto additional_value = additional_product . resolve ( layout_node , percentage_basis ) ;
if ( additional_product . op = = CalculatedStyleValue : : SumOperation : : Add )
value . add ( additional_value , layout_node , percentage_basis ) ;
else if ( additional_product . op = = CalculatedStyleValue : : SumOperation : : Subtract )
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 ) {
auto additional_value = additional_product . resolve ( layout_node , percentage_basis ) ;
if ( additional_product . op = = CSS : : CalculatedStyleValue : : SumOperation : : Add )
value . add ( additional_value , layout_node , percentage_basis ) ;
else if ( additional_product . op = = CalculatedStyleValue : : SumOperation : : Subtract )
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 ) {
additional_value . value . visit (
[ & ] ( CalculatedStyleValue : : CalcValue const & calc_value ) {
VERIFY ( additional_value . op = = CalculatedStyleValue : : ProductOperation : : Multiply ) ;
auto resolved_value = calc_value . resolve ( layout_node , percentage_basis ) ;
value . multiply_by ( resolved_value , layout_node ) ;
} ,
[ & ] ( CalculatedStyleValue : : CalcNumberValue const & calc_number_value ) {
VERIFY ( additional_value . op = = CalculatedStyleValue : : ProductOperation : : Divide ) ;
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 ) {
auto additional_value = additional_number_value . resolve ( layout_node , percentage_basis ) ;
if ( additional_number_value . op = = CalculatedStyleValue : : ProductOperation : : Multiply )
value . multiply_by ( additional_value , layout_node ) ;
else if ( additional_number_value . op = = CalculatedStyleValue : : ProductOperation : : Divide )
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 ) ;
}
2022-02-02 20:39:04 +00:00
String ColorStyleValue : : to_string ( ) const
{
2022-07-12 15:30:13 +01:00
return serialize_a_srgb_value ( m_color ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool ColorStyleValue : : equals ( StyleValue const & other ) const
2022-02-02 20:39:04 +00:00
{
2022-04-18 17:42:03 +01:00
if ( type ( ) ! = other . type ( ) )
return false ;
return m_color = = other . as_color ( ) . m_color ;
2022-02-02 20:39:04 +00:00
}
2022-02-23 19:56:25 +00:00
String ContentStyleValue : : to_string ( ) const
{
if ( has_alt_text ( ) )
return String : : formatted ( " {} / {} " , m_content - > to_string ( ) , m_alt_text - > to_string ( ) ) ;
return m_content - > to_string ( ) ;
}
2022-04-18 17:42:03 +01:00
bool ContentStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_content ( ) ;
if ( ! m_content - > equals ( typed_other . m_content ) )
return false ;
if ( m_alt_text . is_null ( ) ! = typed_other . m_alt_text . is_null ( ) )
return false ;
if ( ! m_alt_text . is_null ( ) )
return m_alt_text - > equals ( * typed_other . m_alt_text ) ;
return true ;
}
2022-02-02 20:39:04 +00:00
String FlexStyleValue : : to_string ( ) const
{
2022-02-02 20:40:34 +00:00
return String : : formatted ( " {} {} {} " , m_grow - > to_string ( ) , m_shrink - > to_string ( ) , m_basis - > to_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool FlexStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_flex ( ) ;
return m_grow - > equals ( typed_other . m_grow )
& & m_shrink - > equals ( typed_other . m_shrink )
& & m_basis - > equals ( typed_other . m_basis ) ;
}
2022-02-02 20:39:04 +00:00
String FlexFlowStyleValue : : to_string ( ) const
{
2022-02-02 20:40:34 +00:00
return String : : formatted ( " {} {} " , m_flex_direction - > to_string ( ) , m_flex_wrap - > to_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool FlexFlowStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_flex_flow ( ) ;
return m_flex_direction - > equals ( typed_other . m_flex_direction )
& & m_flex_wrap - > equals ( typed_other . m_flex_wrap ) ;
}
2022-02-02 20:39:04 +00:00
String FontStyleValue : : to_string ( ) const
{
2022-02-02 20:40:34 +00:00
return String : : formatted ( " {} {} {} / {} {} " , m_font_style - > to_string ( ) , m_font_weight - > to_string ( ) , m_font_size - > to_string ( ) , m_line_height - > to_string ( ) , m_font_families - > to_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool FontStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_font ( ) ;
return m_font_style - > equals ( typed_other . m_font_style )
& & m_font_weight - > equals ( typed_other . m_font_weight )
& & m_font_size - > equals ( typed_other . m_font_size )
& & m_line_height - > equals ( typed_other . m_line_height )
& & m_font_families - > equals ( typed_other . m_font_families ) ;
}
bool FrequencyStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_frequency = = other . as_frequency ( ) . m_frequency ;
}
2021-09-23 19:54:19 +01:00
String IdentifierStyleValue : : to_string ( ) const
{
return CSS : : string_from_value_id ( m_id ) ;
}
2022-04-18 17:42:03 +01:00
bool IdentifierStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_id = = other . as_identifier ( ) . 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 )
2019-10-19 11:49:46 +02:00
: StyleValue ( Type : : Image )
, m_url ( url )
{
2021-10-22 20:55:27 +01:00
}
void ImageStyleValue : : load_bitmap ( DOM : : Document & document )
{
if ( m_bitmap )
return ;
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 ;
2020-06-23 13:33:03 +02:00
m_bitmap = resource ( ) - > bitmap ( ) ;
2020-06-02 13:51:30 +02:00
// 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 ( ) ;
2019-10-19 11:49:46 +02:00
}
2021-10-03 17:56:01 +02:00
2022-02-02 20:39:04 +00:00
String ImageStyleValue : : to_string ( ) const
2021-10-03 17:56:01 +02:00
{
2022-02-02 20:40:34 +00:00
return serialize_a_url ( m_url . to_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool ImageStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_url = = other . as_image ( ) . m_url ;
}
bool InheritStyleValue : : equals ( StyleValue const & other ) const
{
return type ( ) = = other . type ( ) ;
}
bool InitialStyleValue : : equals ( StyleValue const & other ) const
{
return type ( ) = = other . type ( ) ;
}
bool LengthStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_length = = other . as_length ( ) . m_length ;
}
2022-02-02 20:39:04 +00:00
String ListStyleStyleValue : : to_string ( ) const
{
2022-02-02 20:40:34 +00:00
return String : : formatted ( " {} {} {} " , m_position - > to_string ( ) , m_image - > to_string ( ) , m_style_type - > to_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool ListStyleStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_list_style ( ) ;
return m_position - > equals ( typed_other . m_position )
& & m_image - > equals ( typed_other . m_image )
& & m_style_type - > equals ( typed_other . m_style_type ) ;
}
2022-02-02 20:39:04 +00:00
String NumericStyleValue : : to_string ( ) const
{
return m_value . visit (
[ ] ( float value ) {
return String : : formatted ( " {} " , value ) ;
} ,
[ ] ( i64 value ) {
return String : : formatted ( " {} " , value ) ;
} ) ;
}
2022-04-18 17:42:03 +01:00
bool NumericStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
if ( has_integer ( ) ! = other . has_integer ( ) )
return false ;
if ( has_integer ( ) )
return m_value . get < i64 > ( ) = = other . as_numeric ( ) . m_value . get < i64 > ( ) ;
return m_value . get < float > ( ) = = other . as_numeric ( ) . m_value . get < float > ( ) ;
}
2022-02-02 20:39:04 +00:00
String OverflowStyleValue : : to_string ( ) const
{
return String : : formatted ( " {} {} " , m_overflow_x - > to_string ( ) , m_overflow_y - > to_string ( ) ) ;
}
2022-04-18 17:42:03 +01:00
bool OverflowStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_overflow ( ) ;
return m_overflow_x - > equals ( typed_other . m_overflow_x )
& & m_overflow_y - > equals ( typed_other . m_overflow_y ) ;
}
2022-02-02 20:39:04 +00:00
String PercentageStyleValue : : to_string ( ) const
{
return m_percentage . to_string ( ) ;
2021-10-03 17:56:01 +02:00
}
2022-04-18 17:42:03 +01:00
bool PercentageStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_percentage = = other . as_percentage ( ) . m_percentage ;
}
2021-10-31 16:02:29 +00:00
String PositionStyleValue : : to_string ( ) const
{
auto to_string = [ ] ( PositionEdge edge ) {
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 ( ) ;
} ;
return String : : formatted ( " {} {} {} {} " , to_string ( m_edge_x ) , m_offset_x . to_string ( ) , to_string ( m_edge_y ) , m_offset_y . to_string ( ) ) ;
}
2022-04-18 17:42:03 +01:00
bool PositionStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_position ( ) ;
return m_edge_x = = typed_other . m_edge_x
& & m_offset_x = = typed_other . m_offset_x
& & m_edge_y = = typed_other . m_edge_y
& & m_offset_y = = typed_other . m_offset_y ;
}
bool ResolutionStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_resolution = = other . as_resolution ( ) . m_resolution ;
}
String ShadowStyleValue : : to_string ( ) const
{
StringBuilder builder ;
builder . appendff ( " {} {} {} {} {} " , m_color . to_string ( ) , m_offset_x . to_string ( ) , m_offset_y . to_string ( ) , m_blur_radius . to_string ( ) , m_spread_distance . to_string ( ) ) ;
if ( m_placement = = ShadowPlacement : : Inner )
2022-07-11 17:32:29 +00:00
builder . append ( " inset " sv ) ;
2022-04-18 17:42:03 +01:00
return builder . to_string ( ) ;
}
bool ShadowStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_shadow ( ) ;
return m_color = = typed_other . m_color
& & m_offset_x = = typed_other . m_offset_x
& & m_offset_y = = typed_other . m_offset_y
& & m_blur_radius = = typed_other . m_blur_radius
& & m_spread_distance = = typed_other . m_spread_distance
& & m_placement = = typed_other . m_placement ;
}
bool StringStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_string = = other . as_string ( ) . m_string ;
}
2022-02-02 20:39:04 +00:00
String TextDecorationStyleValue : : to_string ( ) const
{
2022-03-06 02:09:00 +01:00
return String : : formatted ( " {} {} {} {} " , m_line - > to_string ( ) , m_thickness - > to_string ( ) , m_style - > to_string ( ) , m_color - > to_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool TextDecorationStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_text_decoration ( ) ;
return m_line - > equals ( typed_other . m_line )
& & m_thickness - > equals ( typed_other . m_thickness )
& & m_style - > equals ( typed_other . m_style )
& & m_color - > equals ( typed_other . m_color ) ;
}
bool TimeStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
return m_time = = other . as_time ( ) . m_time ;
}
2022-02-02 20:39:04 +00:00
String TransformationStyleValue : : to_string ( ) const
{
2022-02-02 21:19:43 +00:00
StringBuilder builder ;
2022-04-17 15:52:30 +01:00
builder . append ( CSS : : to_string ( m_transform_function ) ) ;
2022-02-02 21:19:43 +00:00
builder . append ( ' ( ' ) ;
2022-07-11 17:32:29 +00:00
builder . join ( " , " sv , m_values ) ;
2022-02-02 21:19:43 +00:00
builder . append ( ' ) ' ) ;
return builder . to_string ( ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool TransformationStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_transformation ( ) ;
if ( m_transform_function ! = typed_other . m_transform_function )
return false ;
if ( m_values . size ( ) ! = typed_other . m_values . size ( ) )
return false ;
for ( size_t i = 0 ; i < m_values . size ( ) ; + + i ) {
if ( ! m_values [ i ] . equals ( typed_other . m_values [ i ] ) )
return false ;
}
return true ;
}
2021-12-03 12:28:14 +00:00
String UnresolvedStyleValue : : to_string ( ) const
{
StringBuilder builder ;
for ( auto & value : m_values )
builder . append ( value . to_string ( ) ) ;
return builder . to_string ( ) ;
}
2022-04-18 17:42:03 +01:00
bool UnresolvedStyleValue : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
// This is a case where comparing the strings actually makes sense.
return to_string ( ) = = other . to_string ( ) ;
}
bool UnsetStyleValue : : equals ( StyleValue const & other ) const
{
return type ( ) = = other . type ( ) ;
}
2022-02-02 20:39:04 +00:00
String StyleValueList : : to_string ( ) const
{
2022-02-02 20:53:55 +00:00
String separator = " " ;
switch ( m_separator ) {
case Separator : : Space :
separator = " " ;
break ;
case Separator : : Comma :
separator = " , " ;
break ;
default :
VERIFY_NOT_REACHED ( ) ;
2022-02-02 20:39:04 +00:00
}
2022-02-02 20:53:55 +00:00
return String : : join ( separator , m_values ) ;
2022-02-02 20:39:04 +00:00
}
2022-04-18 17:42:03 +01:00
bool StyleValueList : : equals ( StyleValue const & other ) const
{
if ( type ( ) ! = other . type ( ) )
return false ;
auto const & typed_other = other . as_value_list ( ) ;
if ( m_separator ! = typed_other . m_separator )
return false ;
if ( m_values . size ( ) ! = typed_other . m_values . size ( ) )
return false ;
for ( size_t i = 0 ; i < m_values . size ( ) ; + + i ) {
if ( ! m_values [ i ] . equals ( typed_other . m_values [ i ] ) )
return false ;
}
return true ;
}
2022-02-18 20:26:09 +01:00
NonnullRefPtr < ColorStyleValue > ColorStyleValue : : create ( Color color )
{
if ( color . value ( ) = = 0 ) {
static auto transparent = adopt_ref ( * new ColorStyleValue ( color ) ) ;
return transparent ;
}
if ( color = = Color : : from_rgb ( 0x000000 ) ) {
static auto black = adopt_ref ( * new ColorStyleValue ( color ) ) ;
return black ;
}
if ( color = = Color : : from_rgb ( 0xffffff ) ) {
static auto white = adopt_ref ( * new ColorStyleValue ( color ) ) ;
return white ;
}
return adopt_ref ( * new ColorStyleValue ( color ) ) ;
}
NonnullRefPtr < LengthStyleValue > LengthStyleValue : : create ( Length const & length )
{
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 ) ) ;
}
2022-03-28 12:03:44 +02:00
static Optional < CSS : : Length > absolutized_length ( CSS : : Length const & length , Gfx : : IntRect const & viewport_rect , Gfx : : FontPixelMetrics const & font_metrics , float font_size , float root_font_size )
2022-02-26 01:35:25 +01:00
{
if ( length . is_px ( ) )
return { } ;
if ( length . is_absolute ( ) | | length . is_relative ( ) ) {
auto px = length . to_px ( viewport_rect , font_metrics , font_size , root_font_size ) ;
return CSS : : Length : : make_px ( px ) ;
}
return { } ;
}
2022-03-28 12:03:44 +02:00
NonnullRefPtr < StyleValue > StyleValue : : absolutized ( Gfx : : IntRect const & , Gfx : : FontPixelMetrics const & , float , float ) const
2022-02-26 01:35:25 +01:00
{
return * this ;
}
2022-03-28 12:03:44 +02:00
NonnullRefPtr < StyleValue > LengthStyleValue : : absolutized ( Gfx : : IntRect const & viewport_rect , Gfx : : FontPixelMetrics const & font_metrics , float font_size , float root_font_size ) const
2022-02-26 01:35:25 +01:00
{
if ( auto length = absolutized_length ( m_length , viewport_rect , font_metrics , font_size , root_font_size ) ; length . has_value ( ) )
return LengthStyleValue : : create ( length . release_value ( ) ) ;
return * this ;
}
2022-03-28 12:03:44 +02:00
NonnullRefPtr < StyleValue > ShadowStyleValue : : absolutized ( Gfx : : IntRect const & viewport_rect , Gfx : : FontPixelMetrics const & font_metrics , float font_size , float root_font_size ) const
2022-02-26 01:35:25 +01:00
{
auto absolutized_offset_x = absolutized_length ( m_offset_x , viewport_rect , font_metrics , font_size , root_font_size ) . value_or ( m_offset_x ) ;
auto absolutized_offset_y = absolutized_length ( m_offset_y , viewport_rect , font_metrics , font_size , root_font_size ) . value_or ( m_offset_y ) ;
auto absolutized_blur_radius = absolutized_length ( m_blur_radius , viewport_rect , font_metrics , font_size , root_font_size ) . value_or ( m_blur_radius ) ;
auto absolutized_spread_distance = absolutized_length ( m_spread_distance , viewport_rect , font_metrics , font_size , root_font_size ) . value_or ( m_spread_distance ) ;
2022-03-23 16:55:22 +00:00
return ShadowStyleValue : : create ( m_color , absolutized_offset_x , absolutized_offset_y , absolutized_blur_radius , absolutized_spread_distance , m_placement ) ;
2022-02-26 01:35:25 +01:00
}
2022-03-28 12:03:44 +02:00
NonnullRefPtr < StyleValue > BorderRadiusStyleValue : : absolutized ( Gfx : : IntRect const & viewport_rect , Gfx : : FontPixelMetrics const & font_metrics , float font_size , float root_font_size ) const
2022-02-26 01:35:25 +01:00
{
if ( m_horizontal_radius . is_percentage ( ) & & m_vertical_radius . is_percentage ( ) )
return * this ;
auto absolutized_horizontal_radius = m_horizontal_radius ;
auto absolutized_vertical_radius = m_vertical_radius ;
if ( ! m_horizontal_radius . is_percentage ( ) )
absolutized_horizontal_radius = absolutized_length ( m_horizontal_radius . length ( ) , viewport_rect , font_metrics , font_size , root_font_size ) . value_or ( m_horizontal_radius . length ( ) ) ;
if ( ! m_vertical_radius . is_percentage ( ) )
absolutized_vertical_radius = absolutized_length ( m_vertical_radius . length ( ) , viewport_rect , font_metrics , font_size , root_font_size ) . value_or ( m_vertical_radius . length ( ) ) ;
return BorderRadiusStyleValue : : create ( absolutized_horizontal_radius , absolutized_vertical_radius ) ;
}
2020-03-07 10:27:02 +01:00
}