Size.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Format.h>
  8. #include <LibGfx/Orientation.h>
  9. #include <LibGfx/Point.h>
  10. #include <LibIPC/Forward.h>
  11. namespace Gfx {
  12. template<typename T>
  13. class Size {
  14. public:
  15. Size() = default;
  16. Size(T w, T h)
  17. : m_width(w)
  18. , m_height(h)
  19. {
  20. }
  21. template<typename U>
  22. Size(U width, U height)
  23. : m_width(width)
  24. , m_height(height)
  25. {
  26. }
  27. template<typename U>
  28. explicit Size(Size<U> const& other)
  29. : m_width(other.width())
  30. , m_height(other.height())
  31. {
  32. }
  33. [[nodiscard]] ALWAYS_INLINE T width() const { return m_width; }
  34. [[nodiscard]] ALWAYS_INLINE T height() const { return m_height; }
  35. [[nodiscard]] ALWAYS_INLINE T area() const { return width() * height(); }
  36. ALWAYS_INLINE void set_width(T w) { m_width = w; }
  37. ALWAYS_INLINE void set_height(T h) { m_height = h; }
  38. [[nodiscard]] ALWAYS_INLINE bool is_null() const { return !m_width && !m_height; }
  39. [[nodiscard]] ALWAYS_INLINE bool is_empty() const { return m_width <= 0 || m_height <= 0; }
  40. void scale_by(T dx, T dy)
  41. {
  42. m_width *= dx;
  43. m_height *= dy;
  44. }
  45. void transform_by(AffineTransform const& transform) { *this = transform.map(*this); }
  46. ALWAYS_INLINE void scale_by(T dboth) { scale_by(dboth, dboth); }
  47. ALWAYS_INLINE void scale_by(Point<T> const& s) { scale_by(s.x(), s.y()); }
  48. [[nodiscard]] Size scaled_by(T dx, T dy) const
  49. {
  50. Size<T> size = *this;
  51. size.scale_by(dx, dy);
  52. return size;
  53. }
  54. [[nodiscard]] Size scaled_by(T dboth) const
  55. {
  56. Size<T> size = *this;
  57. size.scale_by(dboth);
  58. return size;
  59. }
  60. [[nodiscard]] Size scaled_by(Point<T> const& s) const
  61. {
  62. Size<T> size = *this;
  63. size.scale_by(s);
  64. return size;
  65. }
  66. [[nodiscard]] Size transformed_by(AffineTransform const& transform) const
  67. {
  68. Size<T> size = *this;
  69. size.transform_by(transform);
  70. return size;
  71. }
  72. template<typename U>
  73. [[nodiscard]] bool contains(Size<U> const& other) const
  74. {
  75. return other.m_width <= m_width && other.m_height <= m_height;
  76. }
  77. template<class U>
  78. [[nodiscard]] bool operator==(Size<U> const& other) const
  79. {
  80. return width() == other.width() && height() == other.height();
  81. }
  82. template<class U>
  83. [[nodiscard]] bool operator!=(Size<U> const& other) const
  84. {
  85. return !(*this == other);
  86. }
  87. Size<T>& operator-=(Size<T> const& other)
  88. {
  89. m_width -= other.m_width;
  90. m_height -= other.m_height;
  91. return *this;
  92. }
  93. Size<T>& operator+=(Size<T> const& other)
  94. {
  95. m_width += other.m_width;
  96. m_height += other.m_height;
  97. return *this;
  98. }
  99. [[nodiscard]] Size<T> operator*(T factor) const { return { m_width * factor, m_height * factor }; }
  100. Size<T>& operator*=(T factor)
  101. {
  102. m_width *= factor;
  103. m_height *= factor;
  104. return *this;
  105. }
  106. [[nodiscard]] T primary_size_for_orientation(Orientation orientation) const
  107. {
  108. return orientation == Orientation::Vertical ? height() : width();
  109. }
  110. void set_primary_size_for_orientation(Orientation orientation, T value)
  111. {
  112. if (orientation == Orientation::Vertical) {
  113. set_height(value);
  114. } else {
  115. set_width(value);
  116. }
  117. }
  118. [[nodiscard]] T secondary_size_for_orientation(Orientation orientation) const
  119. {
  120. return orientation == Orientation::Vertical ? width() : height();
  121. }
  122. void set_secondary_size_for_orientation(Orientation orientation, T value)
  123. {
  124. if (orientation == Orientation::Vertical) {
  125. set_width(value);
  126. } else {
  127. set_height(value);
  128. }
  129. }
  130. template<typename U>
  131. [[nodiscard]] ALWAYS_INLINE Size<U> to_type() const
  132. {
  133. return Size<U>(*this);
  134. }
  135. [[nodiscard]] String to_string() const;
  136. private:
  137. T m_width { 0 };
  138. T m_height { 0 };
  139. };
  140. using IntSize = Size<int>;
  141. using FloatSize = Size<float>;
  142. }
  143. namespace AK {
  144. template<typename T>
  145. struct Formatter<Gfx::Size<T>> : Formatter<StringView> {
  146. void format(FormatBuilder& builder, Gfx::Size<T> const& value)
  147. {
  148. Formatter<StringView>::format(builder, value.to_string());
  149. }
  150. };
  151. }
  152. namespace IPC {
  153. bool encode(Encoder&, Gfx::IntSize const&);
  154. bool decode(Decoder&, Gfx::IntSize&);
  155. }