SDL_gfx: C:/Users/Andreas Schiffler/Desktop/Sources/sdlgfx/SDL_rotozoom.c Source File

SDL_gfx 2.0.24

- Main Page
- Data Structures
- Files

- File List
- Globals

C:/Users/Andreas Schiffler/Desktop/Sources/sdlgfx/SDL_rotozoom.c
Go to the documentation of this file.

    00001 /*
    00002
    00003 SDL_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
    00004
    00005 Copyright (C) 2001-2012  Andreas Schiffler
    00006
    00007 This software is provided 'as-is', without any express or implied
    00008 warranty. In no event will the authors be held liable for any damages
    00009 arising from the use of this software.
    00010
    00011 Permission is granted to anyone to use this software for any purpose,
    00012 including commercial applications, and to alter it and redistribute it
    00013 freely, subject to the following restrictions:
    00014
    00015 1. The origin of this software must not be misrepresented; you must not
    00016 claim that you wrote the original software. If you use this software
    00017 in a product, an acknowledgment in the product documentation would be
    00018 appreciated but is not required.
    00019
    00020 2. Altered source versions must be plainly marked as such, and must not be
    00021 misrepresented as being the original software.
    00022
    00023 3. This notice may not be removed or altered from any source
    00024 distribution.
    00025
    00026 Andreas Schiffler -- aschiffler at ferzkopp dot net
    00027
    00028 */
    00029
    00030 #ifdef WIN32
    00031 #include <windows.h>
    00032 #endif
    00033
    00034 #include <stdlib.h>
    00035 #include <string.h>
    00036
    00037 #include "SDL_rotozoom.h"
    00038
    00039 /* ---- Internally used structures */
    00040
    00044 typedef struct tColorRGBA {
    00045         Uint8 r;
    00046         Uint8 g;
    00047         Uint8 b;
    00048         Uint8 a;
    00049 } tColorRGBA;
    00050
    00054 typedef struct tColorY {
    00055         Uint8 y;
    00056 } tColorY;
    00057
    00061 #define MAX(a,b)    (((a) > (b)) ? (a) : (b))
    00062
    00073 #define GUARD_ROWS (2)
    00074
    00078 #define VALUE_LIMIT     0.001
    00079
    00083 Uint32 _colorkey(SDL_Surface *src)
    00084 {
    00085         Uint32 key = 0;
    00086 #if (SDL_MINOR_VERSION == 3)
    00087         SDL_GetColorKey(src, &key);
    00088 #else
    00089         if (src)
    00090         {
    00091                 key = src->format->colorkey;
    00092         }
    00093 #endif
    00094         return key;
    00095 }
    00096
    00097
    00113 int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
    00114 {
    00115         int x, y, dx, dy, sgap, dgap, ra, ga, ba, aa;
    00116         int n_average;
    00117         tColorRGBA *sp, *osp, *oosp;
    00118         tColorRGBA *dp;
    00119
    00120         /*
    00121         * Averaging integer shrink
    00122         */
    00123
    00124         /* Precalculate division factor */
    00125         n_average = factorx*factory;
    00126
    00127         /*
    00128         * Scan destination
    00129         */
    00130         sp = (tColorRGBA *) src->pixels;
    00131         sgap = src->pitch - src->w * 4;
    00132
    00133         dp = (tColorRGBA *) dst->pixels;
    00134         dgap = dst->pitch - dst->w * 4;
    00135
    00136         for (y = 0; y < dst->h; y++) {
    00137
    00138                 osp=sp;
    00139                 for (x = 0; x < dst->w; x++) {
    00140
    00141                         /* Trace out source box and accumulate */
    00142                         oosp=sp;
    00143                         ra=ga=ba=aa=0;
    00144                         for (dy=0; dy < factory; dy++) {
    00145                                 for (dx=0; dx < factorx; dx++) {
    00146                                         ra += sp->r;
    00147                                         ga += sp->g;
    00148                                         ba += sp->b;
    00149                                         aa += sp->a;
    00150
    00151                                         sp++;
    00152                                 }
    00153                                 /* src dx loop */
    00154                                 sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y
    00155                         }
    00156                         /* src dy loop */
    00157
    00158                         /* next box-x */
    00159                         sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx);
    00160
    00161                         /* Store result in destination */
    00162                         dp->r = ra/n_average;
    00163                         dp->g = ga/n_average;
    00164                         dp->b = ba/n_average;
    00165                         dp->a = aa/n_average;
    00166
    00167                         /*
    00168                         * Advance destination pointer
    00169                         */
    00170                         dp++;
    00171                 }
    00172                 /* dst x loop */
    00173
    00174                 /* next box-y */
    00175                 sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory);
    00176
    00177                 /*
    00178                 * Advance destination pointers
    00179                 */
    00180                 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
    00181         }
    00182         /* dst y loop */
    00183
    00184         return (0);
    00185 }
    00186
    00202 int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
    00203 {
    00204         int x, y, dx, dy, sgap, dgap, a;
    00205         int n_average;
    00206         Uint8 *sp, *osp, *oosp;
    00207         Uint8 *dp;
    00208
    00209         /*
    00210         * Averaging integer shrink
    00211         */
    00212
    00213         /* Precalculate division factor */
    00214         n_average = factorx*factory;
    00215
    00216         /*
    00217         * Scan destination
    00218         */
    00219         sp = (Uint8 *) src->pixels;
    00220         sgap = src->pitch - src->w;
    00221
    00222         dp = (Uint8 *) dst->pixels;
    00223         dgap = dst->pitch - dst->w;
    00224
    00225         for (y = 0; y < dst->h; y++) {
    00226
    00227                 osp=sp;
    00228                 for (x = 0; x < dst->w; x++) {
    00229
    00230                         /* Trace out source box and accumulate */
    00231                         oosp=sp;
    00232                         a=0;
    00233                         for (dy=0; dy < factory; dy++) {
    00234                                 for (dx=0; dx < factorx; dx++) {
    00235                                         a += (*sp);
    00236                                         /* next x */
    00237                                         sp++;
    00238                                 }
    00239                                 /* end src dx loop */
    00240                                 /* next y */
    00241                                 sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx));
    00242                         }
    00243                         /* end src dy loop */
    00244
    00245                         /* next box-x */
    00246                         sp = (Uint8 *)((Uint8*)oosp + factorx);
    00247
    00248                         /* Store result in destination */
    00249                         *dp = a/n_average;
    00250
    00251                         /*
    00252                         * Advance destination pointer
    00253                         */
    00254                         dp++;
    00255                 }
    00256                 /* end dst x loop */
    00257
    00258                 /* next box-y */
    00259                 sp = (Uint8 *)((Uint8*)osp + src->pitch*factory);
    00260
    00261                 /*
    00262                 * Advance destination pointers
    00263                 */
    00264                 dp = (Uint8 *)((Uint8 *)dp + dgap);
    00265         }
    00266         /* end dst y loop */
    00267
    00268         return (0);
    00269 }
    00270
    00286 int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
    00287 {
    00288         int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
    00289         tColorRGBA *c00, *c01, *c10, *c11;
    00290         tColorRGBA *sp, *csp, *dp;
    00291         int spixelgap, spixelw, spixelh, dgap, t1, t2;
    00292
    00293         /*
    00294         * Allocate memory for row/column increments
    00295         */
    00296         if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
    00297                 return (-1);
    00298         }
    00299         if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
    00300                 free(sax);
    00301                 return (-1);
    00302         }
    00303
    00304         /*
    00305         * Precalculate row increments
    00306         */
    00307         spixelw = (src->w - 1);
    00308         spixelh = (src->h - 1);
    00309         if (smooth) {
    00310                 sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1));
    00311                 sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1));
    00312         } else {
    00313                 sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w));
    00314                 sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h));
    00315         }
    00316
    00317         /* Maximum scaled source size */
    00318         ssx = (src->w << 16) - 1;
    00319         ssy = (src->h << 16) - 1;
    00320
    00321         /* Precalculate horizontal row increments */
    00322         csx = 0;
    00323         csax = sax;
    00324         for (x = 0; x <= dst->w; x++) {
    00325                 *csax = csx;
    00326                 csax++;
    00327                 csx += sx;
    00328
    00329                 /* Guard from overflows */
    00330                 if (csx > ssx) {
    00331                         csx = ssx;
    00332                 }
    00333         }
    00334
    00335         /* Precalculate vertical row increments */
    00336         csy = 0;
    00337         csay = say;
    00338         for (y = 0; y <= dst->h; y++) {
    00339                 *csay = csy;
    00340                 csay++;
    00341                 csy += sy;
    00342
    00343                 /* Guard from overflows */
    00344                 if (csy > ssy) {
    00345                         csy = ssy;
    00346                 }
    00347         }
    00348
    00349         sp = (tColorRGBA *) src->pixels;
    00350         dp = (tColorRGBA *) dst->pixels;
    00351         dgap = dst->pitch - dst->w * 4;
    00352         spixelgap = src->pitch/4;
    00353
    00354         if (flipx) sp += spixelw;
    00355         if (flipy) sp += (spixelgap * spixelh);
    00356
    00357         /*
    00358         * Switch between interpolating and non-interpolating code
    00359         */
    00360         if (smooth) {
    00361
    00362                 /*
    00363                 * Interpolating Zoom
    00364                 */
    00365                 csay = say;
    00366                 for (y = 0; y < dst->h; y++) {
    00367                         csp = sp;
    00368                         csax = sax;
    00369                         for (x = 0; x < dst->w; x++) {
    00370                                 /*
    00371                                 * Setup color source pointers
    00372                                 */
    00373                                 ex = (*csax & 0xffff);
    00374                                 ey = (*csay & 0xffff);
    00375                                 cx = (*csax >> 16);
    00376                                 cy = (*csay >> 16);
    00377                                 sstepx = cx < spixelw;
    00378                                 sstepy = cy < spixelh;
    00379                                 c00 = sp;
    00380                                 c01 = sp;
    00381                                 c10 = sp;
    00382                                 if (sstepy) {
    00383                                         if (flipy) {
    00384                                                 c10 -= spixelgap;
    00385                                         } else {
    00386                                                 c10 += spixelgap;
    00387                                         }
    00388                                 }
    00389                                 c11 = c10;
    00390                                 if (sstepx) {
    00391                                         if (flipx) {
    00392                                                 c01--;
    00393                                                 c11--;
    00394                                         } else {
    00395                                                 c01++;
    00396                                                 c11++;
    00397                                         }
    00398                                 }
    00399
    00400                                 /*
    00401                                 * Draw and interpolate colors
    00402                                 */
    00403                                 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
    00404                                 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
    00405                                 dp->r = (((t2 - t1) * ey) >> 16) + t1;
    00406                                 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
    00407                                 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
    00408                                 dp->g = (((t2 - t1) * ey) >> 16) + t1;
    00409                                 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
    00410                                 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
    00411                                 dp->b = (((t2 - t1) * ey) >> 16) + t1;
    00412                                 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
    00413                                 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
    00414                                 dp->a = (((t2 - t1) * ey) >> 16) + t1;
    00415                                 /*
    00416                                 * Advance source pointer x
    00417                                 */
    00418                                 salast = csax;
    00419                                 csax++;
    00420                                 sstep = (*csax >> 16) - (*salast >> 16);
    00421                                 if (flipx) {
    00422                                         sp -= sstep;
    00423                                 } else {
    00424                                         sp += sstep;
    00425                                 }
    00426
    00427                                 /*
    00428                                 * Advance destination pointer x
    00429                                 */
    00430                                 dp++;
    00431                         }
    00432                         /*
    00433                         * Advance source pointer y
    00434                         */
    00435                         salast = csay;
    00436                         csay++;
    00437                         sstep = (*csay >> 16) - (*salast >> 16);
    00438                         sstep *= spixelgap;
    00439                         if (flipy) {
    00440                                 sp = csp - sstep;
    00441                         } else {
    00442                                 sp = csp + sstep;
    00443                         }
    00444
    00445                         /*
    00446                         * Advance destination pointer y
    00447                         */
    00448                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
    00449                 }
    00450         } else {
    00451                 /*
    00452                 * Non-Interpolating Zoom
    00453                 */
    00454                 csay = say;
    00455                 for (y = 0; y < dst->h; y++) {
    00456                         csp = sp;
    00457                         csax = sax;
    00458                         for (x = 0; x < dst->w; x++) {
    00459                                 /*
    00460                                 * Draw
    00461                                 */
    00462                                 *dp = *sp;
    00463
    00464                                 /*
    00465                                 * Advance source pointer x
    00466                                 */
    00467                                 salast = csax;
    00468                                 csax++;
    00469                                 sstep = (*csax >> 16) - (*salast >> 16);
    00470                                 if (flipx) sstep = -sstep;
    00471                                 sp += sstep;
    00472
    00473                                 /*
    00474                                 * Advance destination pointer x
    00475                                 */
    00476                                 dp++;
    00477                         }
    00478                         /*
    00479                         * Advance source pointer y
    00480                         */
    00481                         salast = csay;
    00482                         csay++;
    00483                         sstep = (*csay >> 16) - (*salast >> 16);
    00484                         sstep *= spixelgap;
    00485                         if (flipy) sstep = -sstep;
    00486                         sp = csp + sstep;
    00487
    00488                         /*
    00489                         * Advance destination pointer y
    00490                         */
    00491                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
    00492                 }
    00493         }
    00494
    00495         /*
    00496         * Remove temp arrays
    00497         */
    00498         free(sax);
    00499         free(say);
    00500
    00501         return (0);
    00502 }
    00503
    00519 int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
    00520 {
    00521         int x, y;
    00522         Uint32 *sax, *say, *csax, *csay;
    00523         int csx, csy;
    00524         Uint8 *sp, *dp, *csp;
    00525         int dgap;
    00526
    00527         /*
    00528         * Allocate memory for row increments
    00529         */
    00530         if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
    00531                 return (-1);
    00532         }
    00533         if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
    00534                 free(sax);
    00535                 return (-1);
    00536         }
    00537
    00538         /*
    00539         * Pointer setup
    00540         */
    00541         sp = csp = (Uint8 *) src->pixels;
    00542         dp = (Uint8 *) dst->pixels;
    00543         dgap = dst->pitch - dst->w;
    00544
    00545         if (flipx) csp += (src->w-1);
    00546         if (flipy) csp  = ( (Uint8*)csp + src->pitch*(src->h-1) );
    00547
    00548         /*
    00549         * Precalculate row increments
    00550         */
    00551         csx = 0;
    00552         csax = sax;
    00553         for (x = 0; x < dst->w; x++) {
    00554                 csx += src->w;
    00555                 *csax = 0;
    00556                 while (csx >= dst->w) {
    00557                         csx -= dst->w;
    00558                         (*csax)++;
    00559                 }
    00560                 (*csax) = (*csax) * (flipx ? -1 : 1);
    00561                 csax++;
    00562         }
    00563         csy = 0;
    00564         csay = say;
    00565         for (y = 0; y < dst->h; y++) {
    00566                 csy += src->h;
    00567                 *csay = 0;
    00568                 while (csy >= dst->h) {
    00569                         csy -= dst->h;
    00570                         (*csay)++;
    00571                 }
    00572                 (*csay) = (*csay) * (flipy ? -1 : 1);
    00573                 csay++;
    00574         }
    00575
    00576         /*
    00577         * Draw
    00578         */
    00579         csay = say;
    00580         for (y = 0; y < dst->h; y++) {
    00581                 csax = sax;
    00582                 sp = csp;
    00583                 for (x = 0; x < dst->w; x++) {
    00584                         /*
    00585                         * Draw
    00586                         */
    00587                         *dp = *sp;
    00588                         /*
    00589                         * Advance source pointers
    00590                         */
    00591                         sp += (*csax);
    00592                         csax++;
    00593                         /*
    00594                         * Advance destination pointer
    00595                         */
    00596                         dp++;
    00597                 }
    00598                 /*
    00599                 * Advance source pointer (for row)
    00600                 */
    00601                 csp += ((*csay) * src->pitch);
    00602                 csay++;
    00603
    00604                 /*
    00605                 * Advance destination pointers
    00606                 */
    00607                 dp += dgap;
    00608         }
    00609
    00610         /*
    00611         * Remove temp arrays
    00612         */
    00613         free(sax);
    00614         free(say);
    00615
    00616         return (0);
    00617 }
    00618
    00638 void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
    00639 {
    00640         int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
    00641         tColorRGBA c00, c01, c10, c11, cswap;
    00642         tColorRGBA *pc, *sp;
    00643         int gap;
    00644
    00645         /*
    00646         * Variable setup
    00647         */
    00648         xd = ((src->w - dst->w) << 15);
    00649         yd = ((src->h - dst->h) << 15);
    00650         ax = (cx << 16) - (icos * cx);
    00651         ay = (cy << 16) - (isin * cx);
    00652         sw = src->w - 1;
    00653         sh = src->h - 1;
    00654         pc = (tColorRGBA*) dst->pixels;
    00655         gap = dst->pitch - dst->w * 4;
    00656
    00657         /*
    00658         * Switch between interpolating and non-interpolating code
    00659         */
    00660         if (smooth) {
    00661                 for (y = 0; y < dst->h; y++) {
    00662                         dy = cy - y;
    00663                         sdx = (ax + (isin * dy)) + xd;
    00664                         sdy = (ay - (icos * dy)) + yd;
    00665                         for (x = 0; x < dst->w; x++) {
    00666                                 dx = (sdx >> 16);
    00667                                 dy = (sdy >> 16);
    00668                                 if (flipx) dx = sw - dx;
    00669                                 if (flipy) dy = sh - dy;
    00670                                 if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
    00671                                         sp = (tColorRGBA *)src->pixels;;
    00672                                         sp += ((src->pitch/4) * dy);
    00673                                         sp += dx;
    00674                                         c00 = *sp;
    00675                                         sp += 1;
    00676                                         c01 = *sp;
    00677                                         sp += (src->pitch/4);
    00678                                         c11 = *sp;
    00679                                         sp -= 1;
    00680                                         c10 = *sp;
    00681                                         if (flipx) {
    00682                                                 cswap = c00; c00=c01; c01=cswap;
    00683                                                 cswap = c10; c10=c11; c11=cswap;
    00684                                         }
    00685                                         if (flipy) {
    00686                                                 cswap = c00; c00=c10; c10=cswap;
    00687                                                 cswap = c01; c01=c11; c11=cswap;
    00688                                         }
    00689                                         /*
    00690                                         * Interpolate colors
    00691                                         */
    00692                                         ex = (sdx & 0xffff);
    00693                                         ey = (sdy & 0xffff);
    00694                                         t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
    00695                                         t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
    00696                                         pc->r = (((t2 - t1) * ey) >> 16) + t1;
    00697                                         t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
    00698                                         t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
    00699                                         pc->g = (((t2 - t1) * ey) >> 16) + t1;
    00700                                         t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
    00701                                         t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
    00702                                         pc->b = (((t2 - t1) * ey) >> 16) + t1;
    00703                                         t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
    00704                                         t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
    00705                                         pc->a = (((t2 - t1) * ey) >> 16) + t1;
    00706                                 }
    00707                                 sdx += icos;
    00708                                 sdy += isin;
    00709                                 pc++;
    00710                         }
    00711                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
    00712                 }
    00713         } else {
    00714                 for (y = 0; y < dst->h; y++) {
    00715                         dy = cy - y;
    00716                         sdx = (ax + (isin * dy)) + xd;
    00717                         sdy = (ay - (icos * dy)) + yd;
    00718                         for (x = 0; x < dst->w; x++) {
    00719                                 dx = (short) (sdx >> 16);
    00720                                 dy = (short) (sdy >> 16);
    00721                                 if (flipx) dx = (src->w-1)-dx;
    00722                                 if (flipy) dy = (src->h-1)-dy;
    00723                                 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
    00724                                         sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
    00725                                         sp += dx;
    00726                                         *pc = *sp;
    00727                                 }
    00728                                 sdx += icos;
    00729                                 sdy += isin;
    00730                                 pc++;
    00731                         }
    00732                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
    00733                 }
    00734         }
    00735 }
    00736
    00755 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
    00756 {
    00757         int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh;
    00758         tColorY *pc, *sp;
    00759         int gap;
    00760
    00761         /*
    00762         * Variable setup
    00763         */
    00764         xd = ((src->w - dst->w) << 15);
    00765         yd = ((src->h - dst->h) << 15);
    00766         ax = (cx << 16) - (icos * cx);
    00767         ay = (cy << 16) - (isin * cx);
    00768         sw = src->w - 1;
    00769         sh = src->h - 1;
    00770         pc = (tColorY*) dst->pixels;
    00771         gap = dst->pitch - dst->w;
    00772         /*
    00773         * Clear surface to colorkey
    00774         */
    00775         memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
    00776         /*
    00777         * Iterate through destination surface
    00778         */
    00779         for (y = 0; y < dst->h; y++) {
    00780                 dy = cy - y;
    00781                 sdx = (ax + (isin * dy)) + xd;
    00782                 sdy = (ay - (icos * dy)) + yd;
    00783                 for (x = 0; x < dst->w; x++) {
    00784                         dx = (short) (sdx >> 16);
    00785                         dy = (short) (sdy >> 16);
    00786                         if (flipx) dx = (src->w-1)-dx;
    00787                         if (flipy) dy = (src->h-1)-dy;
    00788                         if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
    00789                                 sp = (tColorY *) (src->pixels);
    00790                                 sp += (src->pitch * dy + dx);
    00791                                 *pc = *sp;
    00792                         }
    00793                         sdx += icos;
    00794                         sdy += isin;
    00795                         pc++;
    00796                 }
    00797                 pc += gap;
    00798         }
    00799 }
    00800
    00814 SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns)
    00815 {
    00816         int row, col, newWidth, newHeight;
    00817         int bpp, src_ipr, dst_ipr;
    00818         SDL_Surface* dst;
    00819         Uint32* srcBuf;
    00820         Uint32* dstBuf;
    00821
    00822         /* Has to be a valid surface pointer and only 32-bit surfaces (for now) */
    00823         if (!src || src->format->BitsPerPixel != 32) { return NULL; }
    00824
    00825         /* normalize numClockwiseTurns */
    00826         while(numClockwiseTurns < 0) { numClockwiseTurns += 4; }
    00827         numClockwiseTurns = (numClockwiseTurns % 4);
    00828
    00829         /* if it's even, our new width will be the same as the source surface */
    00830         newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w);
    00831         newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h);
    00832         dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
    00833                 src->format->Rmask,
    00834                 src->format->Gmask,
    00835                 src->format->Bmask,
    00836                 src->format->Amask);
    00837         if(!dst) {
    00838                 return NULL;
    00839         }
    00840
    00841         if (SDL_MUSTLOCK(dst)) {
    00842                 SDL_LockSurface(dst);
    00843         }
    00844         if (SDL_MUSTLOCK(dst)) {
    00845                 SDL_LockSurface(dst);
    00846         }
    00847
    00848         /* Calculate int-per-row */
    00849         bpp = src->format->BitsPerPixel / 8;
    00850         src_ipr = src->pitch / bpp;
    00851         dst_ipr = dst->pitch / bpp;
    00852
    00853         switch(numClockwiseTurns) {
    00854         case 0: /* Make a copy of the surface */
    00855                 {
    00856                         /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
    00857                         since it does not preserve alpha. */
    00858
    00859                         if (src->pitch == dst->pitch) {
    00860                                 /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
    00861                                 memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
    00862                         }
    00863                         else
    00864                         {
    00865                                 /* If the pitch differs, copy each row separately */
    00866                                 srcBuf = (Uint32*)(src->pixels);
    00867                                 dstBuf = (Uint32*)(dst->pixels);
    00868                                 for (row = 0; row < src->h; row++) {
    00869                                         memcpy(dstBuf, srcBuf, dst->w * bpp);
    00870                                         srcBuf += src_ipr;
    00871                                         dstBuf += dst_ipr;
    00872                                 } /* end for(col) */
    00873                         } /* end for(row) */
    00874                 }
    00875                 break;
    00876
    00877                 /* rotate clockwise */
    00878         case 1: /* rotated 90 degrees clockwise */
    00879                 {
    00880                         for (row = 0; row < src->h; ++row) {
    00881                                 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
    00882                                 dstBuf = (Uint32*)(dst->pixels) + (dst->w - row - 1);
    00883                                 for (col = 0; col < src->w; ++col) {
    00884                                         *dstBuf = *srcBuf;
    00885                                         ++srcBuf;
    00886                                         dstBuf += dst_ipr;
    00887                                 }
    00888                                 /* end for(col) */
    00889                         }
    00890                         /* end for(row) */
    00891                 }
    00892                 break;
    00893
    00894         case 2: /* rotated 180 degrees clockwise */
    00895                 {
    00896                         for (row = 0; row < src->h; ++row) {
    00897                                 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
    00898                                 dstBuf = (Uint32*)(dst->pixels) + ((dst->h - row - 1) * dst_ipr) + (dst->w - 1);
    00899                                 for (col = 0; col < src->w; ++col) {
    00900                                         *dstBuf = *srcBuf;
    00901                                         ++srcBuf;
    00902                                         --dstBuf;
    00903                                 }
    00904                         }
    00905                 }
    00906                 break;
    00907
    00908         case 3:
    00909                 {
    00910                         for (row = 0; row < src->h; ++row) {
    00911                                 srcBuf = (Uint32*)(src->pixels) + (row * src_ipr);
    00912                                 dstBuf = (Uint32*)(dst->pixels) + row + ((dst->h - 1) * dst_ipr);
    00913                                 for (col = 0; col < src->w; ++col) {
    00914                                         *dstBuf = *srcBuf;
    00915                                         ++srcBuf;
    00916                                         dstBuf -= dst_ipr;
    00917                                 }
    00918                         }
    00919                 }
    00920                 break;
    00921         }
    00922         /* end switch */
    00923
    00924         if (SDL_MUSTLOCK(src)) {
    00925                 SDL_UnlockSurface(src);
    00926         }
    00927         if (SDL_MUSTLOCK(dst)) {
    00928                 SDL_UnlockSurface(dst);
    00929         }
    00930
    00931         return dst;
    00932 }
    00933
    00934
    00949 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
    00950         int *dstwidth, int *dstheight,
    00951         double *canglezoom, double *sanglezoom)
    00952 {
    00953         double x, y, cx, cy, sx, sy;
    00954         double radangle;
    00955         int dstwidthhalf, dstheighthalf;
    00956
    00957         /*
    00958         * Determine destination width and height by rotating a centered source box
    00959         */
    00960         radangle = angle * (M_PI / 180.0);
    00961         *sanglezoom = sin(radangle);
    00962         *canglezoom = cos(radangle);
    00963         *sanglezoom *= zoomx;
    00964         *canglezoom *= zoomx;
    00965         x = (double)(width / 2);
    00966         y = (double)(height / 2);
    00967         cx = *canglezoom * x;
    00968         cy = *canglezoom * y;
    00969         sx = *sanglezoom * x;
    00970         sy = *sanglezoom * y;
    00971
    00972         dstwidthhalf = MAX((int)
    00973                 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
    00974         dstheighthalf = MAX((int)
    00975                 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
    00976         *dstwidth = 2 * dstwidthhalf;
    00977         *dstheight = 2 * dstheighthalf;
    00978 }
    00979
    00991 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
    00992 {
    00993         double dummy_sanglezoom, dummy_canglezoom;
    00994
    00995         _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
    00996 }
    00997
    01008 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
    01009 {
    01010         double dummy_sanglezoom, dummy_canglezoom;
    01011
    01012         _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
    01013 }
    01014
    01030 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
    01031 {
    01032         return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
    01033 }
    01034
    01051 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
    01052 {
    01053         SDL_Surface *rz_src;
    01054         SDL_Surface *rz_dst;
    01055         double zoominv;
    01056         double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
    01057         int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
    01058         int is32bit;
    01059         int i, src_converted;
    01060         int flipx,flipy;
    01061         Uint8 r,g,b;
    01062         Uint32 colorkey = 0;
    01063         int colorKeyAvailable = 0;
    01064
    01065         /*
    01066         * Sanity check
    01067         */
    01068         if (src == NULL)
    01069                 return (NULL);
    01070
    01071         if (src->flags & SDL_SRCCOLORKEY)
    01072         {
    01073                 colorkey = _colorkey(src);
    01074                 SDL_GetRGB(colorkey, src->format, &r, &g, &b);
    01075                 colorKeyAvailable = 1;
    01076         }
    01077         /*
    01078         * Determine if source surface is 32bit or 8bit
    01079         */
    01080         is32bit = (src->format->BitsPerPixel == 32);
    01081         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01082                 /*
    01083                 * Use source surface 'as is'
    01084                 */
    01085                 rz_src = src;
    01086                 src_converted = 0;
    01087         } else {
    01088                 /*
    01089                 * New source surface is 32bit with a defined RGBA ordering
    01090                 */
    01091                 rz_src =
    01092                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01093 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01094                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01095 #else
    01096                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01097 #endif
    01098                         );
    01099                 if(colorKeyAvailable)
    01100                         SDL_SetColorKey(src, 0, 0);
    01101
    01102                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01103
    01104                 if(colorKeyAvailable)
    01105                         SDL_SetColorKey(src, SDL_SRCCOLORKEY, colorkey);
    01106                 src_converted = 1;
    01107                 is32bit = 1;
    01108         }
    01109
    01110         /*
    01111         * Sanity check zoom factor
    01112         */
    01113         flipx = (zoomx<0.0);
    01114         if (flipx) zoomx=-zoomx;
    01115         flipy = (zoomy<0.0);
    01116         if (flipy) zoomy=-zoomy;
    01117         if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
    01118         if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
    01119         zoominv = 65536.0 / (zoomx * zoomx);
    01120
    01121         /*
    01122         * Check if we have a rotozoom or just a zoom
    01123         */
    01124         if (fabs(angle) > VALUE_LIMIT) {
    01125
    01126                 /*
    01127                 * Angle!=0: full rotozoom
    01128                 */
    01129                 /*
    01130                 * -----------------------
    01131                 */
    01132
    01133                 /* Determine target size */
    01134                 _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
    01135
    01136                 /*
    01137                 * Calculate target factors from sin/cos and zoom
    01138                 */
    01139                 sanglezoominv = sanglezoom;
    01140                 canglezoominv = canglezoom;
    01141                 sanglezoominv *= zoominv;
    01142                 canglezoominv *= zoominv;
    01143
    01144                 /* Calculate half size */
    01145                 dstwidthhalf = dstwidth / 2;
    01146                 dstheighthalf = dstheight / 2;
    01147
    01148                 /*
    01149                 * Alloc space to completely contain the rotated surface
    01150                 */
    01151                 rz_dst = NULL;
    01152                 if (is32bit) {
    01153                         /*
    01154                         * Target surface is 32bit with source RGBA/ABGR ordering
    01155                         */
    01156                         rz_dst =
    01157                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01158                                 rz_src->format->Rmask, rz_src->format->Gmask,
    01159                                 rz_src->format->Bmask, rz_src->format->Amask);
    01160                 } else {
    01161                         /*
    01162                         * Target surface is 8bit
    01163                         */
    01164                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01165                 }
    01166
    01167                 /* Check target */
    01168                 if (rz_dst == NULL)
    01169                         return NULL;
    01170
    01171                 /* Adjust for guard rows */
    01172                 rz_dst->h = dstheight;
    01173
    01174                 if (colorKeyAvailable == 1){
    01175                         colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
    01176
    01177                         SDL_FillRect(rz_dst, NULL, colorkey );
    01178                 }
    01179
    01180                 /*
    01181                 * Lock source surface
    01182                 */
    01183                 if (SDL_MUSTLOCK(rz_src)) {
    01184                         SDL_LockSurface(rz_src);
    01185                 }
    01186
    01187                 /*
    01188                 * Check which kind of surface we have
    01189                 */
    01190                 if (is32bit) {
    01191                         /*
    01192                         * Call the 32bit transformation routine to do the rotation (using alpha)
    01193                         */
    01194                         _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
    01195                                 (int) (sanglezoominv), (int) (canglezoominv),
    01196                                 flipx, flipy,
    01197                                 smooth);
    01198                         /*
    01199                         * Turn on source-alpha support
    01200                         */
    01201                         SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
    01202                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
    01203                 } else {
    01204                         /*
    01205                         * Copy palette and colorkey info
    01206                         */
    01207                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01208                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01209                         }
    01210                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01211                         /*
    01212                         * Call the 8bit transformation routine to do the rotation
    01213                         */
    01214                         transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
    01215                                 (int) (sanglezoominv), (int) (canglezoominv),
    01216                                 flipx, flipy);
    01217                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
    01218                 }
    01219                 /*
    01220                 * Unlock source surface
    01221                 */
    01222                 if (SDL_MUSTLOCK(rz_src)) {
    01223                         SDL_UnlockSurface(rz_src);
    01224                 }
    01225
    01226         } else {
    01227
    01228                 /*
    01229                 * Angle=0: Just a zoom
    01230                 */
    01231                 /*
    01232                 * --------------------
    01233                 */
    01234
    01235                 /*
    01236                 * Calculate target size
    01237                 */
    01238                 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
    01239
    01240                 /*
    01241                 * Alloc space to completely contain the zoomed surface
    01242                 */
    01243                 rz_dst = NULL;
    01244                 if (is32bit) {
    01245                         /*
    01246                         * Target surface is 32bit with source RGBA/ABGR ordering
    01247                         */
    01248                         rz_dst =
    01249                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01250                                 rz_src->format->Rmask, rz_src->format->Gmask,
    01251                                 rz_src->format->Bmask, rz_src->format->Amask);
    01252                 } else {
    01253                         /*
    01254                         * Target surface is 8bit
    01255                         */
    01256                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01257                 }
    01258
    01259                 /* Check target */
    01260                 if (rz_dst == NULL)
    01261                         return NULL;
    01262
    01263                 /* Adjust for guard rows */
    01264                 rz_dst->h = dstheight;
    01265
    01266                 if (colorKeyAvailable == 1){
    01267                         colorkey = SDL_MapRGB(rz_dst->format, r, g, b);
    01268
    01269                         SDL_FillRect(rz_dst, NULL, colorkey );
    01270                 }
    01271
    01272                 /*
    01273                 * Lock source surface
    01274                 */
    01275                 if (SDL_MUSTLOCK(rz_src)) {
    01276                         SDL_LockSurface(rz_src);
    01277                 }
    01278
    01279                 /*
    01280                 * Check which kind of surface we have
    01281                 */
    01282                 if (is32bit) {
    01283                         /*
    01284                         * Call the 32bit transformation routine to do the zooming (using alpha)
    01285                         */
    01286                         _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
    01287
    01288                         /*
    01289                         * Turn on source-alpha support
    01290                         */
    01291                         SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
    01292                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
    01293                 } else {
    01294                         /*
    01295                         * Copy palette and colorkey info
    01296                         */
    01297                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01298                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01299                         }
    01300                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01301
    01302                         /*
    01303                         * Call the 8bit transformation routine to do the zooming
    01304                         */
    01305                         _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
    01306                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
    01307                 }
    01308
    01309                 /*
    01310                 * Unlock source surface
    01311                 */
    01312                 if (SDL_MUSTLOCK(rz_src)) {
    01313                         SDL_UnlockSurface(rz_src);
    01314                 }
    01315         }
    01316
    01317         /*
    01318         * Cleanup temp surface
    01319         */
    01320         if (src_converted) {
    01321                 SDL_FreeSurface(rz_src);
    01322         }
    01323
    01324         /*
    01325         * Return destination surface
    01326         */
    01327         return (rz_dst);
    01328 }
    01329
    01342 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
    01343 {
    01344         /*
    01345         * Make zoom factors positive
    01346         */
    01347         int flipx, flipy;
    01348         flipx = (zoomx<0.0);
    01349         if (flipx) zoomx = -zoomx;
    01350         flipy = (zoomy<0.0);
    01351         if (flipy) zoomy = -zoomy;
    01352
    01353         /*
    01354         * Sanity check zoom factors
    01355         */
    01356         if (zoomx < VALUE_LIMIT) {
    01357                 zoomx = VALUE_LIMIT;
    01358         }
    01359         if (zoomy < VALUE_LIMIT) {
    01360                 zoomy = VALUE_LIMIT;
    01361         }
    01362
    01363         /*
    01364         * Calculate target size
    01365         */
    01366         *dstwidth = (int) floor(((double) width * zoomx) + 0.5);
    01367         *dstheight = (int) floor(((double) height * zoomy) + 0.5);
    01368         if (*dstwidth < 1) {
    01369                 *dstwidth = 1;
    01370         }
    01371         if (*dstheight < 1) {
    01372                 *dstheight = 1;
    01373         }
    01374 }
    01375
    01392 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
    01393 {
    01394         SDL_Surface *rz_src;
    01395         SDL_Surface *rz_dst;
    01396         int dstwidth, dstheight;
    01397         int is32bit;
    01398         int i, src_converted;
    01399         int flipx, flipy;
    01400
    01401         /*
    01402         * Sanity check
    01403         */
    01404         if (src == NULL)
    01405                 return (NULL);
    01406
    01407         /*
    01408         * Determine if source surface is 32bit or 8bit
    01409         */
    01410         is32bit = (src->format->BitsPerPixel == 32);
    01411         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01412                 /*
    01413                 * Use source surface 'as is'
    01414                 */
    01415                 rz_src = src;
    01416                 src_converted = 0;
    01417         } else {
    01418                 /*
    01419                 * New source surface is 32bit with a defined RGBA ordering
    01420                 */
    01421                 rz_src =
    01422                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01423 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01424                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01425 #else
    01426                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01427 #endif
    01428                         );
    01429                 if (rz_src == NULL) {
    01430                         return NULL;
    01431                 }
    01432                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01433                 src_converted = 1;
    01434                 is32bit = 1;
    01435         }
    01436
    01437         flipx = (zoomx<0.0);
    01438         if (flipx) zoomx = -zoomx;
    01439         flipy = (zoomy<0.0);
    01440         if (flipy) zoomy = -zoomy;
    01441
    01442         /* Get size if target */
    01443         zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
    01444
    01445         /*
    01446         * Alloc space to completely contain the zoomed surface
    01447         */
    01448         rz_dst = NULL;
    01449         if (is32bit) {
    01450                 /*
    01451                 * Target surface is 32bit with source RGBA/ABGR ordering
    01452                 */
    01453                 rz_dst =
    01454                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01455                         rz_src->format->Rmask, rz_src->format->Gmask,
    01456                         rz_src->format->Bmask, rz_src->format->Amask);
    01457         } else {
    01458                 /*
    01459                 * Target surface is 8bit
    01460                 */
    01461                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01462         }
    01463
    01464         /* Check target */
    01465         if (rz_dst == NULL) {
    01466                 /*
    01467                 * Cleanup temp surface
    01468                 */
    01469                 if (src_converted) {
    01470                         SDL_FreeSurface(rz_src);
    01471                 }
    01472                 return NULL;
    01473         }
    01474
    01475         /* Adjust for guard rows */
    01476         rz_dst->h = dstheight;
    01477
    01478         /*
    01479         * Lock source surface
    01480         */
    01481         if (SDL_MUSTLOCK(rz_src)) {
    01482                 SDL_LockSurface(rz_src);
    01483         }
    01484
    01485         /*
    01486         * Check which kind of surface we have
    01487         */
    01488         if (is32bit) {
    01489                 /*
    01490                 * Call the 32bit transformation routine to do the zooming (using alpha)
    01491                 */
    01492                 _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
    01493                 /*
    01494                 * Turn on source-alpha support
    01495                 */
    01496                 SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
    01497         } else {
    01498                 /*
    01499                 * Copy palette and colorkey info
    01500                 */
    01501                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01502                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01503                 }
    01504                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01505                 /*
    01506                 * Call the 8bit transformation routine to do the zooming
    01507                 */
    01508                 _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
    01509                 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
    01510         }
    01511         /*
    01512         * Unlock source surface
    01513         */
    01514         if (SDL_MUSTLOCK(rz_src)) {
    01515                 SDL_UnlockSurface(rz_src);
    01516         }
    01517
    01518         /*
    01519         * Cleanup temp surface
    01520         */
    01521         if (src_converted) {
    01522                 SDL_FreeSurface(rz_src);
    01523         }
    01524
    01525         /*
    01526         * Return destination surface
    01527         */
    01528         return (rz_dst);
    01529 }
    01530
    01547 /*@null@*/
    01548 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
    01549 {
    01550         int result;
    01551         SDL_Surface *rz_src;
    01552         SDL_Surface *rz_dst = NULL;
    01553         int dstwidth, dstheight;
    01554         int is32bit;
    01555         int i, src_converted;
    01556         int haveError = 0;
    01557
    01558         /*
    01559         * Sanity check
    01560         */
    01561         if (src == NULL) {
    01562                 return (NULL);
    01563         }
    01564
    01565         /*
    01566         * Determine if source surface is 32bit or 8bit
    01567         */
    01568         is32bit = (src->format->BitsPerPixel == 32);
    01569         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01570                 /*
    01571                 * Use source surface 'as is'
    01572                 */
    01573                 rz_src = src;
    01574                 src_converted = 0;
    01575         } else {
    01576                 /*
    01577                 * New source surface is 32bit with a defined RGBA ordering
    01578                 */
    01579                 rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01580 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01581                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01582 #else
    01583                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01584 #endif
    01585                         );
    01586                 if (rz_src==NULL) {
    01587                         haveError = 1;
    01588                         goto exitShrinkSurface;
    01589                 }
    01590
    01591                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01592                 src_converted = 1;
    01593                 is32bit = 1;
    01594         }
    01595
    01596         /*
    01597         * Lock the surface
    01598         */
    01599         if (SDL_MUSTLOCK(rz_src)) {
    01600                 if (SDL_LockSurface(rz_src) < 0) {
    01601                         haveError = 1;
    01602                         goto exitShrinkSurface;
    01603                 }
    01604         }
    01605
    01606         /* Get size for target */
    01607         dstwidth=rz_src->w/factorx;
    01608         while (dstwidth*factorx>rz_src->w) { dstwidth--; }
    01609         dstheight=rz_src->h/factory;
    01610         while (dstheight*factory>rz_src->h) { dstheight--; }
    01611
    01612         /*
    01613         * Alloc space to completely contain the shrunken surface
    01614         * (with added guard rows)
    01615         */
    01616         if (is32bit==1) {
    01617                 /*
    01618                 * Target surface is 32bit with source RGBA/ABGR ordering
    01619                 */
    01620                 rz_dst =
    01621                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01622                         rz_src->format->Rmask, rz_src->format->Gmask,
    01623                         rz_src->format->Bmask, rz_src->format->Amask);
    01624         } else {
    01625                 /*
    01626                 * Target surface is 8bit
    01627                 */
    01628                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01629         }
    01630
    01631         /* Check target */
    01632         if (rz_dst == NULL) {
    01633                 haveError = 1;
    01634                 goto exitShrinkSurface;
    01635         }
    01636
    01637         /* Adjust for guard rows */
    01638         rz_dst->h = dstheight;
    01639
    01640         /*
    01641         * Check which kind of surface we have
    01642         */
    01643         if (is32bit==1) {
    01644                 /*
    01645                 * Call the 32bit transformation routine to do the shrinking (using alpha)
    01646                 */
    01647                 result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
    01648                 if ((result!=0) || (rz_dst==NULL)) {
    01649                         haveError = 1;
    01650                         goto exitShrinkSurface;
    01651                 }
    01652
    01653                 /*
    01654                 * Turn on source-alpha support
    01655                 */
    01656                 result = SDL_SetAlpha(rz_dst, SDL_SRCALPHA, 255);
    01657                 if (result!=0) {
    01658                         haveError = 1;
    01659                         goto exitShrinkSurface;
    01660                 }
    01661         } else {
    01662                 /*
    01663                 * Copy palette and colorkey info
    01664                 */
    01665                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01666                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01667                 }
    01668                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01669                 /*
    01670                 * Call the 8bit transformation routine to do the shrinking
    01671                 */
    01672                 result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
    01673                 if (result!=0) {
    01674                         haveError = 1;
    01675                         goto exitShrinkSurface;
    01676                 }
    01677
    01678                 /*
    01679                 * Set colorkey on target
    01680                 */
    01681                 result = SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, _colorkey(rz_src));
    01682                 if (result!=0) {
    01683                         haveError = 1;
    01684                         goto exitShrinkSurface;
    01685                 }
    01686         }
    01687
    01688 exitShrinkSurface:
    01689         if (rz_src!=NULL) {
    01690                 /*
    01691                 * Unlock source surface
    01692                 */
    01693                 if (SDL_MUSTLOCK(rz_src)) {
    01694                         SDL_UnlockSurface(rz_src);
    01695                 }
    01696
    01697                 /*
    01698                 * Cleanup temp surface
    01699                 */
    01700                 if (src_converted==1) {
    01701                         SDL_FreeSurface(rz_src);
    01702                 }
    01703         }
    01704
    01705         /* Check error state; maybe need to cleanup destination */
    01706         if (haveError==1) {
    01707                 if (rz_dst!=NULL) {
    01708                         SDL_FreeSurface(rz_dst);
    01709                 }
    01710                 rz_dst=NULL;
    01711         }
    01712
    01713         /*
    01714         * Return destination surface
    01715         */
    01716         return (rz_dst);
    01717 }