summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2022-03-21 20:54:45 +0000
committerAndreas Kling <kling@serenityos.org>2022-03-22 15:47:36 +0100
commite8ab2dab111aa40af6843f98e8fee3ab4bc7e43e (patch)
treef7b025b1645e6308ba3ed182e4a38fa209198ff3 /Userland/Libraries
parent0795b9f7bbb83e37e9258da6dc780a95a548a56e (diff)
downloadserenity-e8ab2dab111aa40af6843f98e8fee3ab4bc7e43e.zip
LibWeb: Implement a CSS::Number class
We have the same "number and is-integer flag" structure in several places, so let's put that in a class.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r--Userland/Libraries/LibWeb/CSS/Number.h84
-rw-r--r--Userland/Libraries/LibWeb/Forward.h1
2 files changed, 85 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Number.h b/Userland/Libraries/LibWeb/CSS/Number.h
new file mode 100644
index 0000000000..7b48a54881
--- /dev/null
+++ b/Userland/Libraries/LibWeb/CSS/Number.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2022, Sam Atkins <atkinssj@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/Types.h>
+#include <math.h>
+
+namespace Web::CSS {
+
+class Tokenizer;
+
+class Number {
+ friend class Tokenizer;
+
+public:
+ enum class Type {
+ Number,
+ IntegerWithExplicitSign, // This only exists for the nightmarish An+B parsing algorithm
+ Integer
+ };
+
+ Number()
+ : m_value(0)
+ , m_type(Type::Number)
+ {
+ }
+ Number(Type type, float value)
+ : m_value(value)
+ , m_type(type)
+ {
+ }
+
+ float value() const { return m_value; }
+ i64 integer_value() const
+ {
+ // https://www.w3.org/TR/css-values-4/#numeric-types
+ // When a value cannot be explicitly supported due to range/precision limitations, it must be converted
+ // to the closest value supported by the implementation, but how the implementation defines "closest"
+ // is explicitly undefined as well.
+ return llroundf(m_value);
+ }
+ bool is_integer() const { return m_type == Type::Integer || m_type == Type::IntegerWithExplicitSign; }
+ bool is_integer_with_explicit_sign() const { return m_type == Type::IntegerWithExplicitSign; }
+
+ Number operator+(Number const& other) const
+ {
+ if (is_integer() && other.is_integer())
+ return { Type::Integer, m_value + other.m_value };
+ return { Type::Number, m_value + other.m_value };
+ }
+
+ Number operator-(Number const& other) const
+ {
+ if (is_integer() && other.is_integer())
+ return { Type::Integer, m_value - other.m_value };
+ return { Type::Number, m_value - other.m_value };
+ }
+
+ Number operator*(Number const& other) const
+ {
+ if (is_integer() && other.is_integer())
+ return { Type::Integer, m_value * other.m_value };
+ return { Type::Number, m_value * other.m_value };
+ }
+
+ Number operator/(Number const& other) const
+ {
+ return { Type::Number, m_value / other.m_value };
+ }
+
+ auto operator<=>(Number const& other) const
+ {
+ return m_value - other.m_value;
+ }
+
+private:
+ float m_value { 0 };
+ Type m_type;
+};
+}
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index 981936578e..a065362ce7 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -59,6 +59,7 @@ class MediaList;
class MediaQuery;
class MediaQueryList;
class MediaQueryListEvent;
+class Number;
class NumericStyleValue;
class OverflowStyleValue;
class Percentage;