Przeglądaj źródła

LibWeb: Use number value from CSS Tokens

This lets us get rid of `try_parse_float()`, and simplifies the various
places we were calling it before.
Sam Atkins 3 lat temu
rodzic
commit
522faa1554

+ 46 - 152
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -1854,79 +1854,6 @@ Optional<StyleProperty> Parser::convert_to_style_property(StyleDeclarationRule c
     }
 }
 
-Optional<float> Parser::try_parse_float(StringView string)
-{
-    // FIXME: This is copied from DeprecatedCSSParser, so may not be to spec.
-
-    const char* str = string.characters_without_null_termination();
-    size_t len = string.length();
-    size_t weight = 1;
-    int exp_val = 0;
-    float value = 0.0f;
-    float fraction = 0.0f;
-    bool has_sign = false;
-    bool is_negative = false;
-    bool is_fractional = false;
-    bool is_scientific = false;
-
-    if (str[0] == '-') {
-        is_negative = true;
-        has_sign = true;
-    }
-    if (str[0] == '+') {
-        has_sign = true;
-    }
-
-    for (size_t i = has_sign; i < len; i++) {
-
-        // Looks like we're about to start working on the fractional part
-        if (str[i] == '.') {
-            is_fractional = true;
-            continue;
-        }
-
-        if (str[i] == 'e' || str[i] == 'E') {
-            if (str[i + 1] == '-' || str[i + 1] == '+')
-                exp_val = atoi(str + i + 2);
-            else
-                exp_val = atoi(str + i + 1);
-
-            is_scientific = true;
-            continue;
-        }
-
-        if (str[i] < '0' || str[i] > '9' || exp_val != 0)
-            return {};
-
-        if (is_fractional) {
-            fraction *= 10;
-            fraction += str[i] - '0';
-            weight *= 10;
-        } else {
-            value = value * 10;
-            value += str[i] - '0';
-        }
-    }
-
-    fraction /= weight;
-    value += fraction;
-
-    if (is_scientific) {
-        bool divide = exp_val < 0;
-        if (divide)
-            exp_val *= -1;
-
-        for (int i = 0; i < exp_val; i++) {
-            if (divide)
-                value /= 10;
-            else
-                value *= 10;
-        }
-    }
-
-    return is_negative ? -value : value;
-}
-
 RefPtr<StyleValue> Parser::parse_builtin_value(StyleComponentValueRule const& component_value)
 {
     if (component_value.is(Token::Type::Ident)) {
@@ -1975,7 +1902,7 @@ Optional<Length> Parser::parse_length(StyleComponentValueRule const& component_v
     Optional<float> numeric_value;
 
     if (component_value.is(Token::Type::Dimension)) {
-        auto length_string = component_value.token().m_value.string_view();
+        numeric_value = component_value.token().dimension_value();
         auto unit_string = component_value.token().m_unit.string_view();
 
         if (unit_string.equals_ignoring_case("%")) {
@@ -2013,26 +1940,21 @@ Optional<Length> Parser::parse_length(StyleComponentValueRule const& component_v
         } else {
             return {};
         }
-
-        numeric_value = try_parse_float(length_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);
+        numeric_value = component_value.token().percentage();
     } else if (component_value.is(Token::Type::Ident) && component_value.token().ident().equals_ignoring_case("auto")) {
         return Length::make_auto();
     } else if (component_value.is(Token::Type::Number)) {
-        auto value_string = component_value.token().m_value.string_view();
-        if (value_string == "0") {
+        numeric_value = component_value.token().number_value();
+        if (numeric_value == 0) {
             type = Length::Type::Px;
-            numeric_value = 0;
         } else if (m_context.in_quirks_mode() && property_has_quirk(m_context.current_property_id(), Quirk::UnitlessLength)) {
             // https://quirks.spec.whatwg.org/#quirky-length-value
             // FIXME: Disallow quirk when inside a CSS sub-expression (like `calc()`)
             // "The <quirky-length> value must not be supported in arguments to CSS expressions other than the rect()
             // expression, and must not be supported in the supports() static method of the CSS interface."
             type = Length::Type::Px;
-            numeric_value = try_parse_float(value_string);
         }
     }
 
@@ -2054,7 +1976,7 @@ RefPtr<StyleValue> Parser::parse_length_value(StyleComponentValueRule const& com
     // Right now, it instead is quietly converted to an Identifier when needed.
     if (component_value.is(Token::Type::Dimension) || component_value.is(Token::Type::Percentage)
         || (component_value.is(Token::Type::Ident) && component_value.token().ident().equals_ignoring_case("auto"sv))
-        || (m_context.in_quirks_mode() && component_value.is(Token::Type::Number) && component_value.token().m_value.string_view() != "0"sv)) {
+        || (m_context.in_quirks_mode() && property_has_quirk(m_context.current_property_id(), Quirk::UnitlessLength) && component_value.is(Token::Type::Number) && component_value.token().number_value() != 0)) {
         auto length = parse_length(component_value);
         if (length.has_value())
             return LengthStyleValue::create(length.value());
@@ -2067,12 +1989,10 @@ RefPtr<StyleValue> Parser::parse_numeric_value(StyleComponentValueRule const& co
 {
     if (component_value.is(Token::Type::Number)) {
         auto number = component_value.token();
-        if (number.m_number_type == Token::NumberType::Integer) {
+        if (number.number_type() == Token::NumberType::Integer) {
             return NumericStyleValue::create_integer(number.to_integer());
         } else {
-            auto float_value = try_parse_float(number.m_value.string_view());
-            if (float_value.has_value())
-                return NumericStyleValue::create_float(float_value.value());
+            return NumericStyleValue::create_float(number.number_value());
         }
     }
 
@@ -2143,25 +2063,20 @@ Optional<Color> Parser::parse_color(StyleComponentValueRule const& component_val
                 && 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());
+                auto r = r_val.to_integer();
+                auto g = g_val.to_integer();
+                auto b = b_val.to_integer();
+                if (AK::is_within_range<u8>(r) && AK::is_within_range<u8>(g) && AK::is_within_range<u8>(b))
+                    return Color(r, g, b);
 
             } 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);
-                }
+                u8 r = clamp(lroundf(r_val.percentage() * 2.55), 0, 255);
+                u8 g = clamp(lroundf(g_val.percentage() * 2.55), 0, 255);
+                u8 b = clamp(lroundf(b_val.percentage() * 2.55), 0, 255);
+                return Color(r, g, b);
             }
         } else if (function.name().equals_ignoring_case("rgba")) {
             if (params.size() != 4)
@@ -2177,31 +2092,28 @@ Optional<Color> Parser::parse_color(StyleComponentValueRule const& component_val
                 && 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);
-                }
+                auto r = r_val.to_integer();
+                auto g = g_val.to_integer();
+                auto b = b_val.to_integer();
+                auto a = clamp(lroundf(a_val.number_value() * 255.0), 0, 255);
+                if (AK::is_within_range<u8>(r) && AK::is_within_range<u8>(g) && AK::is_within_range<u8>(b))
+                    return Color(r, g, b, 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 = r_val.percentage();
+                auto g = g_val.percentage();
+                auto b = b_val.percentage();
+                auto a = a_val.number_value();
+
+                u8 r_255 = clamp(lroundf(r * 2.55), 0, 255);
+                u8 g_255 = clamp(lroundf(g * 2.55), 0, 255);
+                u8 b_255 = clamp(lroundf(b * 2.55), 0, 255);
+                u8 a_255 = clamp(lroundf(a * 255.0), 0, 255);
+                return Color(r_255, g_255, b_255, a_255);
             }
         } else if (function.name().equals_ignoring_case("hsl")) {
             if (params.size() != 3)
@@ -2215,15 +2127,10 @@ Optional<Color> Parser::parse_color(StyleComponentValueRule const& component_val
                 && 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(static_cast<double>(h), static_cast<double>(s), static_cast<double>(l));
-                }
+                auto h = h_val.number_value();
+                auto s = s_val.percentage() / 100.0;
+                auto l = l_val.percentage() / 100.0;
+                return Color::from_hsl(h, s, l);
             }
         } else if (function.name().equals_ignoring_case("hsla")) {
             if (params.size() != 4)
@@ -2239,17 +2146,11 @@ Optional<Color> Parser::parse_color(StyleComponentValueRule const& component_val
                 && 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(static_cast<double>(h), static_cast<double>(s), static_cast<double>(l), static_cast<double>(a));
-                }
+                auto h = h_val.number_value();
+                auto s = s_val.percentage() / 100.0;
+                auto l = l_val.percentage() / 100.0;
+                auto a = a_val.number_value();
+                return Color::from_hsla(h, s, l, a);
             }
         }
         return {};
@@ -3988,20 +3889,16 @@ Optional<CalculatedStyleValue::CalcValue> Parser::parse_calc_value(TokenStream<S
         auto parsed_calc_sum = parse_calc_sum(block_values);
         if (!parsed_calc_sum)
             return {};
-        return (CalculatedStyleValue::CalcValue) { parsed_calc_sum.release_nonnull() };
+        return CalculatedStyleValue::CalcValue { parsed_calc_sum.release_nonnull() };
     }
 
-    if (current_token.is(Token::Type::Number)) {
-        auto try_the_number = try_parse_float(current_token.token().number_string_value());
-        if (try_the_number.has_value())
-            return (CalculatedStyleValue::CalcValue) { try_the_number.value() };
-        return {};
-    }
+    if (current_token.is(Token::Type::Number))
+        return CalculatedStyleValue::CalcValue { static_cast<float>(current_token.token().number_value()) };
 
     if (current_token.is(Token::Type::Dimension) || current_token.is(Token::Type::Percentage)) {
         auto maybe_length = parse_length(current_token);
         if (maybe_length.has_value() && !maybe_length.value().is_undefined())
-            return (CalculatedStyleValue::CalcValue) { maybe_length.value() };
+            return CalculatedStyleValue::CalcValue { maybe_length.value() };
         return {};
     }
 
@@ -4161,10 +4058,7 @@ Optional<CalculatedStyleValue::CalcNumberValue> Parser::parse_calc_number_value(
         return {};
     tokens.next_token();
 
-    auto try_the_number = try_parse_float(first.token().number_string_value());
-    if (!try_the_number.has_value())
-        return {};
-    return try_the_number.value();
+    return first.token().number_value();
 }
 
 OwnPtr<CalculatedStyleValue::CalcProduct> Parser::parse_calc_product(TokenStream<StyleComponentValueRule>& tokens)

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

@@ -178,7 +178,6 @@ private:
     [[nodiscard]] RefPtr<CSSRule> convert_to_rule(NonnullRefPtr<StyleRule>);
     [[nodiscard]] RefPtr<PropertyOwningCSSStyleDeclaration> convert_to_declaration(NonnullRefPtr<StyleBlockRule>);
 
-    Optional<float> try_parse_float(StringView string);
     Optional<Color> parse_color(StyleComponentValueRule const&);
     Optional<Length> parse_length(StyleComponentValueRule const&);