summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMacDue <macdue@dueutil.tech>2023-04-19 18:51:00 +0100
committerAndreas Kling <kling@serenityos.org>2023-04-28 09:42:28 +0200
commit297d8eebcda4663e44544e9298da192b7d8adecc (patch)
tree7083501c3c472b7f5ad0d25bdd3d9a80f46505f6
parentf099ee3d4767e1f15fe44516c99e9c9079600871 (diff)
downloadserenity-297d8eebcda4663e44544e9298da192b7d8adecc.zip
LibWeb: Add stop-color as a CSS property
(This is to set the color of a stop for an SVG gradient)
-rw-r--r--Userland/Libraries/LibWeb/CSS/ComputedValues.h4
-rw-r--r--Userland/Libraries/LibWeb/CSS/Properties.json8
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleProperties.cpp11
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleProperties.h2
-rw-r--r--Userland/Libraries/LibWeb/Layout/Node.cpp2
-rw-r--r--Userland/Libraries/LibWeb/SVG/AttributeParser.cpp32
-rw-r--r--Userland/Libraries/LibWeb/SVG/AttributeParser.h29
7 files changed, 86 insertions, 2 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h
index f742d79bce..5cba459aef 100644
--- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h
+++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h
@@ -41,6 +41,7 @@ public:
static CSS::TextTransform text_transform() { return CSS::TextTransform::None; }
static CSS::Display display() { return CSS::Display { CSS::Display::Outside::Inline, CSS::Display::Inside::Flow }; }
static Color color() { return Color::Black; }
+ static Color stop_color() { return Color::Black; }
static CSS::BackdropFilter backdrop_filter() { return BackdropFilter::make_none(); }
static Color background_color() { return Color::Transparent; }
static CSS::ListStyleType list_style_type() { return CSS::ListStyleType::Disc; }
@@ -259,6 +260,7 @@ public:
Optional<Color> const& fill() const { return m_inherited.fill; }
Optional<Color> const& stroke() const { return m_inherited.stroke; }
Optional<LengthPercentage> const& stroke_width() const { return m_inherited.stroke_width; }
+ Color stop_color() const { return m_noninherited.stop_color; }
Vector<CSS::Transformation> const& transformations() const { return m_noninherited.transformations; }
CSS::TransformOrigin const& transform_origin() const { return m_noninherited.transform_origin; }
@@ -359,6 +361,7 @@ protected:
CSS::Size row_gap { InitialValues::row_gap() };
CSS::BorderCollapse border_collapse { InitialValues::border_collapse() };
Vector<Vector<String>> grid_template_areas { InitialValues::grid_template_areas() };
+ Gfx::Color stop_color { InitialValues::stop_color() };
} m_noninherited;
};
@@ -446,6 +449,7 @@ public:
void set_fill(Color value) { m_inherited.fill = value; }
void set_stroke(Color value) { m_inherited.stroke = value; }
void set_stroke_width(LengthPercentage value) { m_inherited.stroke_width = value; }
+ void set_stop_color(Color value) { m_noninherited.stop_color = value; }
};
}
diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json
index ab45611cf7..5b9b2990ab 100644
--- a/Userland/Libraries/LibWeb/CSS/Properties.json
+++ b/Userland/Libraries/LibWeb/CSS/Properties.json
@@ -1411,6 +1411,14 @@
"none"
]
},
+ "stop-color": {
+ "affects-layout": false,
+ "inherited": false,
+ "initial": "black",
+ "valid-types": [
+ "color"
+ ]
+ },
"stroke-width": {
"affects-layout": false,
"inherited": true,
diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp
index 204c0b490e..bb4e5b8ade 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp
+++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp
@@ -818,4 +818,15 @@ String StyleProperties::grid_area() const
return value->as_string().to_string().release_value_but_fixme_should_propagate_errors();
}
+Color StyleProperties::stop_color() const
+{
+ auto value = property(CSS::PropertyID::StopColor);
+ if (value->has_color()) {
+ // FIXME: This is used by the SVGStopElement, which does not participate in layout,
+ // so can't pass a layout node (so can't resolve some colors, e.g. palette ones or currentColor)
+ return value->to_color({});
+ }
+ return Color::Black;
+}
+
}
diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.h b/Userland/Libraries/LibWeb/CSS/StyleProperties.h
index 404491dee5..179ba7968e 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleProperties.h
+++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.h
@@ -98,6 +98,8 @@ public:
Vector<CSS::Transformation> transformations() const;
CSS::TransformOrigin transform_origin() const;
+ Color stop_color() const;
+
Gfx::Font const& computed_font() const
{
VERIFY(m_font);
diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp
index eecb8a543b..9d4b6a89c9 100644
--- a/Userland/Libraries/LibWeb/Layout/Node.cpp
+++ b/Userland/Libraries/LibWeb/Layout/Node.cpp
@@ -650,6 +650,8 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
computed_values.set_fill(fill->to_color(*this));
if (auto stroke = computed_style.property(CSS::PropertyID::Stroke); stroke->has_color())
computed_values.set_stroke(stroke->to_color(*this));
+ if (auto stop_color = computed_style.property(CSS::PropertyID::StopColor); stop_color->has_color())
+ computed_values.set_stop_color(stop_color->to_color(*this));
auto stroke_width = computed_style.property(CSS::PropertyID::StrokeWidth);
// FIXME: Converting to pixels isn't really correct - values should be in "user units"
// https://svgwg.org/svg2-draft/coords.html#TermUserUnits
diff --git a/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp b/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp
index 64ccd31c44..f4cc77a016 100644
--- a/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp
+++ b/Userland/Libraries/LibWeb/SVG/AttributeParser.cpp
@@ -66,6 +66,30 @@ Optional<float> AttributeParser::parse_length(StringView input)
return {};
}
+float NumberPercentage::resolve_relative_to(float length)
+{
+ if (!m_is_percentage)
+ return m_value;
+ return m_value * length;
+}
+
+Optional<NumberPercentage> AttributeParser::parse_number_percentage(StringView input)
+{
+ AttributeParser parser { input };
+ parser.parse_whitespace();
+ if (parser.match_number()) {
+ float number = parser.parse_number();
+ bool is_percentage = parser.match('%');
+ if (is_percentage)
+ parser.consume();
+ parser.parse_whitespace();
+ if (parser.done())
+ return NumberPercentage(number, is_percentage);
+ }
+
+ return {};
+}
+
Optional<float> AttributeParser::parse_positive_length(StringView input)
{
// FIXME: Where this is used, the spec usually (always?) says "A negative value is an error (see Error processing)."
@@ -482,11 +506,10 @@ Optional<Vector<Transform>> AttributeParser::parse_transform()
m_lexer.consume_specific(',');
consume_whitespace();
};
-
// FIXME: AttributeParser currently does not handle invalid parses in most cases (e.g. parse_number()) and just crashes.
auto parse_optional_number = [&](float default_value = 0.0f) {
consume_comma_whitespace();
- if (m_lexer.next_is(isdigit))
+ if (match_number())
return parse_number();
return default_value;
};
@@ -586,6 +609,11 @@ bool AttributeParser::match_coordinate() const
return match_length();
}
+bool AttributeParser::match_number() const
+{
+ return match_length();
+}
+
bool AttributeParser::match_length() const
{
return !done() && (isdigit(ch()) || ch() == '-' || ch() == '+' || ch() == '.');
diff --git a/Userland/Libraries/LibWeb/SVG/AttributeParser.h b/Userland/Libraries/LibWeb/SVG/AttributeParser.h
index 164b184a9a..7ddcedc573 100644
--- a/Userland/Libraries/LibWeb/SVG/AttributeParser.h
+++ b/Userland/Libraries/LibWeb/SVG/AttributeParser.h
@@ -88,12 +88,40 @@ struct PreserveAspectRatio {
MeetOrSlice meet_or_slice { MeetOrSlice::Meet };
};
+class NumberPercentage {
+public:
+ NumberPercentage(float value, bool is_percentage)
+ : m_value(is_percentage ? value / 100 : value)
+ , m_is_percentage(is_percentage)
+ {
+ }
+
+ static NumberPercentage create_percentage(float value)
+ {
+ return NumberPercentage(value, true);
+ }
+
+ static NumberPercentage create_number(float value)
+ {
+ return NumberPercentage(value, false);
+ }
+
+ float resolve_relative_to(float length);
+
+ float value() { return m_value; }
+
+private:
+ float m_value;
+ bool m_is_percentage { false };
+};
+
class AttributeParser final {
public:
~AttributeParser() = default;
static Optional<float> parse_coordinate(StringView input);
static Optional<float> parse_length(StringView input);
+ static Optional<NumberPercentage> parse_number_percentage(StringView input);
static Optional<float> parse_positive_length(StringView input);
static Vector<Gfx::FloatPoint> parse_points(StringView input);
static Vector<PathInstruction> parse_path_data(StringView input);
@@ -137,6 +165,7 @@ private:
bool match_comma_whitespace() const;
bool match_coordinate() const;
bool match_length() const;
+ bool match_number() const;
bool match(char c) const { return !done() && ch() == c; }
bool done() const { return m_lexer.is_eof(); }