1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 05:17:34 +00:00

LibWeb: Support two-value background-repeat

The background-repeat value may be specified as either one- or two-value
identifiers (to be interpreted as horizontal and vertical repeat). This
adds two pseudo-properties, background-repeat-x and background-repeat-y,
to handle this. One-value identifiers are mapped to two-value in
accordance with the spec.
This commit is contained in:
Timothy Flynn 2021-04-05 12:05:35 -04:00 committed by Andreas Kling
parent 0794d879f3
commit 5de0e0068c
12 changed files with 152 additions and 35 deletions

View file

@ -92,7 +92,8 @@ public:
Color color() const { return m_inherited.color; }
Color background_color() const { return m_noninherited.background_color; }
CSS::Repeat background_repeat() const { return m_noninherited.background_repeat; }
CSS::Repeat background_repeat_x() const { return m_noninherited.background_repeat_x; }
CSS::Repeat background_repeat_y() const { return m_noninherited.background_repeat_y; }
CSS::ListStyleType list_style_type() const { return m_inherited.list_style_type; }
@ -134,7 +135,8 @@ protected:
BorderData border_right;
BorderData border_bottom;
Color background_color { InitialValues::background_color() };
CSS::Repeat background_repeat { InitialValues::background_repeat() };
CSS::Repeat background_repeat_x { InitialValues::background_repeat() };
CSS::Repeat background_repeat_y { InitialValues::background_repeat() };
CSS::FlexDirection flex_direction { InitialValues::flex_direction() };
CSS::Overflow overflow_x { InitialValues::overflow() };
CSS::Overflow overflow_y { InitialValues::overflow() };
@ -149,7 +151,8 @@ public:
void set_color(const Color& color) { m_inherited.color = color; }
void set_cursor(CSS::Cursor cursor) { m_inherited.cursor = cursor; }
void set_background_color(const Color& color) { m_noninherited.background_color = color; }
void set_background_repeat(CSS::Repeat repeat) { m_noninherited.background_repeat = repeat; }
void set_background_repeat_x(CSS::Repeat repeat) { m_noninherited.background_repeat_x = repeat; }
void set_background_repeat_y(CSS::Repeat repeat) { m_noninherited.background_repeat_y = repeat; }
void set_float(CSS::Float value) { m_noninherited.float_ = value; }
void set_clear(CSS::Clear value) { m_noninherited.clear = value; }
void set_z_index(Optional<int> value) { m_noninherited.z_index = value; }

View file

@ -18,8 +18,20 @@
"initial": "0% 0%"
},
"background-repeat": {
"longhands": [
"background-repeat-x",
"background-repeat-y"
]
},
"background-repeat-x": {
"inherited": false,
"initial": "repeat"
"initial": "repeat",
"pseudo": true
},
"background-repeat-y": {
"inherited": false,
"initial": "repeat",
"pseudo": true
},
"border": {
"longhands": [

View file

@ -612,9 +612,29 @@ Optional<CSS::Overflow> StyleProperties::overflow(CSS::PropertyID property_id) c
}
}
Optional<CSS::Repeat> StyleProperties::background_repeat() const
Optional<CSS::Repeat> StyleProperties::background_repeat_x() const
{
auto value = property(CSS::PropertyID::BackgroundRepeat);
auto value = property(CSS::PropertyID::BackgroundRepeatX);
if (!value.has_value())
return {};
switch (value.value()->to_identifier()) {
case CSS::ValueID::NoRepeat:
return CSS::Repeat::NoRepeat;
case CSS::ValueID::Repeat:
return CSS::Repeat::Repeat;
case CSS::ValueID::Round:
return CSS::Repeat::Round;
case CSS::ValueID::Space:
return CSS::Repeat::Space;
default:
return {};
}
}
Optional<CSS::Repeat> StyleProperties::background_repeat_y() const
{
auto value = property(CSS::PropertyID::BackgroundRepeatY);
if (!value.has_value())
return {};
@ -623,10 +643,6 @@ Optional<CSS::Repeat> StyleProperties::background_repeat() const
return CSS::Repeat::NoRepeat;
case CSS::ValueID::Repeat:
return CSS::Repeat::Repeat;
case CSS::ValueID::RepeatX:
return CSS::Repeat::RepeatX;
case CSS::ValueID::RepeatY:
return CSS::Repeat::RepeatY;
case CSS::ValueID::Round:
return CSS::Repeat::Round;
case CSS::ValueID::Space:

View file

@ -73,7 +73,8 @@ public:
Optional<CSS::FlexDirection> flex_direction() const;
Optional<CSS::Overflow> overflow_x() const;
Optional<CSS::Overflow> overflow_y() const;
Optional<CSS::Repeat> background_repeat() const;
Optional<CSS::Repeat> background_repeat_x() const;
Optional<CSS::Repeat> background_repeat_y() const;
const Gfx::Font& font() const
{

View file

@ -229,6 +229,24 @@ static inline void set_property_border_style(StyleProperties& style, const Style
style.set_property(CSS::PropertyID::BorderLeftStyle, value);
}
static inline bool is_background_repeat_property(const StyleValue& value)
{
if (!value.is_identifier())
return false;
switch (value.to_identifier()) {
case CSS::ValueID::NoRepeat:
case CSS::ValueID::Repeat:
case CSS::ValueID::RepeatX:
case CSS::ValueID::RepeatY:
case CSS::ValueID::Round:
case CSS::ValueID::Space:
return true;
default:
return false;
}
}
static void set_property_expanding_shorthands(StyleProperties& style, CSS::PropertyID property_id, const StyleValue& value, DOM::Document& document, bool is_internally_generated_pseudo_property = false)
{
CSS::ParsingContext context(document);
@ -433,12 +451,22 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
if (values[0].is_color() && color_value_count == 1)
style.set_property(CSS::PropertyID::BackgroundColor, values[0]);
for (auto& value : values) {
if (value.is_identifier())
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeat, value, document);
for (auto it = values.begin(); it != values.end(); ++it) {
auto& value = *it;
if (is_background_repeat_property(value)) {
if ((it + 1 != values.end()) && is_background_repeat_property(*(it + 1))) {
++it;
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, value, document, true);
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, *it, document, true);
} else {
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeat, value, document);
}
}
if (!value.is_string())
continue;
auto string = value.to_string();
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundImage, value, document);
}
return;
@ -464,7 +492,40 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
}
if (property_id == CSS::PropertyID::BackgroundRepeat) {
style.set_property(CSS::PropertyID::BackgroundRepeat, value);
auto parts = split_on_whitespace(value.to_string());
NonnullRefPtrVector<StyleValue> values;
for (auto& part : parts) {
auto value = parse_css_value(context, part);
if (!value || !is_background_repeat_property(*value))
return;
values.append(value.release_nonnull());
}
if (values.size() == 1) {
auto value_id = values[0].to_identifier();
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) {
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatX, values[0], document, true);
set_property_expanding_shorthands(style, CSS::PropertyID::BackgroundRepeatY, values[1], document, true);
}
return;
}
if (property_id == CSS::PropertyID::BackgroundRepeatX || property_id == CSS::PropertyID::BackgroundRepeatY) {
auto value_id = value.to_identifier();
if (value_id == CSS::ValueID::RepeatX || value_id == CSS::ValueID::RepeatY)
return;
style.set_property(property_id, value);
return;
}

View file

@ -192,8 +192,6 @@ enum class Overflow : u8 {
enum class Repeat : u8 {
NoRepeat,
Repeat,
RepeatX,
RepeatY,
Round,
Space,
};