1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | |
22 | /** |
23 | * # CategoryRect |
24 | * |
25 | * Some helper functions for managing rectangles and 2D points, in both |
26 | * integer and floating point versions. |
27 | */ |
28 | |
29 | #ifndef SDL_rect_h_ |
30 | #define SDL_rect_h_ |
31 | |
32 | #include <SDL3/SDL_stdinc.h> |
33 | #include <SDL3/SDL_error.h> |
34 | |
35 | #include <SDL3/SDL_begin_code.h> |
36 | /* Set up for C function definitions, even when using C++ */ |
37 | #ifdef __cplusplus |
38 | extern "C" { |
39 | #endif |
40 | |
41 | /** |
42 | * The structure that defines a point (using integers). |
43 | * |
44 | * \since This struct is available since SDL 3.2.0. |
45 | * |
46 | * \sa SDL_GetRectEnclosingPoints |
47 | * \sa SDL_PointInRect |
48 | */ |
49 | typedef struct SDL_Point |
50 | { |
51 | int x; |
52 | int y; |
53 | } SDL_Point; |
54 | |
55 | /** |
56 | * The structure that defines a point (using floating point values). |
57 | * |
58 | * \since This struct is available since SDL 3.2.0. |
59 | * |
60 | * \sa SDL_GetRectEnclosingPointsFloat |
61 | * \sa SDL_PointInRectFloat |
62 | */ |
63 | typedef struct SDL_FPoint |
64 | { |
65 | float x; |
66 | float y; |
67 | } SDL_FPoint; |
68 | |
69 | |
70 | /** |
71 | * A rectangle, with the origin at the upper left (using integers). |
72 | * |
73 | * \since This struct is available since SDL 3.2.0. |
74 | * |
75 | * \sa SDL_RectEmpty |
76 | * \sa SDL_RectsEqual |
77 | * \sa SDL_HasRectIntersection |
78 | * \sa SDL_GetRectIntersection |
79 | * \sa SDL_GetRectAndLineIntersection |
80 | * \sa SDL_GetRectUnion |
81 | * \sa SDL_GetRectEnclosingPoints |
82 | */ |
83 | typedef struct SDL_Rect |
84 | { |
85 | int x, y; |
86 | int w, h; |
87 | } SDL_Rect; |
88 | |
89 | |
90 | /** |
91 | * A rectangle, with the origin at the upper left (using floating point |
92 | * values). |
93 | * |
94 | * \since This struct is available since SDL 3.2.0. |
95 | * |
96 | * \sa SDL_RectEmptyFloat |
97 | * \sa SDL_RectsEqualFloat |
98 | * \sa SDL_RectsEqualEpsilon |
99 | * \sa SDL_HasRectIntersectionFloat |
100 | * \sa SDL_GetRectIntersectionFloat |
101 | * \sa SDL_GetRectAndLineIntersectionFloat |
102 | * \sa SDL_GetRectUnionFloat |
103 | * \sa SDL_GetRectEnclosingPointsFloat |
104 | * \sa SDL_PointInRectFloat |
105 | */ |
106 | typedef struct SDL_FRect |
107 | { |
108 | float x; |
109 | float y; |
110 | float w; |
111 | float h; |
112 | } SDL_FRect; |
113 | |
114 | |
115 | /** |
116 | * Convert an SDL_Rect to SDL_FRect |
117 | * |
118 | * \param rect a pointer to an SDL_Rect. |
119 | * \param frect a pointer filled in with the floating point representation of |
120 | * `rect`. |
121 | * |
122 | * \threadsafety It is safe to call this function from any thread. |
123 | * |
124 | * \since This function is available since SDL 3.2.0. |
125 | */ |
126 | SDL_FORCE_INLINE void SDL_RectToFRect(const SDL_Rect *rect, SDL_FRect *frect) |
127 | { |
128 | frect->x = (float)rect->x; |
129 | frect->y = (float)rect->y; |
130 | frect->w = (float)rect->w; |
131 | frect->h = (float)rect->h; |
132 | } |
133 | |
134 | /** |
135 | * Determine whether a point resides inside a rectangle. |
136 | * |
137 | * A point is considered part of a rectangle if both `p` and `r` are not NULL, |
138 | * and `p`'s x and y coordinates are >= to the rectangle's top left corner, |
139 | * and < the rectangle's x+w and y+h. So a 1x1 rectangle considers point (0,0) |
140 | * as "inside" and (0,1) as not. |
141 | * |
142 | * Note that this is a forced-inline function in a header, and not a public |
143 | * API function available in the SDL library (which is to say, the code is |
144 | * embedded in the calling program and the linker and dynamic loader will not |
145 | * be able to find this function inside SDL itself). |
146 | * |
147 | * \param p the point to test. |
148 | * \param r the rectangle to test. |
149 | * \returns true if `p` is contained by `r`, false otherwise. |
150 | * |
151 | * \threadsafety It is safe to call this function from any thread. |
152 | * |
153 | * \since This function is available since SDL 3.2.0. |
154 | */ |
155 | SDL_FORCE_INLINE bool SDL_PointInRect(const SDL_Point *p, const SDL_Rect *r) |
156 | { |
157 | return ( p && r && (p->x >= r->x) && (p->x < (r->x + r->w)) && |
158 | (p->y >= r->y) && (p->y < (r->y + r->h)) ) ? true : false; |
159 | } |
160 | |
161 | /** |
162 | * Determine whether a rectangle has no area. |
163 | * |
164 | * A rectangle is considered "empty" for this function if `r` is NULL, or if |
165 | * `r`'s width and/or height are <= 0. |
166 | * |
167 | * Note that this is a forced-inline function in a header, and not a public |
168 | * API function available in the SDL library (which is to say, the code is |
169 | * embedded in the calling program and the linker and dynamic loader will not |
170 | * be able to find this function inside SDL itself). |
171 | * |
172 | * \param r the rectangle to test. |
173 | * \returns true if the rectangle is "empty", false otherwise. |
174 | * |
175 | * \threadsafety It is safe to call this function from any thread. |
176 | * |
177 | * \since This function is available since SDL 3.2.0. |
178 | */ |
179 | SDL_FORCE_INLINE bool SDL_RectEmpty(const SDL_Rect *r) |
180 | { |
181 | return ((!r) || (r->w <= 0) || (r->h <= 0)) ? true : false; |
182 | } |
183 | |
184 | /** |
185 | * Determine whether two rectangles are equal. |
186 | * |
187 | * Rectangles are considered equal if both are not NULL and each of their x, |
188 | * y, width and height match. |
189 | * |
190 | * Note that this is a forced-inline function in a header, and not a public |
191 | * API function available in the SDL library (which is to say, the code is |
192 | * embedded in the calling program and the linker and dynamic loader will not |
193 | * be able to find this function inside SDL itself). |
194 | * |
195 | * \param a the first rectangle to test. |
196 | * \param b the second rectangle to test. |
197 | * \returns true if the rectangles are equal, false otherwise. |
198 | * |
199 | * \threadsafety It is safe to call this function from any thread. |
200 | * |
201 | * \since This function is available since SDL 3.2.0. |
202 | */ |
203 | SDL_FORCE_INLINE bool SDL_RectsEqual(const SDL_Rect *a, const SDL_Rect *b) |
204 | { |
205 | return (a && b && (a->x == b->x) && (a->y == b->y) && |
206 | (a->w == b->w) && (a->h == b->h)) ? true : false; |
207 | } |
208 | |
209 | /** |
210 | * Determine whether two rectangles intersect. |
211 | * |
212 | * If either pointer is NULL the function will return false. |
213 | * |
214 | * \param A an SDL_Rect structure representing the first rectangle. |
215 | * \param B an SDL_Rect structure representing the second rectangle. |
216 | * \returns true if there is an intersection, false otherwise. |
217 | * |
218 | * \threadsafety It is safe to call this function from any thread. |
219 | * |
220 | * \since This function is available since SDL 3.2.0. |
221 | * |
222 | * \sa SDL_GetRectIntersection |
223 | */ |
224 | extern SDL_DECLSPEC bool SDLCALL SDL_HasRectIntersection(const SDL_Rect *A, const SDL_Rect *B); |
225 | |
226 | /** |
227 | * Calculate the intersection of two rectangles. |
228 | * |
229 | * If `result` is NULL then this function will return false. |
230 | * |
231 | * \param A an SDL_Rect structure representing the first rectangle. |
232 | * \param B an SDL_Rect structure representing the second rectangle. |
233 | * \param result an SDL_Rect structure filled in with the intersection of |
234 | * rectangles `A` and `B`. |
235 | * \returns true if there is an intersection, false otherwise. |
236 | * |
237 | * \since This function is available since SDL 3.2.0. |
238 | * |
239 | * \sa SDL_HasRectIntersection |
240 | */ |
241 | extern SDL_DECLSPEC bool SDLCALL SDL_GetRectIntersection(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *result); |
242 | |
243 | /** |
244 | * Calculate the union of two rectangles. |
245 | * |
246 | * \param A an SDL_Rect structure representing the first rectangle. |
247 | * \param B an SDL_Rect structure representing the second rectangle. |
248 | * \param result an SDL_Rect structure filled in with the union of rectangles |
249 | * `A` and `B`. |
250 | * \returns true on success or false on failure; call SDL_GetError() for more |
251 | * information. |
252 | * |
253 | * \since This function is available since SDL 3.2.0. |
254 | */ |
255 | extern SDL_DECLSPEC bool SDLCALL SDL_GetRectUnion(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *result); |
256 | |
257 | /** |
258 | * Calculate a minimal rectangle enclosing a set of points. |
259 | * |
260 | * If `clip` is not NULL then only points inside of the clipping rectangle are |
261 | * considered. |
262 | * |
263 | * \param points an array of SDL_Point structures representing points to be |
264 | * enclosed. |
265 | * \param count the number of structures in the `points` array. |
266 | * \param clip an SDL_Rect used for clipping or NULL to enclose all points. |
267 | * \param result an SDL_Rect structure filled in with the minimal enclosing |
268 | * rectangle. |
269 | * \returns true if any points were enclosed or false if all the points were |
270 | * outside of the clipping rectangle. |
271 | * |
272 | * \since This function is available since SDL 3.2.0. |
273 | */ |
274 | extern SDL_DECLSPEC bool SDLCALL SDL_GetRectEnclosingPoints(const SDL_Point *points, int count, const SDL_Rect *clip, SDL_Rect *result); |
275 | |
276 | /** |
277 | * Calculate the intersection of a rectangle and line segment. |
278 | * |
279 | * This function is used to clip a line segment to a rectangle. A line segment |
280 | * contained entirely within the rectangle or that does not intersect will |
281 | * remain unchanged. A line segment that crosses the rectangle at either or |
282 | * both ends will be clipped to the boundary of the rectangle and the new |
283 | * coordinates saved in `X1`, `Y1`, `X2`, and/or `Y2` as necessary. |
284 | * |
285 | * \param rect an SDL_Rect structure representing the rectangle to intersect. |
286 | * \param X1 a pointer to the starting X-coordinate of the line. |
287 | * \param Y1 a pointer to the starting Y-coordinate of the line. |
288 | * \param X2 a pointer to the ending X-coordinate of the line. |
289 | * \param Y2 a pointer to the ending Y-coordinate of the line. |
290 | * \returns true if there is an intersection, false otherwise. |
291 | * |
292 | * \since This function is available since SDL 3.2.0. |
293 | */ |
294 | extern SDL_DECLSPEC bool SDLCALL SDL_GetRectAndLineIntersection(const SDL_Rect *rect, int *X1, int *Y1, int *X2, int *Y2); |
295 | |
296 | |
297 | /* SDL_FRect versions... */ |
298 | |
299 | /** |
300 | * Determine whether a point resides inside a floating point rectangle. |
301 | * |
302 | * A point is considered part of a rectangle if both `p` and `r` are not NULL, |
303 | * and `p`'s x and y coordinates are >= to the rectangle's top left corner, |
304 | * and <= the rectangle's x+w and y+h. So a 1x1 rectangle considers point |
305 | * (0,0) and (0,1) as "inside" and (0,2) as not. |
306 | * |
307 | * Note that this is a forced-inline function in a header, and not a public |
308 | * API function available in the SDL library (which is to say, the code is |
309 | * embedded in the calling program and the linker and dynamic loader will not |
310 | * be able to find this function inside SDL itself). |
311 | * |
312 | * \param p the point to test. |
313 | * \param r the rectangle to test. |
314 | * \returns true if `p` is contained by `r`, false otherwise. |
315 | * |
316 | * \threadsafety It is safe to call this function from any thread. |
317 | * |
318 | * \since This function is available since SDL 3.2.0. |
319 | */ |
320 | SDL_FORCE_INLINE bool SDL_PointInRectFloat(const SDL_FPoint *p, const SDL_FRect *r) |
321 | { |
322 | return ( p && r && (p->x >= r->x) && (p->x <= (r->x + r->w)) && |
323 | (p->y >= r->y) && (p->y <= (r->y + r->h)) ) ? true : false; |
324 | } |
325 | |
326 | /** |
327 | * Determine whether a floating point rectangle can contain any point. |
328 | * |
329 | * A rectangle is considered "empty" for this function if `r` is NULL, or if |
330 | * `r`'s width and/or height are < 0.0f. |
331 | * |
332 | * Note that this is a forced-inline function in a header, and not a public |
333 | * API function available in the SDL library (which is to say, the code is |
334 | * embedded in the calling program and the linker and dynamic loader will not |
335 | * be able to find this function inside SDL itself). |
336 | * |
337 | * \param r the rectangle to test. |
338 | * \returns true if the rectangle is "empty", false otherwise. |
339 | * |
340 | * \threadsafety It is safe to call this function from any thread. |
341 | * |
342 | * \since This function is available since SDL 3.2.0. |
343 | */ |
344 | SDL_FORCE_INLINE bool SDL_RectEmptyFloat(const SDL_FRect *r) |
345 | { |
346 | return ((!r) || (r->w < 0.0f) || (r->h < 0.0f)) ? true : false; |
347 | } |
348 | |
349 | /** |
350 | * Determine whether two floating point rectangles are equal, within some |
351 | * given epsilon. |
352 | * |
353 | * Rectangles are considered equal if both are not NULL and each of their x, |
354 | * y, width and height are within `epsilon` of each other. If you don't know |
355 | * what value to use for `epsilon`, you should call the SDL_RectsEqualFloat |
356 | * function instead. |
357 | * |
358 | * Note that this is a forced-inline function in a header, and not a public |
359 | * API function available in the SDL library (which is to say, the code is |
360 | * embedded in the calling program and the linker and dynamic loader will not |
361 | * be able to find this function inside SDL itself). |
362 | * |
363 | * \param a the first rectangle to test. |
364 | * \param b the second rectangle to test. |
365 | * \param epsilon the epsilon value for comparison. |
366 | * \returns true if the rectangles are equal, false otherwise. |
367 | * |
368 | * \threadsafety It is safe to call this function from any thread. |
369 | * |
370 | * \since This function is available since SDL 3.2.0. |
371 | * |
372 | * \sa SDL_RectsEqualFloat |
373 | */ |
374 | SDL_FORCE_INLINE bool SDL_RectsEqualEpsilon(const SDL_FRect *a, const SDL_FRect *b, float epsilon) |
375 | { |
376 | return (a && b && ((a == b) || |
377 | ((SDL_fabsf(a->x - b->x) <= epsilon) && |
378 | (SDL_fabsf(a->y - b->y) <= epsilon) && |
379 | (SDL_fabsf(a->w - b->w) <= epsilon) && |
380 | (SDL_fabsf(a->h - b->h) <= epsilon)))) |
381 | ? true : false; |
382 | } |
383 | |
384 | /** |
385 | * Determine whether two floating point rectangles are equal, within a default |
386 | * epsilon. |
387 | * |
388 | * Rectangles are considered equal if both are not NULL and each of their x, |
389 | * y, width and height are within SDL_FLT_EPSILON of each other. This is often |
390 | * a reasonable way to compare two floating point rectangles and deal with the |
391 | * slight precision variations in floating point calculations that tend to pop |
392 | * up. |
393 | * |
394 | * Note that this is a forced-inline function in a header, and not a public |
395 | * API function available in the SDL library (which is to say, the code is |
396 | * embedded in the calling program and the linker and dynamic loader will not |
397 | * be able to find this function inside SDL itself). |
398 | * |
399 | * \param a the first rectangle to test. |
400 | * \param b the second rectangle to test. |
401 | * \returns true if the rectangles are equal, false otherwise. |
402 | * |
403 | * \threadsafety It is safe to call this function from any thread. |
404 | * |
405 | * \since This function is available since SDL 3.2.0. |
406 | * |
407 | * \sa SDL_RectsEqualEpsilon |
408 | */ |
409 | SDL_FORCE_INLINE bool SDL_RectsEqualFloat(const SDL_FRect *a, const SDL_FRect *b) |
410 | { |
411 | return SDL_RectsEqualEpsilon(a, b, SDL_FLT_EPSILON); |
412 | } |
413 | |
414 | /** |
415 | * Determine whether two rectangles intersect with float precision. |
416 | * |
417 | * If either pointer is NULL the function will return false. |
418 | * |
419 | * \param A an SDL_FRect structure representing the first rectangle. |
420 | * \param B an SDL_FRect structure representing the second rectangle. |
421 | * \returns true if there is an intersection, false otherwise. |
422 | * |
423 | * \since This function is available since SDL 3.2.0. |
424 | * |
425 | * \sa SDL_GetRectIntersection |
426 | */ |
427 | extern SDL_DECLSPEC bool SDLCALL SDL_HasRectIntersectionFloat(const SDL_FRect *A, const SDL_FRect *B); |
428 | |
429 | /** |
430 | * Calculate the intersection of two rectangles with float precision. |
431 | * |
432 | * If `result` is NULL then this function will return false. |
433 | * |
434 | * \param A an SDL_FRect structure representing the first rectangle. |
435 | * \param B an SDL_FRect structure representing the second rectangle. |
436 | * \param result an SDL_FRect structure filled in with the intersection of |
437 | * rectangles `A` and `B`. |
438 | * \returns true if there is an intersection, false otherwise. |
439 | * |
440 | * \since This function is available since SDL 3.2.0. |
441 | * |
442 | * \sa SDL_HasRectIntersectionFloat |
443 | */ |
444 | extern SDL_DECLSPEC bool SDLCALL SDL_GetRectIntersectionFloat(const SDL_FRect *A, const SDL_FRect *B, SDL_FRect *result); |
445 | |
446 | /** |
447 | * Calculate the union of two rectangles with float precision. |
448 | * |
449 | * \param A an SDL_FRect structure representing the first rectangle. |
450 | * \param B an SDL_FRect structure representing the second rectangle. |
451 | * \param result an SDL_FRect structure filled in with the union of rectangles |
452 | * `A` and `B`. |
453 | * \returns true on success or false on failure; call SDL_GetError() for more |
454 | * information. |
455 | * |
456 | * \since This function is available since SDL 3.2.0. |
457 | */ |
458 | extern SDL_DECLSPEC bool SDLCALL SDL_GetRectUnionFloat(const SDL_FRect *A, const SDL_FRect *B, SDL_FRect *result); |
459 | |
460 | /** |
461 | * Calculate a minimal rectangle enclosing a set of points with float |
462 | * precision. |
463 | * |
464 | * If `clip` is not NULL then only points inside of the clipping rectangle are |
465 | * considered. |
466 | * |
467 | * \param points an array of SDL_FPoint structures representing points to be |
468 | * enclosed. |
469 | * \param count the number of structures in the `points` array. |
470 | * \param clip an SDL_FRect used for clipping or NULL to enclose all points. |
471 | * \param result an SDL_FRect structure filled in with the minimal enclosing |
472 | * rectangle. |
473 | * \returns true if any points were enclosed or false if all the points were |
474 | * outside of the clipping rectangle. |
475 | * |
476 | * \since This function is available since SDL 3.2.0. |
477 | */ |
478 | extern SDL_DECLSPEC bool SDLCALL SDL_GetRectEnclosingPointsFloat(const SDL_FPoint *points, int count, const SDL_FRect *clip, SDL_FRect *result); |
479 | |
480 | /** |
481 | * Calculate the intersection of a rectangle and line segment with float |
482 | * precision. |
483 | * |
484 | * This function is used to clip a line segment to a rectangle. A line segment |
485 | * contained entirely within the rectangle or that does not intersect will |
486 | * remain unchanged. A line segment that crosses the rectangle at either or |
487 | * both ends will be clipped to the boundary of the rectangle and the new |
488 | * coordinates saved in `X1`, `Y1`, `X2`, and/or `Y2` as necessary. |
489 | * |
490 | * \param rect an SDL_FRect structure representing the rectangle to intersect. |
491 | * \param X1 a pointer to the starting X-coordinate of the line. |
492 | * \param Y1 a pointer to the starting Y-coordinate of the line. |
493 | * \param X2 a pointer to the ending X-coordinate of the line. |
494 | * \param Y2 a pointer to the ending Y-coordinate of the line. |
495 | * \returns true if there is an intersection, false otherwise. |
496 | * |
497 | * \since This function is available since SDL 3.2.0. |
498 | */ |
499 | extern SDL_DECLSPEC bool SDLCALL SDL_GetRectAndLineIntersectionFloat(const SDL_FRect *rect, float *X1, float *Y1, float *X2, float *Y2); |
500 | |
501 | /* Ends C function definitions when using C++ */ |
502 | #ifdef __cplusplus |
503 | } |
504 | #endif |
505 | #include <SDL3/SDL_close_code.h> |
506 | |
507 | #endif /* SDL_rect_h_ */ |
508 | |