PixelUnits.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /*
  2. * Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Math.h>
  7. #include <LibWeb/PixelUnits.h>
  8. namespace Web {
  9. CSSPixels::CSSPixels(int value)
  10. {
  11. if (value > max_integer_value) [[unlikely]]
  12. m_value = NumericLimits<int>::max();
  13. else if (value < min_integer_value) [[unlikely]]
  14. m_value = NumericLimits<int>::min();
  15. else
  16. m_value = value << fractional_bits;
  17. }
  18. CSSPixels::CSSPixels(unsigned int value)
  19. {
  20. if (value > max_integer_value) [[unlikely]]
  21. m_value = NumericLimits<int>::max();
  22. else
  23. m_value = static_cast<int>(value) << fractional_bits;
  24. }
  25. CSSPixels::CSSPixels(unsigned long value)
  26. {
  27. if (value > max_integer_value) [[unlikely]]
  28. m_value = NumericLimits<int>::max();
  29. else
  30. m_value = static_cast<int>(value) << fractional_bits;
  31. }
  32. CSSPixels::CSSPixels(float value)
  33. {
  34. if (!isnan(value))
  35. m_value = AK::clamp_to_int(value * fixed_point_denominator);
  36. }
  37. CSSPixels::CSSPixels(double value)
  38. {
  39. if (!isnan(value))
  40. m_value = AK::clamp_to_int(value * fixed_point_denominator);
  41. }
  42. float CSSPixels::to_float() const
  43. {
  44. return static_cast<float>(m_value) / fixed_point_denominator;
  45. }
  46. double CSSPixels::to_double() const
  47. {
  48. return static_cast<double>(m_value) / fixed_point_denominator;
  49. }
  50. int CSSPixels::to_int() const
  51. {
  52. return m_value / fixed_point_denominator;
  53. }
  54. bool CSSPixels::might_be_saturated() const
  55. {
  56. return raw_value() == NumericLimits<i32>::max() || raw_value() == NumericLimits<i32>::min();
  57. }
  58. bool CSSPixels::operator==(CSSPixels const& other) const = default;
  59. CSSPixels& CSSPixels::operator++()
  60. {
  61. m_value = Checked<int>::saturating_add(m_value, fixed_point_denominator);
  62. return *this;
  63. }
  64. CSSPixels& CSSPixels::operator--()
  65. {
  66. m_value = Checked<int>::saturating_sub(m_value, fixed_point_denominator);
  67. return *this;
  68. }
  69. int CSSPixels::operator<=>(CSSPixels const& other) const
  70. {
  71. return raw_value() > other.raw_value() ? 1 : raw_value() < other.raw_value() ? -1
  72. : 0;
  73. }
  74. CSSPixels CSSPixels::operator+() const
  75. {
  76. return from_raw(+raw_value());
  77. }
  78. CSSPixels CSSPixels::operator-() const
  79. {
  80. return from_raw(-raw_value());
  81. }
  82. CSSPixels CSSPixels::operator+(CSSPixels const& other) const
  83. {
  84. return from_raw(Checked<int>::saturating_add(raw_value(), other.raw_value()));
  85. }
  86. CSSPixels CSSPixels::operator-(CSSPixels const& other) const
  87. {
  88. return from_raw(Checked<int>::saturating_sub(raw_value(), other.raw_value()));
  89. }
  90. CSSPixels CSSPixels::operator*(CSSPixels const& other) const
  91. {
  92. i64 value = raw_value();
  93. value *= other.raw_value();
  94. int int_value = AK::clamp_to_int(value >> fractional_bits);
  95. // Rounding:
  96. // If last bit cut off was 1:
  97. if (value & (1u << (fractional_bits - 1))) {
  98. // If the bit after was 1 as well
  99. if (value & (radix_mask >> 2u)) {
  100. // We need to round away from 0
  101. int_value = Checked<int>::saturating_add(int_value, 1);
  102. } else {
  103. // Otherwise we round to the next even value
  104. // Which means we add the least significant bit of the raw integer value
  105. int_value = Checked<int>::saturating_add(int_value, int_value & 1);
  106. }
  107. }
  108. return from_raw(int_value);
  109. }
  110. CSSPixels CSSPixels::operator/(CSSPixels const& other) const
  111. {
  112. i64 mult = raw_value();
  113. mult <<= fractional_bits;
  114. mult /= other.raw_value();
  115. int int_value = AK::clamp_to_int(mult);
  116. return from_raw(int_value);
  117. }
  118. CSSPixels& CSSPixels::operator+=(CSSPixels const& other)
  119. {
  120. *this = *this + other;
  121. return *this;
  122. }
  123. CSSPixels& CSSPixels::operator-=(CSSPixels const& other)
  124. {
  125. *this = *this - other;
  126. return *this;
  127. }
  128. CSSPixels& CSSPixels::operator*=(CSSPixels const& other)
  129. {
  130. *this = *this * other;
  131. return *this;
  132. }
  133. CSSPixels& CSSPixels::operator/=(CSSPixels const& other)
  134. {
  135. *this = *this / other;
  136. return *this;
  137. }
  138. CSSPixels CSSPixels::abs() const
  139. {
  140. return from_raw(::abs(m_value));
  141. }
  142. }