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