diff options
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Number.h | 84 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 1 |
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; |