Rect.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/StdLibExtras.h>
  7. #include <AK/String.h>
  8. #include <AK/Vector.h>
  9. #include <LibGfx/Rect.h>
  10. #include <LibIPC/Decoder.h>
  11. #include <LibIPC/Encoder.h>
  12. namespace Gfx {
  13. template<typename T>
  14. void Rect<T>::intersect(const Rect<T>& other)
  15. {
  16. T l = max(left(), other.left());
  17. T r = min(right(), other.right());
  18. T t = max(top(), other.top());
  19. T b = min(bottom(), other.bottom());
  20. if (l > r || t > b) {
  21. m_location = {};
  22. m_size = {};
  23. return;
  24. }
  25. m_location.set_x(l);
  26. m_location.set_y(t);
  27. m_size.set_width((r - l) + 1);
  28. m_size.set_height((b - t) + 1);
  29. }
  30. template<typename T>
  31. Rect<T> Rect<T>::united(const Rect<T>& other) const
  32. {
  33. if (is_null())
  34. return other;
  35. if (other.is_null())
  36. return *this;
  37. Rect<T> rect;
  38. rect.set_left(min(left(), other.left()));
  39. rect.set_top(min(top(), other.top()));
  40. rect.set_right(max(right(), other.right()));
  41. rect.set_bottom(max(bottom(), other.bottom()));
  42. return rect;
  43. }
  44. template<typename T>
  45. Vector<Rect<T>, 4> Rect<T>::shatter(const Rect<T>& hammer) const
  46. {
  47. Vector<Rect<T>, 4> pieces;
  48. if (!intersects(hammer)) {
  49. pieces.unchecked_append(*this);
  50. return pieces;
  51. }
  52. Rect<T> top_shard {
  53. x(),
  54. y(),
  55. width(),
  56. hammer.y() - y()
  57. };
  58. Rect<T> bottom_shard {
  59. x(),
  60. hammer.y() + hammer.height(),
  61. width(),
  62. (y() + height()) - (hammer.y() + hammer.height())
  63. };
  64. Rect<T> left_shard {
  65. x(),
  66. max(hammer.y(), y()),
  67. hammer.x() - x(),
  68. min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y())
  69. };
  70. Rect<T> right_shard {
  71. hammer.x() + hammer.width(),
  72. max(hammer.y(), y()),
  73. right() - hammer.right(),
  74. min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y())
  75. };
  76. if (!top_shard.is_empty())
  77. pieces.unchecked_append(top_shard);
  78. if (!bottom_shard.is_empty())
  79. pieces.unchecked_append(bottom_shard);
  80. if (!left_shard.is_empty())
  81. pieces.unchecked_append(left_shard);
  82. if (!right_shard.is_empty())
  83. pieces.unchecked_append(right_shard);
  84. return pieces;
  85. }
  86. template<typename T>
  87. void Rect<T>::align_within(const Rect<T>& other, TextAlignment alignment)
  88. {
  89. switch (alignment) {
  90. case TextAlignment::Center:
  91. center_within(other);
  92. return;
  93. case TextAlignment::TopLeft:
  94. set_location(other.location());
  95. return;
  96. case TextAlignment::TopRight:
  97. set_x(other.x() + other.width() - width());
  98. set_y(other.y());
  99. return;
  100. case TextAlignment::CenterLeft:
  101. set_x(other.x());
  102. center_vertically_within(other);
  103. return;
  104. case TextAlignment::CenterRight:
  105. set_x(other.x() + other.width() - width());
  106. center_vertically_within(other);
  107. return;
  108. case TextAlignment::BottomLeft:
  109. set_x(other.x());
  110. set_y(other.y() + other.height() - height());
  111. return;
  112. case TextAlignment::BottomRight:
  113. set_x(other.x() + other.width() - width());
  114. set_y(other.y() + other.height() - height());
  115. return;
  116. }
  117. }
  118. template<typename T>
  119. void Rect<T>::set_size_around(const Size<T>& new_size, const Point<T>& fixed_point)
  120. {
  121. const T new_x = fixed_point.x() - (T)(new_size.width() * ((float)(fixed_point.x() - x()) / width()));
  122. const T new_y = fixed_point.y() - (T)(new_size.height() * ((float)(fixed_point.y() - y()) / height()));
  123. set_location({ new_x, new_y });
  124. set_size(new_size);
  125. }
  126. template<>
  127. String IntRect::to_string() const
  128. {
  129. return String::formatted("[{},{} {}x{}]", x(), y(), width(), height());
  130. }
  131. template<>
  132. String FloatRect::to_string() const
  133. {
  134. return String::formatted("[{},{} {}x{}]", x(), y(), width(), height());
  135. }
  136. }
  137. namespace IPC {
  138. bool encode(Encoder& encoder, const Gfx::IntRect& rect)
  139. {
  140. encoder << rect.location() << rect.size();
  141. return true;
  142. }
  143. bool decode(Decoder& decoder, Gfx::IntRect& rect)
  144. {
  145. Gfx::IntPoint point;
  146. Gfx::IntSize size;
  147. if (!decoder.decode(point))
  148. return false;
  149. if (!decoder.decode(size))
  150. return false;
  151. rect = { point, size };
  152. return true;
  153. }
  154. }
  155. template class Gfx::Rect<int>;
  156. template class Gfx::Rect<float>;