src/video/SDL_rect.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 20 Oct 2013 21:56:15 -0700
changeset 7860 2b0bcdea3a79
parent 7191 75360622e65f
child 7868 f92ba4923dcd
permissions -rw-r--r--
Fixed bug 2129 - fix for bug 2121 breaks linking for mingw and throws multiple warnings

Andreas Ertelt

The problem in question is caused by changeset 7771 (http://hg.libsdl.org/SDL/rev/4434498bf4b9 / https://bugzilla.libsdl.org/show_bug.cgi?id=2121)

The redefinition of __inline__ (introduced by the addition of begin_code.h:128's "|| __STRICT_ANSI__") results in mingw's gcc throwing multiple

warning: always_inline function might not be inlinable [-Wattributes]

as well as a whole bunch of redefinitions of mingw internals which break linking of projects including the SDL2 headers.
     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 
    27 SDL_bool
    28 SDL_HasIntersection(const SDL_Rect * A, const SDL_Rect * B)
    29 {
    30     int Amin, Amax, Bmin, Bmax;
    31 
    32     if (!A) {
    33         SDL_InvalidParamError("A");
    34         return SDL_FALSE;
    35     }
    36 
    37     if (!B) {
    38         SDL_InvalidParamError("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 
    74 SDL_bool
    75 SDL_IntersectRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
    76 {
    77     int Amin, Amax, Bmin, Bmax;
    78 
    79     if (!A) {
    80         SDL_InvalidParamError("A");
    81         return SDL_FALSE;
    82     }
    83 
    84     if (!B) {
    85         SDL_InvalidParamError("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
   129 SDL_UnionRect(const SDL_Rect * A, const SDL_Rect * B, SDL_Rect * result)
   130 {
   131     int Amin, Amax, Bmin, Bmax;
   132 
   133     if (!A) {
   134         SDL_InvalidParamError("A");
   135         return;
   136     }
   137 
   138     if (!B) {
   139         SDL_InvalidParamError("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
   462 SDL_GetSpanEnclosingRect(int width, int height,
   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: */