|
@@ -142,9 +142,155 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
|
|
|
// 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
|
|
|
+
|
|
|
+ // The resolved value for a given longhand property can be determined as follows:
|
|
|
switch (property_id) {
|
|
|
+ // -> 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.
|
|
|
case PropertyID::BackgroundColor:
|
|
|
return ColorStyleValue::create(layout_node.computed_values().background_color());
|
|
|
+ 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
|
|
|
+ // FIXME: -> width
|
|
|
+ // -> 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.
|
|
|
case PropertyID::BackgroundPosition:
|
|
|
return style_value_for_background_property(
|
|
|
layout_node,
|
|
@@ -182,8 +328,6 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
|
|
|
{ PropertyID::BorderBottomWidth, PropertyID::BorderBottomStyle, PropertyID::BorderBottomColor },
|
|
|
{ width, style, color });
|
|
|
}
|
|
|
- case PropertyID::BorderBottomColor:
|
|
|
- return ColorStyleValue::create(layout_node.computed_values().border_bottom().color);
|
|
|
case PropertyID::BorderColor: {
|
|
|
auto top = ColorStyleValue::create(layout_node.computed_values().border_top().color);
|
|
|
auto right = ColorStyleValue::create(layout_node.computed_values().border_right().color);
|
|
@@ -200,8 +344,6 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
|
|
|
{ PropertyID::BorderLeftWidth, PropertyID::BorderLeftStyle, PropertyID::BorderLeftColor },
|
|
|
{ width, style, color });
|
|
|
}
|
|
|
- case PropertyID::BorderLeftColor:
|
|
|
- return ColorStyleValue::create(layout_node.computed_values().border_left().color);
|
|
|
case PropertyID::BorderRight: {
|
|
|
auto border = layout_node.computed_values().border_right();
|
|
|
auto width = LengthStyleValue::create(Length::make_px(border.width));
|
|
@@ -211,8 +353,6 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
|
|
|
{ PropertyID::BorderRightWidth, PropertyID::BorderRightStyle, PropertyID::BorderRightColor },
|
|
|
{ width, style, color });
|
|
|
}
|
|
|
- case PropertyID::BorderRightColor:
|
|
|
- return ColorStyleValue::create(layout_node.computed_values().border_right().color);
|
|
|
case PropertyID::BorderStyle: {
|
|
|
auto top = IdentifierStyleValue::create(to_value_id(layout_node.computed_values().border_top().line_style));
|
|
|
auto right = IdentifierStyleValue::create(to_value_id(layout_node.computed_values().border_right().line_style));
|
|
@@ -229,8 +369,6 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
|
|
|
{ PropertyID::BorderTopWidth, PropertyID::BorderTopStyle, PropertyID::BorderTopColor },
|
|
|
{ width, style, color });
|
|
|
}
|
|
|
- case PropertyID::BorderTopColor:
|
|
|
- return ColorStyleValue::create(layout_node.computed_values().border_top().color);
|
|
|
case PropertyID::BorderWidth: {
|
|
|
auto top = LengthStyleValue::create(Length::make_px(layout_node.computed_values().border_top().width));
|
|
|
auto right = LengthStyleValue::create(Length::make_px(layout_node.computed_values().border_right().width));
|
|
@@ -238,14 +376,6 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
|
|
|
auto left = LengthStyleValue::create(Length::make_px(layout_node.computed_values().border_left().width));
|
|
|
return style_value_for_sided_shorthand(top, right, bottom, left);
|
|
|
}
|
|
|
- case PropertyID::Bottom:
|
|
|
- return style_value_for_length_percentage(layout_node.computed_values().inset().bottom());
|
|
|
- case PropertyID::Color:
|
|
|
- return ColorStyleValue::create(layout_node.computed_values().color());
|
|
|
- case PropertyID::Height:
|
|
|
- return style_value_for_size(layout_node.computed_values().height());
|
|
|
- case PropertyID::Left:
|
|
|
- return style_value_for_length_percentage(layout_node.computed_values().inset().left());
|
|
|
case PropertyID::Margin: {
|
|
|
auto margin = layout_node.computed_values().margin();
|
|
|
auto top = style_value_for_length_percentage(margin.top());
|
|
@@ -254,16 +384,6 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
|
|
|
auto left = style_value_for_length_percentage(margin.left());
|
|
|
return style_value_for_sided_shorthand(move(top), move(right), move(bottom), move(left));
|
|
|
}
|
|
|
- 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::OutlineColor:
|
|
|
- return ColorStyleValue::create(layout_node.computed_values().outline_color());
|
|
|
case PropertyID::Padding: {
|
|
|
auto padding = layout_node.computed_values().padding();
|
|
|
auto top = style_value_for_length_percentage(padding.top());
|
|
@@ -272,59 +392,6 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
|
|
|
auto left = style_value_for_length_percentage(padding.left());
|
|
|
return style_value_for_sided_shorthand(move(top), move(right), move(bottom), move(left));
|
|
|
}
|
|
|
- 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::Right:
|
|
|
- return style_value_for_length_percentage(layout_node.computed_values().inset().right());
|
|
|
- case PropertyID::TextDecorationColor:
|
|
|
- return ColorStyleValue::create(layout_node.computed_values().text_decoration_color());
|
|
|
- case PropertyID::Top:
|
|
|
- return style_value_for_length_percentage(layout_node.computed_values().inset().top());
|
|
|
- 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);
|
|
|
- }
|
|
|
- case PropertyID::Width:
|
|
|
- return style_value_for_size(layout_node.computed_values().width());
|
|
|
case PropertyID::Invalid:
|
|
|
return IdentifierStyleValue::create(ValueID::Invalid);
|
|
|
case PropertyID::Custom:
|