Ver código fonte

LibWeb: Use IdentifierStyleValue for CSS 'text-decoration-line'

Also 'text-decoration' is actually a shorthand, so treat it that way.
Andreas Kling 4 anos atrás
pai
commit
4d7ce81835

+ 8 - 0
Libraries/LibWeb/CSS/Parser/CSSParser.cpp

@@ -446,6 +446,14 @@ static Optional<CSS::ValueID> value_id_from_string(const String& string)
         return CSS::ValueID::TableHeaderGroup;
     if (string.equals_ignoring_case("table-footer-group"))
         return CSS::ValueID::TableFooterGroup;
+    if (string.equals_ignoring_case("underline"))
+        return CSS::ValueID::Underline;
+    if (string.equals_ignoring_case("overline"))
+        return CSS::ValueID::Overline;
+    if (string.equals_ignoring_case("line-through"))
+        return CSS::ValueID::LineThrough;
+    if (string.equals_ignoring_case("blink"))
+        return CSS::ValueID::Blink;
     if (string.starts_with("-libweb-palette-", CaseSensitivity::CaseInsensitive))
         return value_id_for_palette_string(string.substring_view(16, string.length() - 16));
     return {};

+ 22 - 0
Libraries/LibWeb/CSS/Properties.json

@@ -304,6 +304,28 @@
     "initial": "left"
   },
   "text-decoration": {
+    "inherited": false,
+    "initial": "none",
+    "longhands": [
+      "text-decoration-color",
+      "text-decoration-line",
+      "text-decoration-style",
+      "text-decoration-thickness"
+    ]
+  },
+  "text-decoration-color": {
+    "inherited": false,
+    "initial": "none"
+  },
+  "text-decoration-line": {
+    "inherited": false,
+    "initial": "none"
+  },
+  "text-decoration-style": {
+    "inherited": false,
+    "initial": "none"
+  },
+  "text-decoration-thickness": {
     "inherited": false,
     "initial": "none"
   },

+ 21 - 0
Libraries/LibWeb/CSS/StyleProperties.cpp

@@ -409,4 +409,25 @@ CSS::Display StyleProperties::display() const
     }
 }
 
+Optional<CSS::TextDecorationLine> StyleProperties::text_decoration_line() const
+{
+    auto value = property(CSS::PropertyID::TextDecorationLine);
+    if (!value.has_value() || !value.value()->is_identifier())
+        return {};
+    switch (static_cast<const IdentifierStyleValue&>(*value.value()).id()) {
+    case CSS::ValueID::None:
+        return CSS::TextDecorationLine::None;
+    case CSS::ValueID::Underline:
+        return CSS::TextDecorationLine::Underline;
+    case CSS::ValueID::Overline:
+        return CSS::TextDecorationLine::Overline;
+    case CSS::ValueID::LineThrough:
+        return CSS::TextDecorationLine::LineThrough;
+    case CSS::ValueID::Blink:
+        return CSS::TextDecorationLine::Blink;
+    default:
+        return {};
+    }
+}
+
 }

+ 1 - 0
Libraries/LibWeb/CSS/StyleProperties.h

@@ -66,6 +66,7 @@ public:
     Optional<CSS::Clear> clear() const;
     Optional<CSS::WhiteSpace> white_space() const;
     Optional<CSS::LineStyle> line_style(CSS::PropertyID) const;
+    Optional<CSS::TextDecorationLine> text_decoration_line() const;
 
     const Gfx::Font& font() const
     {

+ 14 - 0
Libraries/LibWeb/CSS/StyleResolver.cpp

@@ -229,6 +229,20 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
 {
     CSS::ParsingContext context(document);
 
+    if (property_id == CSS::PropertyID::TextDecoration) {
+        switch (value.to_identifier()) {
+        case CSS::ValueID::None:
+        case CSS::ValueID::Underline:
+        case CSS::ValueID::Overline:
+        case CSS::ValueID::LineThrough:
+        case CSS::ValueID::Blink:
+            set_property_expanding_shorthands(style, CSS::PropertyID::TextDecorationLine, value, document);
+        default:
+            break;
+        }
+        return;
+    }
+
     if (property_id == CSS::PropertyID::Border) {
         set_property_expanding_shorthands(style, CSS::PropertyID::BorderTop, value, document);
         set_property_expanding_shorthands(style, CSS::PropertyID::BorderRight, value, document);

+ 21 - 0
Libraries/LibWeb/CSS/StyleValue.h

@@ -147,6 +147,10 @@ enum class ValueID {
     TableHeaderGroup,
     TableRowGroup,
     TableFooterGroup,
+    Underline,
+    Overline,
+    LineThrough,
+    Blink,
 };
 
 enum class Position {
@@ -165,6 +169,14 @@ enum class TextAlign {
     VendorSpecificCenter,
 };
 
+enum class TextDecorationLine {
+    None,
+    Underline,
+    Overline,
+    LineThrough,
+    Blink,
+};
+
 enum class Display {
     None,
     Block,
@@ -244,6 +256,8 @@ public:
     virtual Length to_length() const { return Length::make_auto(); }
     virtual Color to_color(const DOM::Document&) const { return {}; }
 
+    CSS::ValueID to_identifier() const;
+
     virtual bool is_auto() const { return false; }
 
     bool operator==(const StyleValue& other) const { return equals(other); }
@@ -410,4 +424,11 @@ private:
     RefPtr<Gfx::Bitmap> m_bitmap;
 };
 
+inline CSS::ValueID StyleValue::to_identifier() const
+{
+    if (is_identifier())
+        return static_cast<const IdentifierStyleValue&>(*this).id();
+    return CSS::ValueID::Invalid;
+}
+
 }

+ 4 - 0
Libraries/LibWeb/Layout/LayoutStyle.h

@@ -39,6 +39,7 @@ public:
     static CSS::WhiteSpace white_space() { return CSS::WhiteSpace::Normal; }
     static CSS::TextAlign text_align() { return CSS::TextAlign::Left; }
     static CSS::Position position() { return CSS::Position::Static; }
+    static CSS::TextDecorationLine text_decoration_line() { return CSS::TextDecorationLine::None; }
 };
 
 struct BorderData {
@@ -54,6 +55,7 @@ public:
     CSS::Clear clear() const { return m_clear; }
     Optional<int> z_index() const { return m_z_index; }
     CSS::TextAlign text_align() const { return m_text_align; }
+    CSS::TextDecorationLine text_decoration_line() const { return m_text_decoration_line; }
     CSS::Position position() const { return m_position; }
     CSS::WhiteSpace white_space() const { return m_white_space; }
     const CSS::Length& width() const { return m_width; }
@@ -77,6 +79,7 @@ protected:
     CSS::Clear m_clear { InitialValues::clear() };
     Optional<int> m_z_index;
     CSS::TextAlign m_text_align { InitialValues::text_align() };
+    CSS::TextDecorationLine m_text_decoration_line { InitialValues::text_decoration_line() };
     CSS::Position m_position { InitialValues::position() };
     CSS::WhiteSpace m_white_space { InitialValues::white_space() };
     CSS::Length m_width;
@@ -103,6 +106,7 @@ public:
     void set_clear(CSS::Clear value) { m_clear = value; }
     void set_z_index(Optional<int> value) { m_z_index = value; }
     void set_text_align(CSS::TextAlign text_align) { m_text_align = text_align; }
+    void set_text_decoration_line(CSS::TextDecorationLine value) { m_text_decoration_line = value; }
     void set_position(CSS::Position position) { m_position = position; }
     void set_white_space(CSS::WhiteSpace value) { m_white_space = value; }
     void set_width(const CSS::Length& width) { m_width = width; }

+ 4 - 0
Libraries/LibWeb/Layout/Node.cpp

@@ -239,6 +239,10 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style)
     if (clear.has_value())
         style.set_clear(clear.value());
 
+    auto text_decoration_line = specified_style.text_decoration_line();
+    if (text_decoration_line.has_value())
+        style.set_text_decoration_line(text_decoration_line.value());
+
     style.set_z_index(specified_style.z_index());
     style.set_width(specified_style.length_or_fallback(CSS::PropertyID::Width, {}));
     style.set_min_width(specified_style.length_or_fallback(CSS::PropertyID::MinWidth, {}));

+ 1 - 3
Libraries/LibWeb/Layout/TextNode.cpp

@@ -80,13 +80,11 @@ void TextNode::paint_fragment(PaintContext& context, const LineBoxFragment& frag
     if (phase == PaintPhase::Foreground) {
         painter.set_font(specified_style().font());
         auto color = specified_style().color_or_fallback(CSS::PropertyID::Color, document(), context.palette().base_text());
-        auto text_decoration = specified_style().string_or_fallback(CSS::PropertyID::TextDecoration, "none");
 
         if (document().inspected_node() == &dom_node())
             context.painter().draw_rect(enclosing_int_rect(fragment.absolute_rect()), Color::Magenta);
 
-        bool is_underline = text_decoration == "underline";
-        if (is_underline)
+        if (style().text_decoration_line() == CSS::TextDecorationLine::Underline)
             painter.draw_line(enclosing_int_rect(fragment.absolute_rect()).bottom_left().translated(0, 1), enclosing_int_rect(fragment.absolute_rect()).bottom_right().translated(0, 1), color);
 
         // FIXME: text-transform should be done already in layout, since uppercase glyphs may be wider than lowercase, etc.