LibWeb: Simplify ComputedCSSStyleDeclaration property lookup

Factor out the per-property StyleValue generation to a separate function
so we don't have to repeat ourselves so much in property(). :^)
This commit is contained in:
Andreas Kling 2021-09-18 13:14:40 +02:00
parent 1735d978ed
commit 99f9667e5d
2 changed files with 81 additions and 219 deletions

View file

@ -379,224 +379,104 @@ static NonnullRefPtr<StyleValue> value_or_default(Optional<StyleProperty> proper
return default_style; return default_style;
} }
Optional<StyleProperty> ComputedCSSStyleDeclaration::property(PropertyID property_id) const RefPtr<StyleValue> ComputedCSSStyleDeclaration::style_value_for_property(Layout::NodeWithStyle const& layout_node, PropertyID property_id) const
{ {
const_cast<DOM::Document&>(m_element->document()).ensure_layout();
if (!m_element->layout_node()) {
auto style = m_element->document().style_resolver().resolve_style(const_cast<DOM::Element&>(*m_element));
if (auto maybe_property = style->property(property_id); maybe_property.has_value()) {
return StyleProperty {
.property_id = property_id,
.value = maybe_property.release_value(),
};
}
return {};
}
auto& layout_node = *m_element->layout_node();
switch (property_id) { switch (property_id) {
case CSS::PropertyID::Float: case CSS::PropertyID::Float:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().float_()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().float_())),
};
case CSS::PropertyID::Clear: case CSS::PropertyID::Clear:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().clear()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().clear())),
};
case CSS::PropertyID::Cursor: case CSS::PropertyID::Cursor:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().cursor()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().cursor())),
};
case CSS::PropertyID::Display: case CSS::PropertyID::Display:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().display()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().display())),
};
case CSS::PropertyID::ZIndex: { case CSS::PropertyID::ZIndex: {
auto maybe_z_index = layout_node.computed_values().z_index(); auto maybe_z_index = layout_node.computed_values().z_index();
if (!maybe_z_index.has_value()) if (!maybe_z_index.has_value())
return {}; return {};
return NumericStyleValue::create(maybe_z_index.release_value());
return StyleProperty {
.property_id = property_id,
.value = NumericStyleValue::create(maybe_z_index.release_value()),
};
} }
case CSS::PropertyID::TextAlign: case CSS::PropertyID::TextAlign:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_align()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_align())),
};
case CSS::PropertyID::TextDecorationLine: case CSS::PropertyID::TextDecorationLine:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_decoration_line()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_decoration_line())),
};
case CSS::PropertyID::TextTransform: case CSS::PropertyID::TextTransform:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_transform()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_transform())),
};
case CSS::PropertyID::Position: case CSS::PropertyID::Position:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().position()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().position())),
};
case CSS::PropertyID::WhiteSpace: case CSS::PropertyID::WhiteSpace:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().white_space()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().white_space())),
};
case CSS::PropertyID::FlexDirection: case CSS::PropertyID::FlexDirection:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().flex_direction()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().flex_direction())),
};
case CSS::PropertyID::FlexWrap: case CSS::PropertyID::FlexWrap:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().flex_wrap()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().flex_wrap())),
};
case CSS::PropertyID::FlexBasis: { case CSS::PropertyID::FlexBasis: {
switch (layout_node.computed_values().flex_basis().type) { switch (layout_node.computed_values().flex_basis().type) {
case FlexBasis::Content: case FlexBasis::Content:
return StyleProperty { return IdentifierStyleValue::create(CSS::ValueID::Content);
.property_id = property_id,
.value = IdentifierStyleValue::create(CSS::ValueID::Content),
};
case FlexBasis::Length: case FlexBasis::Length:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().flex_basis().length);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().flex_basis().length),
};
case FlexBasis::Auto: case FlexBasis::Auto:
return StyleProperty { return IdentifierStyleValue::create(CSS::ValueID::Auto);
.property_id = property_id, default:
.value = IdentifierStyleValue::create(CSS::ValueID::Auto), VERIFY_NOT_REACHED();
};
} }
VERIFY_NOT_REACHED(); break;
}
case CSS::PropertyID::FlexGrow: { case CSS::PropertyID::FlexGrow: {
auto maybe_grow_factor = layout_node.computed_values().flex_grow_factor(); auto maybe_grow_factor = layout_node.computed_values().flex_grow_factor();
if (!maybe_grow_factor.has_value()) if (!maybe_grow_factor.has_value())
return {}; return {};
return NumericStyleValue::create(maybe_grow_factor.release_value());
return StyleProperty {
.property_id = property_id,
.value = NumericStyleValue::create(maybe_grow_factor.release_value()),
};
} }
case CSS::PropertyID::FlexShrink: { case CSS::PropertyID::FlexShrink: {
auto maybe_shrink_factor = layout_node.computed_values().flex_shrink_factor(); auto maybe_shrink_factor = layout_node.computed_values().flex_shrink_factor();
if (!maybe_shrink_factor.has_value()) if (!maybe_shrink_factor.has_value())
return {}; return {};
return NumericStyleValue::create(maybe_shrink_factor.release_value());
return StyleProperty {
.property_id = property_id,
.value = NumericStyleValue::create(maybe_shrink_factor.release_value()),
};
} }
case CSS::PropertyID::Opacity: { case CSS::PropertyID::Opacity: {
auto maybe_opacity = layout_node.computed_values().opacity(); auto maybe_opacity = layout_node.computed_values().opacity();
if (!maybe_opacity.has_value()) if (!maybe_opacity.has_value())
return {}; return {};
return NumericStyleValue::create(maybe_opacity.release_value());
return StyleProperty {
.property_id = property_id,
.value = NumericStyleValue::create(maybe_opacity.release_value()),
};
} }
case CSS::PropertyID::JustifyContent: case CSS::PropertyID::JustifyContent:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().justify_content()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().justify_content())),
};
case CSS::PropertyID::BoxShadow: { case CSS::PropertyID::BoxShadow: {
auto maybe_box_shadow = layout_node.computed_values().box_shadow(); auto maybe_box_shadow = layout_node.computed_values().box_shadow();
if (!maybe_box_shadow.has_value()) if (!maybe_box_shadow.has_value())
return {}; return {};
auto box_shadow_data = maybe_box_shadow.release_value(); auto box_shadow_data = maybe_box_shadow.release_value();
return StyleProperty { return BoxShadowStyleValue::create(box_shadow_data.offset_x, box_shadow_data.offset_y, box_shadow_data.blur_radius, box_shadow_data.color);
.property_id = property_id,
.value = BoxShadowStyleValue::create(box_shadow_data.offset_x, box_shadow_data.offset_y, box_shadow_data.blur_radius, box_shadow_data.color),
};
} }
case CSS::PropertyID::Width: case CSS::PropertyID::Width:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().width());
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().width()),
};
case CSS::PropertyID::MinWidth: case CSS::PropertyID::MinWidth:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().min_width());
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().min_width()),
};
case CSS::PropertyID::MaxWidth: case CSS::PropertyID::MaxWidth:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().max_width());
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().max_width()),
};
case CSS::PropertyID::Height: case CSS::PropertyID::Height:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().height());
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().height()),
};
case CSS::PropertyID::MinHeight: case CSS::PropertyID::MinHeight:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().min_height());
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().min_height()),
};
case CSS::PropertyID::MaxHeight: case CSS::PropertyID::MaxHeight:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().max_height());
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().max_height()),
};
case CSS::PropertyID::MarginTop: case CSS::PropertyID::MarginTop:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().margin().top);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().margin().top),
};
case CSS::PropertyID::MarginRight: case CSS::PropertyID::MarginRight:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().margin().right);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().margin().right),
};
case CSS::PropertyID::MarginBottom: case CSS::PropertyID::MarginBottom:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().margin().bottom);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().margin().bottom),
};
case CSS::PropertyID::MarginLeft: case CSS::PropertyID::MarginLeft:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().margin().left);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().margin().left),
};
case CSS::PropertyID::PaddingTop: case CSS::PropertyID::PaddingTop:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().padding().top);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().padding().top),
};
case CSS::PropertyID::PaddingRight: case CSS::PropertyID::PaddingRight:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().padding().right);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().padding().right),
};
case CSS::PropertyID::PaddingBottom: case CSS::PropertyID::PaddingBottom:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().padding().bottom);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().padding().bottom),
};
case CSS::PropertyID::PaddingLeft: case CSS::PropertyID::PaddingLeft:
return StyleProperty { return LengthStyleValue::create(layout_node.computed_values().padding().left);
.property_id = property_id,
.value = LengthStyleValue::create(layout_node.computed_values().padding().left),
};
case CSS::PropertyID::BorderRadius: { case CSS::PropertyID::BorderRadius: {
auto maybe_top_left_radius = property(CSS::PropertyID::BorderTopLeftRadius); auto maybe_top_left_radius = property(CSS::PropertyID::BorderTopLeftRadius);
auto maybe_top_right_radius = property(CSS::PropertyID::BorderTopRightRadius); auto maybe_top_right_radius = property(CSS::PropertyID::BorderTopRightRadius);
@ -620,69 +500,33 @@ Optional<StyleProperty> ComputedCSSStyleDeclaration::property(PropertyID propert
bottom_right_radius = *static_cast<BorderRadiusStyleValue*>(maybe_bottom_right_radius.value().value.ptr()); bottom_right_radius = *static_cast<BorderRadiusStyleValue*>(maybe_bottom_right_radius.value().value.ptr());
} }
return StyleProperty { return CombinedBorderRadiusStyleValue::create(top_left_radius.release_nonnull(), top_right_radius.release_nonnull(), bottom_right_radius.release_nonnull(), bottom_left_radius.release_nonnull());
.property_id = property_id,
.value = CombinedBorderRadiusStyleValue::create(top_left_radius.release_nonnull(), top_right_radius.release_nonnull(), bottom_right_radius.release_nonnull(), bottom_left_radius.release_nonnull()),
};
} }
// FIXME: The two radius components are not yet stored, as we currently don't actually render them. // FIXME: The two radius components are not yet stored, as we currently don't actually render them.
case CSS::PropertyID::BorderBottomLeftRadius: case CSS::PropertyID::BorderBottomLeftRadius:
return StyleProperty { return BorderRadiusStyleValue::create(layout_node.computed_values().border_bottom_left_radius(), layout_node.computed_values().border_bottom_left_radius());
.property_id = property_id,
.value = BorderRadiusStyleValue::create(layout_node.computed_values().border_bottom_left_radius(), layout_node.computed_values().border_bottom_left_radius()),
};
case CSS::PropertyID::BorderBottomRightRadius: case CSS::PropertyID::BorderBottomRightRadius:
return StyleProperty { return BorderRadiusStyleValue::create(layout_node.computed_values().border_bottom_right_radius(), layout_node.computed_values().border_bottom_right_radius());
.property_id = property_id,
.value = BorderRadiusStyleValue::create(layout_node.computed_values().border_bottom_right_radius(), layout_node.computed_values().border_bottom_right_radius()),
};
case CSS::PropertyID::BorderTopLeftRadius: case CSS::PropertyID::BorderTopLeftRadius:
return StyleProperty { return BorderRadiusStyleValue::create(layout_node.computed_values().border_top_left_radius(), layout_node.computed_values().border_top_left_radius());
.property_id = property_id,
.value = BorderRadiusStyleValue::create(layout_node.computed_values().border_top_left_radius(), layout_node.computed_values().border_top_left_radius()),
};
case CSS::PropertyID::BorderTopRightRadius: case CSS::PropertyID::BorderTopRightRadius:
return StyleProperty { return BorderRadiusStyleValue::create(layout_node.computed_values().border_top_right_radius(), layout_node.computed_values().border_top_right_radius());
.property_id = property_id,
.value = BorderRadiusStyleValue::create(layout_node.computed_values().border_top_right_radius(), layout_node.computed_values().border_top_right_radius()),
};
case CSS::PropertyID::OverflowX: case CSS::PropertyID::OverflowX:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().overflow_x()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().overflow_x())),
};
case CSS::PropertyID::OverflowY: case CSS::PropertyID::OverflowY:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().overflow_y()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().overflow_y())),
};
case CSS::PropertyID::Color: case CSS::PropertyID::Color:
return StyleProperty { return ColorStyleValue::create(layout_node.computed_values().color());
.property_id = property_id,
.value = ColorStyleValue::create(layout_node.computed_values().color()),
};
case PropertyID::BackgroundColor: case PropertyID::BackgroundColor:
return StyleProperty { return ColorStyleValue::create(layout_node.computed_values().background_color());
.property_id = property_id,
.value = ColorStyleValue::create(layout_node.computed_values().background_color()),
};
case CSS::PropertyID::BackgroundRepeatX: case CSS::PropertyID::BackgroundRepeatX:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().background_repeat_x()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().background_repeat_x())),
};
case CSS::PropertyID::BackgroundRepeatY: case CSS::PropertyID::BackgroundRepeatY:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().background_repeat_y()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().background_repeat_y())),
};
case CSS::PropertyID::BackgroundRepeat: { case CSS::PropertyID::BackgroundRepeat: {
auto maybe_background_repeat_x = property(CSS::PropertyID::BackgroundRepeatX); auto maybe_background_repeat_x = property(CSS::PropertyID::BackgroundRepeatX);
auto maybe_background_repeat_y = property(CSS::PropertyID::BackgroundRepeatY); auto maybe_background_repeat_y = property(CSS::PropertyID::BackgroundRepeatY);
return StyleProperty { return BackgroundRepeatStyleValue::create(value_or_default(maybe_background_repeat_x, IdentifierStyleValue::create(CSS::ValueID::RepeatX)), value_or_default(maybe_background_repeat_y, IdentifierStyleValue::create(CSS::ValueID::RepeatY)));
.property_id = property_id,
.value = BackgroundRepeatStyleValue::create(value_or_default(maybe_background_repeat_x, IdentifierStyleValue::create(CSS::ValueID::RepeatX)), value_or_default(maybe_background_repeat_y, IdentifierStyleValue::create(CSS::ValueID::RepeatY))),
};
} }
case CSS::PropertyID::Background: { case CSS::PropertyID::Background: {
auto maybe_background_color = property(CSS::PropertyID::BackgroundColor); auto maybe_background_color = property(CSS::PropertyID::BackgroundColor);
@ -690,21 +534,12 @@ Optional<StyleProperty> ComputedCSSStyleDeclaration::property(PropertyID propert
auto maybe_background_repeat_x = property(CSS::PropertyID::BackgroundRepeatX); auto maybe_background_repeat_x = property(CSS::PropertyID::BackgroundRepeatX);
auto maybe_background_repeat_y = property(CSS::PropertyID::BackgroundRepeatY); auto maybe_background_repeat_y = property(CSS::PropertyID::BackgroundRepeatY);
return StyleProperty { return BackgroundStyleValue::create(value_or_default(maybe_background_color, InitialStyleValue::the()), value_or_default(maybe_background_image, IdentifierStyleValue::create(CSS::ValueID::None)), value_or_default(maybe_background_repeat_x, IdentifierStyleValue::create(CSS::ValueID::RepeatX)), value_or_default(maybe_background_repeat_y, IdentifierStyleValue::create(CSS::ValueID::RepeatX)));
.property_id = property_id,
.value = BackgroundStyleValue::create(value_or_default(maybe_background_color, InitialStyleValue::the()), value_or_default(maybe_background_image, IdentifierStyleValue::create(CSS::ValueID::None)), value_or_default(maybe_background_repeat_x, IdentifierStyleValue::create(CSS::ValueID::RepeatX)), value_or_default(maybe_background_repeat_y, IdentifierStyleValue::create(CSS::ValueID::RepeatX))),
};
} }
case CSS::PropertyID::ListStyleType: case CSS::PropertyID::ListStyleType:
return StyleProperty { return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().list_style_type()));
.property_id = property_id,
.value = IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().list_style_type())),
};
case CSS::PropertyID::Invalid: case CSS::PropertyID::Invalid:
return StyleProperty { return IdentifierStyleValue::create(CSS::ValueID::Invalid);
.property_id = property_id,
.value = IdentifierStyleValue::create(CSS::ValueID::Invalid),
};
case CSS::PropertyID::Custom: case CSS::PropertyID::Custom:
dbgln("Computed style for custom properties was requested (?)"); dbgln("Computed style for custom properties was requested (?)");
return {}; return {};
@ -712,11 +547,36 @@ Optional<StyleProperty> ComputedCSSStyleDeclaration::property(PropertyID propert
dbgln("FIXME: Computed style for the '{}' property was requested", string_from_property_id(property_id)); dbgln("FIXME: Computed style for the '{}' property was requested", string_from_property_id(property_id));
return {}; return {};
} }
}
}
Optional<StyleProperty> ComputedCSSStyleDeclaration::property(PropertyID property_id) const
{
const_cast<DOM::Document&>(m_element->document()).ensure_layout();
if (!m_element->layout_node()) {
auto style = m_element->document().style_resolver().resolve_style(const_cast<DOM::Element&>(*m_element));
if (auto maybe_property = style->property(property_id); maybe_property.has_value()) {
return StyleProperty {
.property_id = property_id,
.value = maybe_property.release_value(),
};
}
return {};
}
auto& layout_node = *m_element->layout_node();
auto value = style_value_for_property(layout_node, property_id);
if (!value)
return {};
return StyleProperty {
.property_id = property_id,
.value = value.release_nonnull(),
};
} }
bool ComputedCSSStyleDeclaration::set_property(PropertyID, StringView) bool ComputedCSSStyleDeclaration::set_property(PropertyID, StringView)
{ {
return false; return false;
} }
} }

View file

@ -27,6 +27,8 @@ public:
private: private:
explicit ComputedCSSStyleDeclaration(DOM::Element&); explicit ComputedCSSStyleDeclaration(DOM::Element&);
RefPtr<StyleValue> style_value_for_property(Layout::NodeWithStyle const&, PropertyID) const;
NonnullRefPtr<DOM::Element> m_element; NonnullRefPtr<DOM::Element> m_element;
}; };