mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 19:47:44 +00:00
LibWeb: Resolve background properties from ValueListStyleValue
As before, there are several sub-properties that we do not support, and we ignore anything after the first comma.
This commit is contained in:
parent
6e08b200d4
commit
29b61123a4
1 changed files with 176 additions and 31 deletions
|
@ -211,7 +211,7 @@ static inline void set_property_border_style(StyleProperties& style, StyleValue
|
||||||
style.set_property(CSS::PropertyID::BorderLeftStyle, value);
|
style.set_property(CSS::PropertyID::BorderLeftStyle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool is_background_repeat_property(StyleValue const& value)
|
static inline bool is_background_repeat(StyleValue const& value)
|
||||||
{
|
{
|
||||||
if (value.is_builtin_or_dynamic())
|
if (value.is_builtin_or_dynamic())
|
||||||
return true;
|
return true;
|
||||||
|
@ -229,6 +229,17 @@ static inline bool is_background_repeat_property(StyleValue const& value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_background_image(StyleValue const& value)
|
||||||
|
{
|
||||||
|
if (value.is_builtin_or_dynamic())
|
||||||
|
return true;
|
||||||
|
if (value.is_image())
|
||||||
|
return true;
|
||||||
|
if (value.to_identifier() == ValueID::None)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool is_color(StyleValue const& value)
|
static inline bool is_color(StyleValue const& value)
|
||||||
{
|
{
|
||||||
if (value.is_builtin_or_dynamic())
|
if (value.is_builtin_or_dynamic())
|
||||||
|
@ -1032,11 +1043,21 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property_id == CSS::PropertyID::Background) {
|
if (property_id == CSS::PropertyID::Background) {
|
||||||
if (value.is_identifier() && static_cast<IdentifierStyleValue const&>(value).id() == CSS::ValueID::None) {
|
if (value.to_identifier() == ValueID::None) {
|
||||||
style.set_property(CSS::PropertyID::BackgroundColor, ColorStyleValue::create(Color::Transparent));
|
style.set_property(CSS::PropertyID::BackgroundColor, ColorStyleValue::create(Color::Transparent));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_background_image(value)) {
|
||||||
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundImage, value, document);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_color(value)) {
|
||||||
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundColor, value, document);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Remove string parsing once DeprecatedCSSParser is gone.
|
// FIXME: Remove string parsing once DeprecatedCSSParser is gone.
|
||||||
if (value.is_string()) {
|
if (value.is_string()) {
|
||||||
auto parts = split_on_whitespace(value.to_string());
|
auto parts = split_on_whitespace(value.to_string());
|
||||||
|
@ -1059,8 +1080,8 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
|
||||||
for (auto it = values.begin(); it != values.end(); ++it) {
|
for (auto it = values.begin(); it != values.end(); ++it) {
|
||||||
auto& value = *it;
|
auto& value = *it;
|
||||||
|
|
||||||
if (is_background_repeat_property(value)) {
|
if (is_background_repeat(value)) {
|
||||||
if ((it + 1 != values.end()) && is_background_repeat_property(*(it + 1))) {
|
if ((it + 1 != values.end()) && is_background_repeat(*(it + 1))) {
|
||||||
++it;
|
++it;
|
||||||
|
|
||||||
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, value, document, true);
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, value, document, true);
|
||||||
|
@ -1077,54 +1098,160 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Implement List parsing.
|
if (value.is_value_list()) {
|
||||||
|
auto parts = static_cast<CSS::ValueListStyleValue const&>(value).values();
|
||||||
|
|
||||||
|
RefPtr<StyleValue> background_color_value;
|
||||||
|
RefPtr<StyleValue> background_image_value;
|
||||||
|
RefPtr<StyleValue> repeat_x_value;
|
||||||
|
RefPtr<StyleValue> repeat_y_value;
|
||||||
|
// FIXME: Implement background-position.
|
||||||
|
// FIXME: Implement background-size.
|
||||||
|
// FIXME: Implement background-attachment.
|
||||||
|
// FIXME: Implement background-clip.
|
||||||
|
// FIXME: Implement background-origin.
|
||||||
|
|
||||||
|
for (size_t i = 0; i < parts.size(); ++i) {
|
||||||
|
auto& part = parts[i];
|
||||||
|
|
||||||
|
// FIXME: Handle multiple backgrounds.
|
||||||
|
if (part.is(Token::Type::Comma))
|
||||||
|
break;
|
||||||
|
|
||||||
|
auto value = Parser::parse_css_value(context, property_id, part);
|
||||||
|
if (!value) {
|
||||||
|
dbgln("Unable to parse token in `background` as a CSS value: '{}'", part.to_debug_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value->is_color()) {
|
||||||
|
if (background_color_value)
|
||||||
|
return;
|
||||||
|
background_color_value = move(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_background_image(*value)) {
|
||||||
|
if (background_image_value)
|
||||||
|
return;
|
||||||
|
background_image_value = move(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (is_background_repeat(*value)) {
|
||||||
|
if (repeat_x_value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto value_id = value->to_identifier();
|
||||||
|
if (value_id == ValueID::RepeatX || value_id == ValueID::RepeatY) {
|
||||||
|
repeat_x_value = IdentifierStyleValue::create(value_id == ValueID::RepeatX ? ValueID::Repeat : ValueID::NoRepeat);
|
||||||
|
repeat_y_value = IdentifierStyleValue::create(value_id == ValueID::RepeatX ? ValueID::NoRepeat : ValueID::Repeat);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check following value, if it's also a repeat, set both.
|
||||||
|
if (i + 1 < parts.size()) {
|
||||||
|
auto next_value = Parser::parse_css_value(context, property_id, parts[i + 1]);
|
||||||
|
if (next_value && is_background_repeat(*next_value)) {
|
||||||
|
++i;
|
||||||
|
repeat_x_value = move(value);
|
||||||
|
repeat_y_value = move(next_value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repeat_x_value = value;
|
||||||
|
repeat_y_value = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgln("Unhandled token in `background` declaration: '{}'", part.to_debug_string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (background_color_value)
|
||||||
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundColor, background_color_value.release_nonnull(), document);
|
||||||
|
if (background_image_value)
|
||||||
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundImage, background_image_value.release_nonnull(), document);
|
||||||
|
if (repeat_x_value)
|
||||||
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, repeat_x_value.release_nonnull(), document, true);
|
||||||
|
if (repeat_y_value)
|
||||||
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, repeat_y_value.release_nonnull(), document, true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property_id == CSS::PropertyID::BackgroundImage) {
|
if (property_id == CSS::PropertyID::BackgroundImage) {
|
||||||
// FIXME: Handle function StyleValues once we have them.
|
if (is_background_image(value)) {
|
||||||
if (!value.is_string())
|
style.set_property(CSS::PropertyID::BackgroundImage, value);
|
||||||
return;
|
return;
|
||||||
auto string = value.to_string();
|
}
|
||||||
if (!string.starts_with("url("))
|
|
||||||
return;
|
|
||||||
if (!string.ends_with(')'))
|
|
||||||
return;
|
|
||||||
auto url = string.substring_view(4, string.length() - 5);
|
|
||||||
if (url.length() >= 2 && url.starts_with('"') && url.ends_with('"'))
|
|
||||||
url = url.substring_view(1, url.length() - 2);
|
|
||||||
else if (url.length() >= 2 && url.starts_with('\'') && url.ends_with('\''))
|
|
||||||
url = url.substring_view(1, url.length() - 2);
|
|
||||||
|
|
||||||
auto background_image_value = ImageStyleValue::create(document.complete_url(url), document);
|
// FIXME: Remove string parsing once DeprecatedCSSParser is gone.
|
||||||
style.set_property(CSS::PropertyID::BackgroundImage, move(background_image_value));
|
if (value.is_string()) {
|
||||||
|
return;
|
||||||
|
auto string = value.to_string();
|
||||||
|
if (!string.starts_with("url("))
|
||||||
|
return;
|
||||||
|
if (!string.ends_with(')'))
|
||||||
|
return;
|
||||||
|
auto url = string.substring_view(4, string.length() - 5);
|
||||||
|
if (url.length() >= 2 && url.starts_with('"') && url.ends_with('"'))
|
||||||
|
url = url.substring_view(1, url.length() - 2);
|
||||||
|
else if (url.length() >= 2 && url.starts_with('\'') && url.ends_with('\''))
|
||||||
|
url = url.substring_view(1, url.length() - 2);
|
||||||
|
|
||||||
|
auto background_image_value = ImageStyleValue::create(document.complete_url(url), document);
|
||||||
|
style.set_property(CSS::PropertyID::BackgroundImage, move(background_image_value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.is_value_list()) {
|
||||||
|
auto parts = static_cast<CSS::ValueListStyleValue const&>(value).values();
|
||||||
|
// FIXME: Handle multiple backgrounds.
|
||||||
|
if (!parts.is_empty()) {
|
||||||
|
auto first_value = Parser::parse_css_value(context, property_id, parts[0]);
|
||||||
|
if (first_value)
|
||||||
|
style.set_property(CSS::PropertyID::BackgroundImage, *first_value);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbgln("Unsure what to do with CSS background-image value '{}'", value.to_string());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property_id == CSS::PropertyID::BackgroundRepeat) {
|
if (property_id == CSS::PropertyID::BackgroundRepeat) {
|
||||||
|
auto assign_background_repeat_from_single_value = [&](StyleValue const& value) {
|
||||||
|
auto value_id = value.to_identifier();
|
||||||
|
if (value_id == ValueID::RepeatX || value_id == ValueID::RepeatY) {
|
||||||
|
auto repeat_x = IdentifierStyleValue::create(value_id == ValueID::RepeatX ? ValueID::Repeat : ValueID::NoRepeat);
|
||||||
|
auto repeat_y = IdentifierStyleValue::create(value_id == ValueID::RepeatX ? ValueID::NoRepeat : ValueID::Repeat);
|
||||||
|
set_property_expanding_shorthands(style, PropertyID::BackgroundRepeatX, repeat_x, document, true);
|
||||||
|
set_property_expanding_shorthands(style, PropertyID::BackgroundRepeatY, repeat_y, document, true);
|
||||||
|
} else {
|
||||||
|
set_property_expanding_shorthands(style, PropertyID::BackgroundRepeatX, value, document, true);
|
||||||
|
set_property_expanding_shorthands(style, PropertyID::BackgroundRepeatY, value, document, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (is_background_repeat(value)) {
|
||||||
|
assign_background_repeat_from_single_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: Remove string parsing once DeprecatedCSSParser is gone.
|
// FIXME: Remove string parsing once DeprecatedCSSParser is gone.
|
||||||
if (value.is_string()) {
|
if (value.is_string()) {
|
||||||
auto parts = split_on_whitespace(value.to_string());
|
auto parts = split_on_whitespace(value.to_string());
|
||||||
NonnullRefPtrVector<StyleValue> values;
|
NonnullRefPtrVector<StyleValue> values;
|
||||||
for (auto& part : parts) {
|
for (auto& part : parts) {
|
||||||
auto value = parse_css_value(deprecated_context, part);
|
auto value = parse_css_value(deprecated_context, part);
|
||||||
if (!value || !is_background_repeat_property(*value))
|
if (!value || !is_background_repeat(*value))
|
||||||
return;
|
return;
|
||||||
values.append(value.release_nonnull());
|
values.append(value.release_nonnull());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.size() == 1) {
|
if (values.size() == 1) {
|
||||||
auto value_id = values[0].to_identifier();
|
assign_background_repeat_from_single_value(values[0]);
|
||||||
if (value_id == CSS::ValueID::RepeatX || value_id == CSS::ValueID::RepeatY) {
|
|
||||||
auto repeat_x = IdentifierStyleValue::create(value_id == CSS::ValueID::RepeatX ? CSS::ValueID::Repeat : CSS::ValueID::NoRepeat);
|
|
||||||
auto repeat_y = IdentifierStyleValue::create(value_id == CSS::ValueID::RepeatX ? CSS::ValueID::NoRepeat : CSS::ValueID::Repeat);
|
|
||||||
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, repeat_x, document, true);
|
|
||||||
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, repeat_y, document, true);
|
|
||||||
} else {
|
|
||||||
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, values[0], document, true);
|
|
||||||
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, values[0], document, true);
|
|
||||||
}
|
|
||||||
} else if (values.size() == 2) {
|
} else if (values.size() == 2) {
|
||||||
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, values[0], document, true);
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, values[0], document, true);
|
||||||
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, values[1], document, true);
|
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, values[1], document, true);
|
||||||
|
@ -1133,7 +1260,25 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Implement List parsing.
|
if (value.is_value_list()) {
|
||||||
|
auto parts = static_cast<CSS::ValueListStyleValue const&>(value).values();
|
||||||
|
NonnullRefPtrVector<StyleValue> repeat_values;
|
||||||
|
for (auto& part : parts) {
|
||||||
|
if (part.is(Token::Type::Comma)) {
|
||||||
|
// FIXME: Handle multiple backgrounds.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto parsed_value = Parser::parse_css_value(context, property_id, part);
|
||||||
|
if (parsed_value)
|
||||||
|
repeat_values.append(parsed_value.release_nonnull());
|
||||||
|
}
|
||||||
|
if (repeat_values.size() == 1) {
|
||||||
|
assign_background_repeat_from_single_value(repeat_values[0]);
|
||||||
|
} else if (repeat_values.size() == 2) {
|
||||||
|
set_property_expanding_shorthands(style, PropertyID::BackgroundRepeatX, repeat_values[0], document, true);
|
||||||
|
set_property_expanding_shorthands(style, PropertyID::BackgroundRepeatY, repeat_values[1], document, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue