FloatRect.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #pragma once
  2. #include <AK/LogStream.h>
  3. #include <AK/String.h>
  4. #include <LibDraw/FloatPoint.h>
  5. #include <LibDraw/FloatSize.h>
  6. #include <LibDraw/Orientation.h>
  7. #include <LibDraw/Rect.h>
  8. #include <LibDraw/TextAlignment.h>
  9. #include <math.h>
  10. class FloatRect {
  11. public:
  12. FloatRect() {}
  13. FloatRect(float x, float y, float width, float height)
  14. : m_location(x, y)
  15. , m_size(width, height)
  16. {
  17. }
  18. FloatRect(const FloatPoint& location, const FloatSize& size)
  19. : m_location(location)
  20. , m_size(size)
  21. {
  22. }
  23. FloatRect(const FloatRect& other)
  24. : m_location(other.m_location)
  25. , m_size(other.m_size)
  26. {
  27. }
  28. bool is_null() const
  29. {
  30. return width() == 0 && height() == 0;
  31. }
  32. bool is_empty() const
  33. {
  34. return width() <= 0 || height() <= 0;
  35. }
  36. void move_by(float dx, float dy)
  37. {
  38. m_location.move_by(dx, dy);
  39. }
  40. void move_by(const FloatPoint& delta)
  41. {
  42. m_location.move_by(delta);
  43. }
  44. FloatPoint center() const
  45. {
  46. return { x() + width() / 2, y() + height() / 2 };
  47. }
  48. void set_location(const FloatPoint& location)
  49. {
  50. m_location = location;
  51. }
  52. void set_size(const FloatSize& size)
  53. {
  54. m_size = size;
  55. }
  56. void set_size(float width, float height)
  57. {
  58. m_size.set_width(width);
  59. m_size.set_height(height);
  60. }
  61. void inflate(float w, float h)
  62. {
  63. set_x(x() - w / 2);
  64. set_width(width() + w);
  65. set_y(y() - h / 2);
  66. set_height(height() + h);
  67. }
  68. void shrink(float w, float h)
  69. {
  70. set_x(x() + w / 2);
  71. set_width(width() - w);
  72. set_y(y() + h / 2);
  73. set_height(height() - h);
  74. }
  75. FloatRect shrunken(float w, float h) const
  76. {
  77. FloatRect rect = *this;
  78. rect.shrink(w, h);
  79. return rect;
  80. }
  81. FloatRect inflated(float w, float h) const
  82. {
  83. FloatRect rect = *this;
  84. rect.inflate(w, h);
  85. return rect;
  86. }
  87. FloatRect translated(float dx, float dy) const
  88. {
  89. FloatRect rect = *this;
  90. rect.move_by(dx, dy);
  91. return rect;
  92. }
  93. FloatRect translated(const FloatPoint& delta) const
  94. {
  95. FloatRect rect = *this;
  96. rect.move_by(delta);
  97. return rect;
  98. }
  99. bool contains_vertically(float y) const
  100. {
  101. return y >= top() && y <= bottom();
  102. }
  103. bool contains_horizontally(float x) const
  104. {
  105. return x >= left() && x <= right();
  106. }
  107. bool contains(float x, float y) const
  108. {
  109. return x >= m_location.x() && x <= right() && y >= m_location.y() && y <= bottom();
  110. }
  111. bool contains(const FloatPoint& point) const
  112. {
  113. return contains(point.x(), point.y());
  114. }
  115. bool contains(const FloatRect& other) const
  116. {
  117. return left() <= other.left()
  118. && right() >= other.right()
  119. && top() <= other.top()
  120. && bottom() >= other.bottom();
  121. }
  122. float primary_offset_for_orientation(Orientation orientation) const { return m_location.primary_offset_for_orientation(orientation); }
  123. void set_primary_offset_for_orientation(Orientation orientation, float value) { m_location.set_primary_offset_for_orientation(orientation, value); }
  124. float secondary_offset_for_orientation(Orientation orientation) const { return m_location.secondary_offset_for_orientation(orientation); }
  125. void set_secondary_offset_for_orientation(Orientation orientation, float value) { m_location.set_secondary_offset_for_orientation(orientation, value); }
  126. float primary_size_for_orientation(Orientation orientation) const { return m_size.primary_size_for_orientation(orientation); }
  127. float secondary_size_for_orientation(Orientation orientation) const { return m_size.secondary_size_for_orientation(orientation); }
  128. void set_primary_size_for_orientation(Orientation orientation, float value) { m_size.set_primary_size_for_orientation(orientation, value); }
  129. void set_secondary_size_for_orientation(Orientation orientation, float value) { m_size.set_secondary_size_for_orientation(orientation, value); }
  130. float first_edge_for_orientation(Orientation orientation) const
  131. {
  132. if (orientation == Orientation::Vertical)
  133. return top();
  134. return left();
  135. }
  136. float last_edge_for_orientation(Orientation orientation) const
  137. {
  138. if (orientation == Orientation::Vertical)
  139. return bottom();
  140. return right();
  141. }
  142. float left() const { return x(); }
  143. float right() const { return x() + width() - 1; }
  144. float top() const { return y(); }
  145. float bottom() const { return y() + height() - 1; }
  146. void set_left(float left)
  147. {
  148. set_x(left);
  149. }
  150. void set_top(float top)
  151. {
  152. set_y(top);
  153. }
  154. void set_right(float right)
  155. {
  156. set_width(right - x() + 1);
  157. }
  158. void set_bottom(float bottom)
  159. {
  160. set_height(bottom - y() + 1);
  161. }
  162. void set_right_without_resize(float new_right)
  163. {
  164. float delta = new_right - right();
  165. move_by(delta, 0);
  166. }
  167. void set_bottom_without_resize(float new_bottom)
  168. {
  169. float delta = new_bottom - bottom();
  170. move_by(0, delta);
  171. }
  172. bool intersects(const FloatRect& other) const
  173. {
  174. return left() <= other.right()
  175. && other.left() <= right()
  176. && top() <= other.bottom()
  177. && other.top() <= bottom();
  178. }
  179. float x() const { return location().x(); }
  180. float y() const { return location().y(); }
  181. float width() const { return m_size.width(); }
  182. float height() const { return m_size.height(); }
  183. void set_x(float x) { m_location.set_x(x); }
  184. void set_y(float y) { m_location.set_y(y); }
  185. void set_width(float width) { m_size.set_width(width); }
  186. void set_height(float height) { m_size.set_height(height); }
  187. FloatPoint location() const { return m_location; }
  188. FloatSize size() const { return m_size; }
  189. Vector<FloatRect, 4> shatter(const FloatRect& hammer) const;
  190. bool operator==(const FloatRect& other) const
  191. {
  192. return m_location == other.m_location
  193. && m_size == other.m_size;
  194. }
  195. void intersect(const FloatRect&);
  196. static FloatRect intersection(const FloatRect& a, const FloatRect& b)
  197. {
  198. FloatRect r(a);
  199. r.intersect(b);
  200. return r;
  201. }
  202. FloatRect intersected(const FloatRect& other) const
  203. {
  204. return intersection(*this, other);
  205. }
  206. FloatRect united(const FloatRect&) const;
  207. FloatPoint top_left() const { return { left(), top() }; }
  208. FloatPoint top_right() const { return { right(), top() }; }
  209. FloatPoint bottom_left() const { return { left(), bottom() }; }
  210. FloatPoint bottom_right() const { return { right(), bottom() }; }
  211. void align_within(const FloatRect&, TextAlignment);
  212. void center_within(const FloatRect& other)
  213. {
  214. center_horizontally_within(other);
  215. center_vertically_within(other);
  216. }
  217. void center_horizontally_within(const FloatRect& other)
  218. {
  219. set_x(other.center().x() - width() / 2);
  220. }
  221. void center_vertically_within(const FloatRect& other)
  222. {
  223. set_y(other.center().y() - height() / 2);
  224. }
  225. String to_string() const { return String::format("[%g,%g %gx%g]", x(), y(), width(), height()); }
  226. private:
  227. FloatPoint m_location;
  228. FloatSize m_size;
  229. };
  230. inline void FloatPoint::constrain(const FloatRect& rect)
  231. {
  232. if (x() < rect.left())
  233. set_x(rect.left());
  234. else if (x() > rect.right())
  235. set_x(rect.right());
  236. if (y() < rect.top())
  237. set_y(rect.top());
  238. else if (y() > rect.bottom())
  239. set_y(rect.bottom());
  240. }
  241. inline const LogStream& operator<<(const LogStream& stream, const FloatRect& value)
  242. {
  243. return stream << value.to_string();
  244. }
  245. inline Rect enclosing_int_rect(const FloatRect& float_rect)
  246. {
  247. return { (int)float_rect.x(), (int)float_rect.y(), (int)ceilf(float_rect.width()), (int)ceilf(float_rect.height()) };
  248. }