2021-09-12 15:05:29 -03:00
/*
2023-02-20 14:56:08 -03:00
* Copyright ( c ) 2021 - 2023 , Andreas Kling < kling @ serenityos . org >
2021-09-13 14:54:54 -03:00
* Copyright ( c ) 2021 , Tobias Christiansen < tobyase @ serenityos . org >
2023-03-23 14:44:13 -03:00
* Copyright ( c ) 2022 - 2023 , Sam Atkins < atkinssj @ serenityos . org >
2021-09-12 15:05:29 -03:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2022-02-06 10:17:42 -03:00
# include <AK/Debug.h>
2022-12-06 03:08:20 -03:00
# include <AK/Format.h>
2021-09-13 19:38:46 -03:00
# include <AK/NonnullRefPtr.h>
2022-04-13 16:05:56 -03:00
# include <LibWeb/CSS/Enums.h>
2021-09-23 07:35:56 -03:00
# include <LibWeb/CSS/ResolvedCSSStyleDeclaration.h>
2021-09-24 08:49:57 -03:00
# include <LibWeb/CSS/StyleComputer.h>
2023-03-23 14:44:13 -03:00
# include <LibWeb/CSS/StyleValues/BackgroundRepeatStyleValue.h>
2023-05-27 11:50:17 -03:00
# include <LibWeb/CSS/StyleValues/BackgroundSizeStyleValue.h>
2023-03-24 21:33:20 -03:00
# include <LibWeb/CSS/StyleValues/BorderRadiusStyleValue.h>
2023-03-30 13:34:14 -03:00
# include <LibWeb/CSS/StyleValues/CalculatedStyleValue.h>
2023-03-23 18:12:15 -03:00
# include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
2023-04-02 20:04:00 -03:00
# include <LibWeb/CSS/StyleValues/EdgeStyleValue.h>
2023-03-24 11:53:08 -03:00
# include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
2023-04-29 12:59:07 -03:00
# include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
2023-03-24 12:04:24 -03:00
# include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h>
2023-03-24 13:55:44 -03:00
# include <LibWeb/CSS/StyleValues/InitialStyleValue.h>
2023-06-01 13:10:28 -03:00
# include <LibWeb/CSS/StyleValues/IntegerStyleValue.h>
2023-03-24 14:04:04 -03:00
# include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
2023-06-01 12:16:15 -03:00
# include <LibWeb/CSS/StyleValues/NumberStyleValue.h>
2023-03-24 14:28:43 -03:00
# include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
2023-03-24 14:35:31 -03:00
# include <LibWeb/CSS/StyleValues/PositionStyleValue.h>
2023-06-08 11:25:16 -03:00
# include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
2023-03-24 21:02:50 -03:00
# include <LibWeb/CSS/StyleValues/RectStyleValue.h>
2023-03-24 14:45:25 -03:00
# include <LibWeb/CSS/StyleValues/ShadowStyleValue.h>
2023-09-19 11:27:13 -03:00
# include <LibWeb/CSS/StyleValues/ShorthandStyleValue.h>
2023-03-24 21:12:21 -03:00
# include <LibWeb/CSS/StyleValues/StyleValueList.h>
2023-05-27 17:05:48 -03:00
# include <LibWeb/CSS/StyleValues/TimeStyleValue.h>
2023-03-24 14:59:33 -03:00
# include <LibWeb/CSS/StyleValues/TransformationStyleValue.h>
2023-06-15 12:52:45 -03:00
# include <LibWeb/CSS/StyleValues/URLStyleValue.h>
2021-09-12 15:05:29 -03:00
# include <LibWeb/DOM/Document.h>
# include <LibWeb/DOM/Element.h>
2023-02-25 07:04:29 -03:00
# include <LibWeb/Layout/Viewport.h>
2022-07-19 12:44:24 -03:00
# include <LibWeb/Painting/PaintableBox.h>
# include <LibWeb/Painting/StackingContext.h>
2023-08-19 03:38:51 -03:00
# include <LibWeb/Painting/ViewportPaintable.h>
2021-09-12 15:05:29 -03:00
namespace Web : : CSS {
2023-08-13 08:05:26 -03:00
JS : : NonnullGCPtr < ResolvedCSSStyleDeclaration > ResolvedCSSStyleDeclaration : : create ( DOM : : Element & element )
2022-08-07 11:21:26 -03:00
{
2023-08-13 08:05:26 -03:00
return element . realm ( ) . heap ( ) . allocate < ResolvedCSSStyleDeclaration > ( element . realm ( ) , element ) ;
2022-08-07 11:21:26 -03:00
}
2021-09-23 07:35:56 -03:00
ResolvedCSSStyleDeclaration : : ResolvedCSSStyleDeclaration ( DOM : : Element & element )
2022-09-24 19:34:04 -03:00
: CSSStyleDeclaration ( element . realm ( ) )
2022-08-07 11:21:26 -03:00
, m_element ( element )
2021-09-12 15:05:29 -03:00
{
}
2022-08-28 08:42:07 -03:00
void ResolvedCSSStyleDeclaration : : visit_edges ( Cell : : Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_element . ptr ( ) ) ;
}
2021-09-23 07:35:56 -03:00
size_t ResolvedCSSStyleDeclaration : : length ( ) const
2021-09-12 15:05:29 -03:00
{
return 0 ;
}
2023-09-06 04:07:24 -03:00
String ResolvedCSSStyleDeclaration : : item ( size_t index ) const
2021-09-12 15:05:29 -03:00
{
( void ) index ;
return { } ;
}
2023-08-19 11:45:00 -03:00
static NonnullRefPtr < StyleValue const > style_value_for_background_property ( Layout : : NodeWithStyle const & layout_node , Function < NonnullRefPtr < StyleValue const > ( BackgroundLayerData const & ) > callback , Function < NonnullRefPtr < StyleValue const > ( ) > default_value )
2023-03-30 18:26:28 -03:00
{
auto const & background_layers = layout_node . background_layers ( ) ;
if ( background_layers . is_empty ( ) )
return default_value ( ) ;
if ( background_layers . size ( ) = = 1 )
return callback ( background_layers . first ( ) ) ;
StyleValueVector values ;
2023-08-19 11:45:00 -03:00
values . ensure_capacity ( background_layers . size ( ) ) ;
2023-03-30 18:26:28 -03:00
for ( auto const & layer : background_layers )
2023-08-19 11:45:00 -03:00
values . unchecked_append ( callback ( layer ) ) ;
2023-05-02 10:52:31 -03:00
return StyleValueList : : create ( move ( values ) , StyleValueList : : Separator : : Comma ) ;
2023-03-30 18:26:28 -03:00
}
2023-08-19 10:00:10 -03:00
static NonnullRefPtr < StyleValue const > style_value_for_length_percentage ( LengthPercentage const & length_percentage )
2022-01-19 08:52:01 -03:00
{
2023-04-19 07:20:50 -03:00
if ( length_percentage . is_auto ( ) )
2023-05-02 10:52:31 -03:00
return IdentifierStyleValue : : create ( ValueID : : Auto ) ;
2022-01-19 08:52:01 -03:00
if ( length_percentage . is_percentage ( ) )
2023-05-02 10:52:31 -03:00
return PercentageStyleValue : : create ( length_percentage . percentage ( ) ) ;
2022-04-03 17:05:03 -03:00
if ( length_percentage . is_length ( ) )
2023-05-02 10:52:31 -03:00
return LengthStyleValue : : create ( length_percentage . length ( ) ) ;
2022-04-03 17:05:03 -03:00
return length_percentage . calculated ( ) ;
2022-01-19 08:52:01 -03:00
}
2023-08-19 10:00:10 -03:00
static NonnullRefPtr < StyleValue const > style_value_for_size ( Size const & size )
2022-09-25 10:48:23 -03:00
{
if ( size . is_none ( ) )
2023-05-02 10:52:31 -03:00
return IdentifierStyleValue : : create ( ValueID : : None ) ;
2022-09-25 10:48:23 -03:00
if ( size . is_percentage ( ) )
2023-05-02 10:52:31 -03:00
return PercentageStyleValue : : create ( size . percentage ( ) ) ;
2022-09-25 10:48:23 -03:00
if ( size . is_length ( ) )
2023-05-02 10:52:31 -03:00
return LengthStyleValue : : create ( size . length ( ) ) ;
2022-09-25 10:48:23 -03:00
if ( size . is_auto ( ) )
2023-05-02 10:52:31 -03:00
return IdentifierStyleValue : : create ( ValueID : : Auto ) ;
2023-03-30 06:50:40 -03:00
if ( size . is_calculated ( ) )
return size . calculated ( ) ;
2022-09-25 10:48:23 -03:00
if ( size . is_min_content ( ) )
2023-05-02 10:52:31 -03:00
return IdentifierStyleValue : : create ( ValueID : : MinContent ) ;
2022-09-25 10:48:23 -03:00
if ( size . is_max_content ( ) )
2023-05-02 10:52:31 -03:00
return IdentifierStyleValue : : create ( ValueID : : MaxContent ) ;
2022-09-25 10:48:23 -03:00
// FIXME: Support fit-content(<length>)
2023-08-30 06:53:50 -03:00
if ( size . is_fit_content ( ) )
return IdentifierStyleValue : : create ( ValueID : : FitContent ) ;
2022-09-25 10:48:23 -03:00
TODO ( ) ;
}
2023-08-19 10:00:10 -03:00
static NonnullRefPtr < StyleValue const > style_value_for_sided_shorthand ( ValueComparingNonnullRefPtr < StyleValue const > top , ValueComparingNonnullRefPtr < StyleValue const > right , ValueComparingNonnullRefPtr < StyleValue const > bottom , ValueComparingNonnullRefPtr < StyleValue const > left )
2023-05-27 12:24:33 -03:00
{
bool top_and_bottom_same = top = = bottom ;
bool left_and_right_same = left = = right ;
if ( top_and_bottom_same & & left_and_right_same & & top = = left )
return top ;
if ( top_and_bottom_same & & left_and_right_same )
return StyleValueList : : create ( StyleValueVector { move ( top ) , move ( right ) } , StyleValueList : : Separator : : Space ) ;
if ( left_and_right_same )
return StyleValueList : : create ( StyleValueVector { move ( top ) , move ( right ) , move ( bottom ) } , StyleValueList : : Separator : : Space ) ;
return StyleValueList : : create ( StyleValueVector { move ( top ) , move ( right ) , move ( bottom ) , move ( left ) } , StyleValueList : : Separator : : Space ) ;
}
2023-08-19 11:45:00 -03:00
RefPtr < StyleValue const > ResolvedCSSStyleDeclaration : : style_value_for_property ( Layout : : NodeWithStyle const & layout_node , PropertyID property_id ) const
2021-09-12 15:05:29 -03:00
{
2023-09-09 08:04:40 -03:00
// A limited number of properties have special rules for producing their "resolved value".
// We also have to manually construct shorthands from their longhands here.
// Everything else uses the computed value.
// https://www.w3.org/TR/cssom-1/#resolved-values
2023-09-29 09:58:01 -03:00
// The resolved value for a given longhand property can be determined as follows:
2021-09-12 15:05:29 -03:00
switch ( property_id ) {
2023-09-29 09:58:01 -03:00
// -> background-color
// FIXME: -> border-block-end-color
// FIXME: -> border-block-start-color
// -> border-bottom-color
// FIXME: -> border-inline-end-color
// FIXME: -> border-inline-start-color
// -> border-left-color
// -> border-right-color
// -> border-top-color
// FIXME: -> box-shadow
// FIXME: -> caret-color
// -> color
// -> outline-color
// -> A resolved value special case property like color defined in another specification
// The resolved value is the used value.
2022-07-14 13:04:03 -03:00
case PropertyID : : BackgroundColor :
2023-05-02 10:52:31 -03:00
return ColorStyleValue : : create ( layout_node . computed_values ( ) . background_color ( ) ) ;
2023-09-29 09:58:01 -03:00
case PropertyID : : BorderBottomColor :
return ColorStyleValue : : create ( layout_node . computed_values ( ) . border_bottom ( ) . color ) ;
case PropertyID : : BorderLeftColor :
return ColorStyleValue : : create ( layout_node . computed_values ( ) . border_left ( ) . color ) ;
case PropertyID : : BorderRightColor :
return ColorStyleValue : : create ( layout_node . computed_values ( ) . border_right ( ) . color ) ;
case PropertyID : : BorderTopColor :
return ColorStyleValue : : create ( layout_node . computed_values ( ) . border_top ( ) . color ) ;
case PropertyID : : Color :
return ColorStyleValue : : create ( layout_node . computed_values ( ) . color ( ) ) ;
case PropertyID : : OutlineColor :
return ColorStyleValue : : create ( layout_node . computed_values ( ) . outline_color ( ) ) ;
case PropertyID : : TextDecorationColor :
return ColorStyleValue : : create ( layout_node . computed_values ( ) . text_decoration_color ( ) ) ;
// FIXME: -> line-height
// The resolved value is normal if the computed value is normal, or the used value otherwise.
// FIXME: -> block-size
// -> height
// FIXME: -> inline-size
// FIXME: -> margin-block-end
// FIXME: -> margin-block-start
// -> margin-bottom
// FIXME: -> margin-inline-end
// FIXME: -> margin-inline-start
// -> margin-left
// -> margin-right
// -> margin-top
// FIXME: -> padding-block-end
// FIXME: -> padding-block-start
// -> padding-bottom
// FIXME: -> padding-inline-end
// FIXME: -> padding-inline-start
// -> padding-left
// -> padding-right
// -> padding-top
2023-09-29 09:02:11 -03:00
// -> width
2023-09-29 09:58:01 -03:00
// -> A resolved value special case property like height defined in another specification
// FIXME: If the property applies to the element or pseudo-element and the resolved value of the
// display property is not none or contents, then the resolved value is the used value.
// Otherwise the resolved value is the computed value.
case PropertyID : : Height :
return style_value_for_size ( layout_node . computed_values ( ) . height ( ) ) ;
case PropertyID : : MarginBottom :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . margin ( ) . bottom ( ) ) ;
case PropertyID : : MarginLeft :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . margin ( ) . left ( ) ) ;
case PropertyID : : MarginRight :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . margin ( ) . right ( ) ) ;
case PropertyID : : MarginTop :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . margin ( ) . top ( ) ) ;
case PropertyID : : PaddingBottom :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . padding ( ) . bottom ( ) ) ;
case PropertyID : : PaddingLeft :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . padding ( ) . left ( ) ) ;
case PropertyID : : PaddingRight :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . padding ( ) . right ( ) ) ;
case PropertyID : : PaddingTop :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . padding ( ) . top ( ) ) ;
case PropertyID : : Width :
return style_value_for_size ( layout_node . computed_values ( ) . width ( ) ) ;
// -> bottom
// -> left
// FIXME: -> inset-block-end
// FIXME: -> inset-block-start
// FIXME: -> inset-inline-end
// FIXME: -> inset-inline-start
// -> right
// -> top
// -> A resolved value special case property like top defined in another specification
// FIXME: If the property applies to a positioned element and the resolved value of the display property is not
// none or contents, and the property is not over-constrained, then the resolved value is the used value.
// Otherwise the resolved value is the computed value.
case PropertyID : : Bottom :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . inset ( ) . bottom ( ) ) ;
case PropertyID : : Left :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . inset ( ) . left ( ) ) ;
case PropertyID : : Right :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . inset ( ) . right ( ) ) ;
case PropertyID : : Top :
return style_value_for_length_percentage ( layout_node . computed_values ( ) . inset ( ) . top ( ) ) ;
// -> A resolved value special case property defined in another specification
// As defined in the relevant specification.
case PropertyID : : Transform : {
// NOTE: The computed value for `transform` serializes as a single `matrix(...)` value, instead of
// the original list of transform functions. So, we produce a StyleValue for that.
// https://www.w3.org/TR/css-transforms-1/#serialization-of-the-computed-value
// FIXME: Computing values should happen in the StyleComputer!
auto transformations = layout_node . computed_values ( ) . transformations ( ) ;
if ( transformations . is_empty ( ) )
return IdentifierStyleValue : : create ( ValueID : : None ) ;
// The transform matrix is held by the StackingContext, so we need to make sure we have one first.
auto const * viewport = layout_node . document ( ) . paintable ( ) ;
VERIFY ( viewport ) ;
const_cast < Painting : : ViewportPaintable & > ( * viewport ) . build_stacking_context_tree_if_needed ( ) ;
VERIFY ( layout_node . paintable ( ) ) ;
auto const & paintable_box = verify_cast < Painting : : PaintableBox const > ( layout_node . paintable ( ) ) ;
VERIFY ( paintable_box - > stacking_context ( ) ) ;
// FIXME: This needs to serialize to matrix3d if the transformation matrix is a 3D matrix.
// https://w3c.github.io/csswg-drafts/css-transforms-2/#serialization-of-the-computed-value
auto affine_matrix = paintable_box - > stacking_context ( ) - > affine_transform_matrix ( ) ;
StyleValueVector parameters ;
parameters . ensure_capacity ( 6 ) ;
parameters . unchecked_append ( NumberStyleValue : : create ( affine_matrix . a ( ) ) ) ;
parameters . unchecked_append ( NumberStyleValue : : create ( affine_matrix . b ( ) ) ) ;
parameters . unchecked_append ( NumberStyleValue : : create ( affine_matrix . c ( ) ) ) ;
parameters . unchecked_append ( NumberStyleValue : : create ( affine_matrix . d ( ) ) ) ;
parameters . unchecked_append ( NumberStyleValue : : create ( affine_matrix . e ( ) ) ) ;
parameters . unchecked_append ( NumberStyleValue : : create ( affine_matrix . f ( ) ) ) ;
NonnullRefPtr < StyleValue > matrix_function = TransformationStyleValue : : create ( TransformFunction : : Matrix , move ( parameters ) ) ;
// Elsewhere we always store the transform property's value as a StyleValueList of TransformationStyleValues,
// so this is just for consistency.
StyleValueVector matrix_functions { matrix_function } ;
return StyleValueList : : create ( move ( matrix_functions ) , StyleValueList : : Separator : : Space ) ;
}
// -> Any other property
// The resolved value is the computed value.
// NOTE: This is handled inside the `default` case.
// NOTE: Everything below is a shorthand that requires some manual construction.
2023-05-27 11:44:37 -03:00
case PropertyID : : BackgroundPosition :
return style_value_for_background_property (
layout_node ,
2023-08-19 11:45:00 -03:00
[ ] ( auto & layer ) - > NonnullRefPtr < StyleValue > {
2023-05-27 11:44:37 -03:00
return PositionStyleValue : : create (
2023-08-19 10:00:10 -03:00
EdgeStyleValue : : create ( layer . position_edge_x , layer . position_offset_x ) ,
EdgeStyleValue : : create ( layer . position_edge_y , layer . position_offset_y ) ) ;
2023-05-27 11:44:37 -03:00
} ,
2023-08-19 11:45:00 -03:00
[ ] ( ) - > NonnullRefPtr < StyleValue > {
2023-05-27 11:44:37 -03:00
return PositionStyleValue : : create (
2023-08-19 10:00:10 -03:00
EdgeStyleValue : : create ( PositionEdge : : Left , Percentage ( 0 ) ) ,
EdgeStyleValue : : create ( PositionEdge : : Top , Percentage ( 0 ) ) ) ;
2023-05-27 11:44:37 -03:00
} ) ;
2023-05-27 12:32:08 -03:00
case PropertyID : : Border : {
2023-09-29 09:02:11 -03:00
auto width = style_value_for_property ( layout_node , PropertyID : : BorderWidth ) ;
auto style = style_value_for_property ( layout_node , PropertyID : : BorderStyle ) ;
auto color = style_value_for_property ( layout_node , PropertyID : : BorderColor ) ;
2023-05-27 12:32:08 -03:00
// `border` only has a reasonable value if all four sides are the same.
2023-09-29 09:02:11 -03:00
if ( width - > is_value_list ( ) | | style - > is_value_list ( ) | | color - > is_value_list ( ) )
2023-05-27 12:32:08 -03:00
return nullptr ;
2023-09-20 08:50:48 -03:00
return ShorthandStyleValue : : create ( property_id ,
{ PropertyID : : BorderWidth , PropertyID : : BorderStyle , PropertyID : : BorderColor } ,
2023-09-29 09:02:11 -03:00
{ width . release_nonnull ( ) , style . release_nonnull ( ) , color . release_nonnull ( ) } ) ;
2023-05-27 12:32:08 -03:00
}
case PropertyID : : BorderColor : {
2023-09-29 09:02:11 -03:00
auto top = style_value_for_property ( layout_node , PropertyID : : BorderTopColor ) ;
auto right = style_value_for_property ( layout_node , PropertyID : : BorderRightColor ) ;
auto bottom = style_value_for_property ( layout_node , PropertyID : : BorderBottomColor ) ;
auto left = style_value_for_property ( layout_node , PropertyID : : BorderLeftColor ) ;
return style_value_for_sided_shorthand ( top . release_nonnull ( ) , right . release_nonnull ( ) , bottom . release_nonnull ( ) , left . release_nonnull ( ) ) ;
2023-05-27 12:32:08 -03:00
}
case PropertyID : : BorderStyle : {
2023-09-29 09:02:11 -03:00
auto top = style_value_for_property ( layout_node , PropertyID : : BorderTopStyle ) ;
auto right = style_value_for_property ( layout_node , PropertyID : : BorderRightStyle ) ;
auto bottom = style_value_for_property ( layout_node , PropertyID : : BorderBottomStyle ) ;
auto left = style_value_for_property ( layout_node , PropertyID : : BorderLeftStyle ) ;
return style_value_for_sided_shorthand ( top . release_nonnull ( ) , right . release_nonnull ( ) , bottom . release_nonnull ( ) , left . release_nonnull ( ) ) ;
2023-05-27 12:32:08 -03:00
}
case PropertyID : : BorderWidth : {
2023-09-29 09:02:11 -03:00
auto top = style_value_for_property ( layout_node , PropertyID : : BorderTopWidth ) ;
auto right = style_value_for_property ( layout_node , PropertyID : : BorderRightWidth ) ;
auto bottom = style_value_for_property ( layout_node , PropertyID : : BorderBottomWidth ) ;
auto left = style_value_for_property ( layout_node , PropertyID : : BorderLeftWidth ) ;
return style_value_for_sided_shorthand ( top . release_nonnull ( ) , right . release_nonnull ( ) , bottom . release_nonnull ( ) , left . release_nonnull ( ) ) ;
2023-05-27 12:32:08 -03:00
}
2023-05-27 11:52:49 -03:00
case PropertyID : : Margin : {
2023-09-29 09:02:11 -03:00
auto top = style_value_for_property ( layout_node , PropertyID : : MarginTop ) ;
auto right = style_value_for_property ( layout_node , PropertyID : : MarginRight ) ;
auto bottom = style_value_for_property ( layout_node , PropertyID : : MarginBottom ) ;
auto left = style_value_for_property ( layout_node , PropertyID : : MarginLeft ) ;
return style_value_for_sided_shorthand ( top . release_nonnull ( ) , right . release_nonnull ( ) , bottom . release_nonnull ( ) , left . release_nonnull ( ) ) ;
2021-10-05 13:11:38 -03:00
}
2023-05-27 11:52:49 -03:00
case PropertyID : : Padding : {
2023-09-29 09:02:11 -03:00
auto top = style_value_for_property ( layout_node , PropertyID : : PaddingTop ) ;
auto right = style_value_for_property ( layout_node , PropertyID : : PaddingRight ) ;
auto bottom = style_value_for_property ( layout_node , PropertyID : : PaddingBottom ) ;
auto left = style_value_for_property ( layout_node , PropertyID : : PaddingLeft ) ;
return style_value_for_sided_shorthand ( top . release_nonnull ( ) , right . release_nonnull ( ) , bottom . release_nonnull ( ) , left . release_nonnull ( ) ) ;
2021-10-05 13:11:38 -03:00
}
2023-05-27 11:52:49 -03:00
case PropertyID : : Invalid :
return IdentifierStyleValue : : create ( ValueID : : Invalid ) ;
case PropertyID : : Custom :
2022-02-06 10:17:42 -03:00
dbgln_if ( LIBWEB_CSS_DEBUG , " Computed style for custom properties was requested (?) " ) ;
2023-05-02 10:52:31 -03:00
return nullptr ;
2021-09-12 15:05:29 -03:00
default :
2023-09-09 08:04:40 -03:00
if ( ! property_is_shorthand ( property_id ) )
return static_cast < DOM : : Element const & > ( * layout_node . dom_node ( ) ) . computed_css_values ( ) - > property ( property_id ) ;
2023-09-26 10:05:57 -03:00
// Handle shorthands in a generic way
auto longhand_ids = longhands_for_shorthand ( property_id ) ;
StyleValueVector longhand_values ;
longhand_values . ensure_capacity ( longhand_ids . size ( ) ) ;
for ( auto longhand_id : longhand_ids )
longhand_values . append ( style_value_for_property ( layout_node , longhand_id ) . release_nonnull ( ) ) ;
return ShorthandStyleValue : : create ( property_id , move ( longhand_ids ) , move ( longhand_values ) ) ;
2021-09-12 15:05:29 -03:00
}
2021-09-18 08:14:40 -03:00
}
2021-09-23 07:35:56 -03:00
Optional < StyleProperty > ResolvedCSSStyleDeclaration : : property ( PropertyID property_id ) const
2021-09-18 08:14:40 -03:00
{
2023-05-10 10:33:10 -03:00
// https://www.w3.org/TR/cssom-1/#dom-window-getcomputedstyle
// NOTE: This is a partial enforcement of step 5 ("If elt is connected, ...")
if ( ! m_element - > is_connected ( ) )
return { } ;
2023-05-27 11:52:49 -03:00
if ( property_affects_layout ( property_id ) ) {
2022-03-20 17:12:19 -03:00
const_cast < DOM : : Document & > ( m_element - > document ( ) ) . update_layout ( ) ;
} else {
// FIXME: If we had a way to update style for a single element, this would be a good place to use it.
const_cast < DOM : : Document & > ( m_element - > document ( ) ) . update_style ( ) ;
}
2021-09-18 08:14:40 -03:00
if ( ! m_element - > layout_node ( ) ) {
2022-12-06 03:08:20 -03:00
auto style_or_error = m_element - > document ( ) . style_computer ( ) . compute_style ( const_cast < DOM : : Element & > ( * m_element ) ) ;
if ( style_or_error . is_error ( ) ) {
dbgln ( " ResolvedCSSStyleDeclaration::property style computer failed " ) ;
return { } ;
}
auto style = style_or_error . release_value ( ) ;
2022-10-28 11:42:18 -03:00
// FIXME: This is a stopgap until we implement shorthand -> longhand conversion.
auto value = style - > maybe_null_property ( property_id ) ;
if ( ! value ) {
dbgln ( " FIXME: ResolvedCSSStyleDeclaration::property(property_id=0x{:x}) No value for property ID in newly computed style case. " , to_underlying ( property_id ) ) ;
return { } ;
}
2022-04-14 07:52:35 -03:00
return StyleProperty {
. property_id = property_id ,
2022-10-28 11:42:18 -03:00
. value = value . release_nonnull ( ) ,
2022-04-14 07:52:35 -03:00
} ;
2021-09-18 08:14:40 -03:00
}
auto & layout_node = * m_element - > layout_node ( ) ;
2023-08-19 11:45:00 -03:00
auto value = style_value_for_property ( layout_node , property_id ) ;
2021-09-18 08:14:40 -03:00
if ( ! value )
return { } ;
return StyleProperty {
. property_id = property_id ,
. value = value . release_nonnull ( ) ,
} ;
2021-09-12 15:05:29 -03:00
}
2022-04-11 11:10:55 -03:00
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty
2022-09-25 13:03:42 -03:00
WebIDL : : ExceptionOr < void > ResolvedCSSStyleDeclaration : : set_property ( PropertyID , StringView , StringView )
2021-09-12 15:05:29 -03:00
{
2022-04-11 11:10:55 -03:00
// 1. If the computed flag is set, then throw a NoModificationAllowedError exception.
2023-09-06 01:03:01 -03:00
return WebIDL : : NoModificationAllowedError : : create ( realm ( ) , " Cannot modify properties in result of getComputedStyle() " _fly_string ) ;
2022-04-11 11:10:55 -03:00
}
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-removeproperty
2023-09-06 04:07:24 -03:00
WebIDL : : ExceptionOr < String > ResolvedCSSStyleDeclaration : : remove_property ( PropertyID )
2022-04-11 11:10:55 -03:00
{
// 1. If the computed flag is set, then throw a NoModificationAllowedError exception.
2023-09-06 01:03:01 -03:00
return WebIDL : : NoModificationAllowedError : : create ( realm ( ) , " Cannot remove properties from result of getComputedStyle() " _fly_string ) ;
2021-09-12 15:05:29 -03:00
}
2021-10-01 14:57:45 -03:00
2022-12-04 15:02:33 -03:00
DeprecatedString ResolvedCSSStyleDeclaration : : serialized ( ) const
2021-10-01 14:57:45 -03:00
{
2021-10-15 15:38:39 -03:00
// https://www.w3.org/TR/cssom/#dom-cssstyledeclaration-csstext
2021-10-01 14:57:45 -03:00
// If the computed flag is set, then return the empty string.
// NOTE: ResolvedCSSStyleDeclaration is something you would only get from window.getComputedStyle(),
// which returns what the spec calls "resolved style". The "computed flag" is always set here.
2022-12-04 15:02:33 -03:00
return DeprecatedString : : empty ( ) ;
2021-10-01 14:57:45 -03:00
}
2022-11-05 01:51:05 -03:00
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext
WebIDL : : ExceptionOr < void > ResolvedCSSStyleDeclaration : : set_css_text ( StringView )
{
// 1. If the computed flag is set, then throw a NoModificationAllowedError exception.
2023-09-06 01:03:01 -03:00
return WebIDL : : NoModificationAllowedError : : create ( realm ( ) , " Cannot modify properties in result of getComputedStyle() " _fly_string ) ;
2022-11-05 01:51:05 -03:00
}
2021-09-12 15:05:29 -03:00
}