diff options
author | MacDue <macdue@dueutil.tech> | 2023-04-19 18:51:00 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-04-28 09:42:28 +0200 |
commit | 297d8eebcda4663e44544e9298da192b7d8adecc (patch) | |
tree | 7083501c3c472b7f5ad0d25bdd3d9a80f46505f6 | |
parent | f099ee3d4767e1f15fe44516c99e9c9079600871 (diff) | |
download | serenity-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.h | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Properties.json | 8 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleProperties.cpp | 11 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleProperties.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/Node.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/AttributeParser.cpp | 32 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/SVG/AttributeParser.h | 29 |
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(); } |