zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SDL_rect.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2013 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 #include "SDL_config.h"
22 
23 #include "SDL_rect.h"
24 #include "SDL_rect_c.h"
25 
26 
28 SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B)
29 {
30  int Amin, Amax, Bmin, Bmax;
31 
32  if (!A) {
34  return SDL_FALSE;
35  }
36 
37  if (!B) {
39  return SDL_FALSE;
40  }
41 
42  /* Special cases for empty rects */
43  if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) {
44  return SDL_FALSE;
45  }
46 
47  /* Horizontal intersection */
48  Amin = A->x;
49  Amax = Amin + A->w;
50  Bmin = B->x;
51  Bmax = Bmin + B->w;
52  if (Bmin > Amin)
53  Amin = Bmin;
54  if (Bmax < Amax)
55  Amax = Bmax;
56  if (Amax <= Amin)
57  return SDL_FALSE;
58 
59  /* Vertical intersection */
60  Amin = A->y;
61  Amax = Amin + A->h;
62  Bmin = B->y;
63  Bmax = Bmin + B->h;
64  if (Bmin > Amin)
65  Amin = Bmin;
66  if (Bmax < Amax)
67  Amax = Bmax;
68  if (Amax <= Amin)
69  return SDL_FALSE;
70 
71  return SDL_TRUE;
72 }
73 
76 {
77  int Amin, Amax, Bmin, Bmax;
78 
79  if (!A) {
81  return SDL_FALSE;
82  }
83 
84  if (!B) {
86  return SDL_FALSE;
87  }
88 
89  if (!result) {
90  SDL_InvalidParamError("result");
91  return SDL_FALSE;
92  }
93 
94  /* Special cases for empty rects */
95  if (SDL_RectEmpty(A) || SDL_RectEmpty(B)) {
96  result->w = 0;
97  result->h = 0;
98  return SDL_FALSE;
99  }
100 
101  /* Horizontal intersection */
102  Amin = A->x;
103  Amax = Amin + A->w;
104  Bmin = B->x;
105  Bmax = Bmin + B->w;
106  if (Bmin > Amin)
107  Amin = Bmin;
108  result->x = Amin;
109  if (Bmax < Amax)
110  Amax = Bmax;
111  result->w = Amax - Amin;
112 
113  /* Vertical intersection */
114  Amin = A->y;
115  Amax = Amin + A->h;
116  Bmin = B->y;
117  Bmax = Bmin + B->h;
118  if (Bmin > Amin)
119  Amin = Bmin;
120  result->y = Amin;
121  if (Bmax < Amax)
122  Amax = Bmax;
123  result->h = Amax - Amin;
124 
125  return !SDL_RectEmpty(result);
126 }
127 
128 void
130 {
131  int Amin, Amax, Bmin, Bmax;
132 
133  if (!A) {
135  return;
136  }
137 
138  if (!B) {
140  return;
141  }
142 
143  if (!result) {
144  SDL_InvalidParamError("result");
145  return;
146  }
147 
148  /* Special cases for empty Rects */
149  if (SDL_RectEmpty(A)) {
150  if (SDL_RectEmpty(B)) {
151  /* A and B empty */
152  return;
153  } else {
154  /* A empty, B not empty */
155  *result = *B;
156  return;
157  }
158  } else {
159  if (SDL_RectEmpty(B)) {
160  /* A not empty, B empty */
161  *result = *A;
162  return;
163  }
164  }
165 
166  /* Horizontal union */
167  Amin = A->x;
168  Amax = Amin + A->w;
169  Bmin = B->x;
170  Bmax = Bmin + B->w;
171  if (Bmin < Amin)
172  Amin = Bmin;
173  result->x = Amin;
174  if (Bmax > Amax)
175  Amax = Bmax;
176  result->w = Amax - Amin;
177 
178  /* Vertical union */
179  Amin = A->y;
180  Amax = Amin + A->h;
181  Bmin = B->y;
182  Bmax = Bmin + B->h;
183  if (Bmin < Amin)
184  Amin = Bmin;
185  result->y = Amin;
186  if (Bmax > Amax)
187  Amax = Bmax;
188  result->h = Amax - Amin;
189 }
190 
191 SDL_bool
192 SDL_EnclosePoints(const SDL_Point * points, int count, const SDL_Rect * clip,
193  SDL_Rect * result)
194 {
195  int minx = 0;
196  int miny = 0;
197  int maxx = 0;
198  int maxy = 0;
199  int x, y, i;
200 
201  if (!points) {
202  SDL_InvalidParamError("points");
203  return SDL_FALSE;
204  }
205 
206  if (count < 1) {
207  SDL_InvalidParamError("count");
208  return SDL_FALSE;
209  }
210 
211  if (clip) {
212  SDL_bool added = SDL_FALSE;
213  const int clip_minx = clip->x;
214  const int clip_miny = clip->y;
215  const int clip_maxx = clip->x+clip->w-1;
216  const int clip_maxy = clip->y+clip->h-1;
217 
218  /* Special case for empty rectangle */
219  if (SDL_RectEmpty(clip)) {
220  return SDL_FALSE;
221  }
222 
223  for (i = 0; i < count; ++i) {
224  x = points[i].x;
225  y = points[i].y;
226 
227  if (x < clip_minx || x > clip_maxx ||
228  y < clip_miny || y > clip_maxy) {
229  continue;
230  }
231  if (!added) {
232  /* Special case: if no result was requested, we are done */
233  if (result == NULL) {
234  return SDL_TRUE;
235  }
236 
237  /* First point added */
238  minx = maxx = x;
239  miny = maxy = y;
240  added = SDL_TRUE;
241  continue;
242  }
243  if (x < minx) {
244  minx = x;
245  } else if (x > maxx) {
246  maxx = x;
247  }
248  if (y < miny) {
249  miny = y;
250  } else if (y > maxy) {
251  maxy = y;
252  }
253  }
254  if (!added) {
255  return SDL_FALSE;
256  }
257  } else {
258  /* Special case: if no result was requested, we are done */
259  if (result == NULL) {
260  return SDL_TRUE;
261  }
262 
263  /* No clipping, always add the first point */
264  minx = maxx = points[0].x;
265  miny = maxy = points[0].y;
266 
267  for (i = 1; i < count; ++i) {
268  x = points[i].x;
269  y = points[i].y;
270 
271  if (x < minx) {
272  minx = x;
273  } else if (x > maxx) {
274  maxx = x;
275  }
276  if (y < miny) {
277  miny = y;
278  } else if (y > maxy) {
279  maxy = y;
280  }
281  }
282  }
283 
284  if (result) {
285  result->x = minx;
286  result->y = miny;
287  result->w = (maxx-minx)+1;
288  result->h = (maxy-miny)+1;
289  }
290  return SDL_TRUE;
291 }
292 
293 /* Use the Cohen-Sutherland algorithm for line clipping */
294 #define CODE_BOTTOM 1
295 #define CODE_TOP 2
296 #define CODE_LEFT 4
297 #define CODE_RIGHT 8
298 
299 static int ComputeOutCode(const SDL_Rect * rect, int x, int y)
300 {
301  int code = 0;
302  if (y < 0) {
303  code |= CODE_TOP;
304  } else if (y >= rect->y + rect->h) {
305  code |= CODE_BOTTOM;
306  }
307  if (x < 0) {
308  code |= CODE_LEFT;
309  } else if (x >= rect->x + rect->w) {
310  code |= CODE_RIGHT;
311  }
312  return code;
313 }
314 
315 SDL_bool
316 SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, int *Y1, int *X2,
317  int *Y2)
318 {
319  int x = 0;
320  int y = 0;
321  int x1, y1;
322  int x2, y2;
323  int rectx1;
324  int recty1;
325  int rectx2;
326  int recty2;
327  int outcode1, outcode2;
328 
329  if (!rect) {
330  SDL_InvalidParamError("rect");
331  return SDL_FALSE;
332  }
333 
334  if (!X1) {
335  SDL_InvalidParamError("X1");
336  return SDL_FALSE;
337  }
338 
339  if (!Y1) {
340  SDL_InvalidParamError("Y1");
341  return SDL_FALSE;
342  }
343 
344  if (!X2) {
345  SDL_InvalidParamError("X2");
346  return SDL_FALSE;
347  }
348 
349  if (!Y2) {
350  SDL_InvalidParamError("Y2");
351  return SDL_FALSE;
352  }
353 
354  /* Special case for empty rect */
355  if (SDL_RectEmpty(rect)) {
356  return SDL_FALSE;
357  }
358 
359  x1 = *X1;
360  y1 = *Y1;
361  x2 = *X2;
362  y2 = *Y2;
363  rectx1 = rect->x;
364  recty1 = rect->y;
365  rectx2 = rect->x + rect->w - 1;
366  recty2 = rect->y + rect->h - 1;
367 
368  /* Check to see if entire line is inside rect */
369  if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 &&
370  y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2) {
371  return SDL_TRUE;
372  }
373 
374  /* Check to see if entire line is to one side of rect */
375  if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
376  (y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2)) {
377  return SDL_FALSE;
378  }
379 
380  if (y1 == y2) {
381  /* Horizontal line, easy to clip */
382  if (x1 < rectx1) {
383  *X1 = rectx1;
384  } else if (x1 > rectx2) {
385  *X1 = rectx2;
386  }
387  if (x2 < rectx1) {
388  *X2 = rectx1;
389  } else if (x2 > rectx2) {
390  *X2 = rectx2;
391  }
392  return SDL_TRUE;
393  }
394 
395  if (x1 == x2) {
396  /* Vertical line, easy to clip */
397  if (y1 < recty1) {
398  *Y1 = recty1;
399  } else if (y1 > recty2) {
400  *Y1 = recty2;
401  }
402  if (y2 < recty1) {
403  *Y2 = recty1;
404  } else if (y2 > recty2) {
405  *Y2 = recty2;
406  }
407  return SDL_TRUE;
408  }
409 
410  /* More complicated Cohen-Sutherland algorithm */
411  outcode1 = ComputeOutCode(rect, x1, y1);
412  outcode2 = ComputeOutCode(rect, x2, y2);
413  while (outcode1 || outcode2) {
414  if (outcode1 & outcode2) {
415  return SDL_FALSE;
416  }
417 
418  if (outcode1) {
419  if (outcode1 & CODE_TOP) {
420  y = recty1;
421  x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
422  } else if (outcode1 & CODE_BOTTOM) {
423  y = recty2;
424  x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
425  } else if (outcode1 & CODE_LEFT) {
426  x = rectx1;
427  y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
428  } else if (outcode1 & CODE_RIGHT) {
429  x = rectx2;
430  y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
431  }
432  x1 = x;
433  y1 = y;
434  outcode1 = ComputeOutCode(rect, x, y);
435  } else {
436  if (outcode2 & CODE_TOP) {
437  y = recty1;
438  x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
439  } else if (outcode2 & CODE_BOTTOM) {
440  y = recty2;
441  x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
442  } else if (outcode2 & CODE_LEFT) {
443  x = rectx1;
444  y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
445  } else if (outcode2 & CODE_RIGHT) {
446  x = rectx2;
447  y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
448  }
449  x2 = x;
450  y2 = y;
451  outcode2 = ComputeOutCode(rect, x, y);
452  }
453  }
454  *X1 = x1;
455  *Y1 = y1;
456  *X2 = x2;
457  *Y2 = y2;
458  return SDL_TRUE;
459 }
460 
461 SDL_bool
463  int numrects, const SDL_Rect * rects, SDL_Rect *span)
464 {
465  int i;
466  int span_y1, span_y2;
467  int rect_y1, rect_y2;
468 
469  if (width < 1) {
470  SDL_InvalidParamError("width");
471  return SDL_FALSE;
472  }
473 
474  if (height < 1) {
475  SDL_InvalidParamError("height");
476  return SDL_FALSE;
477  }
478 
479  if (!rects) {
480  SDL_InvalidParamError("rects");
481  return SDL_FALSE;
482  }
483 
484  if (!span) {
485  SDL_InvalidParamError("span");
486  return SDL_FALSE;
487  }
488 
489  if (numrects < 1) {
490  SDL_InvalidParamError("numrects");
491  return SDL_FALSE;
492  }
493 
494  /* Initialize to empty rect */
495  span_y1 = height;
496  span_y2 = 0;
497 
498  for (i = 0; i < numrects; ++i) {
499  rect_y1 = rects[i].y;
500  rect_y2 = rect_y1 + rects[i].h;
501 
502  /* Clip out of bounds rectangles, and expand span rect */
503  if (rect_y1 < 0) {
504  span_y1 = 0;
505  } else if (rect_y1 < span_y1) {
506  span_y1 = rect_y1;
507  }
508  if (rect_y2 > height) {
509  span_y2 = height;
510  } else if (rect_y2 > span_y2) {
511  span_y2 = rect_y2;
512  }
513  }
514  if (span_y2 > span_y1) {
515  span->x = 0;
516  span->y = span_y1;
517  span->w = width;
518  span->h = (span_y2 - span_y1);
519  return SDL_TRUE;
520  }
521  return SDL_FALSE;
522 }
523 
524 /* vi: set ts=4 sw=4 expandtab: */
DECLSPEC SDL_bool SDLCALL SDL_IntersectRectAndLine(const SDL_Rect *rect, int *X1, int *Y1, int *X2, int *Y2)
Calculate the intersection of a rectangle and line segment.
Definition: SDL_rect.c:316
#define CODE_TOP
Definition: SDL_rect.c:295
#define NULL
Definition: ftobjs.h:61
SDL_bool
Definition: SDL_stdinc.h:116
#define CODE_RIGHT
Definition: SDL_rect.c:297
EGLSurface EGLint x
Definition: eglext.h:293
The structure that defines a point.
Definition: SDL_rect.h:47
EGLSurface EGLint EGLint EGLint EGLint height
Definition: eglext.h:293
#define CODE_BOTTOM
Definition: SDL_rect.c:294
static int ComputeOutCode(const SDL_Rect *rect, int x, int y)
Definition: SDL_rect.c:299
DECLSPEC SDL_bool SDLCALL SDL_EnclosePoints(const SDL_Point *points, int count, const SDL_Rect *clip, SDL_Rect *result)
Calculate a minimal rectangle enclosing a set of points.
Definition: SDL_rect.c:192
#define SDL_InvalidParamError(param)
Definition: SDL_error.h:54
GLuint GLfloat GLfloat GLfloat GLfloat y1
Definition: glew.h:11582
GLfixed GLfixed GLfixed y2
Definition: glext.h:4559
SDL_FORCE_INLINE SDL_bool SDL_RectEmpty(const SDL_Rect *r)
Returns true if the rectangle has no area.
Definition: SDL_rect.h:72
int x
Definition: SDL_rect.h:49
GLuint64EXT * result
Definition: glew.h:12708
DECLSPEC void SDLCALL SDL_UnionRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *result)
Calculate the union of two rectangles.
Definition: SDL_rect.c:129
DECLSPEC SDL_bool SDLCALL SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *result)
Calculate the intersection of two rectangles.
Definition: SDL_rect.c:75
int y
Definition: SDL_rect.h:50
EGLSurface EGLint EGLint EGLint width
Definition: eglext.h:293
GLint GLsizei count
Definition: gl2ext.h:1011
DECLSPEC SDL_bool SDLCALL SDL_HasIntersection(const SDL_Rect *A, const SDL_Rect *B)
Determine whether two rectangles intersect.
Definition: SDL_rect.c:28
#define CODE_LEFT
Definition: SDL_rect.c:296
int x
Definition: SDL_rect.h:65
int w
Definition: SDL_rect.h:66
GLuint GLfloat GLfloat GLfloat x1
Definition: glew.h:11582
Definition: inftrees.h:24
EGLSurface EGLint EGLint y
Definition: eglext.h:293
int h
Definition: SDL_rect.h:66
GLfixed GLfixed x2
Definition: glext.h:4559
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glew.h:3337
int i
Definition: pngrutil.c:1377
GLenum GLenum GLvoid GLvoid GLvoid * span
Definition: glew.h:4447
int y
Definition: SDL_rect.h:65
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:63
SDL_bool SDL_GetSpanEnclosingRect(int width, int height, int numrects, const SDL_Rect *rects, SDL_Rect *span)
Definition: SDL_rect.c:462