Преглед на файлове

LibWeb: Convert CSS parse_{color,length}() lambdas into methods

This lets us get the Length and Color values directly, without having to
create a StyleValue object and then throw it away again, when parsing
the box-shadow property in the next commit.
Sam Atkins преди 4 години
родител
ревизия
697bffa3bd
променени са 2 файла, в които са добавени 217 реда и са изтрити 213 реда
  1. 215 213
      Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
  2. 2 0
      Userland/Libraries/LibWeb/CSS/Parser/Parser.h

+ 215 - 213
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -1414,74 +1414,75 @@ RefPtr<StyleValue> Parser::parse_keyword_or_custom_value(ParsingContext const&,
     return {};
     return {};
 }
 }
 
 
-RefPtr<StyleValue> Parser::parse_length_value(ParsingContext const& context, StyleComponentValueRule const& component_value)
+Optional<Length> Parser::parse_length(ParsingContext const& context, StyleComponentValueRule const& component_value)
 {
 {
-    auto parse_length = [&]() -> Optional<Length> {
-        Length::Type type = Length::Type::Undefined;
-        Optional<float> numeric_value;
-
-        if (component_value.is(Token::Type::Dimension)) {
-            auto length_string = component_value.token().m_value.string_view();
-            auto unit_string = component_value.token().m_unit.string_view();
-
-            if (unit_string.equals_ignoring_case("%")) {
-                type = Length::Type::Percentage;
-            } else if (unit_string.equals_ignoring_case("px")) {
-                type = Length::Type::Px;
-            } else if (unit_string.equals_ignoring_case("pt")) {
-                type = Length::Type::Pt;
-            } else if (unit_string.equals_ignoring_case("pc")) {
-                type = Length::Type::Pc;
-            } else if (unit_string.equals_ignoring_case("mm")) {
-                type = Length::Type::Mm;
-            } else if (unit_string.equals_ignoring_case("rem")) {
-                type = Length::Type::Rem;
-            } else if (unit_string.equals_ignoring_case("em")) {
-                type = Length::Type::Em;
-            } else if (unit_string.equals_ignoring_case("ex")) {
-                type = Length::Type::Ex;
-            } else if (unit_string.equals_ignoring_case("vw")) {
-                type = Length::Type::Vw;
-            } else if (unit_string.equals_ignoring_case("vh")) {
-                type = Length::Type::Vh;
-            } else if (unit_string.equals_ignoring_case("vmax")) {
-                type = Length::Type::Vmax;
-            } else if (unit_string.equals_ignoring_case("vmin")) {
-                type = Length::Type::Vmin;
-            } else if (unit_string.equals_ignoring_case("cm")) {
-                type = Length::Type::Cm;
-            } else if (unit_string.equals_ignoring_case("in")) {
-                type = Length::Type::In;
-            } else if (unit_string.equals_ignoring_case("Q")) {
-                type = Length::Type::Q;
-            } else if (context.in_quirks_mode()) {
-                type = Length::Type::Px;
-            }
+    Length::Type type = Length::Type::Undefined;
+    Optional<float> numeric_value;
 
 
-            numeric_value = try_parse_float(length_string);
-        } else if (component_value.is(Token::Type::Number)) {
-            auto value_string = component_value.token().m_value.string_view();
-            if (value_string == "0") {
-                type = Length::Type::Px;
-                numeric_value = 0;
-            } else if (context.in_quirks_mode()) {
-                type = Length::Type::Px;
-                numeric_value = try_parse_float(value_string);
-            }
-        } else if (component_value.is(Token::Type::Percentage)) {
+    if (component_value.is(Token::Type::Dimension)) {
+        auto length_string = component_value.token().m_value.string_view();
+        auto unit_string = component_value.token().m_unit.string_view();
+
+        if (unit_string.equals_ignoring_case("%")) {
             type = Length::Type::Percentage;
             type = Length::Type::Percentage;
-            auto value_string = component_value.token().m_value.string_view();
+        } else if (unit_string.equals_ignoring_case("px")) {
+            type = Length::Type::Px;
+        } else if (unit_string.equals_ignoring_case("pt")) {
+            type = Length::Type::Pt;
+        } else if (unit_string.equals_ignoring_case("pc")) {
+            type = Length::Type::Pc;
+        } else if (unit_string.equals_ignoring_case("mm")) {
+            type = Length::Type::Mm;
+        } else if (unit_string.equals_ignoring_case("rem")) {
+            type = Length::Type::Rem;
+        } else if (unit_string.equals_ignoring_case("em")) {
+            type = Length::Type::Em;
+        } else if (unit_string.equals_ignoring_case("ex")) {
+            type = Length::Type::Ex;
+        } else if (unit_string.equals_ignoring_case("vw")) {
+            type = Length::Type::Vw;
+        } else if (unit_string.equals_ignoring_case("vh")) {
+            type = Length::Type::Vh;
+        } else if (unit_string.equals_ignoring_case("vmax")) {
+            type = Length::Type::Vmax;
+        } else if (unit_string.equals_ignoring_case("vmin")) {
+            type = Length::Type::Vmin;
+        } else if (unit_string.equals_ignoring_case("cm")) {
+            type = Length::Type::Cm;
+        } else if (unit_string.equals_ignoring_case("in")) {
+            type = Length::Type::In;
+        } else if (unit_string.equals_ignoring_case("Q")) {
+            type = Length::Type::Q;
+        } else if (context.in_quirks_mode()) {
+            type = Length::Type::Px;
+        }
+
+        numeric_value = try_parse_float(length_string);
+    } else if (component_value.is(Token::Type::Number)) {
+        auto value_string = component_value.token().m_value.string_view();
+        if (value_string == "0") {
+            type = Length::Type::Px;
+            numeric_value = 0;
+        } else if (context.in_quirks_mode()) {
+            type = Length::Type::Px;
             numeric_value = try_parse_float(value_string);
             numeric_value = try_parse_float(value_string);
         }
         }
+    } else if (component_value.is(Token::Type::Percentage)) {
+        type = Length::Type::Percentage;
+        auto value_string = component_value.token().m_value.string_view();
+        numeric_value = try_parse_float(value_string);
+    }
 
 
-        if (!numeric_value.has_value())
-            return {};
+    if (!numeric_value.has_value())
+        return {};
 
 
-        return Length(numeric_value.value(), type);
-    };
+    return Length(numeric_value.value(), type);
+}
 
 
+RefPtr<StyleValue> Parser::parse_length_value(ParsingContext const& context, StyleComponentValueRule const& component_value)
+{
     if (component_value.is(Token::Type::Dimension) || component_value.is(Token::Type::Number) || component_value.is(Token::Type::Percentage)) {
     if (component_value.is(Token::Type::Dimension) || component_value.is(Token::Type::Number) || component_value.is(Token::Type::Percentage)) {
-        auto length = parse_length();
+        auto length = parse_length(context, component_value);
         if (length.has_value())
         if (length.has_value())
             return LengthStyleValue::create(length.value());
             return LengthStyleValue::create(length.value());
     }
     }
@@ -1516,178 +1517,179 @@ RefPtr<StyleValue> Parser::parse_identifier_value(ParsingContext const&, StyleCo
     return {};
     return {};
 }
 }
 
 
-RefPtr<StyleValue> Parser::parse_color_value(ParsingContext const&, StyleComponentValueRule const& component_value)
+Optional<Color> Parser::parse_color(ParsingContext const&, StyleComponentValueRule const& component_value)
 {
 {
     // https://www.w3.org/TR/css-color-3/
     // https://www.w3.org/TR/css-color-3/
-    auto parse_css_color = [&]() -> Optional<Color> {
-        if (component_value.is(Token::Type::Ident)) {
-            auto ident = component_value.token().ident();
-            if (ident.equals_ignoring_case("transparent"))
-                return Color::from_rgba(0x00000000);
-
-            auto color = Color::from_string(ident.to_string().to_lowercase());
-            if (color.has_value())
-                return color;
-
-        } else if (component_value.is(Token::Type::Hash)) {
-            // FIXME: Read it directly
-            auto color = Color::from_string(String::formatted("#{}", component_value.token().m_value.to_string().to_lowercase()));
-            if (color.has_value())
-                return color;
-
-        } else if (component_value.is_function()) {
-            auto& function = component_value.function();
-            auto& values = function.values();
-
-            Vector<Token> params;
-            for (size_t i = 0; i < values.size(); ++i) {
-                auto& value = values.at(i);
-                if (value.is(Token::Type::Whitespace))
-                    continue;
+    if (component_value.is(Token::Type::Ident)) {
+        auto ident = component_value.token().ident();
+        if (ident.equals_ignoring_case("transparent"))
+            return Color::from_rgba(0x00000000);
+
+        auto color = Color::from_string(ident.to_string().to_lowercase());
+        if (color.has_value())
+            return color;
+
+    } else if (component_value.is(Token::Type::Hash)) {
+        // FIXME: Read it directly
+        auto color = Color::from_string(String::formatted("#{}", component_value.token().m_value.to_string().to_lowercase()));
+        if (color.has_value())
+            return color;
+
+    } else if (component_value.is_function()) {
+        auto& function = component_value.function();
+        auto& values = function.values();
+
+        Vector<Token> params;
+        for (size_t i = 0; i < values.size(); ++i) {
+            auto& value = values.at(i);
+            if (value.is(Token::Type::Whitespace))
+                continue;
+
+            if (value.is(Token::Type::Percentage) || value.is(Token::Type::Number)) {
+                params.append(value.token());
+                // Eat following comma and whitespace
+                while ((i + 1) < values.size()) {
+                    auto& next = values.at(i + 1);
+                    if (next.is(Token::Type::Whitespace))
+                        i++;
+                    else if (next.is(Token::Type::Comma))
+                        break;
 
 
-                if (value.is(Token::Type::Percentage) || value.is(Token::Type::Number)) {
-                    params.append(value.token());
-                    // Eat following comma and whitespace
-                    while ((i + 1) < values.size()) {
-                        auto& next = values.at(i + 1);
-                        if (next.is(Token::Type::Whitespace))
-                            i++;
-                        else if (next.is(Token::Type::Comma))
-                            break;
-
-                        return {};
-                    }
+                    return {};
                 }
                 }
             }
             }
+        }
 
 
-            if (function.name().equals_ignoring_case("rgb")) {
-                if (params.size() != 3)
-                    return {};
+        if (function.name().equals_ignoring_case("rgb")) {
+            if (params.size() != 3)
+                return {};
 
 
-                auto r_val = params[0];
-                auto g_val = params[1];
-                auto b_val = params[2];
-
-                if (r_val.is(Token::NumberType::Integer)
-                    && g_val.is(Token::NumberType::Integer)
-                    && b_val.is(Token::NumberType::Integer)) {
-
-                    auto maybe_r = r_val.m_value.string_view().to_uint<u8>();
-                    auto maybe_g = g_val.m_value.string_view().to_uint<u8>();
-                    auto maybe_b = b_val.m_value.string_view().to_uint<u8>();
-                    if (maybe_r.has_value() && maybe_g.has_value() && maybe_b.has_value())
-                        return Color(maybe_r.value(), maybe_g.value(), maybe_b.value());
-
-                } else if (r_val.is(Token::Type::Percentage)
-                    && g_val.is(Token::Type::Percentage)
-                    && b_val.is(Token::Type::Percentage)) {
-
-                    auto maybe_r = try_parse_float(r_val.m_value.string_view());
-                    auto maybe_g = try_parse_float(g_val.m_value.string_view());
-                    auto maybe_b = try_parse_float(b_val.m_value.string_view());
-                    if (maybe_r.has_value() && maybe_g.has_value() && maybe_b.has_value()) {
-                        u8 r = clamp(lroundf(maybe_r.value() * 2.55f), 0, 255);
-                        u8 g = clamp(lroundf(maybe_g.value() * 2.55f), 0, 255);
-                        u8 b = clamp(lroundf(maybe_b.value() * 2.55f), 0, 255);
-                        return Color(r, g, b);
-                    }
+            auto r_val = params[0];
+            auto g_val = params[1];
+            auto b_val = params[2];
+
+            if (r_val.is(Token::NumberType::Integer)
+                && g_val.is(Token::NumberType::Integer)
+                && b_val.is(Token::NumberType::Integer)) {
+
+                auto maybe_r = r_val.m_value.string_view().to_uint<u8>();
+                auto maybe_g = g_val.m_value.string_view().to_uint<u8>();
+                auto maybe_b = b_val.m_value.string_view().to_uint<u8>();
+                if (maybe_r.has_value() && maybe_g.has_value() && maybe_b.has_value())
+                    return Color(maybe_r.value(), maybe_g.value(), maybe_b.value());
+
+            } else if (r_val.is(Token::Type::Percentage)
+                && g_val.is(Token::Type::Percentage)
+                && b_val.is(Token::Type::Percentage)) {
+
+                auto maybe_r = try_parse_float(r_val.m_value.string_view());
+                auto maybe_g = try_parse_float(g_val.m_value.string_view());
+                auto maybe_b = try_parse_float(b_val.m_value.string_view());
+                if (maybe_r.has_value() && maybe_g.has_value() && maybe_b.has_value()) {
+                    u8 r = clamp(lroundf(maybe_r.value() * 2.55f), 0, 255);
+                    u8 g = clamp(lroundf(maybe_g.value() * 2.55f), 0, 255);
+                    u8 b = clamp(lroundf(maybe_b.value() * 2.55f), 0, 255);
+                    return Color(r, g, b);
                 }
                 }
-            } else if (function.name().equals_ignoring_case("rgba")) {
-                if (params.size() != 4)
-                    return {};
+            }
+        } else if (function.name().equals_ignoring_case("rgba")) {
+            if (params.size() != 4)
+                return {};
 
 
-                auto r_val = params[0];
-                auto g_val = params[1];
-                auto b_val = params[2];
-                auto a_val = params[3];
-
-                if (r_val.is(Token::NumberType::Integer)
-                    && g_val.is(Token::NumberType::Integer)
-                    && b_val.is(Token::NumberType::Integer)
-                    && a_val.is(Token::Type::Number)) {
-
-                    auto maybe_r = r_val.m_value.string_view().to_uint<u8>();
-                    auto maybe_g = g_val.m_value.string_view().to_uint<u8>();
-                    auto maybe_b = b_val.m_value.string_view().to_uint<u8>();
-                    auto maybe_a = try_parse_float(a_val.m_value.string_view());
-                    if (maybe_r.has_value() && maybe_g.has_value() && maybe_b.has_value() && maybe_a.has_value()) {
-                        u8 a = clamp(lroundf(maybe_a.value() * 255.0f), 0, 255);
-                        return Color(maybe_r.value(), maybe_g.value(), maybe_b.value(), a);
-                    }
-
-                } else if (r_val.is(Token::Type::Percentage)
-                    && g_val.is(Token::Type::Percentage)
-                    && b_val.is(Token::Type::Percentage)
-                    && a_val.is(Token::Type::Number)) {
-
-                    auto maybe_r = try_parse_float(r_val.m_value.string_view());
-                    auto maybe_g = try_parse_float(g_val.m_value.string_view());
-                    auto maybe_b = try_parse_float(b_val.m_value.string_view());
-                    auto maybe_a = try_parse_float(a_val.m_value.string_view());
-                    if (maybe_r.has_value() && maybe_g.has_value() && maybe_b.has_value() && maybe_a.has_value()) {
-                        u8 r = clamp(lroundf(maybe_r.value() * 2.55f), 0, 255);
-                        u8 g = clamp(lroundf(maybe_g.value() * 2.55f), 0, 255);
-                        u8 b = clamp(lroundf(maybe_b.value() * 2.55f), 0, 255);
-                        u8 a = clamp(lroundf(maybe_a.value() * 255.0f), 0, 255);
-                        return Color(r, g, b, a);
-                    }
+            auto r_val = params[0];
+            auto g_val = params[1];
+            auto b_val = params[2];
+            auto a_val = params[3];
+
+            if (r_val.is(Token::NumberType::Integer)
+                && g_val.is(Token::NumberType::Integer)
+                && b_val.is(Token::NumberType::Integer)
+                && a_val.is(Token::Type::Number)) {
+
+                auto maybe_r = r_val.m_value.string_view().to_uint<u8>();
+                auto maybe_g = g_val.m_value.string_view().to_uint<u8>();
+                auto maybe_b = b_val.m_value.string_view().to_uint<u8>();
+                auto maybe_a = try_parse_float(a_val.m_value.string_view());
+                if (maybe_r.has_value() && maybe_g.has_value() && maybe_b.has_value() && maybe_a.has_value()) {
+                    u8 a = clamp(lroundf(maybe_a.value() * 255.0f), 0, 255);
+                    return Color(maybe_r.value(), maybe_g.value(), maybe_b.value(), a);
                 }
                 }
-            } else if (function.name().equals_ignoring_case("hsl")) {
-                if (params.size() != 3)
-                    return {};
 
 
-                auto h_val = params[0];
-                auto s_val = params[1];
-                auto l_val = params[2];
-
-                if (h_val.is(Token::Type::Number)
-                    && s_val.is(Token::Type::Percentage)
-                    && l_val.is(Token::Type::Percentage)) {
-
-                    auto maybe_h = try_parse_float(h_val.m_value.string_view());
-                    auto maybe_s = try_parse_float(s_val.m_value.string_view());
-                    auto maybe_l = try_parse_float(l_val.m_value.string_view());
-                    if (maybe_h.has_value() && maybe_s.has_value() && maybe_l.has_value()) {
-                        float h = maybe_h.value();
-                        float s = maybe_s.value() / 100.0f;
-                        float l = maybe_l.value() / 100.0f;
-                        return Color::from_hsl(h, s, l);
-                    }
+            } else if (r_val.is(Token::Type::Percentage)
+                && g_val.is(Token::Type::Percentage)
+                && b_val.is(Token::Type::Percentage)
+                && a_val.is(Token::Type::Number)) {
+
+                auto maybe_r = try_parse_float(r_val.m_value.string_view());
+                auto maybe_g = try_parse_float(g_val.m_value.string_view());
+                auto maybe_b = try_parse_float(b_val.m_value.string_view());
+                auto maybe_a = try_parse_float(a_val.m_value.string_view());
+                if (maybe_r.has_value() && maybe_g.has_value() && maybe_b.has_value() && maybe_a.has_value()) {
+                    u8 r = clamp(lroundf(maybe_r.value() * 2.55f), 0, 255);
+                    u8 g = clamp(lroundf(maybe_g.value() * 2.55f), 0, 255);
+                    u8 b = clamp(lroundf(maybe_b.value() * 2.55f), 0, 255);
+                    u8 a = clamp(lroundf(maybe_a.value() * 255.0f), 0, 255);
+                    return Color(r, g, b, a);
                 }
                 }
-            } else if (function.name().equals_ignoring_case("hsla")) {
-                if (params.size() != 4)
-                    return {};
+            }
+        } else if (function.name().equals_ignoring_case("hsl")) {
+            if (params.size() != 3)
+                return {};
 
 
-                auto h_val = params[0];
-                auto s_val = params[1];
-                auto l_val = params[2];
-                auto a_val = params[3];
-
-                if (h_val.is(Token::Type::Number)
-                    && s_val.is(Token::Type::Percentage)
-                    && l_val.is(Token::Type::Percentage)
-                    && a_val.is(Token::Type::Number)) {
-
-                    auto maybe_h = try_parse_float(h_val.m_value.string_view());
-                    auto maybe_s = try_parse_float(s_val.m_value.string_view());
-                    auto maybe_l = try_parse_float(l_val.m_value.string_view());
-                    auto maybe_a = try_parse_float(a_val.m_value.string_view());
-                    if (maybe_h.has_value() && maybe_s.has_value() && maybe_l.has_value() && maybe_a.has_value()) {
-                        float h = maybe_h.value();
-                        float s = maybe_s.value() / 100.0f;
-                        float l = maybe_l.value() / 100.0f;
-                        float a = maybe_a.value();
-                        return Color::from_hsla(h, s, l, a);
-                    }
+            auto h_val = params[0];
+            auto s_val = params[1];
+            auto l_val = params[2];
+
+            if (h_val.is(Token::Type::Number)
+                && s_val.is(Token::Type::Percentage)
+                && l_val.is(Token::Type::Percentage)) {
+
+                auto maybe_h = try_parse_float(h_val.m_value.string_view());
+                auto maybe_s = try_parse_float(s_val.m_value.string_view());
+                auto maybe_l = try_parse_float(l_val.m_value.string_view());
+                if (maybe_h.has_value() && maybe_s.has_value() && maybe_l.has_value()) {
+                    float h = maybe_h.value();
+                    float s = maybe_s.value() / 100.0f;
+                    float l = maybe_l.value() / 100.0f;
+                    return Color::from_hsl(h, s, l);
                 }
                 }
             }
             }
-            return {};
-        }
+        } else if (function.name().equals_ignoring_case("hsla")) {
+            if (params.size() != 4)
+                return {};
 
 
+            auto h_val = params[0];
+            auto s_val = params[1];
+            auto l_val = params[2];
+            auto a_val = params[3];
+
+            if (h_val.is(Token::Type::Number)
+                && s_val.is(Token::Type::Percentage)
+                && l_val.is(Token::Type::Percentage)
+                && a_val.is(Token::Type::Number)) {
+
+                auto maybe_h = try_parse_float(h_val.m_value.string_view());
+                auto maybe_s = try_parse_float(s_val.m_value.string_view());
+                auto maybe_l = try_parse_float(l_val.m_value.string_view());
+                auto maybe_a = try_parse_float(a_val.m_value.string_view());
+                if (maybe_h.has_value() && maybe_s.has_value() && maybe_l.has_value() && maybe_a.has_value()) {
+                    float h = maybe_h.value();
+                    float s = maybe_s.value() / 100.0f;
+                    float l = maybe_l.value() / 100.0f;
+                    float a = maybe_a.value();
+                    return Color::from_hsla(h, s, l, a);
+                }
+            }
+        }
         return {};
         return {};
-    };
+    }
 
 
-    auto color = parse_css_color();
+    return {};
+}
+
+RefPtr<StyleValue> Parser::parse_color_value(ParsingContext const& context, StyleComponentValueRule const& component_value)
+{
+    auto color = parse_color(context, component_value);
     if (color.has_value())
     if (color.has_value())
         return ColorStyleValue::create(color.value());
         return ColorStyleValue::create(color.value());
 
 

+ 2 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.h

@@ -165,6 +165,8 @@ private:
     [[nodiscard]] Optional<StyleProperty> convert_to_style_property(StyleDeclarationRule&);
     [[nodiscard]] Optional<StyleProperty> convert_to_style_property(StyleDeclarationRule&);
 
 
     static Optional<float> try_parse_float(StringView string);
     static Optional<float> try_parse_float(StringView string);
+    static Optional<Color> parse_color(ParsingContext const&, StyleComponentValueRule const&);
+    static Optional<Length> parse_length(ParsingContext const&, StyleComponentValueRule const&);
     static Optional<URL> parse_url_function(ParsingContext const&, StyleComponentValueRule const&);
     static Optional<URL> parse_url_function(ParsingContext const&, StyleComponentValueRule const&);
 
 
     static RefPtr<StyleValue> parse_keyword_or_custom_value(ParsingContext const&, StyleComponentValueRule const&);
     static RefPtr<StyleValue> parse_keyword_or_custom_value(ParsingContext const&, StyleComponentValueRule const&);