2020-01-18 09:38:21 +01:00
/*
2024-08-02 13:59:19 +02:00
* Copyright ( c ) 2018 - 2024 , Andreas Kling < andreas @ ladybird . org >
2024-10-01 09:20:06 +01:00
* Copyright ( c ) 2021 - 2024 , Sam Atkins < sam @ ladybird . 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
*/
2024-11-03 13:20:04 +01:00
# include <AK/NonnullRawPtr.h>
2021-05-30 20:22:25 +02:00
# include <AK/TypeCasts.h>
2020-02-06 15:04:03 +01:00
# include <LibCore/DirIterator.h>
2022-07-31 18:47:09 +02:00
# include <LibWeb/CSS/Clip.h>
2020-03-07 10:32:51 +01:00
# include <LibWeb/CSS/StyleProperties.h>
2023-03-23 17:26:13 +00:00
# include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
2024-08-14 11:46:56 +01:00
# include <LibWeb/CSS/StyleValues/CSSKeywordValue.h>
2023-03-23 21:17:43 +00:00
# include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
2024-07-24 15:47:11 +01:00
# include <LibWeb/CSS/StyleValues/CounterDefinitionsStyleValue.h>
2024-07-18 20:29:02 +01:00
# include <LibWeb/CSS/StyleValues/CounterStyleValue.h>
2023-04-26 21:05:38 +02:00
# include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
2023-08-17 20:25:18 +02:00
# include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
2023-03-24 14:25:00 +00:00
# include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
2023-03-24 14:53:08 +00:00
# include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
2023-04-29 17:59:07 +02:00
# include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
2023-06-01 17:01:09 +01:00
# include <LibWeb/CSS/StyleValues/IntegerStyleValue.h>
2023-05-27 12:28:25 +01:00
# include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
2023-09-07 15:29:54 +01:00
# include <LibWeb/CSS/StyleValues/MathDepthStyleValue.h>
2023-06-01 16:16:15 +01:00
# include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
2024-10-01 09:20:06 +01:00
# include <LibWeb/CSS/StyleValues/OpenTypeTaggedStyleValue.h>
2023-03-24 17:28:43 +00:00
# include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
2023-10-16 13:52:51 +02:00
# include <LibWeb/CSS/StyleValues/PositionStyleValue.h>
2023-03-25 00:02:50 +00:00
# include <LibWeb/CSS/StyleValues/RectStyleValue.h>
2024-10-16 08:50:35 +02:00
# include <LibWeb/CSS/StyleValues/RotationStyleValue.h>
2024-11-22 18:07:16 +01:00
# include <LibWeb/CSS/StyleValues/ScaleStyleValue.h>
2024-06-26 23:19:38 +01:00
# include <LibWeb/CSS/StyleValues/ScrollbarGutterStyleValue.h>
2023-03-24 17:45:25 +00:00
# include <LibWeb/CSS/StyleValues/ShadowStyleValue.h>
2023-03-24 17:48:42 +00:00
# include <LibWeb/CSS/StyleValues/StringStyleValue.h>
2023-03-25 00:12:21 +00:00
# include <LibWeb/CSS/StyleValues/StyleValueList.h>
2023-03-24 17:59:33 +00:00
# include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
2024-11-22 16:42:20 +01:00
# include <LibWeb/CSS/StyleValues/TranslationStyleValue.h>
2021-10-06 20:02:41 +02:00
# include <LibWeb/Layout/BlockContainer.h>
2021-08-12 16:41:09 +01:00
# include <LibWeb/Layout/Node.h>
2022-09-17 21:25:50 +02:00
# include <LibWeb/Platform/FontPlugin.h>
2019-09-21 15:32:17 +03:00
2020-07-26 20:01:35 +02:00
namespace Web : : CSS {
2020-03-07 10:27:02 +01:00
2024-09-10 11:46:32 +02:00
NonnullRefPtr < StyleProperties : : Data > StyleProperties : : Data : : clone ( ) const
2024-08-02 13:59:19 +02:00
{
2024-09-10 11:46:32 +02:00
auto clone = adopt_ref ( * new StyleProperties : : Data ) ;
2024-09-19 14:14:13 +01:00
clone - > m_animation_name_source = m_animation_name_source ;
clone - > m_transition_property_source = m_transition_property_source ;
2024-08-02 13:59:19 +02:00
clone - > m_property_values = m_property_values ;
clone - > m_property_important = m_property_important ;
clone - > m_property_inherited = m_property_inherited ;
2024-09-19 14:14:13 +01:00
clone - > m_animated_property_values = m_animated_property_values ;
clone - > m_math_depth = m_math_depth ;
2024-08-02 13:59:19 +02:00
clone - > m_font_list = m_font_list ;
clone - > m_line_height = m_line_height ;
return clone ;
}
2024-03-16 07:44:48 +01:00
bool StyleProperties : : is_property_important ( CSS : : PropertyID property_id ) const
{
2024-08-02 13:59:19 +02:00
size_t n = to_underlying ( property_id ) ;
2024-09-10 11:46:32 +02:00
return m_data - > m_property_important [ n / 8 ] & ( 1 < < ( n % 8 ) ) ;
2024-08-02 13:59:19 +02:00
}
void StyleProperties : : set_property_important ( CSS : : PropertyID property_id , Important important )
{
size_t n = to_underlying ( property_id ) ;
if ( important = = Important : : Yes )
2024-09-10 11:46:32 +02:00
m_data - > m_property_important [ n / 8 ] | = ( 1 < < ( n % 8 ) ) ;
2024-08-02 13:59:19 +02:00
else
2024-09-10 11:46:32 +02:00
m_data - > m_property_important [ n / 8 ] & = ~ ( 1 < < ( n % 8 ) ) ;
2024-03-16 07:44:48 +01:00
}
bool StyleProperties : : is_property_inherited ( CSS : : PropertyID property_id ) const
{
2024-08-02 13:59:19 +02:00
size_t n = to_underlying ( property_id ) ;
2024-09-10 11:46:32 +02:00
return m_data - > m_property_inherited [ n / 8 ] & ( 1 < < ( n % 8 ) ) ;
2024-08-02 13:59:19 +02:00
}
void StyleProperties : : set_property_inherited ( CSS : : PropertyID property_id , Inherited inherited )
{
size_t n = to_underlying ( property_id ) ;
if ( inherited = = Inherited : : Yes )
2024-09-10 11:46:32 +02:00
m_data - > m_property_inherited [ n / 8 ] | = ( 1 < < ( n % 8 ) ) ;
2024-08-02 13:59:19 +02:00
else
2024-09-10 11:46:32 +02:00
m_data - > m_property_inherited [ n / 8 ] & = ~ ( 1 < < ( n % 8 ) ) ;
2024-03-16 07:44:48 +01:00
}
2024-08-14 11:10:54 +01:00
void StyleProperties : : set_property ( CSS : : PropertyID id , NonnullRefPtr < CSSStyleValue const > value , Inherited inherited , Important important )
2024-03-16 07:44:48 +01:00
{
2024-09-10 11:46:32 +02:00
m_data - > m_property_values [ to_underlying ( id ) ] = move ( value ) ;
2024-08-02 13:59:19 +02:00
set_property_important ( id , important ) ;
set_property_inherited ( id , inherited ) ;
2024-03-16 07:44:48 +01:00
}
2024-08-04 10:08:28 +02:00
void StyleProperties : : revert_property ( CSS : : PropertyID id , StyleProperties const & style_for_revert )
{
2024-09-10 11:46:32 +02:00
m_data - > m_property_values [ to_underlying ( id ) ] = style_for_revert . m_data - > m_property_values [ to_underlying ( id ) ] ;
2024-08-04 10:08:28 +02:00
set_property_important ( id , style_for_revert . is_property_important ( id ) ? Important : : Yes : Important : : No ) ;
set_property_inherited ( id , style_for_revert . is_property_inherited ( id ) ? Inherited : : Yes : Inherited : : No ) ;
}
2024-08-14 11:10:54 +01:00
void StyleProperties : : set_animated_property ( CSS : : PropertyID id , NonnullRefPtr < CSSStyleValue const > value )
2024-03-16 07:44:48 +01:00
{
2024-09-10 11:46:32 +02:00
m_data - > m_animated_property_values . set ( id , move ( value ) ) ;
2024-03-16 07:44:48 +01:00
}
void StyleProperties : : reset_animated_properties ( )
{
2024-09-10 11:46:32 +02:00
m_data - > m_animated_property_values . clear ( ) ;
2019-09-21 15:32:17 +03:00
}
2024-11-03 13:20:04 +01:00
CSSStyleValue const & StyleProperties : : property ( CSS : : PropertyID property_id , WithAnimationsApplied return_animated_value ) const
2019-09-21 15:32:17 +03:00
{
2024-09-19 10:46:32 +01:00
if ( return_animated_value = = WithAnimationsApplied : : Yes ) {
2024-11-03 13:20:04 +01:00
if ( auto animated_value = m_data - > m_animated_property_values . get ( property_id ) ; animated_value . has_value ( ) )
return * animated_value . value ( ) ;
2024-09-19 10:46:32 +01:00
}
2024-03-16 07:44:48 +01:00
2022-04-14 11:52:35 +01:00
// By the time we call this method, all properties have values assigned.
2024-09-10 11:46:32 +02:00
return * m_data - > m_property_values [ to_underlying ( property_id ) ] ;
2019-09-21 15:32:17 +03:00
}
2024-11-03 13:20:04 +01:00
CSSStyleValue const * StyleProperties : : maybe_null_property ( CSS : : PropertyID property_id ) const
2022-10-28 15:42:18 +01:00
{
2024-11-03 13:20:04 +01:00
if ( auto animated_value = m_data - > m_animated_property_values . get ( property_id ) ; animated_value . has_value ( ) )
return animated_value . value ( ) ;
2024-09-10 11:46:32 +02:00
return m_data - > m_property_values [ to_underlying ( property_id ) ] ;
2023-05-26 23:25:25 +03:30
}
2024-11-09 17:38:09 +01:00
Variant < LengthPercentage , NormalGap > StyleProperties : : gap_value ( CSS : : PropertyID id ) const
{
auto const & value = property ( id ) ;
if ( value . is_keyword ( ) ) {
VERIFY ( value . as_keyword ( ) . keyword ( ) = = CSS : : Keyword : : Normal ) ;
return NormalGap { } ;
}
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) )
return LengthPercentage { const_cast < CalculatedStyleValue & > ( value . as_calculated ( ) ) } ;
2024-11-09 17:38:09 +01:00
if ( value . is_percentage ( ) )
return LengthPercentage { value . as_percentage ( ) . percentage ( ) } ;
if ( value . is_length ( ) )
return LengthPercentage { value . as_length ( ) . length ( ) } ;
VERIFY_NOT_REACHED ( ) ;
}
2022-09-25 15:47:40 +02:00
CSS : : Size StyleProperties : : size_value ( CSS : : PropertyID id ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( id ) ;
if ( value . is_keyword ( ) ) {
switch ( value . to_keyword ( ) ) {
2024-08-14 14:06:03 +01:00
case Keyword : : Auto :
2022-09-25 15:47:40 +02:00
return CSS : : Size : : make_auto ( ) ;
2024-08-14 14:06:03 +01:00
case Keyword : : MinContent :
2022-09-25 15:47:40 +02:00
return CSS : : Size : : make_min_content ( ) ;
2024-08-14 14:06:03 +01:00
case Keyword : : MaxContent :
2022-09-25 15:47:40 +02:00
return CSS : : Size : : make_max_content ( ) ;
2024-08-14 14:06:03 +01:00
case Keyword : : FitContent :
2023-05-26 18:58:06 +02:00
return CSS : : Size : : make_fit_content ( ) ;
2024-08-14 14:06:03 +01:00
case Keyword : : None :
2022-09-25 15:47:40 +02:00
return CSS : : Size : : make_none ( ) ;
default :
VERIFY_NOT_REACHED ( ) ;
}
}
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) )
return CSS : : Size : : make_calculated ( const_cast < CalculatedStyleValue & > ( value . as_calculated ( ) ) ) ;
2022-09-25 15:47:40 +02:00
2024-11-03 13:20:04 +01:00
if ( value . is_percentage ( ) )
return CSS : : Size : : make_percentage ( value . as_percentage ( ) . percentage ( ) ) ;
2022-09-25 15:47:40 +02:00
2024-11-03 13:20:04 +01:00
if ( value . is_length ( ) ) {
auto length = value . as_length ( ) . length ( ) ;
2022-09-25 15:47:40 +02:00
if ( length . is_auto ( ) )
return CSS : : Size : : make_auto ( ) ;
2023-05-27 12:28:25 +01:00
return CSS : : Size : : make_length ( length ) ;
2022-09-25 15:47:40 +02:00
}
// FIXME: Support `fit-content(<length>)`
2024-12-07 00:59:49 +01:00
dbgln ( " FIXME: Unsupported size value: `{}`, treating as `auto` " , value . to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2022-09-25 15:47:40 +02:00
return CSS : : Size : : make_auto ( ) ;
}
2022-01-19 16:19:43 +00:00
LengthPercentage StyleProperties : : length_percentage_or_fallback ( CSS : : PropertyID id , LengthPercentage const & fallback ) const
2022-02-18 15:10:11 +00:00
{
return length_percentage ( id ) . value_or ( fallback ) ;
}
Optional < LengthPercentage > StyleProperties : : length_percentage ( CSS : : PropertyID id ) const
2022-01-19 16:19:43 +00:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( id ) ;
2022-01-19 16:19:43 +00:00
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) )
return LengthPercentage { const_cast < CalculatedStyleValue & > ( value . as_calculated ( ) ) } ;
2022-01-19 16:19:43 +00:00
2024-11-03 13:20:04 +01:00
if ( value . is_percentage ( ) )
return value . as_percentage ( ) . percentage ( ) ;
2022-01-19 16:19:43 +00:00
2024-11-03 13:20:04 +01:00
if ( value . is_length ( ) )
return value . as_length ( ) . length ( ) ;
2022-01-19 16:19:43 +00:00
2024-11-03 13:20:04 +01:00
if ( value . has_auto ( ) )
2023-04-19 11:26:49 +01:00
return LengthPercentage { Length : : make_auto ( ) } ;
2022-02-18 15:10:11 +00:00
return { } ;
2019-09-21 15:32:17 +03:00
}
2019-09-25 11:55:04 +03:00
2020-12-15 20:01:00 +01:00
LengthBox StyleProperties : : length_box ( CSS : : PropertyID left_id , CSS : : PropertyID top_id , CSS : : PropertyID right_id , CSS : : PropertyID bottom_id , const CSS : : Length & default_value ) const
2020-05-11 23:04:59 +02:00
{
2020-06-24 17:45:42 +02:00
LengthBox box ;
2022-09-13 17:42:39 +02:00
box . left ( ) = length_percentage_or_fallback ( left_id , default_value ) ;
box . top ( ) = length_percentage_or_fallback ( top_id , default_value ) ;
box . right ( ) = length_percentage_or_fallback ( right_id , default_value ) ;
box . bottom ( ) = length_percentage_or_fallback ( bottom_id , default_value ) ;
2020-06-24 17:45:42 +02:00
return box ;
2020-05-11 23:04:59 +02:00
}
2021-09-16 19:20:20 +01:00
Color StyleProperties : : color_or_fallback ( CSS : : PropertyID id , Layout : : NodeWithStyle const & node , Color fallback ) const
2019-09-28 22:18:19 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( id ) ;
if ( ! value . has_color ( ) )
2019-09-28 22:18:19 +02:00
return fallback ;
2024-11-03 13:20:04 +01:00
return value . to_color ( node ) ;
2019-09-28 22:18:19 +02:00
}
2019-10-06 11:23:58 +02:00
2023-02-20 18:56:08 +01:00
NonnullRefPtr < Gfx : : Font const > StyleProperties : : font_fallback ( bool monospace , bool bold )
2021-04-22 20:47:47 +02:00
{
if ( monospace & & bold )
2022-09-17 21:25:50 +02:00
return Platform : : FontPlugin : : the ( ) . default_fixed_width_font ( ) . bold_variant ( ) ;
2021-04-22 20:47:47 +02:00
if ( monospace )
2022-09-17 21:25:50 +02:00
return Platform : : FontPlugin : : the ( ) . default_fixed_width_font ( ) ;
2021-04-22 20:47:47 +02:00
if ( bold )
2022-09-17 21:25:50 +02:00
return Platform : : FontPlugin : : the ( ) . default_font ( ) . bold_variant ( ) ;
2021-04-22 20:47:47 +02:00
2022-09-17 21:25:50 +02:00
return Platform : : FontPlugin : : the ( ) . default_font ( ) ;
2021-04-22 20:47:47 +02:00
}
2024-01-12 12:39:40 +01:00
CSSPixels StyleProperties : : compute_line_height ( CSSPixelRect const & viewport_rect , Length : : FontMetrics const & font_metrics , Length : : FontMetrics const & root_font_metrics ) const
2023-03-17 23:08:45 +01:00
{
2024-11-03 13:20:04 +01:00
auto const & line_height = property ( CSS : : PropertyID : : LineHeight ) ;
2023-03-17 23:08:45 +01:00
2024-11-03 13:20:04 +01:00
if ( line_height . is_keyword ( ) & & line_height . to_keyword ( ) = = Keyword : : Normal )
2023-04-28 16:29:12 +01:00
return font_metrics . line_height ;
2023-03-17 23:08:45 +01:00
2024-11-03 13:20:04 +01:00
if ( line_height . is_length ( ) ) {
auto line_height_length = line_height . as_length ( ) . length ( ) ;
2023-03-17 23:08:45 +01:00
if ( ! line_height_length . is_auto ( ) )
2023-04-28 16:29:12 +01:00
return line_height_length . to_px ( viewport_rect , font_metrics , root_font_metrics ) ;
2023-03-17 23:08:45 +01:00
}
2024-11-03 13:20:04 +01:00
if ( line_height . is_number ( ) )
return Length ( line_height . as_number ( ) . number ( ) , Length : : Type : : Em ) . to_px ( viewport_rect , font_metrics , root_font_metrics ) ;
2023-03-17 23:08:45 +01:00
2024-11-03 13:20:04 +01:00
if ( line_height . is_percentage ( ) ) {
2023-03-17 23:08:45 +01:00
// Percentages are relative to 1em. https://www.w3.org/TR/css-inline-3/#valdef-line-height-percentage
2024-11-03 13:20:04 +01:00
auto const & percentage = line_height . as_percentage ( ) . percentage ( ) ;
2023-04-28 16:29:12 +01:00
return Length ( percentage . as_fraction ( ) , Length : : Type : : Em ) . to_px ( viewport_rect , font_metrics , root_font_metrics ) ;
2023-03-17 23:08:45 +01:00
}
2024-12-11 15:05:56 +00:00
if ( line_height . is_calculated ( ) ) {
if ( line_height . as_calculated ( ) . resolves_to_number ( ) ) {
auto resolved = line_height . as_calculated ( ) . resolve_number ( ) ;
2024-01-12 12:39:40 +01:00
if ( ! resolved . has_value ( ) ) {
2024-12-11 15:05:56 +00:00
dbgln ( " FIXME: Failed to resolve calc() line-height (number): {} " , line_height . as_calculated ( ) . to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2024-09-10 11:46:32 +02:00
return CSSPixels : : nearest_value_for ( m_data - > m_font_list - > first ( ) . pixel_metrics ( ) . line_spacing ( ) ) ;
2024-01-12 12:39:40 +01:00
}
return Length ( resolved . value ( ) , Length : : Type : : Em ) . to_px ( viewport_rect , font_metrics , root_font_metrics ) ;
}
2024-12-11 15:05:56 +00:00
auto resolved = line_height . as_calculated ( ) . resolve_length ( Length : : ResolutionContext { viewport_rect , font_metrics , root_font_metrics } ) ;
2024-01-12 12:39:40 +01:00
if ( ! resolved . has_value ( ) ) {
2024-12-11 15:05:56 +00:00
dbgln ( " FIXME: Failed to resolve calc() line-height: {} " , line_height . as_calculated ( ) . to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2024-09-10 11:46:32 +02:00
return CSSPixels : : nearest_value_for ( m_data - > m_font_list - > first ( ) . pixel_metrics ( ) . line_spacing ( ) ) ;
2024-01-12 12:39:40 +01:00
}
return resolved - > to_px ( viewport_rect , font_metrics , root_font_metrics ) ;
2023-03-18 21:15:51 +01:00
}
2023-03-17 23:08:45 +01:00
2023-04-28 16:29:12 +01:00
return font_metrics . line_height ;
2023-03-17 23:08:45 +01:00
}
2020-06-15 17:29:35 +02:00
Optional < int > StyleProperties : : z_index ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ZIndex ) ;
if ( value . has_auto ( ) )
2022-03-04 15:01:01 +01:00
return { } ;
2024-11-03 13:20:04 +01:00
if ( value . is_integer ( ) ) {
2023-04-26 07:19:07 +02:00
// Clamp z-index to the range of a signed 32-bit integer for consistency with other engines.
2024-11-03 13:20:04 +01:00
auto integer = value . as_integer ( ) . integer ( ) ;
2023-06-01 17:01:09 +01:00
if ( integer > = NumericLimits < int > : : max ( ) )
2023-04-26 07:19:07 +02:00
return NumericLimits < int > : : max ( ) ;
2023-06-01 17:01:09 +01:00
if ( integer < = NumericLimits < int > : : min ( ) )
2023-04-26 07:19:07 +02:00
return NumericLimits < int > : : min ( ) ;
return static_cast < int > ( integer ) ;
}
2021-09-10 20:37:09 +01:00
return { } ;
2020-06-15 17:29:35 +02:00
}
2024-08-14 11:10:54 +01:00
float StyleProperties : : resolve_opacity_value ( CSSStyleValue const & value )
2021-07-23 13:18:09 +03:00
{
2022-01-27 17:44:22 +00:00
float unclamped_opacity = 1.0f ;
2023-06-01 16:16:15 +01:00
if ( value . is_number ( ) ) {
unclamped_opacity = value . as_number ( ) . number ( ) ;
2024-12-11 15:05:56 +00:00
} else if ( value . is_calculated ( ) ) {
auto const & calculated = value . as_calculated ( ) ;
2023-06-30 16:29:06 +01:00
if ( calculated . resolves_to_percentage ( ) ) {
2024-12-11 15:05:56 +00:00
auto maybe_percentage = value . as_calculated ( ) . resolve_percentage ( ) ;
2022-01-27 17:44:22 +00:00
if ( maybe_percentage . has_value ( ) )
unclamped_opacity = maybe_percentage - > as_fraction ( ) ;
else
2024-12-07 00:59:49 +01:00
dbgln ( " Unable to resolve calc() as opacity (percentage): {} " , value . to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2023-06-30 16:29:06 +01:00
} else if ( calculated . resolves_to_number ( ) ) {
2024-12-11 15:05:56 +00:00
auto maybe_number = const_cast < CalculatedStyleValue & > ( value . as_calculated ( ) ) . resolve_number ( ) ;
2022-01-27 17:44:22 +00:00
if ( maybe_number . has_value ( ) )
unclamped_opacity = maybe_number . value ( ) ;
else
2024-12-07 00:59:49 +01:00
dbgln ( " Unable to resolve calc() as opacity (number): {} " , value . to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2022-01-27 17:44:22 +00:00
}
2023-05-19 20:35:39 +01:00
} else if ( value . is_percentage ( ) ) {
unclamped_opacity = value . as_percentage ( ) . percentage ( ) . as_fraction ( ) ;
2022-01-27 17:44:22 +00:00
}
2021-07-23 13:18:09 +03:00
2022-01-27 17:44:22 +00:00
return clamp ( unclamped_opacity , 0.0f , 1.0f ) ;
2021-07-23 13:18:09 +03:00
}
2023-05-19 20:35:39 +01:00
float StyleProperties : : opacity ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Opacity ) ;
return resolve_opacity_value ( value ) ;
2023-05-19 20:35:39 +01:00
}
float StyleProperties : : fill_opacity ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FillOpacity ) ;
return resolve_opacity_value ( value ) ;
2023-05-19 20:35:39 +01:00
}
2024-10-10 10:15:49 -04:00
Optional < CSS : : StrokeLinecap > StyleProperties : : stroke_linecap ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : StrokeLinecap ) ;
return keyword_to_stroke_linecap ( value . to_keyword ( ) ) ;
2024-10-10 10:15:49 -04:00
}
2024-10-28 20:51:16 -04:00
Optional < CSS : : StrokeLinejoin > StyleProperties : : stroke_linejoin ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : StrokeLinejoin ) ;
return keyword_to_stroke_linejoin ( value . to_keyword ( ) ) ;
2024-10-28 20:51:16 -04:00
}
NumberOrCalculated StyleProperties : : stroke_miterlimit ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : StrokeMiterlimit ) ;
2024-10-28 20:51:16 -04:00
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) ) {
auto const & math_value = value . as_calculated ( ) ;
2024-10-28 20:51:16 -04:00
VERIFY ( math_value . resolves_to_number ( ) ) ;
return NumberOrCalculated { math_value } ;
}
2024-11-03 13:20:04 +01:00
return NumberOrCalculated { value . as_number ( ) . number ( ) } ;
2024-10-28 20:51:16 -04:00
}
2023-05-19 20:35:39 +01:00
float StyleProperties : : stroke_opacity ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : StrokeOpacity ) ;
return resolve_opacity_value ( value ) ;
2023-05-19 20:35:39 +01:00
}
float StyleProperties : : stop_opacity ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : StopOpacity ) ;
return resolve_opacity_value ( value ) ;
2023-05-19 20:35:39 +01:00
}
2023-06-11 16:43:46 +01:00
Optional < CSS : : FillRule > StyleProperties : : fill_rule ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FillRule ) ;
return keyword_to_fill_rule ( value . to_keyword ( ) ) ;
2023-06-11 16:43:46 +01:00
}
2024-05-12 20:19:43 +01:00
Optional < CSS : : ClipRule > StyleProperties : : clip_rule ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ClipRule ) ;
return keyword_to_fill_rule ( value . to_keyword ( ) ) ;
2024-05-12 20:19:43 +01:00
}
2021-01-18 17:41:57 +01:00
Optional < CSS : : FlexDirection > StyleProperties : : flex_direction ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FlexDirection ) ;
return keyword_to_flex_direction ( value . to_keyword ( ) ) ;
2021-01-18 17:41:57 +01:00
}
2021-05-30 12:11:32 +02:00
Optional < CSS : : FlexWrap > StyleProperties : : flex_wrap ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FlexWrap ) ;
return keyword_to_flex_wrap ( value . to_keyword ( ) ) ;
2021-05-30 12:11:32 +02:00
}
2023-06-21 19:39:07 +02:00
Optional < CSS : : FlexBasis > StyleProperties : : flex_basis ( ) const
2021-05-30 14:23:43 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FlexBasis ) ;
2021-05-30 14:23:43 +02:00
2024-11-03 13:20:04 +01:00
if ( value . is_keyword ( ) & & value . to_keyword ( ) = = CSS : : Keyword : : Content )
2023-06-21 19:39:07 +02:00
return CSS : : FlexBasisContent { } ;
2021-05-30 14:23:43 +02:00
2023-06-21 19:39:07 +02:00
return size_value ( CSS : : PropertyID : : FlexBasis ) ;
2021-05-30 14:23:43 +02:00
}
2021-10-19 15:22:08 +02:00
float StyleProperties : : flex_grow ( ) const
2021-05-30 20:22:25 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FlexGrow ) ;
if ( ! value . is_number ( ) )
2021-10-19 15:22:08 +02:00
return 0 ;
2024-11-03 13:20:04 +01:00
return value . as_number ( ) . number ( ) ;
2021-05-30 20:22:25 +02:00
}
2021-10-19 15:22:08 +02:00
float StyleProperties : : flex_shrink ( ) const
2021-05-30 20:22:25 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FlexShrink ) ;
if ( ! value . is_number ( ) )
2021-10-19 15:22:08 +02:00
return 1 ;
2024-11-03 13:20:04 +01:00
return value . as_number ( ) . number ( ) ;
2021-05-30 20:22:25 +02:00
}
2021-10-19 15:22:08 +02:00
2022-03-31 22:11:38 +02:00
int StyleProperties : : order ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Order ) ;
if ( ! value . is_integer ( ) )
2022-03-31 22:11:38 +02:00
return 0 ;
2024-11-03 13:20:04 +01:00
return value . as_integer ( ) . integer ( ) ;
2022-03-31 22:11:38 +02:00
}
2022-02-18 12:21:27 +01:00
Optional < CSS : : ImageRendering > StyleProperties : : image_rendering ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ImageRendering ) ;
return keyword_to_image_rendering ( value . to_keyword ( ) ) ;
2022-02-18 12:21:27 +01:00
}
2024-10-09 13:36:09 +02:00
CSS : : Length StyleProperties : : border_spacing_horizontal ( Layout : : Node const & layout_node ) const
2023-06-16 02:35:03 +00:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : BorderSpacing ) ;
if ( value . is_length ( ) )
return value . as_length ( ) . length ( ) ;
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) )
return value . as_calculated ( ) . resolve_length ( layout_node ) . value_or ( CSS : : Length ( 0 , CSS : : Length : : Type : : Px ) ) ;
2024-11-03 13:20:04 +01:00
auto const & list = value . as_value_list ( ) ;
2023-06-16 02:35:03 +00:00
return list . value_at ( 0 , false ) - > as_length ( ) . length ( ) ;
}
2024-10-09 13:36:09 +02:00
CSS : : Length StyleProperties : : border_spacing_vertical ( Layout : : Node const & layout_node ) const
2023-06-16 02:35:03 +00:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : BorderSpacing ) ;
if ( value . is_length ( ) )
return value . as_length ( ) . length ( ) ;
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) )
return value . as_calculated ( ) . resolve_length ( layout_node ) . value_or ( CSS : : Length ( 0 , CSS : : Length : : Type : : Px ) ) ;
2024-11-03 13:20:04 +01:00
auto const & list = value . as_value_list ( ) ;
2023-06-16 02:35:03 +00:00
return list . value_at ( 1 , false ) - > as_length ( ) . length ( ) ;
}
2023-06-07 02:10:55 +00:00
Optional < CSS : : CaptionSide > StyleProperties : : caption_side ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : CaptionSide ) ;
return keyword_to_caption_side ( value . to_keyword ( ) ) ;
2023-06-07 02:10:55 +00:00
}
2022-07-31 18:47:09 +02:00
CSS : : Clip StyleProperties : : clip ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Clip ) ;
if ( ! value . is_rect ( ) )
2022-07-31 18:47:09 +02:00
return CSS : : Clip : : make_auto ( ) ;
2024-11-03 13:20:04 +01:00
return CSS : : Clip ( value . as_rect ( ) . rect ( ) ) ;
2022-07-31 18:47:09 +02:00
}
2021-07-16 18:38:26 +02:00
Optional < CSS : : JustifyContent > StyleProperties : : justify_content ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : JustifyContent ) ;
return keyword_to_justify_content ( value . to_keyword ( ) ) ;
2021-07-16 18:38:26 +02:00
}
2021-05-30 20:22:25 +02:00
2023-07-14 20:49:22 +02:00
Optional < CSS : : JustifyItems > StyleProperties : : justify_items ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : JustifyItems ) ;
return keyword_to_justify_items ( value . to_keyword ( ) ) ;
2023-07-14 20:49:22 +02:00
}
2023-07-14 14:41:22 +02:00
Optional < CSS : : JustifySelf > StyleProperties : : justify_self ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : JustifySelf ) ;
return keyword_to_justify_self ( value . to_keyword ( ) ) ;
2023-07-14 14:41:22 +02:00
}
2024-08-14 11:10:54 +01:00
Vector < CSS : : Transformation > StyleProperties : : transformations_for_style_value ( CSSStyleValue const & value )
2021-09-18 17:20:00 +02:00
{
2024-08-14 14:06:03 +01:00
if ( value . is_keyword ( ) & & value . to_keyword ( ) = = CSS : : Keyword : : None )
2021-09-18 17:20:00 +02:00
return { } ;
2024-01-06 18:05:21 +01:00
if ( ! value . is_value_list ( ) )
2021-09-18 17:20:00 +02:00
return { } ;
2024-01-06 18:05:21 +01:00
auto & list = value . as_value_list ( ) ;
2021-09-18 17:20:00 +02:00
Vector < CSS : : Transformation > transformations ;
for ( auto & it : list . values ( ) ) {
2023-03-06 14:33:11 +01:00
if ( ! it - > is_transformation ( ) )
2021-09-18 17:20:00 +02:00
return { } ;
2023-03-06 14:33:11 +01:00
auto & transformation_style_value = it - > as_transformation ( ) ;
2023-10-13 17:25:23 +01:00
auto function = transformation_style_value . transform_function ( ) ;
2024-01-08 18:51:19 +01:00
auto function_metadata = transform_function_metadata ( function ) ;
2022-07-14 17:45:23 +01:00
Vector < TransformValue > values ;
2024-01-08 18:51:19 +01:00
size_t argument_index = 0 ;
2021-09-18 17:20:00 +02:00
for ( auto & transformation_value : transformation_style_value . values ( ) ) {
2024-12-11 15:05:56 +00:00
if ( transformation_value - > is_calculated ( ) ) {
auto & calculated = transformation_value - > as_calculated ( ) ;
2024-01-09 12:39:17 +04:00
if ( calculated . resolves_to_length_percentage ( ) ) {
2023-07-15 10:23:43 +02:00
values . append ( CSS : : LengthPercentage { calculated } ) ;
2023-05-27 19:21:42 +02:00
} else if ( calculated . resolves_to_percentage ( ) ) {
2024-01-08 18:51:19 +01:00
// FIXME: Maybe transform this for loop to always check the metadata for the correct types
if ( function_metadata . parameters [ argument_index ] . type = = TransformFunctionParameterType : : NumberPercentage ) {
values . append ( NumberPercentage { calculated . resolve_percentage ( ) . value ( ) } ) ;
} else {
values . append ( LengthPercentage { calculated . resolve_percentage ( ) . value ( ) } ) ;
}
2023-05-27 19:21:42 +02:00
} else if ( calculated . resolves_to_number ( ) ) {
2024-01-08 18:51:19 +01:00
values . append ( { Number ( Number : : Type : : Number , calculated . resolve_number ( ) . value ( ) ) } ) ;
2023-05-27 19:21:42 +02:00
} else if ( calculated . resolves_to_angle ( ) ) {
values . append ( { calculated . resolve_angle ( ) . value ( ) } ) ;
} else {
2024-12-07 00:59:49 +01:00
dbgln ( " FIXME: Unsupported calc value in transform! {} " , calculated . to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2023-05-27 19:21:42 +02:00
}
} else if ( transformation_value - > is_length ( ) ) {
2023-05-27 12:28:25 +01:00
values . append ( { transformation_value - > as_length ( ) . length ( ) } ) ;
2023-03-06 14:33:11 +01:00
} else if ( transformation_value - > is_percentage ( ) ) {
2024-01-08 18:51:19 +01:00
if ( function_metadata . parameters [ argument_index ] . type = = TransformFunctionParameterType : : NumberPercentage ) {
values . append ( NumberPercentage { transformation_value - > as_percentage ( ) . percentage ( ) } ) ;
} else {
values . append ( LengthPercentage { transformation_value - > as_percentage ( ) . percentage ( ) } ) ;
}
2023-06-01 16:16:15 +01:00
} else if ( transformation_value - > is_number ( ) ) {
2024-01-08 18:51:19 +01:00
values . append ( { Number ( Number : : Type : : Number , transformation_value - > as_number ( ) . number ( ) ) } ) ;
2023-03-06 14:33:11 +01:00
} else if ( transformation_value - > is_angle ( ) ) {
values . append ( { transformation_value - > as_angle ( ) . angle ( ) } ) ;
2021-09-18 17:20:00 +02:00
} else {
2024-12-07 00:59:49 +01:00
dbgln ( " FIXME: Unsupported value in transform! {} " , transformation_value - > to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2021-09-18 17:20:00 +02:00
}
2024-01-08 18:51:19 +01:00
argument_index + + ;
2021-09-18 17:20:00 +02:00
}
2023-10-13 17:25:23 +01:00
transformations . empend ( function , move ( values ) ) ;
2021-09-18 17:20:00 +02:00
}
return transformations ;
}
2024-01-06 18:05:21 +01:00
Vector < CSS : : Transformation > StyleProperties : : transformations ( ) const
{
return transformations_for_style_value ( property ( CSS : : PropertyID : : Transform ) ) ;
}
2024-10-16 08:50:35 +02:00
Optional < CSS : : Transformation > StyleProperties : : rotate ( Layout : : Node const & layout_node ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Rotate ) ;
if ( ! value . is_rotation ( ) )
2024-10-16 08:50:35 +02:00
return { } ;
2024-11-03 13:20:04 +01:00
auto & rotation = value . as_rotation ( ) ;
2024-10-16 08:50:35 +02:00
auto resolve_angle = [ & layout_node ] ( CSSStyleValue const & value ) - > Optional < Angle > {
if ( value . is_angle ( ) )
return value . as_angle ( ) . angle ( ) ;
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) & & value . as_calculated ( ) . resolves_to_angle ( ) )
return value . as_calculated ( ) . resolve_angle ( layout_node ) ;
2024-10-16 08:50:35 +02:00
return { } ;
} ;
auto resolve_number = [ & ] ( CSSStyleValue const & value ) - > Optional < double > {
if ( value . is_number ( ) )
return value . as_number ( ) . number ( ) ;
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) & & value . as_calculated ( ) . resolves_to_number ( ) )
return value . as_calculated ( ) . resolve_number ( ) ;
2024-10-16 08:50:35 +02:00
return { } ;
} ;
auto x = resolve_number ( rotation . rotation_x ( ) ) . value_or ( 0 ) ;
auto y = resolve_number ( rotation . rotation_y ( ) ) . value_or ( 0 ) ;
auto z = resolve_number ( rotation . rotation_z ( ) ) . value_or ( 0 ) ;
auto angle = resolve_angle ( rotation . angle ( ) ) . value_or ( Angle : : make_degrees ( 0 ) ) ;
Vector < TransformValue > values ;
values . append ( { Number ( Number : : Type : : Number , x ) } ) ;
values . append ( { Number ( Number : : Type : : Number , y ) } ) ;
values . append ( { Number ( Number : : Type : : Number , z ) } ) ;
values . append ( { angle } ) ;
return CSS : : Transformation ( CSS : : TransformFunction : : Rotate3d , move ( values ) ) ;
}
2024-11-22 16:42:20 +01:00
Optional < CSS : : Transformation > StyleProperties : : translate ( ) const
{
auto const & value = property ( CSS : : PropertyID : : Translate ) ;
if ( ! value . is_translation ( ) )
return { } ;
auto const & translation = value . as_translation ( ) ;
Vector < TransformValue > values ;
values . append ( translation . x ( ) ) ;
values . append ( translation . y ( ) ) ;
return CSS : : Transformation ( CSS : : TransformFunction : : Translate , move ( values ) ) ;
}
2024-11-22 18:07:16 +01:00
Optional < CSS : : Transformation > StyleProperties : : scale ( ) const
{
auto const & value = property ( CSS : : PropertyID : : Scale ) ;
if ( ! value . is_scale ( ) )
return { } ;
auto const & scale = value . as_scale ( ) ;
Vector < TransformValue > values ;
values . append ( scale . x ( ) ) ;
values . append ( scale . y ( ) ) ;
return CSS : : Transformation ( CSS : : TransformFunction : : Scale , move ( values ) ) ;
}
2024-08-14 11:10:54 +01:00
static Optional < LengthPercentage > length_percentage_for_style_value ( CSSStyleValue const & value )
2022-03-21 19:38:00 +01:00
{
if ( value . is_length ( ) )
2023-05-27 12:28:25 +01:00
return value . as_length ( ) . length ( ) ;
2022-03-21 19:38:00 +01:00
if ( value . is_percentage ( ) )
return value . as_percentage ( ) . percentage ( ) ;
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) )
return LengthPercentage { const_cast < CalculatedStyleValue & > ( value . as_calculated ( ) ) } ;
2022-03-21 19:38:00 +01:00
return { } ;
}
2024-01-25 17:02:37 +00:00
Optional < CSS : : TransformBox > StyleProperties : : transform_box ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TransformBox ) ;
return keyword_to_transform_box ( value . to_keyword ( ) ) ;
2024-01-25 17:02:37 +00:00
}
2022-03-21 19:38:00 +01:00
CSS : : TransformOrigin StyleProperties : : transform_origin ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TransformOrigin ) ;
if ( ! value . is_value_list ( ) | | value . as_value_list ( ) . size ( ) ! = 2 )
2022-03-21 19:38:00 +01:00
return { } ;
2024-11-03 13:20:04 +01:00
auto const & list = value . as_value_list ( ) ;
2022-03-21 19:38:00 +01:00
auto x_value = length_percentage_for_style_value ( list . values ( ) [ 0 ] ) ;
auto y_value = length_percentage_for_style_value ( list . values ( ) [ 1 ] ) ;
if ( ! x_value . has_value ( ) | | ! y_value . has_value ( ) ) {
return { } ;
}
return { x_value . value ( ) , y_value . value ( ) } ;
}
2023-03-18 20:49:00 +01:00
Optional < Color > StyleProperties : : accent_color ( Layout : : NodeWithStyle const & node ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : AccentColor ) ;
if ( value . has_color ( ) )
return value . to_color ( node ) ;
2023-03-18 20:49:00 +01:00
return { } ;
}
2022-10-14 13:50:06 +02:00
Optional < CSS : : AlignContent > StyleProperties : : align_content ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : AlignContent ) ;
return keyword_to_align_content ( value . to_keyword ( ) ) ;
2022-10-14 13:50:06 +02:00
}
2021-09-15 18:27:20 +02:00
Optional < CSS : : AlignItems > StyleProperties : : align_items ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : AlignItems ) ;
return keyword_to_align_items ( value . to_keyword ( ) ) ;
2021-09-15 18:27:20 +02:00
}
2022-07-11 23:52:36 +02:00
Optional < CSS : : AlignSelf > StyleProperties : : align_self ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : AlignSelf ) ;
return keyword_to_align_self ( value . to_keyword ( ) ) ;
2022-07-11 23:52:36 +02:00
}
2022-07-22 16:05:11 +01:00
Optional < CSS : : Appearance > StyleProperties : : appearance ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Appearance ) ;
auto appearance = keyword_to_appearance ( value . to_keyword ( ) ) ;
2022-07-22 16:05:11 +01:00
if ( appearance . has_value ( ) ) {
switch ( * appearance ) {
// Note: All these compatibility values can be treated as 'auto'
case CSS : : Appearance : : Textfield :
case CSS : : Appearance : : MenulistButton :
case CSS : : Appearance : : Searchfield :
case CSS : : Appearance : : Textarea :
case CSS : : Appearance : : PushButton :
case CSS : : Appearance : : SliderHorizontal :
case CSS : : Appearance : : Checkbox :
case CSS : : Appearance : : Radio :
case CSS : : Appearance : : SquareButton :
case CSS : : Appearance : : Menulist :
case CSS : : Appearance : : Listbox :
case CSS : : Appearance : : Meter :
case CSS : : Appearance : : ProgressBar :
case CSS : : Appearance : : Button :
appearance = CSS : : Appearance : : Auto ;
break ;
default :
break ;
}
}
return appearance ;
}
2024-10-25 11:00:22 +02:00
CSS : : Filter StyleProperties : : backdrop_filter ( ) const
2022-09-15 08:31:19 +01:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : BackdropFilter ) ;
if ( value . is_filter_value_list ( ) )
return Filter ( value . as_filter_value_list ( ) ) ;
2024-10-25 11:00:22 +02:00
return Filter : : make_none ( ) ;
}
CSS : : Filter StyleProperties : : filter ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Filter ) ;
if ( value . is_filter_value_list ( ) )
return Filter ( value . as_filter_value_list ( ) ) ;
2024-10-25 11:00:22 +02:00
return Filter : : make_none ( ) ;
2022-09-15 08:31:19 +01:00
}
2023-10-27 15:17:36 +02:00
Optional < CSS : : Positioning > StyleProperties : : position ( ) const
2020-03-23 17:29:15 +01:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Position ) ;
return keyword_to_positioning ( value . to_keyword ( ) ) ;
2020-03-23 17:29:15 +01:00
}
2022-04-01 20:58:27 +03:00
bool StyleProperties : : operator = = ( StyleProperties const & other ) const
2019-10-14 18:32:02 +02:00
{
2024-09-10 11:46:32 +02:00
if ( m_data - > m_property_values . size ( ) ! = other . m_data - > m_property_values . size ( ) )
2019-10-14 18:32:02 +02:00
return false ;
2024-09-10 11:46:32 +02:00
for ( size_t i = 0 ; i < m_data - > m_property_values . size ( ) ; + + i ) {
auto const & my_style = m_data - > m_property_values [ i ] ;
auto const & other_style = other . m_data - > m_property_values [ i ] ;
2024-08-02 13:59:19 +02:00
if ( ! my_style ) {
if ( other_style )
2022-02-18 20:21:49 +01:00
return false ;
continue ;
}
2024-08-02 13:59:19 +02:00
if ( ! other_style )
2019-10-14 18:32:02 +02:00
return false ;
2024-08-02 13:59:19 +02:00
auto const & my_value = * my_style ;
auto const & other_value = * other_style ;
2019-10-14 18:32:02 +02:00
if ( my_value . type ( ) ! = other_value . type ( ) )
return false ;
2020-12-14 15:56:01 +01:00
if ( my_value ! = other_value )
2019-10-14 18:32:02 +02:00
return false ;
}
return true ;
}
2020-03-07 10:27:02 +01:00
2023-07-19 19:12:00 +01:00
Optional < CSS : : TextAnchor > StyleProperties : : text_anchor ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TextAnchor ) ;
return keyword_to_text_anchor ( value . to_keyword ( ) ) ;
2023-07-19 19:12:00 +01:00
}
2020-12-14 18:38:02 +01:00
Optional < CSS : : TextAlign > StyleProperties : : text_align ( ) const
2020-06-13 10:54:58 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TextAlign ) ;
return keyword_to_text_align ( value . to_keyword ( ) ) ;
2022-03-12 19:31:32 +00:00
}
Optional < CSS : : TextJustify > StyleProperties : : text_justify ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TextJustify ) ;
return keyword_to_text_justify ( value . to_keyword ( ) ) ;
2020-06-13 10:54:58 +02:00
}
2024-07-24 20:58:17 +02:00
Optional < CSS : : TextOverflow > StyleProperties : : text_overflow ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TextOverflow ) ;
return keyword_to_text_overflow ( value . to_keyword ( ) ) ;
2024-07-24 20:58:17 +02:00
}
2021-10-05 19:47:13 +01:00
Optional < CSS : : PointerEvents > StyleProperties : : pointer_events ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : PointerEvents ) ;
return keyword_to_pointer_events ( value . to_keyword ( ) ) ;
2021-10-05 19:47:13 +01:00
}
2024-10-01 13:07:06 +01:00
Variant < LengthOrCalculated , NumberOrCalculated > StyleProperties : : tab_size ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TabSize ) ;
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) ) {
auto const & math_value = value . as_calculated ( ) ;
2024-10-01 13:07:06 +01:00
if ( math_value . resolves_to_length ( ) ) {
return LengthOrCalculated { math_value } ;
}
if ( math_value . resolves_to_number ( ) ) {
return NumberOrCalculated { math_value } ;
}
}
2024-11-03 13:20:04 +01:00
if ( value . is_length ( ) )
return LengthOrCalculated { value . as_length ( ) . length ( ) } ;
2024-10-01 13:07:06 +01:00
2024-11-03 13:20:04 +01:00
return NumberOrCalculated { value . as_number ( ) . number ( ) } ;
2024-10-01 13:07:06 +01:00
}
2024-10-25 16:47:05 +01:00
Optional < CSS : : WordBreak > StyleProperties : : word_break ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : WordBreak ) ;
return keyword_to_word_break ( value . to_keyword ( ) ) ;
2024-10-25 16:47:05 +01:00
}
2024-10-18 21:00:28 +01:00
Optional < CSS : : LengthOrCalculated > StyleProperties : : word_spacing ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : WordSpacing ) ;
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) ) {
auto & math_value = value . as_calculated ( ) ;
2024-10-18 21:00:28 +01:00
if ( math_value . resolves_to_length ( ) ) {
return LengthOrCalculated { math_value } ;
}
}
2024-11-03 13:20:04 +01:00
if ( value . is_length ( ) )
return LengthOrCalculated { value . as_length ( ) . length ( ) } ;
2024-10-18 21:00:28 +01:00
return { } ;
}
2020-06-24 16:37:44 +02:00
Optional < CSS : : WhiteSpace > StyleProperties : : white_space ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : WhiteSpace ) ;
return keyword_to_white_space ( value . to_keyword ( ) ) ;
2020-06-24 16:37:44 +02:00
}
2024-10-22 14:21:20 +01:00
Optional < LengthOrCalculated > StyleProperties : : letter_spacing ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : LetterSpacing ) ;
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) ) {
auto const & math_value = value . as_calculated ( ) ;
2024-10-22 14:21:20 +01:00
if ( math_value . resolves_to_length ( ) ) {
return LengthOrCalculated { math_value } ;
}
}
2024-11-03 13:20:04 +01:00
if ( value . is_length ( ) )
return LengthOrCalculated { value . as_length ( ) . length ( ) } ;
2024-10-22 14:21:20 +01:00
return { } ;
}
2020-12-04 16:11:55 +01:00
Optional < CSS : : LineStyle > StyleProperties : : line_style ( CSS : : PropertyID property_id ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( property_id ) ;
return keyword_to_line_style ( value . to_keyword ( ) ) ;
2023-08-02 17:24:14 +01:00
}
Optional < CSS : : OutlineStyle > StyleProperties : : outline_style ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : OutlineStyle ) ;
return keyword_to_outline_style ( value . to_keyword ( ) ) ;
2020-12-04 16:11:55 +01:00
}
2020-06-26 15:08:42 +02:00
Optional < CSS : : Float > StyleProperties : : float_ ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Float ) ;
return keyword_to_float ( value . to_keyword ( ) ) ;
2020-06-26 15:08:42 +02:00
}
2020-12-06 01:45:51 +01:00
Optional < CSS : : Clear > StyleProperties : : clear ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Clear ) ;
return keyword_to_clear ( value . to_keyword ( ) ) ;
2020-12-06 01:45:51 +01:00
}
2024-08-20 20:23:55 -04:00
Optional < CSS : : ColumnSpan > StyleProperties : : column_span ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ColumnSpan ) ;
return keyword_to_column_span ( value . to_keyword ( ) ) ;
2024-08-20 20:23:55 -04:00
}
2024-07-18 20:29:02 +01:00
StyleProperties : : ContentDataAndQuoteNestingLevel StyleProperties : : content ( DOM : : Element & element , u32 initial_quote_nesting_level ) const
2022-02-24 16:52:58 +00:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Content ) ;
2023-09-12 14:22:46 +01:00
auto quotes_data = quotes ( ) ;
2023-09-18 15:41:17 +01:00
auto quote_nesting_level = initial_quote_nesting_level ;
2023-09-12 14:22:46 +01:00
auto get_quote_string = [ & ] ( bool open , auto depth ) {
switch ( quotes_data . type ) {
case QuotesData : : Type : : None :
2024-07-17 12:42:12 +01:00
return FlyString { } ;
2023-09-12 14:22:46 +01:00
case QuotesData : : Type : : Auto :
// FIXME: "A typographically appropriate used value for quotes is automatically chosen by the UA
// based on the content language of the element and/or its parent."
if ( open )
2024-07-17 12:42:12 +01:00
return depth = = 0 ? " “ " _fly_string : " ‘ " _fly_string ;
return depth = = 0 ? " ” " _fly_string : " ’ " _fly_string ;
2023-09-12 14:22:46 +01:00
case QuotesData : : Type : : Specified :
2023-09-18 15:28:40 +01:00
// If the depth is greater than the number of pairs, the last pair is repeated.
auto & level = quotes_data . strings [ min ( depth , quotes_data . strings . size ( ) - 1 ) ] ;
2023-09-12 14:22:46 +01:00
return open ? level [ 0 ] : level [ 1 ] ;
}
VERIFY_NOT_REACHED ( ) ;
} ;
2024-11-03 13:20:04 +01:00
if ( value . is_content ( ) ) {
auto & content_style_value = value . as_content ( ) ;
2022-02-24 16:52:58 +00:00
CSS : : ContentData content_data ;
// FIXME: The content is a list of things: strings, identifiers or functions that return strings, and images.
// So it can't always be represented as a single String, but may have to be multiple boxes.
// For now, we'll just assume strings since that is easiest.
StringBuilder builder ;
for ( auto const & item : content_style_value . content ( ) . values ( ) ) {
2023-03-06 14:33:11 +01:00
if ( item - > is_string ( ) ) {
2023-09-12 11:33:11 +01:00
builder . append ( item - > as_string ( ) . string_value ( ) ) ;
2024-08-14 11:46:56 +01:00
} else if ( item - > is_keyword ( ) ) {
2024-08-14 14:06:03 +01:00
switch ( item - > to_keyword ( ) ) {
case Keyword : : OpenQuote :
2023-09-18 15:41:17 +01:00
builder . append ( get_quote_string ( true , quote_nesting_level + + ) ) ;
2023-09-12 14:22:46 +01:00
break ;
2024-08-14 14:06:03 +01:00
case Keyword : : CloseQuote :
2023-09-18 15:41:17 +01:00
// A 'close-quote' or 'no-close-quote' that would make the depth negative is in error and is ignored
// (at rendering time): the depth stays at 0 and no quote mark is rendered (although the rest of the
// 'content' property's value is still inserted).
// - https://www.w3.org/TR/CSS21/generate.html#quotes-insert
// (This is missing from the CONTENT-3 spec.)
if ( quote_nesting_level > 0 )
builder . append ( get_quote_string ( false , - - quote_nesting_level ) ) ;
2023-09-12 14:22:46 +01:00
break ;
2024-08-14 14:06:03 +01:00
case Keyword : : NoOpenQuote :
2023-09-18 15:41:17 +01:00
quote_nesting_level + + ;
2023-09-12 14:22:46 +01:00
break ;
2024-08-14 14:06:03 +01:00
case Keyword : : NoCloseQuote :
2023-09-18 15:41:17 +01:00
// NOTE: See CloseQuote
if ( quote_nesting_level > 0 )
quote_nesting_level - - ;
2023-09-12 14:22:46 +01:00
break ;
default :
2024-12-07 00:59:49 +01:00
dbgln ( " `{}` is not supported in `content` (yet?) " , item - > to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2023-09-12 14:22:46 +01:00
break ;
}
2024-07-18 20:29:02 +01:00
} else if ( item - > is_counter ( ) ) {
builder . append ( item - > as_counter ( ) . resolve ( element ) ) ;
2022-02-24 16:52:58 +00:00
} else {
2024-07-18 20:29:02 +01:00
// TODO: Implement images, and other things.
2024-12-07 00:59:49 +01:00
dbgln ( " `{}` is not supported in `content` (yet?) " , item - > to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2022-02-24 16:52:58 +00:00
}
}
content_data . type = ContentData : : Type : : String ;
2023-09-12 14:22:46 +01:00
content_data . data = MUST ( builder . to_string ( ) ) ;
2022-02-24 16:52:58 +00:00
if ( content_style_value . has_alt_text ( ) ) {
StringBuilder alt_text_builder ;
for ( auto const & item : content_style_value . alt_text ( ) - > values ( ) ) {
2023-03-06 14:33:11 +01:00
if ( item - > is_string ( ) ) {
2023-09-12 11:33:11 +01:00
alt_text_builder . append ( item - > as_string ( ) . string_value ( ) ) ;
2024-07-18 20:29:02 +01:00
} else if ( item - > is_counter ( ) ) {
alt_text_builder . append ( item - > as_counter ( ) . resolve ( element ) ) ;
2022-02-24 16:52:58 +00:00
} else {
2024-12-07 00:59:49 +01:00
dbgln ( " `{}` is not supported in `content` alt-text (yet?) " , item - > to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2022-02-24 16:52:58 +00:00
}
}
2023-09-12 14:22:46 +01:00
content_data . alt_text = MUST ( alt_text_builder . to_string ( ) ) ;
2022-02-24 16:52:58 +00:00
}
2023-09-18 15:41:17 +01:00
return { content_data , quote_nesting_level } ;
2022-02-24 16:52:58 +00:00
}
2024-11-03 13:20:04 +01:00
switch ( value . to_keyword ( ) ) {
2024-08-14 14:06:03 +01:00
case Keyword : : None :
2023-09-18 15:41:17 +01:00
return { { ContentData : : Type : : None } , quote_nesting_level } ;
2024-08-14 14:06:03 +01:00
case Keyword : : Normal :
2023-09-18 15:41:17 +01:00
return { { ContentData : : Type : : Normal } , quote_nesting_level } ;
2022-02-24 16:52:58 +00:00
default :
break ;
}
2023-09-18 15:41:17 +01:00
return { { } , quote_nesting_level } ;
2022-02-24 16:52:58 +00:00
}
2024-06-23 14:52:56 +02:00
Optional < CSS : : ContentVisibility > StyleProperties : : content_visibility ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ContentVisibility ) ;
return keyword_to_content_visibility ( value . to_keyword ( ) ) ;
2024-06-23 14:52:56 +02:00
}
2021-02-21 17:41:00 +00:00
Optional < CSS : : Cursor > StyleProperties : : cursor ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Cursor ) ;
return keyword_to_cursor ( value . to_keyword ( ) ) ;
2021-02-21 17:41:00 +00:00
}
2022-03-21 15:42:57 +01:00
Optional < CSS : : Visibility > StyleProperties : : visibility ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Visibility ) ;
if ( ! value . is_keyword ( ) )
2022-03-21 15:42:57 +01:00
return { } ;
2024-11-03 13:20:04 +01:00
return keyword_to_visibility ( value . to_keyword ( ) ) ;
2022-03-21 15:42:57 +01:00
}
2023-04-26 21:05:38 +02:00
Display StyleProperties : : display ( ) const
2020-06-24 16:22:16 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( PropertyID : : Display ) ;
if ( value . is_display ( ) ) {
return value . as_display ( ) . display ( ) ;
2020-12-14 22:22:35 +01:00
}
2023-04-26 21:05:38 +02:00
return Display : : from_short ( Display : : Short : : Inline ) ;
2020-06-24 16:22:16 +02:00
}
2022-04-14 16:22:35 +01:00
Vector < CSS : : TextDecorationLine > StyleProperties : : text_decoration_line ( ) const
2020-12-15 13:36:27 +01:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TextDecorationLine ) ;
2022-04-14 16:22:35 +01:00
2024-11-03 13:20:04 +01:00
if ( value . is_value_list ( ) ) {
2022-04-14 16:22:35 +01:00
Vector < CSS : : TextDecorationLine > lines ;
2024-11-03 13:20:04 +01:00
auto & values = value . as_value_list ( ) . values ( ) ;
2022-04-14 16:22:35 +01:00
for ( auto const & item : values ) {
2024-08-14 14:06:03 +01:00
lines . append ( keyword_to_text_decoration_line ( item - > to_keyword ( ) ) . value ( ) ) ;
2022-04-14 16:22:35 +01:00
}
return lines ;
}
2024-11-03 13:20:04 +01:00
if ( value . is_keyword ( ) & & value . to_keyword ( ) = = Keyword : : None )
2022-04-14 16:22:35 +01:00
return { } ;
2024-12-07 00:59:49 +01:00
dbgln ( " FIXME: Unsupported value for text-decoration-line: {} " , value . to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2022-11-02 19:07:17 +01:00
return { } ;
2020-12-15 13:36:27 +01:00
}
2022-01-20 20:27:55 +01:00
Optional < CSS : : TextDecorationStyle > StyleProperties : : text_decoration_style ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TextDecorationStyle ) ;
return keyword_to_text_decoration_style ( value . to_keyword ( ) ) ;
2022-01-20 20:27:55 +01:00
}
2020-12-15 14:15:49 +01:00
Optional < CSS : : TextTransform > StyleProperties : : text_transform ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TextTransform ) ;
return keyword_to_text_transform ( value . to_keyword ( ) ) ;
2020-12-15 14:15:49 +01:00
}
2020-12-15 16:50:39 +01:00
Optional < CSS : : ListStyleType > StyleProperties : : list_style_type ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ListStyleType ) ;
return keyword_to_list_style_type ( value . to_keyword ( ) ) ;
2020-12-15 16:50:39 +01:00
}
2023-06-02 23:05:15 +02:00
Optional < CSS : : ListStylePosition > StyleProperties : : list_style_position ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ListStylePosition ) ;
return keyword_to_list_style_position ( value . to_keyword ( ) ) ;
2023-06-02 23:05:15 +02:00
}
2021-02-22 15:20:31 +01:00
Optional < CSS : : Overflow > StyleProperties : : overflow_x ( ) const
{
return overflow ( CSS : : PropertyID : : OverflowX ) ;
}
Optional < CSS : : Overflow > StyleProperties : : overflow_y ( ) const
{
return overflow ( CSS : : PropertyID : : OverflowY ) ;
}
Optional < CSS : : Overflow > StyleProperties : : overflow ( CSS : : PropertyID property_id ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( property_id ) ;
return keyword_to_overflow ( value . to_keyword ( ) ) ;
2021-02-22 15:20:31 +01:00
}
2023-05-31 16:07:06 -04:00
Vector < ShadowData > StyleProperties : : shadow ( PropertyID property_id , Layout : : Node const & layout_node ) const
2021-07-23 21:22:31 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( property_id ) ;
2021-07-23 21:22:31 +02:00
2024-08-14 11:10:54 +01:00
auto resolve_to_length = [ & layout_node ] ( NonnullRefPtr < CSSStyleValue const > const & value ) - > Optional < Length > {
2023-05-31 16:07:06 -04:00
if ( value - > is_length ( ) )
return value - > as_length ( ) . length ( ) ;
2024-12-11 15:05:56 +00:00
if ( value - > is_calculated ( ) )
return value - > as_calculated ( ) . resolve_length ( layout_node ) ;
2023-05-31 16:07:06 -04:00
return { } ;
} ;
2024-08-15 11:06:18 +01:00
auto make_shadow_data = [ resolve_to_length , & layout_node ] ( ShadowStyleValue const & value ) - > Optional < ShadowData > {
2023-05-31 16:07:06 -04:00
auto maybe_offset_x = resolve_to_length ( value . offset_x ( ) ) ;
if ( ! maybe_offset_x . has_value ( ) )
return { } ;
auto maybe_offset_y = resolve_to_length ( value . offset_y ( ) ) ;
if ( ! maybe_offset_y . has_value ( ) )
return { } ;
auto maybe_blur_radius = resolve_to_length ( value . blur_radius ( ) ) ;
if ( ! maybe_blur_radius . has_value ( ) )
return { } ;
auto maybe_spread_distance = resolve_to_length ( value . spread_distance ( ) ) ;
if ( ! maybe_spread_distance . has_value ( ) )
return { } ;
return ShadowData {
maybe_offset_x . release_value ( ) ,
maybe_offset_y . release_value ( ) ,
maybe_blur_radius . release_value ( ) ,
maybe_spread_distance . release_value ( ) ,
2024-11-11 13:51:09 +04:00
value . color ( ) - > to_color ( verify_cast < Layout : : NodeWithStyle > ( layout_node ) ) ,
2023-05-31 16:07:06 -04:00
value . placement ( )
} ;
2022-02-08 14:48:37 +00:00
} ;
2024-11-03 13:20:04 +01:00
if ( value . is_value_list ( ) ) {
auto const & value_list = value . as_value_list ( ) ;
2022-02-08 14:48:37 +00:00
2022-03-23 21:16:36 +00:00
Vector < ShadowData > shadow_data ;
shadow_data . ensure_capacity ( value_list . size ( ) ) ;
2023-05-31 16:07:06 -04:00
for ( auto const & layer_value : value_list . values ( ) ) {
auto maybe_shadow_data = make_shadow_data ( layer_value - > as_shadow ( ) ) ;
if ( ! maybe_shadow_data . has_value ( ) )
return { } ;
shadow_data . append ( maybe_shadow_data . release_value ( ) ) ;
}
2022-02-08 14:48:37 +00:00
2022-03-23 21:16:36 +00:00
return shadow_data ;
2022-02-08 14:48:37 +00:00
}
2024-11-03 13:20:04 +01:00
if ( value . is_shadow ( ) ) {
auto maybe_shadow_data = make_shadow_data ( value . as_shadow ( ) ) ;
2023-05-31 16:07:06 -04:00
if ( ! maybe_shadow_data . has_value ( ) )
return { } ;
return { maybe_shadow_data . release_value ( ) } ;
2022-02-08 14:48:37 +00:00
}
return { } ;
2021-07-23 21:22:31 +02:00
}
2021-10-05 16:55:02 +01:00
2023-05-31 16:07:06 -04:00
Vector < ShadowData > StyleProperties : : box_shadow ( Layout : : Node const & layout_node ) const
2022-03-23 21:16:36 +00:00
{
2023-05-31 16:07:06 -04:00
return shadow ( PropertyID : : BoxShadow , layout_node ) ;
2022-03-23 21:16:36 +00:00
}
2023-05-31 16:07:06 -04:00
Vector < ShadowData > StyleProperties : : text_shadow ( Layout : : Node const & layout_node ) const
2022-03-23 21:16:36 +00:00
{
2023-05-31 16:07:06 -04:00
return shadow ( PropertyID : : TextShadow , layout_node ) ;
2022-03-23 21:16:36 +00:00
}
2022-04-13 19:33:56 +01:00
Optional < CSS : : BoxSizing > StyleProperties : : box_sizing ( ) const
2021-10-05 16:55:02 +01:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : BoxSizing ) ;
return keyword_to_box_sizing ( value . to_keyword ( ) ) ;
2021-10-05 16:55:02 +01:00
}
2022-02-26 01:34:07 +01:00
Variant < CSS : : VerticalAlign , CSS : : LengthPercentage > StyleProperties : : vertical_align ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : VerticalAlign ) ;
2022-02-26 01:34:07 +01:00
2024-11-03 13:20:04 +01:00
if ( value . is_keyword ( ) )
return keyword_to_vertical_align ( value . to_keyword ( ) ) . release_value ( ) ;
2022-02-26 01:34:07 +01:00
2024-11-03 13:20:04 +01:00
if ( value . is_length ( ) )
return CSS : : LengthPercentage ( value . as_length ( ) . length ( ) ) ;
2022-02-26 01:34:07 +01:00
2024-11-03 13:20:04 +01:00
if ( value . is_percentage ( ) )
return CSS : : LengthPercentage ( value . as_percentage ( ) . percentage ( ) ) ;
2022-02-26 01:34:07 +01:00
2024-12-11 15:05:56 +00:00
if ( value . is_calculated ( ) )
return LengthPercentage { const_cast < CalculatedStyleValue & > ( value . as_calculated ( ) ) } ;
2023-06-17 00:09:41 +02:00
2022-02-26 01:34:07 +01:00
VERIFY_NOT_REACHED ( ) ;
}
2024-09-27 17:11:05 +01:00
Optional < FlyString > StyleProperties : : font_language_override ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FontLanguageOverride ) ;
if ( value . is_string ( ) )
return value . as_string ( ) . string_value ( ) ;
2024-09-27 17:11:05 +01:00
return { } ;
}
2024-12-05 01:19:03 +01:00
Optional < Gfx : : FontVariantAlternates > StyleProperties : : font_variant_alternates ( ) const
{
auto const & value = property ( CSS : : PropertyID : : FontVariantAlternates ) ;
return value . to_font_variant_alternates ( ) ;
}
Optional < FontVariantCaps > StyleProperties : : font_variant_caps ( ) const
{
auto const & value = property ( CSS : : PropertyID : : FontVariantCaps ) ;
return value . to_font_variant_caps ( ) ;
}
Optional < Gfx : : FontVariantEastAsian > StyleProperties : : font_variant_east_asian ( ) const
{
auto const & value = property ( CSS : : PropertyID : : FontVariantEastAsian ) ;
return value . to_font_variant_east_asian ( ) ;
}
Optional < FontVariantEmoji > StyleProperties : : font_variant_emoji ( ) const
{
auto const & value = property ( CSS : : PropertyID : : FontVariantEmoji ) ;
return value . to_font_variant_emoji ( ) ;
}
Optional < Gfx : : FontVariantLigatures > StyleProperties : : font_variant_ligatures ( ) const
{
auto const & value = property ( CSS : : PropertyID : : FontVariantLigatures ) ;
return value . to_font_variant_ligatures ( ) ;
}
Optional < Gfx : : FontVariantNumeric > StyleProperties : : font_variant_numeric ( ) const
{
auto const & value = property ( CSS : : PropertyID : : FontVariantNumeric ) ;
return value . to_font_variant_numeric ( ) ;
}
Optional < FontVariantPosition > StyleProperties : : font_variant_position ( ) const
{
auto const & value = property ( CSS : : PropertyID : : FontVariantPosition ) ;
return value . to_font_variant_position ( ) ;
}
2024-10-01 09:37:43 +01:00
Optional < HashMap < FlyString , IntegerOrCalculated > > StyleProperties : : font_feature_settings ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( PropertyID : : FontFeatureSettings ) ;
2024-10-01 09:37:43 +01:00
2024-11-03 13:20:04 +01:00
if ( value . is_keyword ( ) )
2024-10-01 09:37:43 +01:00
return { } ; // normal
2024-11-03 13:20:04 +01:00
if ( value . is_value_list ( ) ) {
auto const & feature_tags = value . as_value_list ( ) . values ( ) ;
2024-10-01 09:37:43 +01:00
HashMap < FlyString , IntegerOrCalculated > result ;
result . ensure_capacity ( feature_tags . size ( ) ) ;
for ( auto const & tag_value : feature_tags ) {
auto const & feature_tag = tag_value - > as_open_type_tagged ( ) ;
if ( feature_tag . value ( ) - > is_integer ( ) ) {
result . set ( feature_tag . tag ( ) , feature_tag . value ( ) - > as_integer ( ) . value ( ) ) ;
} else {
2024-12-11 15:05:56 +00:00
VERIFY ( feature_tag . value ( ) - > is_calculated ( ) ) ;
result . set ( feature_tag . tag ( ) , IntegerOrCalculated { feature_tag . value ( ) - > as_calculated ( ) } ) ;
2024-10-01 09:37:43 +01:00
}
}
return result ;
}
return { } ;
}
2024-10-01 09:20:06 +01:00
Optional < HashMap < FlyString , NumberOrCalculated > > StyleProperties : : font_variation_settings ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : FontVariationSettings ) ;
2024-10-01 09:20:06 +01:00
2024-11-03 13:20:04 +01:00
if ( value . is_keyword ( ) )
2024-10-01 09:20:06 +01:00
return { } ; // normal
2024-11-03 13:20:04 +01:00
if ( value . is_value_list ( ) ) {
auto const & axis_tags = value . as_value_list ( ) . values ( ) ;
2024-10-01 09:20:06 +01:00
HashMap < FlyString , NumberOrCalculated > result ;
result . ensure_capacity ( axis_tags . size ( ) ) ;
for ( auto const & tag_value : axis_tags ) {
auto const & axis_tag = tag_value - > as_open_type_tagged ( ) ;
if ( axis_tag . value ( ) - > is_number ( ) ) {
result . set ( axis_tag . tag ( ) , axis_tag . value ( ) - > as_number ( ) . value ( ) ) ;
} else {
2024-12-11 15:05:56 +00:00
VERIFY ( axis_tag . value ( ) - > is_calculated ( ) ) ;
result . set ( axis_tag . tag ( ) , NumberOrCalculated { axis_tag . value ( ) - > as_calculated ( ) } ) ;
2024-10-01 09:20:06 +01:00
}
}
return result ;
}
return { } ;
}
2023-05-21 18:08:41 +03:00
CSS : : GridTrackSizeList StyleProperties : : grid_auto_columns ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridAutoColumns ) ;
return value . as_grid_track_size_list ( ) . grid_track_size_list ( ) ;
2023-05-21 18:08:41 +03:00
}
CSS : : GridTrackSizeList StyleProperties : : grid_auto_rows ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridAutoRows ) ;
return value . as_grid_track_size_list ( ) . grid_track_size_list ( ) ;
2023-05-21 18:08:41 +03:00
}
2022-10-30 13:27:57 +01:00
CSS : : GridTrackSizeList StyleProperties : : grid_template_columns ( ) const
2022-08-23 19:49:07 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridTemplateColumns ) ;
return value . as_grid_track_size_list ( ) . grid_track_size_list ( ) ;
2022-08-23 19:49:07 +02:00
}
2022-10-30 13:27:57 +01:00
CSS : : GridTrackSizeList StyleProperties : : grid_template_rows ( ) const
2022-08-23 19:49:07 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridTemplateRows ) ;
return value . as_grid_track_size_list ( ) . grid_track_size_list ( ) ;
2022-08-23 19:49:07 +02:00
}
2023-08-17 20:25:18 +02:00
CSS : : GridAutoFlow StyleProperties : : grid_auto_flow ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridAutoFlow ) ;
if ( ! value . is_grid_auto_flow ( ) )
2023-08-17 20:25:18 +02:00
return CSS : : GridAutoFlow { } ;
2024-11-03 13:20:04 +01:00
auto & grid_auto_flow_value = value . as_grid_auto_flow ( ) ;
2023-08-17 20:25:18 +02:00
return CSS : : GridAutoFlow { . row = grid_auto_flow_value . is_row ( ) , . dense = grid_auto_flow_value . is_dense ( ) } ;
}
2022-08-23 19:58:00 +02:00
CSS : : GridTrackPlacement StyleProperties : : grid_column_end ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridColumnEnd ) ;
return value . as_grid_track_placement ( ) . grid_track_placement ( ) ;
2022-08-23 19:58:00 +02:00
}
CSS : : GridTrackPlacement StyleProperties : : grid_column_start ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridColumnStart ) ;
return value . as_grid_track_placement ( ) . grid_track_placement ( ) ;
2022-08-23 19:58:00 +02:00
}
CSS : : GridTrackPlacement StyleProperties : : grid_row_end ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridRowEnd ) ;
return value . as_grid_track_placement ( ) . grid_track_placement ( ) ;
2022-08-23 19:58:00 +02:00
}
CSS : : GridTrackPlacement StyleProperties : : grid_row_start ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridRowStart ) ;
return value . as_grid_track_placement ( ) . grid_track_placement ( ) ;
2022-08-23 19:58:00 +02:00
}
2023-01-02 23:01:29 +01:00
Optional < CSS : : BorderCollapse > StyleProperties : : border_collapse ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : BorderCollapse ) ;
return keyword_to_border_collapse ( value . to_keyword ( ) ) ;
2023-01-02 23:01:29 +01:00
}
2023-01-16 18:17:05 +01:00
Vector < Vector < String > > StyleProperties : : grid_template_areas ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : GridTemplateAreas ) ;
return value . as_grid_template_area ( ) . grid_template_area ( ) ;
2023-01-16 18:17:05 +01:00
}
2023-08-01 20:06:50 +02:00
Optional < CSS : : ObjectFit > StyleProperties : : object_fit ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ObjectFit ) ;
return keyword_to_object_fit ( value . to_keyword ( ) ) ;
2023-08-01 20:06:50 +02:00
}
2024-02-26 11:33:54 +01:00
CSS : : ObjectPosition StyleProperties : : object_position ( ) const
2023-10-16 13:52:51 +02:00
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ObjectPosition ) ;
auto const & position = value . as_position ( ) ;
2024-02-26 11:33:54 +01:00
CSS : : ObjectPosition object_position ;
auto const & edge_x = position . edge_x ( ) ;
auto const & edge_y = position . edge_y ( ) ;
if ( edge_x - > is_edge ( ) ) {
auto const & edge = edge_x - > as_edge ( ) ;
2024-11-29 22:44:14 +11:00
object_position . edge_x = edge . edge ( ) . value_or ( PositionEdge : : Left ) ;
2024-02-26 11:33:54 +01:00
object_position . offset_x = edge . offset ( ) ;
}
if ( edge_y - > is_edge ( ) ) {
auto const & edge = edge_y - > as_edge ( ) ;
2024-11-29 22:44:14 +11:00
object_position . edge_y = edge . edge ( ) . value_or ( PositionEdge : : Top ) ;
2024-02-26 11:33:54 +01:00
object_position . offset_y = edge . offset ( ) ;
}
return object_position ;
2023-10-16 13:52:51 +02:00
}
2023-08-07 01:32:52 +00:00
Optional < CSS : : TableLayout > StyleProperties : : table_layout ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : TableLayout ) ;
return keyword_to_table_layout ( value . to_keyword ( ) ) ;
2023-08-07 01:32:52 +00:00
}
2024-08-10 23:13:26 +01:00
Optional < CSS : : Direction > StyleProperties : : direction ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Direction ) ;
return keyword_to_direction ( value . to_keyword ( ) ) ;
2024-08-10 23:13:26 +01:00
}
2024-10-03 21:09:29 +02:00
Optional < CSS : : UnicodeBidi > StyleProperties : : unicode_bidi ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : UnicodeBidi ) ;
return keyword_to_unicode_bidi ( value . to_keyword ( ) ) ;
2024-10-03 21:09:29 +02:00
}
2024-10-27 22:12:54 +00:00
Optional < CSS : : WritingMode > StyleProperties : : writing_mode ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : WritingMode ) ;
return keyword_to_writing_mode ( value . to_keyword ( ) ) ;
2024-10-27 22:12:54 +00:00
}
2023-10-08 11:06:34 +01:00
Optional < CSS : : MaskType > StyleProperties : : mask_type ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : MaskType ) ;
return keyword_to_mask_type ( value . to_keyword ( ) ) ;
2023-10-08 11:06:34 +01:00
}
2023-04-19 18:51:00 +01:00
Color StyleProperties : : stop_color ( ) const
{
2024-11-03 13:20:04 +01:00
NonnullRawPtr < CSSStyleValue const > value = property ( CSS : : PropertyID : : StopColor ) ;
2024-08-14 11:46:56 +01:00
if ( value - > is_keyword ( ) ) {
2023-07-28 22:24:36 +01:00
// Workaround lack of layout node to resolve current color.
2024-11-03 13:20:04 +01:00
auto const & keyword = value - > as_keyword ( ) ;
2024-08-14 14:06:03 +01:00
if ( keyword . keyword ( ) = = CSS : : Keyword : : Currentcolor )
2023-07-28 22:24:36 +01:00
value = property ( CSS : : PropertyID : : Color ) ;
}
2023-04-19 18:51:00 +01:00
if ( value - > has_color ( ) ) {
// FIXME: This is used by the SVGStopElement, which does not participate in layout,
2023-07-28 22:24:36 +01:00
// so can't pass a layout node (so can't resolve some colors, e.g. palette ones)
2023-04-19 18:51:00 +01:00
return value - > to_color ( { } ) ;
}
return Color : : Black ;
}
2023-09-07 15:29:54 +01:00
void StyleProperties : : set_math_depth ( int math_depth )
{
2024-09-10 11:46:32 +02:00
m_data - > m_math_depth = math_depth ;
2023-09-07 15:29:54 +01:00
// Make our children inherit our computed value, not our specified value.
set_property ( PropertyID : : MathDepth , MathDepthStyleValue : : create_integer ( IntegerStyleValue : : create ( math_depth ) ) ) ;
}
2023-09-12 11:34:26 +01:00
QuotesData StyleProperties : : quotes ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : Quotes ) ;
if ( value . is_keyword ( ) ) {
switch ( value . to_keyword ( ) ) {
2024-08-14 14:06:03 +01:00
case Keyword : : Auto :
2023-09-12 11:34:26 +01:00
return QuotesData { . type = QuotesData : : Type : : Auto } ;
2024-08-14 14:06:03 +01:00
case Keyword : : None :
2023-09-12 11:34:26 +01:00
return QuotesData { . type = QuotesData : : Type : : None } ;
default :
break ;
}
}
2024-11-03 13:20:04 +01:00
if ( value . is_value_list ( ) ) {
auto & value_list = value . as_value_list ( ) ;
2023-09-12 11:34:26 +01:00
QuotesData quotes_data { . type = QuotesData : : Type : : Specified } ;
VERIFY ( value_list . size ( ) % 2 = = 0 ) ;
for ( auto i = 0u ; i < value_list . size ( ) ; i + = 2 ) {
quotes_data . strings . empend (
value_list . value_at ( i , false ) - > as_string ( ) . string_value ( ) ,
value_list . value_at ( i + 1 , false ) - > as_string ( ) . string_value ( ) ) ;
}
return quotes_data ;
}
return InitialValues : : quotes ( ) ;
}
2024-07-24 15:47:11 +01:00
Vector < CounterData > StyleProperties : : counter_data ( PropertyID property_id ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( property_id ) ;
2024-07-24 15:47:11 +01:00
2024-11-03 13:20:04 +01:00
if ( value . is_counter_definitions ( ) ) {
auto & counter_definitions = value . as_counter_definitions ( ) . counter_definitions ( ) ;
2024-07-24 15:47:11 +01:00
Vector < CounterData > result ;
for ( auto & counter : counter_definitions ) {
CounterData data {
. name = counter . name ,
. is_reversed = counter . is_reversed ,
. value = { } ,
} ;
if ( counter . value ) {
if ( counter . value - > is_integer ( ) ) {
data . value = AK : : clamp_to < i32 > ( counter . value - > as_integer ( ) . integer ( ) ) ;
2024-12-11 15:05:56 +00:00
} else if ( counter . value - > is_calculated ( ) ) {
auto maybe_int = counter . value - > as_calculated ( ) . resolve_integer ( ) ;
2024-07-24 15:47:11 +01:00
if ( maybe_int . has_value ( ) )
data . value = AK : : clamp_to < i32 > ( * maybe_int ) ;
} else {
2024-12-07 00:59:49 +01:00
dbgln ( " Unimplemented type for {} integer value: '{}' " , string_from_property_id ( property_id ) , counter . value - > to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2024-07-24 15:47:11 +01:00
}
}
result . append ( move ( data ) ) ;
}
return result ;
}
2024-11-03 13:20:04 +01:00
if ( value . to_keyword ( ) = = Keyword : : None )
2024-07-24 15:47:11 +01:00
return { } ;
2024-12-07 00:59:49 +01:00
dbgln ( " Unhandled type for {} value: '{}' " , string_from_property_id ( property_id ) , value . to_string ( CSSStyleValue : : SerializationMode : : Normal ) ) ;
2024-07-24 15:47:11 +01:00
return { } ;
}
2024-02-27 09:37:18 +01:00
Optional < CSS : : ScrollbarWidth > StyleProperties : : scrollbar_width ( ) const
{
2024-11-03 13:20:04 +01:00
auto const & value = property ( CSS : : PropertyID : : ScrollbarWidth ) ;
return keyword_to_scrollbar_width ( value . to_keyword ( ) ) ;
2024-02-27 09:37:18 +01:00
}
2020-03-07 10:27:02 +01:00
}