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
38extern "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 */
49typedef 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 */
63typedef 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 */
83typedef 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 */
106typedef 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 */
126SDL_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 */
155SDL_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 */
179SDL_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 */
203SDL_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 */
224extern 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 */
241extern 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 */
255extern 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 */
274extern 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 */
294extern 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 */
320SDL_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 */
344SDL_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 */
374SDL_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 */
409SDL_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 */
427extern 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 */
444extern 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 */
458extern 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 */
478extern 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 */
499extern 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