Browse Source

LibWeb: Parse css math constants

stelar7 2 years ago
parent
commit
ba7af82c5c

+ 27 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -8209,6 +8209,33 @@ ErrorOr<OwnPtr<CalculationNode>> Parser::parse_a_calculation(Vector<ComponentVal
             }
         }
 
+        if (value.is(Token::Type::Ident)) {
+            if (value.token().ident().equals_ignoring_ascii_case("e"sv)) {
+                TRY(values.try_append({ TRY(ConstantCalculationNode::create(CalculationNode::ConstantType::E)) }));
+                continue;
+            }
+
+            if (value.token().ident().equals_ignoring_ascii_case("pi"sv)) {
+                TRY(values.try_append({ TRY(ConstantCalculationNode::create(CalculationNode::ConstantType::PI)) }));
+                continue;
+            }
+
+            if (value.token().ident().equals_ignoring_ascii_case("infinity"sv)) {
+                TRY(values.try_append({ TRY(ConstantCalculationNode::create(CalculationNode::ConstantType::Infinity)) }));
+                continue;
+            }
+
+            if (value.token().ident().equals_ignoring_ascii_case("-infinity"sv)) {
+                TRY(values.try_append({ TRY(ConstantCalculationNode::create(CalculationNode::ConstantType::MinusInfinity)) }));
+                continue;
+            }
+
+            if (value.token().ident().equals_ignoring_ascii_case("NaN"sv)) {
+                TRY(values.try_append({ TRY(ConstantCalculationNode::create(CalculationNode::ConstantType::NaN)) }));
+                continue;
+            }
+        }
+
         if (value.is(Token::Type::Number)) {
             TRY(values.try_append({ TRY(NumericCalculationNode::create(value.token().number())) }));
             continue;

+ 65 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp

@@ -777,6 +777,71 @@ ErrorOr<void> SignCalculationNode::dump(StringBuilder& builder, int indent) cons
     return {};
 }
 
+ErrorOr<NonnullOwnPtr<ConstantCalculationNode>> ConstantCalculationNode::create(ConstantType constant)
+{
+    return adopt_nonnull_own_or_enomem(new (nothrow) ConstantCalculationNode(constant));
+}
+
+ConstantCalculationNode::ConstantCalculationNode(ConstantType constant)
+    : CalculationNode(Type::Constant)
+    , m_constant(constant)
+{
+}
+
+ConstantCalculationNode::~ConstantCalculationNode() = default;
+
+ErrorOr<String> ConstantCalculationNode::to_string() const
+{
+    switch (m_constant) {
+    case CalculationNode::ConstantType::E:
+        return "e"_short_string;
+    case CalculationNode::ConstantType::PI:
+        return "pi"_short_string;
+    case CalculationNode::ConstantType::Infinity:
+        return "infinity"_string;
+    case CalculationNode::ConstantType::MinusInfinity:
+        return "-infinity"_string;
+    case CalculationNode::ConstantType::NaN:
+        return "NaN"_string;
+    }
+
+    VERIFY_NOT_REACHED();
+}
+Optional<CalculatedStyleValue::ResolvedType> ConstantCalculationNode::resolved_type() const
+{
+    return CalculatedStyleValue::ResolvedType::Number;
+}
+
+CalculatedStyleValue::CalculationResult ConstantCalculationNode::resolve([[maybe_unused]] Optional<Length::ResolutionContext const&> context, [[maybe_unused]] CalculatedStyleValue::PercentageBasis const& percentage_basis) const
+{
+    switch (m_constant) {
+    case CalculationNode::ConstantType::E:
+        return { Number(Number::Type::Number, M_E) };
+    case CalculationNode::ConstantType::PI:
+        return { Number(Number::Type::Number, M_PI) };
+    // FIXME: We need to keep track of Infinity and NaN across all nodes, since they require special handling.
+    case CalculationNode::ConstantType::Infinity:
+        return { Number(Number::Type::Number, NumericLimits<float>::max()) };
+    case CalculationNode::ConstantType::MinusInfinity:
+        return { Number(Number::Type::Number, NumericLimits<float>::lowest()) };
+    case CalculationNode::ConstantType::NaN:
+        return { Number(Number::Type::Number, NAN) };
+    }
+
+    VERIFY_NOT_REACHED();
+}
+
+ErrorOr<void> ConstantCalculationNode::for_each_child_node([[maybe_unused]] Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const& callback)
+{
+    return {};
+}
+
+ErrorOr<void> ConstantCalculationNode::dump(StringBuilder& builder, int indent) const
+{
+    TRY(builder.try_appendff("{: >{}}CONSTANT: {}\n", "", indent, TRY(to_string())));
+    return {};
+}
+
 void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other, Optional<Length::ResolutionContext const&> context, PercentageBasis const& percentage_basis)
 {
     add_or_subtract_internal(SumOperation::Add, other, context, percentage_basis);

+ 32 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h

@@ -115,6 +115,16 @@ private:
 // https://www.w3.org/TR/css-values-4/#calculation-tree
 class CalculationNode {
 public:
+    // https://drafts.csswg.org/css-values-4/#calc-constants
+    // https://drafts.csswg.org/css-values-4/#calc-error-constants
+    enum class ConstantType {
+        E,
+        PI,
+        NaN,
+        Infinity,
+        MinusInfinity,
+    };
+
     enum class Type {
         Numeric,
         // NOTE: Currently, any value with a `var()` or `attr()` function in it is always an
@@ -138,6 +148,10 @@ public:
         Abs,
         Sign,
 
+        // Constant Nodes
+        // https://drafts.csswg.org/css-values-4/#calc-constants
+        Constant,
+
         // This only exists during parsing.
         Unparsed,
     };
@@ -354,4 +368,22 @@ private:
     NonnullOwnPtr<CalculationNode> m_value;
 };
 
+class ConstantCalculationNode final : public CalculationNode {
+public:
+    static ErrorOr<NonnullOwnPtr<ConstantCalculationNode>> create(CalculationNode::ConstantType);
+    ~ConstantCalculationNode();
+
+    virtual ErrorOr<String> to_string() const override;
+    virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
+    virtual bool contains_percentage() const override { return false; };
+    virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const&) const override;
+    virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override;
+
+    virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;
+
+private:
+    ConstantCalculationNode(ConstantType);
+    CalculationNode::ConstantType m_constant;
+};
+
 }