RECT.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Command & Conquer *
  23. * *
  24. * Archive : /Sun/RECT.H *
  25. * *
  26. * Author : Joe_b *
  27. * *
  28. * Modtime : 11/21/97 4:40p *
  29. * *
  30. * Revision : 20 *
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * Union -- Combines two rectangles into one larger one. *
  35. * Intersect -- Find the intersection between two rectangles. *
  36. * Intersect -- Simple intersect between two rectangles. *
  37. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  38. #pragma once
  39. #ifndef RECT_H
  40. #define RECT_H
  41. #include <stddef.h>
  42. #include "point.h"
  43. /*
  44. ** This class manages a rectangle. Typically, this is used for tracking regions on a surface
  45. ** and for clipping operations. This is a lightweight class in that it defines few support
  46. ** functions and exposes the member variables for direct access.
  47. */
  48. template<class T>
  49. class TRect
  50. {
  51. public:
  52. TRect(void) {} // Default constructor does nothing by design.
  53. TRect(T x, T y, T w, T h) : X(x), Y(y), Width(w), Height(h) {}
  54. TRect(TPoint2D<T> const & point, T w, T h) : X(point.X), Y(point.Y), Width(w), Height(h) {}
  55. // Equality comparison operators.
  56. bool operator == (TRect<T> const & rvalue) const {return(X==rvalue.X && Y==rvalue.Y && Width==rvalue.Width && Height==rvalue.Height);}
  57. bool operator != (TRect<T> const & rvalue) const {return(X!=rvalue.X || Y!=rvalue.Y || Width!=rvalue.Width || Height!=rvalue.Height);}
  58. // Addition and subtraction operators.
  59. TRect<T> const & operator += (TPoint2D<T> const & point) {X += point.X;Y += point.Y;return(*this);}
  60. TRect<T> const & operator -= (TPoint2D<T> const & point) {X -= point.X;Y -= point.Y;return(*this);}
  61. TRect<T> const operator + (TPoint2D<T> const & point) {return(TRect<T>(Top_Left() + point, Width, Height));}
  62. TRect<T> const operator - (TPoint2D<T> const & point) {return(TRect<T>(Top_Left() - point, Width, Height));}
  63. /*
  64. ** Bias this rectangle within another.
  65. */
  66. TRect<T> const Bias_To(TRect<T> const & rect) const {return(TRect<T>(Top_Left() + rect.Top_Left(), Width, Height));}
  67. // Assign values
  68. void Set(T x, T y, T w, T h) {X = x; Y = y; Width = w; Height = h;}
  69. /*
  70. ** Determine if two rectangles overlap.
  71. */
  72. bool Is_Overlapping(TRect<T> const & rect) const {return(X < rect.X+rect.Width && Y < rect.Y+rect.Height && X+Width > rect.X && Y+Height > rect.Y);}
  73. /*
  74. ** Determine is rectangle is valid.
  75. */
  76. bool Is_Valid(void) const {return(Width > 0 && Height > 0);}
  77. __declspec(property(get=Is_Valid)) bool IsValid;
  78. /*
  79. ** Returns size of rectangle if each discrete location within it is presumed
  80. ** to be of size 1.
  81. */
  82. int Size(void) const {return(int(Width) * int(Height));}
  83. /*
  84. ** Fetch points of rectangle (used as a convenience for the programmer).
  85. */
  86. TPoint2D<T> Top_Left(void) const {return(TPoint2D<T>(X, Y));}
  87. __declspec(property(get=Top_Left)) TPoint2D<T> TopLeft;
  88. TPoint2D<T> Top_Right(void) const {return(TPoint2D<T>(T(X + Width - 1), Y));}
  89. __declspec(property(get=Top_Right)) TPoint2D<T> TopRight;
  90. TPoint2D<T> Bottom_Left(void) const {return(TPoint2D<T>(X, T(Y + Height - 1)));}
  91. __declspec(property(get=Bottom_Left)) TPoint2D<T> BottomLeft;
  92. TPoint2D<T> Bottom_Right(void) const {return(TPoint2D<T>(T(X + Width - 1), T(Y + Height - 1)));}
  93. __declspec(property(get=Bottom_Right)) TPoint2D<T> BottomRight;
  94. /*
  95. ** Determine if a point lies within the rectangle.
  96. */
  97. bool Is_Point_Within(TPoint2D<T> const & point) const {return(point.X >= X && point.X < X+Width && point.Y >= Y && point.Y < Y+Height);}
  98. public:
  99. /*
  100. ** Coordinate of upper left corner of rectangle.
  101. */
  102. T X;
  103. T Y;
  104. /*
  105. ** Dimensions of rectangle. If the width or height is less than or equal to
  106. ** zero, then the rectangle is in an invalid state.
  107. */
  108. T Width;
  109. T Height;
  110. };
  111. template<class T>
  112. TPoint2D<T> const Bias_To(TPoint2D<T> const & point, TRect<T> const & rect)
  113. {
  114. return(TPoint2D<T>(T(point.X + rect.X), T(point.Y + rect.Y)));
  115. }
  116. /***********************************************************************************************
  117. * Union -- Combines two rectangles into one larger one. *
  118. * *
  119. * This routine will combine the two specified rectangles such that a larger one is *
  120. * returned that encompasses both rectangles. *
  121. * *
  122. * INPUT: rect1 -- One rectangle to combine. *
  123. * rect2 -- The other rectangle to combine. *
  124. * *
  125. * OUTPUT: Returns with the smallest rectangle that encompasses both specified rectangles. *
  126. * *
  127. * WARNINGS: none *
  128. * *
  129. * HISTORY: *
  130. * 06/04/1997 JLB : Created. *
  131. *=============================================================================================*/
  132. template<class T>
  133. TRect<T> const Union(TRect<T> const & rect1, TRect<T> const & rect2)
  134. {
  135. if (rect1.Is_Valid()) {
  136. if (rect2.Is_Valid()) {
  137. TRect<T> result = rect1;
  138. if (result.X > rect2.X) {
  139. result.Width += T(result.X-rect2.X);
  140. result.X = rect2.X;
  141. }
  142. if (result.Y > rect2.Y) {
  143. result.Height += T(result.Y-rect2.Y);
  144. result.Y = rect2.Y;
  145. }
  146. if (result.X+result.Width < rect2.X+rect2.Width) {
  147. result.Width = T(((rect2.X+rect2.Width)-result.X)+1);
  148. }
  149. if (result.Y+result.Height < rect2.Y+rect2.Height) {
  150. result.Height = T(((rect2.Y+rect2.Height)-result.Y)+1);
  151. }
  152. return(result);
  153. }
  154. return(rect1);
  155. }
  156. return(rect2);
  157. }
  158. /***********************************************************************************************
  159. * Intersect -- Find the intersection between two rectangles. *
  160. * *
  161. * This routine will take two rectangles and return the intersecting rectangle. It also *
  162. * tracks how much on rectangle was clipped off of the top and left edges and returns *
  163. * these values. It can be handy to use these returned clipping values for blit operations *
  164. * between rectangles. *
  165. * *
  166. * INPUT: bounding_rect -- The rectangle of the bounding box (clipping rectangle). *
  167. * *
  168. * draw_rect -- The rectangle that will be clipped into the bounding rectangle. *
  169. * *
  170. * x,y -- Place to store the clipping offset performed on the draw_rect. *
  171. * If this offset is applied to a subsiquent blit operation from *
  172. * the draw_rect source, it will appear to be properly clipped *
  173. * against the clipping rectangle rather than offset to the *
  174. * clipping rectangle. *
  175. * *
  176. * OUTPUT: Returns with the rectangle that is the intersection of the two rectangles. *
  177. * *
  178. * WARNINGS: The returned rectangle may be clipped into nothingness. Check for Is_Valid *
  179. * to catch this case. *
  180. * *
  181. * HISTORY: *
  182. * 06/04/1997 JLB : Created. *
  183. *=============================================================================================*/
  184. template<class T>
  185. TRect<T> const Intersect(TRect<T> const & bounding_rect, TRect<T> const & draw_rect, T * x, T * y)
  186. {
  187. TRect<T> bad_rect(0, 0, 0, 0); // Dummy (illegal) draw_rect.
  188. TRect<T> new_draw_rect = draw_rect; // Working draw_rect.
  189. /*
  190. ** Both draw_rects must be valid or else no intersection can occur. In such
  191. ** a case, return an illegal draw_rect.
  192. */
  193. if (!bounding_rect.Is_Valid() || !draw_rect.Is_Valid()) return(bad_rect);
  194. /*
  195. ** The draw_rect spills past the left edge.
  196. */
  197. if (new_draw_rect.X < bounding_rect.X) {
  198. new_draw_rect.Width -= T(bounding_rect.X - new_draw_rect.X);
  199. new_draw_rect.X = bounding_rect.X;
  200. }
  201. if (new_draw_rect.Width < 1) return(bad_rect);
  202. /*
  203. ** The draw_rect spills past top edge.
  204. */
  205. if (new_draw_rect.Y < bounding_rect.Y) {
  206. new_draw_rect.Height -= T(bounding_rect.Y - new_draw_rect.Y);
  207. new_draw_rect.Y = bounding_rect.Y;
  208. }
  209. if (new_draw_rect.Height < 1) return(bad_rect);
  210. /*
  211. ** The draw_rect spills past the right edge.
  212. */
  213. if (new_draw_rect.X + new_draw_rect.Width > bounding_rect.X + bounding_rect.Width) {
  214. new_draw_rect.Width -= T((new_draw_rect.X + new_draw_rect.Width) - (bounding_rect.X + bounding_rect.Width));
  215. }
  216. if (new_draw_rect.Width < 1) return(bad_rect);
  217. /*
  218. ** The draw_rect spills past the bottom edge.
  219. */
  220. if (new_draw_rect.Y + new_draw_rect.Height > bounding_rect.Y + bounding_rect.Height) {
  221. new_draw_rect.Height -= T((new_draw_rect.Y + new_draw_rect.Height) - (bounding_rect.Y + bounding_rect.Height));
  222. }
  223. if (new_draw_rect.Height < 1) return(bad_rect);
  224. /*
  225. ** Adjust Height relative draw position according to Height new draw_rect
  226. ** union.
  227. */
  228. if (x != NULL) {
  229. *x -= T(new_draw_rect.X - draw_rect.X);
  230. }
  231. if (y != NULL) {
  232. *y -= T(new_draw_rect.Y - draw_rect.Y);
  233. }
  234. return(new_draw_rect);
  235. }
  236. /***********************************************************************************************
  237. * Intersect -- Simple intersect between two rectangles. *
  238. * *
  239. * This will return with the rectangle that represents the intersection of the two *
  240. * rectangles specified. *
  241. * *
  242. * INPUT: rect1 -- The first rectangle. *
  243. * *
  244. * rect2 -- The second rectangle. *
  245. * *
  246. * OUTPUT: Returns with the intersecting rectangle between the two rectangles specified. *
  247. * *
  248. * WARNINGS: If there is no valid intersection between the two rectangles, then a rectangle *
  249. * of illegal value is returned. Check for this case by using the Is_Valid() *
  250. * function. *
  251. * *
  252. * HISTORY: *
  253. * 06/04/1997 JLB : Created. *
  254. *=============================================================================================*/
  255. template<class T>
  256. TRect<T> const Intersect(TRect<T> const & rect1, TRect<T> const & rect2)
  257. {
  258. return(Intersect(rect1, rect2, (T*)NULL, (T*)NULL));
  259. }
  260. /*
  261. ** This typedef provides an uncluttered type name for a rectangle that
  262. ** is composed of integers.
  263. */
  264. typedef TRect<int> Rect;
  265. const Rect RECT_NONE(0,0,0,0);
  266. #endif