src/video/SDL_rect.c
author Sam Lantinga <slouken@libsdl.org>
Tue, 08 Feb 2011 16:50:51 -0800
changeset 5229 c015d3e63631
parent 5156 307ccc9c135e
child 5262 b530ef003506
permissions -rw-r--r--
Fixed setting the texture unit, still doesn't work.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2010 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library 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 GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 #include "SDL_config.h"
    23 
    24 #include "SDL_rect.h"
    25 
    26 SDL_bool
    27 SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B)
    28 {
    29     int Amin, Amax, Bmin, Bmax;
    30 
    31     /* Horizontal intersection */
    32     Amin = A->x;
    33     Amax = Amin + A->w;
    34     Bmin = B->x;
    35     Bmax = Bmin + B->w;
    36     if (Bmin > Amin)
    37         Amin = Bmin;
    38     if (Bmax < Amax)
    39         Amax = Bmax;
    40     if (Amax <= Amin)
    41         return SDL_FALSE;
    42 
    43     /* Vertical intersection */
    44     Amin = A->y;
    45     Amax = Amin + A->h;
    46     Bmin = B->y;
    47     Bmax = Bmin + B->h;
    48     if (Bmin > Amin)
    49         Amin = Bmin;
    50     if (Bmax < Amax)
    51         Amax = Bmax;
    52     if (Amax <= Amin)
    53         return SDL_FALSE;
    54 
    55     return SDL_TRUE;
    56 }
    57 
    58 SDL_bool
    59 SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
    60 {
    61     int Amin, Amax, Bmin, Bmax;
    62 
    63     /* Horizontal intersection */
    64     Amin = A->x;
    65     Amax = Amin + A->w;
    66     Bmin = B->x;
    67     Bmax = Bmin + B->w;
    68     if (Bmin > Amin)
    69         Amin = Bmin;
    70     result->x = Amin;
    71     if (Bmax < Amax)
    72         Amax = Bmax;
    73     result->w = Amax - Amin;
    74 
    75     /* Vertical intersection */
    76     Amin = A->y;
    77     Amax = Amin + A->h;
    78     Bmin = B->y;
    79     Bmax = Bmin + B->h;
    80     if (Bmin > Amin)
    81         Amin = Bmin;
    82     result->y = Amin;
    83     if (Bmax < Amax)
    84         Amax = Bmax;
    85     result->h = Amax - Amin;
    86 
    87     return !SDL_RectEmpty(result);
    88 }
    89 
    90 void
    91 SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
    92 {
    93     int Amin, Amax, Bmin, Bmax;
    94 
    95     /* Horizontal union */
    96     Amin = A->x;
    97     Amax = Amin + A->w;
    98     Bmin = B->x;
    99     Bmax = Bmin + B->w;
   100     if (Bmin < Amin)
   101         Amin = Bmin;
   102     result->x = Amin;
   103     if (Bmax > Amax)
   104         Amax = Bmax;
   105     result->w = Amax - Amin;
   106 
   107     /* Vertical intersection */
   108     Amin = A->y;
   109     Amax = Amin + A->h;
   110     Bmin = B->y;
   111     Bmax = Bmin + B->h;
   112     if (Bmin < Amin)
   113         Amin = Bmin;
   114     result->y = Amin;
   115     if (Bmax > Amax)
   116         Amax = Bmax;
   117     result->h = Amax - Amin;
   118 }
   119 
   120 SDL_bool
   121 SDL_EnclosePoints(const SDL_Point * points, int count, const SDL_Rect * clip,
   122                   SDL_Rect * result)
   123 {
   124     int minx = 0;
   125     int miny = 0;
   126     int maxx = 0;
   127     int maxy = 0;
   128     int x, y, i;
   129 
   130     if (count < 1) {
   131         return SDL_FALSE;
   132     }
   133 
   134     if (clip) {
   135         SDL_bool added = SDL_FALSE;
   136         int clip_minx = clip->x;
   137         int clip_miny = clip->y;
   138         int clip_maxx = clip->x+clip->w-1;
   139         int clip_maxy = clip->y+clip->h-1;
   140 
   141         for (i = 0; i < count; ++i) {
   142             x = points[i].x;
   143             y = points[i].y;
   144 
   145             if (x < clip_minx || x > clip_maxx ||
   146                 y < clip_miny || y > clip_maxy) {
   147                 continue;
   148             }
   149             if (!added) {
   150                 minx = maxx = x;
   151                 miny = maxy = y;
   152                 added = SDL_TRUE;
   153                 continue;
   154             }
   155             if (x < minx) {
   156                 minx = x;
   157             } else if (x > maxx) {
   158                 maxx = x;
   159             }
   160             if (y < miny) {
   161                 miny = y;
   162             } else if (y > maxy) {
   163                 maxy = y;
   164             }
   165         }
   166         if (!added) {
   167             return SDL_FALSE;
   168         }
   169     } else {
   170         /* No clipping, always add the first point */
   171         minx = maxx = points[0].x;
   172         miny = maxy = points[0].y;
   173 
   174         for (i = 1; i < count; ++i) {
   175             x = points[i].x;
   176             y = points[i].y;
   177 
   178             if (x < minx) {
   179                 minx = x;
   180             } else if (x > maxx) {
   181                 maxx = x;
   182             }
   183             if (y < miny) {
   184                 miny = y;
   185             } else if (y > maxy) {
   186                 maxy = y;
   187             }
   188         }
   189     }
   190 
   191     if (result) {
   192         result->x = minx;
   193         result->y = miny;
   194         result->w = (maxx-minx)+1;
   195         result->h = (maxy-miny)+1;
   196     }
   197     return SDL_TRUE;
   198 }
   199 
   200 /* Use the Cohen-Sutherland algorithm for line clipping */
   201 #define CODE_BOTTOM 1
   202 #define CODE_TOP    2
   203 #define CODE_LEFT   4
   204 #define CODE_RIGHT  8
   205 
   206 static int ComputeOutCode(const SDL_Rect * rect, int x, int y)
   207 {
   208     int code = 0;
   209     if (y < 0) {
   210         code |= CODE_TOP;
   211     } else if (y >= rect->y + rect->h) {
   212         code |= CODE_BOTTOM;
   213     }
   214     if (x < 0) {
   215         code |= CODE_LEFT;
   216     } else if (x >= rect->x + rect->w) {
   217         code |= CODE_RIGHT;
   218     }
   219     return code;
   220 }
   221 
   222 SDL_bool
   223 SDL_IntersectRectAndLine(const SDL_Rect * rect, int *X1, int *Y1, int *X2,
   224                          int *Y2)
   225 {
   226     int x = 0;
   227     int y = 0;
   228     int x1, y1;
   229     int x2, y2;
   230     int rectx1;
   231     int recty1;
   232     int rectx2;
   233     int recty2;
   234     int outcode1, outcode2;
   235 
   236     if (!rect || !X1 || !Y1 || !X2 || !Y2) {
   237         return SDL_FALSE;
   238     }
   239 
   240     x1 = *X1;
   241     y1 = *Y1;
   242     x2 = *X2;
   243     y2 = *Y2;
   244     rectx1 = rect->x;
   245     recty1 = rect->y;
   246     rectx2 = rect->x + rect->w - 1;
   247     recty2 = rect->y + rect->h - 1;
   248 
   249     /* Check to see if entire line is inside rect */
   250     if (x1 >= rectx1 && x1 <= rectx2 && x2 >= rectx1 && x2 <= rectx2 &&
   251         y1 >= recty1 && y1 <= recty2 && y2 >= recty1 && y2 <= recty2) {
   252         return SDL_TRUE;
   253     }
   254 
   255     /* Check to see if entire line is to one side of rect */
   256     if ((x1 < rectx1 && x2 < rectx1) || (x1 > rectx2 && x2 > rectx2) ||
   257         (y1 < recty1 && y2 < recty1) || (y1 > recty2 && y2 > recty2)) {
   258         return SDL_FALSE;
   259     }
   260 
   261     if (y1 == y2) {
   262         /* Horizontal line, easy to clip */
   263         if (x1 < rectx1) {
   264             *X1 = rectx1;
   265         } else if (x1 > rectx2) {
   266             *X1 = rectx2;
   267         }
   268         if (x2 < rectx1) {
   269             *X2 = rectx1;
   270         } else if (x2 > rectx2) {
   271             *X2 = rectx2;
   272         }
   273         return SDL_TRUE;
   274     }
   275 
   276     if (x1 == x2) {
   277         /* Vertical line, easy to clip */
   278         if (y1 < recty1) {
   279             *Y1 = recty1;
   280         } else if (y1 > recty2) {
   281             *Y1 = recty2;
   282         }
   283         if (y2 < recty1) {
   284             *Y2 = recty1;
   285         } else if (y2 > recty2) {
   286             *Y2 = recty2;
   287         }
   288         return SDL_TRUE;
   289     }
   290 
   291     /* More complicated Cohen-Sutherland algorithm */
   292     outcode1 = ComputeOutCode(rect, x1, y1);
   293     outcode2 = ComputeOutCode(rect, x2, y2);
   294     while (outcode1 || outcode2) {
   295         if (outcode1 & outcode2) {
   296             return SDL_FALSE;
   297         }
   298 
   299         if (outcode1) {
   300             if (outcode1 & CODE_TOP) {
   301                 y = recty1;
   302                 x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
   303             } else if (outcode1 & CODE_BOTTOM) {
   304                 y = recty2;
   305                 x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
   306             } else if (outcode1 & CODE_LEFT) {
   307                 x = rectx1;
   308                 y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
   309             } else if (outcode1 & CODE_RIGHT) {
   310                 x = rectx2;
   311                 y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
   312             }
   313             x1 = x;
   314             y1 = y;
   315             outcode1 = ComputeOutCode(rect, x, y);
   316         } else {
   317             if (outcode2 & CODE_TOP) {
   318                 y = recty1;
   319                 x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
   320             } else if (outcode2 & CODE_BOTTOM) {
   321                 y = recty2;
   322                 x = x1 + ((x2 - x1) * (y - y1)) / (y2 - y1);
   323             } else if (outcode2 & CODE_LEFT) {
   324                 x = rectx1;
   325                 y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
   326             } else if (outcode2 & CODE_RIGHT) {
   327                 x = rectx2;
   328                 y = y1 + ((y2 - y1) * (x - x1)) / (x2 - x1);
   329             }
   330             x2 = x;
   331             y2 = y;
   332             outcode2 = ComputeOutCode(rect, x, y);
   333         }
   334     }
   335     *X1 = x1;
   336     *Y1 = y1;
   337     *X2 = x2;
   338     *Y2 = y2;
   339     return SDL_TRUE;
   340 }
   341 
   342 /* vi: set ts=4 sw=4 expandtab: */