
...as opposed to storing StyleValues, which we have to later check are IdentifierStyleValues, which store identifiers that we can convert to Repeat values later. It's fewer allocations, and we can't end up with invalid values by mistake. :^)
726 lines
30 KiB
C++
726 lines
30 KiB
C++
/*
|
|
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
|
|
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/NonnullRefPtr.h>
|
|
#include <LibWeb/CSS/ResolvedCSSStyleDeclaration.h>
|
|
#include <LibWeb/CSS/StyleComputer.h>
|
|
#include <LibWeb/DOM/Document.h>
|
|
#include <LibWeb/DOM/Element.h>
|
|
|
|
namespace Web::CSS {
|
|
|
|
ResolvedCSSStyleDeclaration::ResolvedCSSStyleDeclaration(DOM::Element& element)
|
|
: m_element(element)
|
|
{
|
|
}
|
|
|
|
ResolvedCSSStyleDeclaration::~ResolvedCSSStyleDeclaration()
|
|
{
|
|
}
|
|
|
|
size_t ResolvedCSSStyleDeclaration::length() const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
String ResolvedCSSStyleDeclaration::item(size_t index) const
|
|
{
|
|
(void)index;
|
|
return {};
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::BoxSizing value)
|
|
{
|
|
switch (value) {
|
|
case CSS::BoxSizing::BorderBox:
|
|
return CSS::ValueID::BorderBox;
|
|
case CSS::BoxSizing::ContentBox:
|
|
return CSS::ValueID::ContentBox;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static RefPtr<StyleValue> style_value_for_display(CSS::Display display)
|
|
{
|
|
if (display.is_none())
|
|
return IdentifierStyleValue::create(CSS::ValueID::None);
|
|
|
|
if (display.it_outside_and_inside()) {
|
|
NonnullRefPtrVector<StyleValue> values;
|
|
switch (display.outside()) {
|
|
case CSS::Display::Outside::Inline:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::Inline));
|
|
break;
|
|
case CSS::Display::Outside::Block:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::Block));
|
|
break;
|
|
case CSS::Display::Outside::RunIn:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::RunIn));
|
|
break;
|
|
}
|
|
switch (display.inside()) {
|
|
case CSS::Display::Inside::Flow:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::Flow));
|
|
break;
|
|
case CSS::Display::Inside::FlowRoot:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::FlowRoot));
|
|
break;
|
|
case CSS::Display::Inside::Table:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::Table));
|
|
break;
|
|
case CSS::Display::Inside::Flex:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::Flex));
|
|
break;
|
|
case CSS::Display::Inside::Grid:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::Grid));
|
|
break;
|
|
case CSS::Display::Inside::Ruby:
|
|
values.append(IdentifierStyleValue::create(CSS::ValueID::Ruby));
|
|
break;
|
|
}
|
|
|
|
return StyleValueList::create(move(values));
|
|
}
|
|
|
|
if (display.is_internal()) {
|
|
switch (display.internal()) {
|
|
case CSS::Display::Internal::TableRowGroup:
|
|
return IdentifierStyleValue::create(CSS::ValueID::TableRowGroup);
|
|
case CSS::Display::Internal::TableHeaderGroup:
|
|
return IdentifierStyleValue::create(CSS::ValueID::TableHeaderGroup);
|
|
case CSS::Display::Internal::TableFooterGroup:
|
|
return IdentifierStyleValue::create(CSS::ValueID::TableFooterGroup);
|
|
case CSS::Display::Internal::TableRow:
|
|
return IdentifierStyleValue::create(CSS::ValueID::TableRow);
|
|
case CSS::Display::Internal::TableCell:
|
|
return IdentifierStyleValue::create(CSS::ValueID::TableCell);
|
|
case CSS::Display::Internal::TableColumnGroup:
|
|
return IdentifierStyleValue::create(CSS::ValueID::TableColumnGroup);
|
|
case CSS::Display::Internal::TableColumn:
|
|
return IdentifierStyleValue::create(CSS::ValueID::TableColumn);
|
|
case CSS::Display::Internal::TableCaption:
|
|
return IdentifierStyleValue::create(CSS::ValueID::TableCaption);
|
|
case CSS::Display::Internal::RubyBase:
|
|
return IdentifierStyleValue::create(CSS::ValueID::RubyBase);
|
|
case CSS::Display::Internal::RubyText:
|
|
return IdentifierStyleValue::create(CSS::ValueID::RubyText);
|
|
case CSS::Display::Internal::RubyBaseContainer:
|
|
return IdentifierStyleValue::create(CSS::ValueID::RubyBaseContainer);
|
|
case CSS::Display::Internal::RubyTextContainer:
|
|
return IdentifierStyleValue::create(CSS::ValueID::RubyTextContainer);
|
|
}
|
|
}
|
|
|
|
TODO();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::Float value)
|
|
{
|
|
switch (value) {
|
|
case Float::None:
|
|
return CSS::ValueID::None;
|
|
case Float::Left:
|
|
return CSS::ValueID::Left;
|
|
case Float::Right:
|
|
return CSS::ValueID::Right;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::Clear value)
|
|
{
|
|
switch (value) {
|
|
case Clear::None:
|
|
return CSS::ValueID::None;
|
|
case Clear::Left:
|
|
return CSS::ValueID::Left;
|
|
case Clear::Right:
|
|
return CSS::ValueID::Right;
|
|
case Clear::Both:
|
|
return CSS::ValueID::Both;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::TextDecorationLine value)
|
|
{
|
|
switch (value) {
|
|
case TextDecorationLine::None:
|
|
return CSS::ValueID::None;
|
|
case TextDecorationLine::Underline:
|
|
return CSS::ValueID::Underline;
|
|
case TextDecorationLine::Overline:
|
|
return CSS::ValueID::Overline;
|
|
case TextDecorationLine::LineThrough:
|
|
return CSS::ValueID::LineThrough;
|
|
case TextDecorationLine::Blink:
|
|
return CSS::ValueID::Blink;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::Cursor value)
|
|
{
|
|
switch (value) {
|
|
case Cursor::Auto:
|
|
return CSS::ValueID::Auto;
|
|
case Cursor::Default:
|
|
return CSS::ValueID::Default;
|
|
case Cursor::None:
|
|
return CSS::ValueID::None;
|
|
case Cursor::ContextMenu:
|
|
return CSS::ValueID::ContextMenu;
|
|
case Cursor::Help:
|
|
return CSS::ValueID::Help;
|
|
case Cursor::Pointer:
|
|
return CSS::ValueID::Pointer;
|
|
case Cursor::Progress:
|
|
return CSS::ValueID::Progress;
|
|
case Cursor::Wait:
|
|
return CSS::ValueID::Wait;
|
|
case Cursor::Cell:
|
|
return CSS::ValueID::Cell;
|
|
case Cursor::Crosshair:
|
|
return CSS::ValueID::Crosshair;
|
|
case Cursor::Text:
|
|
return CSS::ValueID::Text;
|
|
case Cursor::VerticalText:
|
|
return CSS::ValueID::VerticalText;
|
|
case Cursor::Alias:
|
|
return CSS::ValueID::Alias;
|
|
case Cursor::Copy:
|
|
return CSS::ValueID::Copy;
|
|
case Cursor::Move:
|
|
return CSS::ValueID::Move;
|
|
case Cursor::NoDrop:
|
|
return CSS::ValueID::NoDrop;
|
|
case Cursor::NotAllowed:
|
|
return CSS::ValueID::NotAllowed;
|
|
case Cursor::Grab:
|
|
return CSS::ValueID::Grab;
|
|
case Cursor::Grabbing:
|
|
return CSS::ValueID::Grabbing;
|
|
case Cursor::EResize:
|
|
return CSS::ValueID::EResize;
|
|
case Cursor::NResize:
|
|
return CSS::ValueID::NResize;
|
|
case Cursor::NeResize:
|
|
return CSS::ValueID::NeResize;
|
|
case Cursor::NwResize:
|
|
return CSS::ValueID::NwResize;
|
|
case Cursor::SResize:
|
|
return CSS::ValueID::SResize;
|
|
case Cursor::SeResize:
|
|
return CSS::ValueID::SeResize;
|
|
case Cursor::SwResize:
|
|
return CSS::ValueID::SwResize;
|
|
case Cursor::WResize:
|
|
return CSS::ValueID::WResize;
|
|
case Cursor::EwResize:
|
|
return CSS::ValueID::EwResize;
|
|
case Cursor::NsResize:
|
|
return CSS::ValueID::NsResize;
|
|
case Cursor::NeswResize:
|
|
return CSS::ValueID::NeswResize;
|
|
case Cursor::NwseResize:
|
|
return CSS::ValueID::NwseResize;
|
|
case Cursor::ColResize:
|
|
return CSS::ValueID::ColResize;
|
|
case Cursor::RowResize:
|
|
return CSS::ValueID::RowResize;
|
|
case Cursor::AllScroll:
|
|
return CSS::ValueID::AllScroll;
|
|
case Cursor::ZoomIn:
|
|
return CSS::ValueID::ZoomIn;
|
|
case Cursor::ZoomOut:
|
|
return CSS::ValueID::ZoomOut;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::TextAlign value)
|
|
{
|
|
switch (value) {
|
|
case TextAlign::Left:
|
|
return CSS::ValueID::Left;
|
|
case TextAlign::Center:
|
|
return CSS::ValueID::Center;
|
|
case TextAlign::Right:
|
|
return CSS::ValueID::Right;
|
|
case TextAlign::Justify:
|
|
return CSS::ValueID::Justify;
|
|
case TextAlign::LibwebCenter:
|
|
return CSS::ValueID::LibwebCenter;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::TextTransform value)
|
|
{
|
|
switch (value) {
|
|
case TextTransform::None:
|
|
return CSS::ValueID::None;
|
|
case TextTransform::Capitalize:
|
|
return CSS::ValueID::Capitalize;
|
|
case TextTransform::Uppercase:
|
|
return CSS::ValueID::Uppercase;
|
|
case TextTransform::Lowercase:
|
|
return CSS::ValueID::Lowercase;
|
|
case TextTransform::FullWidth:
|
|
return CSS::ValueID::FullWidth;
|
|
case TextTransform::FullSizeKana:
|
|
return CSS::ValueID::FullSizeKana;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::Position value)
|
|
{
|
|
switch (value) {
|
|
case Position::Static:
|
|
return CSS::ValueID::Static;
|
|
case Position::Relative:
|
|
return CSS::ValueID::Relative;
|
|
case Position::Absolute:
|
|
return CSS::ValueID::Absolute;
|
|
case Position::Fixed:
|
|
return CSS::ValueID::Fixed;
|
|
case Position::Sticky:
|
|
return CSS::ValueID::Sticky;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::WhiteSpace value)
|
|
{
|
|
switch (value) {
|
|
case WhiteSpace::Normal:
|
|
return CSS::ValueID::Normal;
|
|
case WhiteSpace::Pre:
|
|
return CSS::ValueID::Pre;
|
|
case WhiteSpace::Nowrap:
|
|
return CSS::ValueID::Nowrap;
|
|
case WhiteSpace::PreLine:
|
|
return CSS::ValueID::PreLine;
|
|
case WhiteSpace::PreWrap:
|
|
return CSS::ValueID::PreWrap;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::FlexDirection value)
|
|
{
|
|
switch (value) {
|
|
case FlexDirection::Row:
|
|
return CSS::ValueID::Row;
|
|
case FlexDirection::RowReverse:
|
|
return CSS::ValueID::RowReverse;
|
|
case FlexDirection::Column:
|
|
return CSS::ValueID::Column;
|
|
case FlexDirection::ColumnReverse:
|
|
return CSS::ValueID::ColumnReverse;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::FlexWrap value)
|
|
{
|
|
switch (value) {
|
|
case FlexWrap::Nowrap:
|
|
return CSS::ValueID::Nowrap;
|
|
case FlexWrap::Wrap:
|
|
return CSS::ValueID::Wrap;
|
|
case FlexWrap::WrapReverse:
|
|
return CSS::ValueID::WrapReverse;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::JustifyContent value)
|
|
{
|
|
switch (value) {
|
|
case JustifyContent::FlexStart:
|
|
return CSS::ValueID::FlexStart;
|
|
case JustifyContent::FlexEnd:
|
|
return CSS::ValueID::FlexEnd;
|
|
case JustifyContent::Center:
|
|
return CSS::ValueID::Center;
|
|
case JustifyContent::SpaceBetween:
|
|
return CSS::ValueID::SpaceBetween;
|
|
case JustifyContent::SpaceAround:
|
|
return CSS::ValueID::SpaceAround;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::Overflow value)
|
|
{
|
|
switch (value) {
|
|
case Overflow::Auto:
|
|
return CSS::ValueID::Auto;
|
|
case Overflow::Clip:
|
|
return CSS::ValueID::Clip;
|
|
case Overflow::Hidden:
|
|
return CSS::ValueID::Hidden;
|
|
case Overflow::Scroll:
|
|
return CSS::ValueID::Scroll;
|
|
case Overflow::Visible:
|
|
return CSS::ValueID::Visible;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::ListStyleType value)
|
|
{
|
|
switch (value) {
|
|
case ListStyleType::None:
|
|
return CSS::ValueID::None;
|
|
case ListStyleType::Disc:
|
|
return CSS::ValueID::Disc;
|
|
case ListStyleType::Circle:
|
|
return CSS::ValueID::Circle;
|
|
case ListStyleType::Square:
|
|
return CSS::ValueID::Square;
|
|
case ListStyleType::Decimal:
|
|
return CSS::ValueID::Decimal;
|
|
case ListStyleType::DecimalLeadingZero:
|
|
return CSS::ValueID::DecimalLeadingZero;
|
|
case ListStyleType::LowerAlpha:
|
|
return CSS::ValueID::LowerAlpha;
|
|
case ListStyleType::LowerLatin:
|
|
return CSS::ValueID::LowerLatin;
|
|
case ListStyleType::LowerRoman:
|
|
return CSS::ValueID::LowerRoman;
|
|
case ListStyleType::UpperAlpha:
|
|
return CSS::ValueID::UpperAlpha;
|
|
case ListStyleType::UpperLatin:
|
|
return CSS::ValueID::UpperLatin;
|
|
case ListStyleType::UpperRoman:
|
|
return CSS::ValueID::UpperRoman;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static CSS::ValueID to_css_value_id(CSS::LineStyle value)
|
|
{
|
|
switch (value) {
|
|
case CSS::LineStyle::None:
|
|
return CSS::ValueID::None;
|
|
case CSS::LineStyle::Hidden:
|
|
return CSS::ValueID::Hidden;
|
|
case CSS::LineStyle::Dotted:
|
|
return CSS::ValueID::Dotted;
|
|
case CSS::LineStyle::Dashed:
|
|
return CSS::ValueID::Dashed;
|
|
case CSS::LineStyle::Solid:
|
|
return CSS::ValueID::Solid;
|
|
case CSS::LineStyle::Double:
|
|
return CSS::ValueID::Double;
|
|
case CSS::LineStyle::Groove:
|
|
return CSS::ValueID::Groove;
|
|
case CSS::LineStyle::Ridge:
|
|
return CSS::ValueID::Ridge;
|
|
case CSS::LineStyle::Inset:
|
|
return CSS::ValueID::Inset;
|
|
case CSS::LineStyle::Outset:
|
|
return CSS::ValueID::Outset;
|
|
}
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
static NonnullRefPtr<StyleValue> value_or_default(Optional<StyleProperty> property, NonnullRefPtr<StyleValue> default_style)
|
|
{
|
|
if (property.has_value())
|
|
return property.value().value;
|
|
return default_style;
|
|
}
|
|
|
|
RefPtr<StyleValue> ResolvedCSSStyleDeclaration::style_value_for_property(Layout::NodeWithStyle const& layout_node, PropertyID property_id) const
|
|
{
|
|
switch (property_id) {
|
|
case CSS::PropertyID::Float:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().float_()));
|
|
case CSS::PropertyID::Clear:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().clear()));
|
|
case CSS::PropertyID::Cursor:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().cursor()));
|
|
case CSS::PropertyID::Display:
|
|
return style_value_for_display(layout_node.computed_values().display());
|
|
case CSS::PropertyID::ZIndex: {
|
|
auto maybe_z_index = layout_node.computed_values().z_index();
|
|
if (!maybe_z_index.has_value())
|
|
return {};
|
|
return NumericStyleValue::create_integer(maybe_z_index.release_value());
|
|
}
|
|
case CSS::PropertyID::TextAlign:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_align()));
|
|
case CSS::PropertyID::TextDecorationLine:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_decoration_line()));
|
|
case CSS::PropertyID::TextTransform:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().text_transform()));
|
|
case CSS::PropertyID::Position:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().position()));
|
|
case CSS::PropertyID::WhiteSpace:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().white_space()));
|
|
case CSS::PropertyID::FlexDirection:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().flex_direction()));
|
|
case CSS::PropertyID::FlexWrap:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().flex_wrap()));
|
|
case CSS::PropertyID::FlexBasis: {
|
|
switch (layout_node.computed_values().flex_basis().type) {
|
|
case FlexBasis::Content:
|
|
return IdentifierStyleValue::create(CSS::ValueID::Content);
|
|
case FlexBasis::Length:
|
|
return LengthStyleValue::create(layout_node.computed_values().flex_basis().length);
|
|
case FlexBasis::Auto:
|
|
return IdentifierStyleValue::create(CSS::ValueID::Auto);
|
|
default:
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
break;
|
|
case CSS::PropertyID::FlexGrow:
|
|
return NumericStyleValue::create_float(layout_node.computed_values().flex_grow());
|
|
case CSS::PropertyID::FlexShrink:
|
|
return NumericStyleValue::create_float(layout_node.computed_values().flex_shrink());
|
|
case CSS::PropertyID::Opacity:
|
|
return NumericStyleValue::create_float(layout_node.computed_values().opacity());
|
|
case CSS::PropertyID::JustifyContent:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().justify_content()));
|
|
case CSS::PropertyID::BoxShadow: {
|
|
auto maybe_box_shadow = layout_node.computed_values().box_shadow();
|
|
if (!maybe_box_shadow.has_value())
|
|
return {};
|
|
auto box_shadow_data = maybe_box_shadow.release_value();
|
|
return 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:
|
|
return LengthStyleValue::create(layout_node.computed_values().width());
|
|
case CSS::PropertyID::MinWidth:
|
|
if (layout_node.computed_values().min_width().is_undefined_or_auto())
|
|
return IdentifierStyleValue::create(CSS::ValueID::Auto);
|
|
return LengthStyleValue::create(layout_node.computed_values().min_width());
|
|
case CSS::PropertyID::MaxWidth:
|
|
if (layout_node.computed_values().max_width().is_undefined())
|
|
return IdentifierStyleValue::create(CSS::ValueID::None);
|
|
return LengthStyleValue::create(layout_node.computed_values().max_width());
|
|
case CSS::PropertyID::Height:
|
|
return LengthStyleValue::create(layout_node.computed_values().height());
|
|
case CSS::PropertyID::MinHeight:
|
|
if (layout_node.computed_values().min_height().is_undefined_or_auto())
|
|
return IdentifierStyleValue::create(CSS::ValueID::Auto);
|
|
return LengthStyleValue::create(layout_node.computed_values().min_height());
|
|
case CSS::PropertyID::MaxHeight:
|
|
if (layout_node.computed_values().max_height().is_undefined())
|
|
return IdentifierStyleValue::create(CSS::ValueID::None);
|
|
return LengthStyleValue::create(layout_node.computed_values().max_height());
|
|
case CSS::PropertyID::Margin: {
|
|
auto margin = layout_node.computed_values().margin();
|
|
auto values = NonnullRefPtrVector<StyleValue> {};
|
|
values.append(LengthStyleValue::create(margin.top));
|
|
values.append(LengthStyleValue::create(margin.right));
|
|
values.append(LengthStyleValue::create(margin.bottom));
|
|
values.append(LengthStyleValue::create(margin.left));
|
|
return StyleValueList::create(move(values));
|
|
}
|
|
case CSS::PropertyID::MarginTop:
|
|
return LengthStyleValue::create(layout_node.computed_values().margin().top);
|
|
case CSS::PropertyID::MarginRight:
|
|
return LengthStyleValue::create(layout_node.computed_values().margin().right);
|
|
case CSS::PropertyID::MarginBottom:
|
|
return LengthStyleValue::create(layout_node.computed_values().margin().bottom);
|
|
case CSS::PropertyID::MarginLeft:
|
|
return LengthStyleValue::create(layout_node.computed_values().margin().left);
|
|
case CSS::PropertyID::Padding: {
|
|
auto padding = layout_node.computed_values().padding();
|
|
auto values = NonnullRefPtrVector<StyleValue> {};
|
|
values.append(LengthStyleValue::create(padding.top));
|
|
values.append(LengthStyleValue::create(padding.right));
|
|
values.append(LengthStyleValue::create(padding.bottom));
|
|
values.append(LengthStyleValue::create(padding.left));
|
|
return StyleValueList::create(move(values));
|
|
}
|
|
case CSS::PropertyID::PaddingTop:
|
|
return LengthStyleValue::create(layout_node.computed_values().padding().top);
|
|
case CSS::PropertyID::PaddingRight:
|
|
return LengthStyleValue::create(layout_node.computed_values().padding().right);
|
|
case CSS::PropertyID::PaddingBottom:
|
|
return LengthStyleValue::create(layout_node.computed_values().padding().bottom);
|
|
case CSS::PropertyID::PaddingLeft:
|
|
return LengthStyleValue::create(layout_node.computed_values().padding().left);
|
|
case CSS::PropertyID::BorderRadius: {
|
|
auto maybe_top_left_radius = property(CSS::PropertyID::BorderTopLeftRadius);
|
|
auto maybe_top_right_radius = property(CSS::PropertyID::BorderTopRightRadius);
|
|
auto maybe_bottom_left_radius = property(CSS::PropertyID::BorderBottomLeftRadius);
|
|
auto maybe_bottom_right_radius = property(CSS::PropertyID::BorderBottomRightRadius);
|
|
RefPtr<BorderRadiusStyleValue> top_left_radius, top_right_radius, bottom_left_radius, bottom_right_radius;
|
|
if (maybe_top_left_radius.has_value()) {
|
|
VERIFY(maybe_top_left_radius.value().value->is_border_radius());
|
|
top_left_radius = maybe_top_left_radius.value().value->as_border_radius();
|
|
}
|
|
if (maybe_top_right_radius.has_value()) {
|
|
VERIFY(maybe_top_right_radius.value().value->is_border_radius());
|
|
top_right_radius = maybe_top_right_radius.value().value->as_border_radius();
|
|
}
|
|
if (maybe_bottom_left_radius.has_value()) {
|
|
VERIFY(maybe_bottom_left_radius.value().value->is_border_radius());
|
|
bottom_left_radius = maybe_bottom_left_radius.value().value->as_border_radius();
|
|
}
|
|
if (maybe_bottom_right_radius.has_value()) {
|
|
VERIFY(maybe_bottom_right_radius.value().value->is_border_radius());
|
|
bottom_right_radius = maybe_bottom_right_radius.value().value->as_border_radius();
|
|
}
|
|
|
|
return 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.
|
|
case CSS::PropertyID::BorderBottomLeftRadius:
|
|
return BorderRadiusStyleValue::create(layout_node.computed_values().border_bottom_left_radius(), layout_node.computed_values().border_bottom_left_radius());
|
|
case CSS::PropertyID::BorderBottomRightRadius:
|
|
return BorderRadiusStyleValue::create(layout_node.computed_values().border_bottom_right_radius(), layout_node.computed_values().border_bottom_right_radius());
|
|
case CSS::PropertyID::BorderTopLeftRadius:
|
|
return BorderRadiusStyleValue::create(layout_node.computed_values().border_top_left_radius(), layout_node.computed_values().border_top_left_radius());
|
|
case CSS::PropertyID::BorderTopRightRadius:
|
|
return BorderRadiusStyleValue::create(layout_node.computed_values().border_top_right_radius(), layout_node.computed_values().border_top_right_radius());
|
|
case CSS::PropertyID::BorderTopWidth:
|
|
return LengthStyleValue::create(Length::make_px(layout_node.computed_values().border_top().width));
|
|
case CSS::PropertyID::BorderRightWidth:
|
|
return LengthStyleValue::create(Length::make_px(layout_node.computed_values().border_right().width));
|
|
case CSS::PropertyID::BorderBottomWidth:
|
|
return LengthStyleValue::create(Length::make_px(layout_node.computed_values().border_bottom().width));
|
|
case CSS::PropertyID::BorderLeftWidth:
|
|
return LengthStyleValue::create(Length::make_px(layout_node.computed_values().border_left().width));
|
|
case CSS::PropertyID::BorderTopColor:
|
|
return ColorStyleValue::create(layout_node.computed_values().border_top().color);
|
|
case CSS::PropertyID::BorderRightColor:
|
|
return ColorStyleValue::create(layout_node.computed_values().border_right().color);
|
|
case CSS::PropertyID::BorderBottomColor:
|
|
return ColorStyleValue::create(layout_node.computed_values().border_bottom().color);
|
|
case CSS::PropertyID::BorderLeftColor:
|
|
return ColorStyleValue::create(layout_node.computed_values().border_left().color);
|
|
case CSS::PropertyID::BorderTopStyle:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().border_top().line_style));
|
|
case CSS::PropertyID::BorderRightStyle:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().border_right().line_style));
|
|
case CSS::PropertyID::BorderBottomStyle:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().border_bottom().line_style));
|
|
case CSS::PropertyID::BorderLeftStyle:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().border_left().line_style));
|
|
case CSS::PropertyID::BorderTop: {
|
|
auto border = layout_node.computed_values().border_top();
|
|
auto width = LengthStyleValue::create(Length::make_px(border.width));
|
|
auto style = IdentifierStyleValue::create(to_css_value_id(border.line_style));
|
|
auto color = ColorStyleValue::create(border.color);
|
|
return BorderStyleValue::create(width, style, color);
|
|
}
|
|
case CSS::PropertyID::BorderRight: {
|
|
auto border = layout_node.computed_values().border_right();
|
|
auto width = LengthStyleValue::create(Length::make_px(border.width));
|
|
auto style = IdentifierStyleValue::create(to_css_value_id(border.line_style));
|
|
auto color = ColorStyleValue::create(border.color);
|
|
return BorderStyleValue::create(width, style, color);
|
|
}
|
|
case CSS::PropertyID::BorderBottom: {
|
|
auto border = layout_node.computed_values().border_bottom();
|
|
auto width = LengthStyleValue::create(Length::make_px(border.width));
|
|
auto style = IdentifierStyleValue::create(to_css_value_id(border.line_style));
|
|
auto color = ColorStyleValue::create(border.color);
|
|
return BorderStyleValue::create(width, style, color);
|
|
}
|
|
case CSS::PropertyID::BorderLeft: {
|
|
auto border = layout_node.computed_values().border_left();
|
|
auto width = LengthStyleValue::create(Length::make_px(border.width));
|
|
auto style = IdentifierStyleValue::create(to_css_value_id(border.line_style));
|
|
auto color = ColorStyleValue::create(border.color);
|
|
return BorderStyleValue::create(width, style, color);
|
|
}
|
|
case CSS::PropertyID::OverflowX:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().overflow_x()));
|
|
case CSS::PropertyID::OverflowY:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().overflow_y()));
|
|
case CSS::PropertyID::Color:
|
|
return ColorStyleValue::create(layout_node.computed_values().color());
|
|
case PropertyID::BackgroundColor:
|
|
return ColorStyleValue::create(layout_node.computed_values().background_color());
|
|
case CSS::PropertyID::BackgroundRepeat:
|
|
return BackgroundRepeatStyleValue::create(
|
|
layout_node.computed_values().background_repeat().repeat_x,
|
|
layout_node.computed_values().background_repeat().repeat_y);
|
|
case CSS::PropertyID::Background: {
|
|
auto maybe_background_color = property(CSS::PropertyID::BackgroundColor);
|
|
auto maybe_background_image = property(CSS::PropertyID::BackgroundImage);
|
|
auto maybe_background_position = property(CSS::PropertyID::BackgroundPosition);
|
|
auto maybe_background_repeat = property(CSS::PropertyID::BackgroundRepeat);
|
|
auto maybe_background_attachment = property(CSS::PropertyID::BackgroundAttachment);
|
|
auto maybe_background_origin = property(CSS::PropertyID::BackgroundOrigin);
|
|
auto maybe_background_clip = property(CSS::PropertyID::BackgroundClip);
|
|
|
|
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_position, PositionStyleValue::create(PositionEdge::Left, Length::make_px(0), PositionEdge::Top, Length::make_px(0))),
|
|
value_or_default(maybe_background_repeat, BackgroundRepeatStyleValue::create(CSS::Repeat::Repeat, CSS::Repeat::Repeat)),
|
|
value_or_default(maybe_background_attachment, IdentifierStyleValue::create(CSS::ValueID::Scroll)),
|
|
value_or_default(maybe_background_origin, IdentifierStyleValue::create(CSS::ValueID::PaddingBox)),
|
|
value_or_default(maybe_background_clip, IdentifierStyleValue::create(CSS::ValueID::BorderBox)));
|
|
}
|
|
case CSS::PropertyID::ListStyleType:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().list_style_type()));
|
|
case CSS::PropertyID::BoxSizing:
|
|
return IdentifierStyleValue::create(to_css_value_id(layout_node.computed_values().box_sizing()));
|
|
case CSS::PropertyID::Invalid:
|
|
return IdentifierStyleValue::create(CSS::ValueID::Invalid);
|
|
case CSS::PropertyID::Custom:
|
|
dbgln("Computed style for custom properties was requested (?)");
|
|
return {};
|
|
default:
|
|
dbgln("FIXME: Computed style for the '{}' property was requested", string_from_property_id(property_id));
|
|
return {};
|
|
}
|
|
}
|
|
}
|
|
|
|
Optional<StyleProperty> ResolvedCSSStyleDeclaration::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_computer().compute_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 ResolvedCSSStyleDeclaration::set_property(PropertyID, StringView)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
String ResolvedCSSStyleDeclaration::serialized() const
|
|
{
|
|
// https://www.w3.org/TR/cssom/#dom-cssstyledeclaration-csstext
|
|
// 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.
|
|
return String::empty();
|
|
}
|
|
|
|
}
|