diff --git a/Userland/Libraries/LibWeb/PixelUnits.cpp b/Userland/Libraries/LibWeb/PixelUnits.cpp index 195fa3ba6e..6fba84f09b 100644 --- a/Userland/Libraries/LibWeb/PixelUnits.cpp +++ b/Userland/Libraries/LibWeb/PixelUnits.cpp @@ -9,44 +9,6 @@ namespace Web { -CSSPixels::CSSPixels(int value) -{ - if (value > max_integer_value) [[unlikely]] - m_value = NumericLimits::max(); - else if (value < min_integer_value) [[unlikely]] - m_value = NumericLimits::min(); - else - m_value = value << fractional_bits; -} - -CSSPixels::CSSPixels(unsigned int value) -{ - if (value > max_integer_value) [[unlikely]] - m_value = NumericLimits::max(); - else - m_value = static_cast(value) << fractional_bits; -} - -CSSPixels::CSSPixels(unsigned long value) -{ - if (value > max_integer_value) [[unlikely]] - m_value = NumericLimits::max(); - else - m_value = static_cast(value) << fractional_bits; -} - -CSSPixels::CSSPixels(float value) -{ - if (!isnan(value)) - m_value = AK::clamp_to_int(value * fixed_point_denominator); -} - -CSSPixels::CSSPixels(double value) -{ - if (!isnan(value)) - m_value = AK::clamp_to_int(value * fixed_point_denominator); -} - float CSSPixels::to_float() const { return static_cast(m_value) / fixed_point_denominator; @@ -62,111 +24,4 @@ int CSSPixels::to_int() const return m_value / fixed_point_denominator; } -bool CSSPixels::might_be_saturated() const -{ - return raw_value() == NumericLimits::max() || raw_value() == NumericLimits::min(); -} - -bool CSSPixels::operator==(CSSPixels const& other) const = default; - -CSSPixels& CSSPixels::operator++() -{ - m_value = Checked::saturating_add(m_value, fixed_point_denominator); - return *this; -} -CSSPixels& CSSPixels::operator--() -{ - m_value = Checked::saturating_sub(m_value, fixed_point_denominator); - return *this; -} - -int CSSPixels::operator<=>(CSSPixels const& other) const -{ - return raw_value() > other.raw_value() ? 1 : raw_value() < other.raw_value() ? -1 - : 0; -} - -CSSPixels CSSPixels::operator+() const -{ - return from_raw(+raw_value()); -} - -CSSPixels CSSPixels::operator-() const -{ - return from_raw(-raw_value()); -} - -CSSPixels CSSPixels::operator+(CSSPixels const& other) const -{ - return from_raw(Checked::saturating_add(raw_value(), other.raw_value())); -} - -CSSPixels CSSPixels::operator-(CSSPixels const& other) const -{ - return from_raw(Checked::saturating_sub(raw_value(), other.raw_value())); -} - -CSSPixels CSSPixels::operator*(CSSPixels const& other) const -{ - i64 value = raw_value(); - value *= other.raw_value(); - - int int_value = AK::clamp_to_int(value >> fractional_bits); - - // Rounding: - // If last bit cut off was 1: - if (value & (1u << (fractional_bits - 1))) { - // If the bit after was 1 as well - if (value & (radix_mask >> 2u)) { - // We need to round away from 0 - int_value = Checked::saturating_add(int_value, 1); - } else { - // Otherwise we round to the next even value - // Which means we add the least significant bit of the raw integer value - int_value = Checked::saturating_add(int_value, int_value & 1); - } - } - - return from_raw(int_value); -} - -CSSPixels CSSPixels::operator/(CSSPixels const& other) const -{ - i64 mult = raw_value(); - mult <<= fractional_bits; - mult /= other.raw_value(); - - int int_value = AK::clamp_to_int(mult); - return from_raw(int_value); -} - -CSSPixels& CSSPixels::operator+=(CSSPixels const& other) -{ - *this = *this + other; - return *this; -} - -CSSPixels& CSSPixels::operator-=(CSSPixels const& other) -{ - *this = *this - other; - return *this; -} - -CSSPixels& CSSPixels::operator*=(CSSPixels const& other) -{ - *this = *this * other; - return *this; -} - -CSSPixels& CSSPixels::operator/=(CSSPixels const& other) -{ - *this = *this / other; - return *this; -} - -CSSPixels CSSPixels::abs() const -{ - return from_raw(::abs(m_value)); -} - } diff --git a/Userland/Libraries/LibWeb/PixelUnits.h b/Userland/Libraries/LibWeb/PixelUnits.h index 39d4606d07..7879728a63 100644 --- a/Userland/Libraries/LibWeb/PixelUnits.h +++ b/Userland/Libraries/LibWeb/PixelUnits.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -60,14 +61,40 @@ public: static constexpr i32 max_integer_value = NumericLimits::max() >> fractional_bits; static constexpr i32 min_integer_value = NumericLimits::min() >> fractional_bits; - CSSPixels() = default; - CSSPixels(int value); - CSSPixels(unsigned int value); - CSSPixels(unsigned long value); - CSSPixels(float value); - CSSPixels(double value); + constexpr CSSPixels() = default; + template + constexpr CSSPixels(I value) + { + if (value > max_integer_value) [[unlikely]] + m_value = NumericLimits::max(); + else if (value < min_integer_value) [[unlikely]] + m_value = NumericLimits::min(); + else + m_value = static_cast(value) << fractional_bits; + } - static CSSPixels from_raw(int value) + CSSPixels(float value) + { + if (!isnan(value)) + m_value = AK::clamp_to_int(value * fixed_point_denominator); + } + + CSSPixels(double value) + { + if (!isnan(value)) + m_value = AK::clamp_to_int(value * fixed_point_denominator); + } + + template + constexpr CSSPixels(U value) + { + if (value > max_integer_value) [[unlikely]] + m_value = NumericLimits::max(); + else + m_value = static_cast(value) << fractional_bits; + } + + static constexpr CSSPixels from_raw(int value) { CSSPixels res; res.set_raw_value(value); @@ -78,63 +105,133 @@ public: double to_double() const; int to_int() const; - inline int raw_value() const { return m_value; } - inline void set_raw_value(int value) { m_value = value; } + constexpr int raw_value() const { return m_value; } + constexpr void set_raw_value(int value) { m_value = value; } - bool might_be_saturated() const; + constexpr bool might_be_saturated() const { return raw_value() == NumericLimits::max() || raw_value() == NumericLimits::min(); } - bool operator==(CSSPixels const& other) const; + constexpr bool operator==(CSSPixels const& other) const = default; explicit operator double() const { return to_double(); } - CSSPixels& operator++(); - CSSPixels& operator--(); + constexpr CSSPixels& operator++() + { + m_value = Checked::saturating_add(m_value, fixed_point_denominator); + return *this; + } + constexpr CSSPixels& operator--() + { + m_value = Checked::saturating_sub(m_value, fixed_point_denominator); + return *this; + } - int operator<=>(CSSPixels const& other) const; + constexpr int operator<=>(CSSPixels const& other) const + { + return raw_value() > other.raw_value() + ? 1 + : raw_value() < other.raw_value() + ? -1 + : 0; + } - CSSPixels operator+() const; - CSSPixels operator-() const; + constexpr CSSPixels operator+() const { return from_raw(+raw_value()); } + constexpr CSSPixels operator-() const { return from_raw(-raw_value()); } - CSSPixels operator+(CSSPixels const& other) const; - CSSPixels operator-(CSSPixels const& other) const; - CSSPixels operator*(CSSPixels const& other) const; - CSSPixels operator/(CSSPixels const& other) const; + constexpr CSSPixels operator+(CSSPixels const& other) const + { + return from_raw(Checked::saturating_add(raw_value(), other.raw_value())); + } - CSSPixels& operator+=(CSSPixels const& other); - CSSPixels& operator-=(CSSPixels const& other); - CSSPixels& operator*=(CSSPixels const& other); - CSSPixels& operator/=(CSSPixels const& other); + constexpr CSSPixels operator-(CSSPixels const& other) const + { + return from_raw(Checked::saturating_sub(raw_value(), other.raw_value())); + } - CSSPixels abs() const; + constexpr CSSPixels operator*(CSSPixels const& other) const + { + i64 value = raw_value(); + value *= other.raw_value(); + + int int_value = AK::clamp_to_int(value >> fractional_bits); + + // Rounding: + // If last bit cut off was 1: + if (value & (1u << (fractional_bits - 1))) { + // If the bit after was 1 as well + if (value & (radix_mask >> 2u)) { + // We need to round away from 0 + int_value = Checked::saturating_add(int_value, 1); + } else { + // Otherwise we round to the next even value + // Which means we add the least significant bit of the raw integer value + int_value = Checked::saturating_add(int_value, int_value & 1); + } + } + + return from_raw(int_value); + } + + constexpr CSSPixels operator/(CSSPixels const& other) const + { + i64 mult = raw_value(); + mult <<= fractional_bits; + mult /= other.raw_value(); + + int int_value = AK::clamp_to_int(mult); + return from_raw(int_value); + } + + constexpr CSSPixels& operator+=(CSSPixels const& other) + { + *this = *this + other; + return *this; + } + constexpr CSSPixels& operator-=(CSSPixels const& other) + { + *this = *this - other; + return *this; + } + constexpr CSSPixels& operator*=(CSSPixels const& other) + { + *this = *this * other; + return *this; + } + constexpr CSSPixels& operator/=(CSSPixels const& other) + { + *this = *this / other; + return *this; + } + + constexpr CSSPixels abs() const { return from_raw(::abs(m_value)); } private: i32 m_value { 0 }; }; -inline bool operator==(CSSPixels left, int right) { return left == CSSPixels(right); } +constexpr bool operator==(CSSPixels left, int right) { return left == CSSPixels(right); } inline bool operator==(CSSPixels left, float right) { return left.to_float() == right; } inline bool operator==(CSSPixels left, double right) { return left.to_double() == right; } -inline bool operator>(CSSPixels left, int right) { return left > CSSPixels(right); } +constexpr bool operator>(CSSPixels left, int right) { return left > CSSPixels(right); } inline bool operator>(CSSPixels left, float right) { return left.to_float() > right; } inline bool operator>(CSSPixels left, double right) { return left.to_double() > right; } -inline bool operator<(CSSPixels left, int right) { return left < CSSPixels(right); } +constexpr bool operator<(CSSPixels left, int right) { return left < CSSPixels(right); } inline bool operator<(CSSPixels left, float right) { return left.to_float() < right; } inline bool operator<(CSSPixels left, double right) { return left.to_double() < right; } -inline CSSPixels operator*(CSSPixels left, int right) { return left * CSSPixels(right); } -inline CSSPixels operator*(CSSPixels left, unsigned long right) { return left * CSSPixels(right); } +constexpr CSSPixels operator*(CSSPixels left, int right) { return left * CSSPixels(right); } +constexpr CSSPixels operator*(CSSPixels left, unsigned long right) { return left * CSSPixels(right); } inline float operator*(CSSPixels left, float right) { return left.to_float() * right; } inline double operator*(CSSPixels left, double right) { return left.to_double() * right; } -inline CSSPixels operator*(int left, CSSPixels right) { return right * CSSPixels(left); } -inline CSSPixels operator*(unsigned long left, CSSPixels right) { return right * CSSPixels(left); } +constexpr CSSPixels operator*(int left, CSSPixels right) { return right * CSSPixels(left); } +constexpr CSSPixels operator*(unsigned long left, CSSPixels right) { return right * CSSPixels(left); } inline float operator*(float left, CSSPixels right) { return right.to_float() * left; } inline double operator*(double left, CSSPixels right) { return right.to_double() * left; } -inline CSSPixels operator/(CSSPixels left, int right) { return left / CSSPixels(right); } -inline CSSPixels operator/(CSSPixels left, unsigned long right) { return left / CSSPixels(right); } +constexpr CSSPixels operator/(CSSPixels left, int right) { return left / CSSPixels(right); } +constexpr CSSPixels operator/(CSSPixels left, unsigned long right) { return left / CSSPixels(right); } inline float operator/(CSSPixels left, float right) { return left.to_float() / right; } inline double operator/(CSSPixels left, double right) { return left.to_double() / right; }