Geometry.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. */
  7. #pragma once
  8. #include <algorithm>
  9. #include <functional>
  10. #include <tuple>
  11. #include <folly/Hash.h>
  12. #include <react/graphics/Float.h>
  13. namespace facebook {
  14. namespace react {
  15. /*
  16. * Point
  17. */
  18. struct Point {
  19. Float x{0};
  20. Float y{0};
  21. Point &operator+=(const Point &point) {
  22. x += point.x;
  23. y += point.y;
  24. return *this;
  25. }
  26. Point &operator-=(const Point &point) {
  27. x -= point.x;
  28. y -= point.y;
  29. return *this;
  30. }
  31. Point &operator*=(const Point &point) {
  32. x *= point.x;
  33. y *= point.y;
  34. return *this;
  35. }
  36. friend Point operator+(Point lhs, const Point &rhs) {
  37. return lhs += rhs;
  38. }
  39. friend Point operator-(Point lhs, const Point &rhs) {
  40. return lhs -= rhs;
  41. }
  42. bool operator==(const Point &rhs) const {
  43. return std::tie(this->x, this->y) == std::tie(rhs.x, rhs.y);
  44. }
  45. bool operator!=(const Point &rhs) const {
  46. return !(*this == rhs);
  47. }
  48. };
  49. struct Vector {
  50. Float x{0};
  51. Float y{0};
  52. Float z{0};
  53. Float w{0};
  54. };
  55. /*
  56. * Size
  57. */
  58. struct Size {
  59. Float width{0};
  60. Float height{0};
  61. Size &operator+=(const Point &point) {
  62. width += point.x;
  63. height += point.y;
  64. return *this;
  65. }
  66. Size &operator*=(const Point &point) {
  67. width *= point.x;
  68. height *= point.y;
  69. return *this;
  70. }
  71. bool operator==(const Size &rhs) const {
  72. return std::tie(this->width, this->height) ==
  73. std::tie(rhs.width, rhs.height);
  74. }
  75. bool operator!=(const Size &rhs) const {
  76. return !(*this == rhs);
  77. }
  78. };
  79. /*
  80. * Rect: Point and Size
  81. */
  82. struct Rect {
  83. Point origin{0, 0};
  84. Size size{0, 0};
  85. bool operator==(const Rect &rhs) const {
  86. return std::tie(this->origin, this->size) == std::tie(rhs.origin, rhs.size);
  87. }
  88. bool operator!=(const Rect &rhs) const {
  89. return !(*this == rhs);
  90. }
  91. Float getMaxX() const {
  92. return size.width > 0 ? origin.x + size.width : origin.x;
  93. }
  94. Float getMaxY() const {
  95. return size.height > 0 ? origin.y + size.height : origin.y;
  96. }
  97. Float getMinX() const {
  98. return size.width >= 0 ? origin.x : origin.x + size.width;
  99. }
  100. Float getMinY() const {
  101. return size.height >= 0 ? origin.y : origin.y + size.height;
  102. }
  103. Float getMidX() const {
  104. return origin.x + size.width / 2;
  105. }
  106. Float getMidY() const {
  107. return origin.y + size.height / 2;
  108. }
  109. Point getCenter() const {
  110. return {getMidX(), getMidY()};
  111. }
  112. void unionInPlace(const Rect &rect) {
  113. auto x1 = std::min(getMinX(), rect.getMinX());
  114. auto y1 = std::min(getMinY(), rect.getMinY());
  115. auto x2 = std::max(getMaxX(), rect.getMaxX());
  116. auto y2 = std::max(getMaxY(), rect.getMaxY());
  117. origin = {x1, y1};
  118. size = {x2 - x1, y2 - y1};
  119. }
  120. bool containsPoint(Point point) {
  121. return point.x >= origin.x && point.y >= origin.y &&
  122. point.x <= (origin.x + size.width) &&
  123. point.y <= (origin.y + size.height);
  124. }
  125. static Rect
  126. boundingRect(Point const &a, Point const &b, Point const &c, Point const &d) {
  127. auto leftTopPoint = a;
  128. auto rightBottomPoint = a;
  129. leftTopPoint.x = std::min(leftTopPoint.x, b.x);
  130. leftTopPoint.x = std::min(leftTopPoint.x, c.x);
  131. leftTopPoint.x = std::min(leftTopPoint.x, d.x);
  132. leftTopPoint.y = std::min(leftTopPoint.y, b.y);
  133. leftTopPoint.y = std::min(leftTopPoint.y, c.y);
  134. leftTopPoint.y = std::min(leftTopPoint.y, d.y);
  135. rightBottomPoint.x = std::max(rightBottomPoint.x, b.x);
  136. rightBottomPoint.x = std::max(rightBottomPoint.x, c.x);
  137. rightBottomPoint.x = std::max(rightBottomPoint.x, d.x);
  138. rightBottomPoint.y = std::max(rightBottomPoint.y, b.y);
  139. rightBottomPoint.y = std::max(rightBottomPoint.y, c.y);
  140. rightBottomPoint.y = std::max(rightBottomPoint.y, d.y);
  141. return {leftTopPoint,
  142. {rightBottomPoint.x - leftTopPoint.x,
  143. rightBottomPoint.y - leftTopPoint.y}};
  144. }
  145. };
  146. /*
  147. * Generic data structure describes some values associated with *edges*
  148. * of a rectangle.
  149. */
  150. template <typename T>
  151. struct RectangleEdges {
  152. T left{};
  153. T top{};
  154. T right{};
  155. T bottom{};
  156. bool operator==(const RectangleEdges<T> &rhs) const {
  157. return std::tie(this->left, this->top, this->right, this->bottom) ==
  158. std::tie(rhs.left, rhs.top, rhs.right, rhs.bottom);
  159. }
  160. bool operator!=(const RectangleEdges<T> &rhs) const {
  161. return !(*this == rhs);
  162. }
  163. bool isUniform() const {
  164. return left == top && left == right && left == bottom;
  165. }
  166. };
  167. template <typename T>
  168. RectangleEdges<T> operator+(
  169. RectangleEdges<T> const &lhs,
  170. RectangleEdges<T> const &rhs) {
  171. return RectangleEdges<T>{lhs.left + rhs.left,
  172. lhs.top + rhs.top,
  173. lhs.right + rhs.right,
  174. lhs.bottom + rhs.bottom};
  175. }
  176. template <typename T>
  177. RectangleEdges<T> operator-(
  178. RectangleEdges<T> const &lhs,
  179. RectangleEdges<T> const &rhs) {
  180. return RectangleEdges<T>{lhs.left - rhs.left,
  181. lhs.top - rhs.top,
  182. lhs.right - rhs.right,
  183. lhs.bottom - rhs.bottom};
  184. }
  185. /*
  186. * Generic data structure describes some values associated with *corners*
  187. * of a rectangle.
  188. */
  189. template <typename T>
  190. struct RectangleCorners {
  191. T topLeft{};
  192. T topRight{};
  193. T bottomLeft{};
  194. T bottomRight{};
  195. bool operator==(const RectangleCorners<T> &rhs) const {
  196. return std::tie(
  197. this->topLeft,
  198. this->topRight,
  199. this->bottomLeft,
  200. this->bottomRight) ==
  201. std::tie(rhs.topLeft, rhs.topRight, rhs.bottomLeft, rhs.bottomRight);
  202. }
  203. bool operator!=(const RectangleCorners<T> &rhs) const {
  204. return !(*this == rhs);
  205. }
  206. bool isUniform() const {
  207. return topLeft == topRight && topLeft == bottomLeft &&
  208. topLeft == bottomRight;
  209. }
  210. };
  211. /*
  212. * EdgeInsets
  213. */
  214. using EdgeInsets = RectangleEdges<Float>;
  215. /*
  216. * CornerInsets
  217. */
  218. using CornerInsets = RectangleCorners<Float>;
  219. } // namespace react
  220. } // namespace facebook
  221. namespace std {
  222. template <>
  223. struct hash<facebook::react::Point> {
  224. size_t operator()(const facebook::react::Point &point) const {
  225. return folly::hash::hash_combine(0, point.x, point.y);
  226. }
  227. };
  228. template <>
  229. struct hash<facebook::react::Size> {
  230. size_t operator()(const facebook::react::Size &size) const {
  231. return folly::hash::hash_combine(0, size.width, size.height);
  232. }
  233. };
  234. template <>
  235. struct hash<facebook::react::Rect> {
  236. size_t operator()(const facebook::react::Rect &rect) const {
  237. return folly::hash::hash_combine(0, rect.origin, rect.size);
  238. }
  239. };
  240. template <typename T>
  241. struct hash<facebook::react::RectangleEdges<T>> {
  242. size_t operator()(const facebook::react::RectangleEdges<T> &edges) const {
  243. return folly::hash::hash_combine(
  244. 0, edges.left, edges.right, edges.top, edges.bottom);
  245. }
  246. };
  247. template <typename T>
  248. struct hash<facebook::react::RectangleCorners<T>> {
  249. size_t operator()(const facebook::react::RectangleCorners<T> &corners) const {
  250. return folly::hash::hash_combine(
  251. 0,
  252. corners.topLeft,
  253. corners.bottomLeft,
  254. corners.topRight,
  255. corners.bottomRight);
  256. }
  257. };
  258. } // namespace std