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 )
{
}
StyleValue : : ~ StyleValue ( )
{
}
2019-10-06 10:25:08 +02:00
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 ) ;
}
BoxShadowStyleValue const & StyleValue : : as_box_shadow ( ) const
{
VERIFY ( is_box_shadow ( ) ) ;
return static_cast < BoxShadowStyleValue const & > ( * this ) ;
}
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 ) ;
}
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 ) ;
}
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 ) ;
}
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 )
builder . append ( " , " ) ;
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-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 ) ) ;
}
String BackgroundSizeStyleValue : : to_string ( ) const
{
return String : : formatted ( " {} {} " , m_size_x . to_string ( ) , m_size_y . to_string ( ) ) ;
}
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
}
String BorderRadiusStyleValue : : to_string ( ) const
{
return String : : formatted ( " {} / {} " , m_horizontal_radius . to_string ( ) , m_vertical_radius . to_string ( ) ) ;
}
String BoxShadowStyleValue : : to_string ( ) const
{
2022-02-08 13:47:11 +00:00
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 = = BoxShadowPlacement : : Inner )
builder . append ( " inset " ) ;
return builder . to_string ( ) ;
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 ) {
m_value = Number {
. is_integer = number . is_integer & & other_number . is_integer ,
. value = number . value + other_number . value
} ;
} else {
m_value = Number {
. is_integer = number . is_integer & & other_number . is_integer ,
. value = number . value - other_number . value
} ;
}
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 ) ;
}
} ,
[ & ] ( 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 ;
if ( op = = SumOperation : : Add )
new_value . add ( * this , layout_node , percentage_basis ) ;
else
new_value . subtract ( * this , layout_node , percentage_basis ) ;
* 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-02-02 12:34:32 +00:00
auto other_number = other . m_value . get < Number > ( ) ;
m_value = Number {
. is_integer = number . is_integer & & other_number . is_integer ,
. value = number . value * other_number . value
} ;
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 ) {
m_value = Angle : : make_degrees ( angle . to_degrees ( ) * other . m_value . get < Number > ( ) . value ) ;
} ,
2022-02-21 17:49:47 +00:00
[ & ] ( Frequency const & frequency ) {
m_value = Frequency : : make_hertz ( frequency . to_hertz ( ) * other . m_value . get < Number > ( ) . value ) ;
} ,
2022-01-27 14:50:31 +00:00
[ & ] ( Length const & length ) {
2022-01-27 14:51:51 +00:00
VERIFY ( layout_node ) ;
2022-02-02 12:34:32 +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
} ,
[ & ] ( Percentage const & percentage ) {
2022-02-02 12:34:32 +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.
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 {
. is_integer = false ,
. value = number . value / denominator
} ;
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 ) ;
} ,
[ & ] ( 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 ( ) ) ;
}
String CalculatedStyleValue : : CalcNumberValue : : to_string ( ) const
{
return value . visit (
[ ] ( Number const & number ) { return String : : number ( number . value ) ; } ,
[ ] ( NonnullOwnPtr < CalcNumberSum > const & sum ) { return String : : formatted ( " ({}) " , sum - > to_string ( ) ) ; } ) ;
}
String CalculatedStyleValue : : CalcValue : : to_string ( ) const
{
return value . visit (
[ ] ( 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 { } ;
}
Optional < float > CalculatedStyleValue : : resolve_number ( )
{
auto result = m_expression - > resolve ( nullptr , { } ) ;
2022-02-02 12:34:32 +00:00
if ( result . value ( ) . has < Number > ( ) )
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 > ( ) )
return lroundf ( result . value ( ) . get < Number > ( ) . 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 > {
return { number . is_integer ? ResolvedType : : Integer : ResolvedType : : Number } ;
} ,
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-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 > {
return { number . is_integer ? ResolvedType : : Integer : ResolvedType : : Number } ;
} ,
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.
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
// https://www.w3.org/TR/css-color-4/#serializing-sRGB-values
String ColorStyleValue : : to_string ( ) const
{
if ( m_color . alpha ( ) = = 1 )
return String : : formatted ( " rgb({}, {}, {}) " , m_color . red ( ) , m_color . green ( ) , m_color . blue ( ) ) ;
return String : : formatted ( " rgba({}, {}, {}, {}) " , m_color . red ( ) , m_color . green ( ) , m_color . blue ( ) , ( float ) ( m_color . alpha ( ) ) / 255.0f ) ;
}
String CombinedBorderRadiusStyleValue : : 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 ( ) ) ;
}
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
}
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
}
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
}
2021-09-23 19:54:19 +01:00
String IdentifierStyleValue : : to_string ( ) const
{
return CSS : : string_from_value_id ( m_id ) ;
}
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
2021-02-23 20:42:32 +01:00
VERIFY ( document . page ( ) ) ;
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 ( ) )
2021-05-30 12:36:53 +02: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
}
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
}
String NumericStyleValue : : to_string ( ) const
{
return m_value . visit (
[ ] ( float value ) {
return String : : formatted ( " {} " , value ) ;
} ,
[ ] ( i64 value ) {
return String : : formatted ( " {} " , value ) ;
} ) ;
}
String OverflowStyleValue : : to_string ( ) const
{
return String : : formatted ( " {} {} " , m_overflow_x - > to_string ( ) , m_overflow_y - > to_string ( ) ) ;
}
String PercentageStyleValue : : to_string ( ) const
{
return m_percentage . to_string ( ) ;
2021-10-03 17:56:01 +02:00
}
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-02-02 20:39:04 +00:00
String TextDecorationStyleValue : : to_string ( ) const
{
2022-02-02 20:40:34 +00:00
return String : : formatted ( " {} {} {} " , m_line - > to_string ( ) , m_style - > to_string ( ) , m_color - > to_string ( ) ) ;
2022-02-02 20:39:04 +00:00
}
String TransformationStyleValue : : to_string ( ) const
{
2022-02-02 21:19:43 +00:00
StringBuilder builder ;
switch ( m_transform_function ) {
case TransformFunction : : TranslateY :
builder . append ( " translateY " ) ;
break ;
default :
VERIFY_NOT_REACHED ( ) ;
}
builder . append ( ' ( ' ) ;
builder . join ( " , " , m_values ) ;
builder . append ( ' ) ' ) ;
return builder . to_string ( ) ;
2022-02-02 20:39:04 +00:00
}
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-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-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 ) ) ;
}
2020-03-07 10:27:02 +01:00
}