SDL2_gfx: I:/Sources/sdl2gfx/SDL2_rotozoom.c Source File

SDL2_gfx 1.0.0 GraphicsprimitivesandsurfacefunctionsforSDL2

- Main Page
- Data Structures
- Files

- File List
- Globals

I:/Sources/sdl2gfx/SDL2_rotozoom.c
Go to the documentation of this file.

    00001 /*
    00002
    00003 SDL2_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
    00004
    00005 Copyright (C) 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 "SDL2_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         SDL_GetColorKey(src, &key);
    00087         return key;
    00088 }
    00089
    00090
    00106 int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
    00107 {
    00108         int x, y, dx, dy, dgap, ra, ga, ba, aa;
    00109         int n_average;
    00110         tColorRGBA *sp, *osp, *oosp;
    00111         tColorRGBA *dp;
    00112
    00113         /*
    00114         * Averaging integer shrink
    00115         */
    00116
    00117         /* Precalculate division factor */
    00118         n_average = factorx*factory;
    00119
    00120         /*
    00121         * Scan destination
    00122         */
    00123         sp = (tColorRGBA *) src->pixels;
    00124
    00125         dp = (tColorRGBA *) dst->pixels;
    00126         dgap = dst->pitch - dst->w * 4;
    00127
    00128         for (y = 0; y < dst->h; y++) {
    00129
    00130                 osp=sp;
    00131                 for (x = 0; x < dst->w; x++) {
    00132
    00133                         /* Trace out source box and accumulate */
    00134                         oosp=sp;
    00135                         ra=ga=ba=aa=0;
    00136                         for (dy=0; dy < factory; dy++) {
    00137                                 for (dx=0; dx < factorx; dx++) {
    00138                                         ra += sp->r;
    00139                                         ga += sp->g;
    00140                                         ba += sp->b;
    00141                                         aa += sp->a;
    00142
    00143                                         sp++;
    00144                                 }
    00145                                 /* src dx loop */
    00146                                 sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y
    00147                         }
    00148                         /* src dy loop */
    00149
    00150                         /* next box-x */
    00151                         sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx);
    00152
    00153                         /* Store result in destination */
    00154                         dp->r = ra/n_average;
    00155                         dp->g = ga/n_average;
    00156                         dp->b = ba/n_average;
    00157                         dp->a = aa/n_average;
    00158
    00159                         /*
    00160                         * Advance destination pointer
    00161                         */
    00162                         dp++;
    00163                 }
    00164                 /* dst x loop */
    00165
    00166                 /* next box-y */
    00167                 sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory);
    00168
    00169                 /*
    00170                 * Advance destination pointers
    00171                 */
    00172                 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
    00173         }
    00174         /* dst y loop */
    00175
    00176         return (0);
    00177 }
    00178
    00194 int _shrinkSurfaceY(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
    00195 {
    00196         int x, y, dx, dy, dgap, a;
    00197         int n_average;
    00198         Uint8 *sp, *osp, *oosp;
    00199         Uint8 *dp;
    00200
    00201         /*
    00202         * Averaging integer shrink
    00203         */
    00204
    00205         /* Precalculate division factor */
    00206         n_average = factorx*factory;
    00207
    00208         /*
    00209         * Scan destination
    00210         */
    00211         sp = (Uint8 *) src->pixels;
    00212
    00213         dp = (Uint8 *) dst->pixels;
    00214         dgap = dst->pitch - dst->w;
    00215
    00216         for (y = 0; y < dst->h; y++) {
    00217
    00218                 osp=sp;
    00219                 for (x = 0; x < dst->w; x++) {
    00220
    00221                         /* Trace out source box and accumulate */
    00222                         oosp=sp;
    00223                         a=0;
    00224                         for (dy=0; dy < factory; dy++) {
    00225                                 for (dx=0; dx < factorx; dx++) {
    00226                                         a += (*sp);
    00227                                         /* next x */
    00228                                         sp++;
    00229                                 }
    00230                                 /* end src dx loop */
    00231                                 /* next y */
    00232                                 sp = (Uint8 *)((Uint8*)sp + (src->pitch - factorx));
    00233                         }
    00234                         /* end src dy loop */
    00235
    00236                         /* next box-x */
    00237                         sp = (Uint8 *)((Uint8*)oosp + factorx);
    00238
    00239                         /* Store result in destination */
    00240                         *dp = a/n_average;
    00241
    00242                         /*
    00243                         * Advance destination pointer
    00244                         */
    00245                         dp++;
    00246                 }
    00247                 /* end dst x loop */
    00248
    00249                 /* next box-y */
    00250                 sp = (Uint8 *)((Uint8*)osp + src->pitch*factory);
    00251
    00252                 /*
    00253                 * Advance destination pointers
    00254                 */
    00255                 dp = (Uint8 *)((Uint8 *)dp + dgap);
    00256         }
    00257         /* end dst y loop */
    00258
    00259         return (0);
    00260 }
    00261
    00277 int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
    00278 {
    00279         int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
    00280         tColorRGBA *c00, *c01, *c10, *c11;
    00281         tColorRGBA *sp, *csp, *dp;
    00282         int spixelgap, spixelw, spixelh, dgap, t1, t2;
    00283
    00284         /*
    00285         * Allocate memory for row/column increments
    00286         */
    00287         if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
    00288                 return (-1);
    00289         }
    00290         if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
    00291                 free(sax);
    00292                 return (-1);
    00293         }
    00294
    00295         /*
    00296         * Precalculate row increments
    00297         */
    00298         spixelw = (src->w - 1);
    00299         spixelh = (src->h - 1);
    00300         if (smooth) {
    00301                 sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1));
    00302                 sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1));
    00303         } else {
    00304                 sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w));
    00305                 sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h));
    00306         }
    00307
    00308         /* Maximum scaled source size */
    00309         ssx = (src->w << 16) - 1;
    00310         ssy = (src->h << 16) - 1;
    00311
    00312         /* Precalculate horizontal row increments */
    00313         csx = 0;
    00314         csax = sax;
    00315         for (x = 0; x <= dst->w; x++) {
    00316                 *csax = csx;
    00317                 csax++;
    00318                 csx += sx;
    00319
    00320                 /* Guard from overflows */
    00321                 if (csx > ssx) {
    00322                         csx = ssx;
    00323                 }
    00324         }
    00325
    00326         /* Precalculate vertical row increments */
    00327         csy = 0;
    00328         csay = say;
    00329         for (y = 0; y <= dst->h; y++) {
    00330                 *csay = csy;
    00331                 csay++;
    00332                 csy += sy;
    00333
    00334                 /* Guard from overflows */
    00335                 if (csy > ssy) {
    00336                         csy = ssy;
    00337                 }
    00338         }
    00339
    00340         sp = (tColorRGBA *) src->pixels;
    00341         dp = (tColorRGBA *) dst->pixels;
    00342         dgap = dst->pitch - dst->w * 4;
    00343         spixelgap = src->pitch/4;
    00344
    00345         if (flipx) sp += spixelw;
    00346         if (flipy) sp += (spixelgap * spixelh);
    00347
    00348         /*
    00349         * Switch between interpolating and non-interpolating code
    00350         */
    00351         if (smooth) {
    00352
    00353                 /*
    00354                 * Interpolating Zoom
    00355                 */
    00356                 csay = say;
    00357                 for (y = 0; y < dst->h; y++) {
    00358                         csp = sp;
    00359                         csax = sax;
    00360                         for (x = 0; x < dst->w; x++) {
    00361                                 /*
    00362                                 * Setup color source pointers
    00363                                 */
    00364                                 ex = (*csax & 0xffff);
    00365                                 ey = (*csay & 0xffff);
    00366                                 cx = (*csax >> 16);
    00367                                 cy = (*csay >> 16);
    00368                                 sstepx = cx < spixelw;
    00369                                 sstepy = cy < spixelh;
    00370                                 c00 = sp;
    00371                                 c01 = sp;
    00372                                 c10 = sp;
    00373                                 if (sstepy) {
    00374                                         if (flipy) {
    00375                                                 c10 -= spixelgap;
    00376                                         } else {
    00377                                                 c10 += spixelgap;
    00378                                         }
    00379                                 }
    00380                                 c11 = c10;
    00381                                 if (sstepx) {
    00382                                         if (flipx) {
    00383                                                 c01--;
    00384                                                 c11--;
    00385                                         } else {
    00386                                                 c01++;
    00387                                                 c11++;
    00388                                         }
    00389                                 }
    00390
    00391                                 /*
    00392                                 * Draw and interpolate colors
    00393                                 */
    00394                                 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
    00395                                 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
    00396                                 dp->r = (((t2 - t1) * ey) >> 16) + t1;
    00397                                 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
    00398                                 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
    00399                                 dp->g = (((t2 - t1) * ey) >> 16) + t1;
    00400                                 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
    00401                                 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
    00402                                 dp->b = (((t2 - t1) * ey) >> 16) + t1;
    00403                                 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
    00404                                 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
    00405                                 dp->a = (((t2 - t1) * ey) >> 16) + t1;
    00406                                 /*
    00407                                 * Advance source pointer x
    00408                                 */
    00409                                 salast = csax;
    00410                                 csax++;
    00411                                 sstep = (*csax >> 16) - (*salast >> 16);
    00412                                 if (flipx) {
    00413                                         sp -= sstep;
    00414                                 } else {
    00415                                         sp += sstep;
    00416                                 }
    00417
    00418                                 /*
    00419                                 * Advance destination pointer x
    00420                                 */
    00421                                 dp++;
    00422                         }
    00423                         /*
    00424                         * Advance source pointer y
    00425                         */
    00426                         salast = csay;
    00427                         csay++;
    00428                         sstep = (*csay >> 16) - (*salast >> 16);
    00429                         sstep *= spixelgap;
    00430                         if (flipy) {
    00431                                 sp = csp - sstep;
    00432                         } else {
    00433                                 sp = csp + sstep;
    00434                         }
    00435
    00436                         /*
    00437                         * Advance destination pointer y
    00438                         */
    00439                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
    00440                 }
    00441         } else {
    00442                 /*
    00443                 * Non-Interpolating Zoom
    00444                 */
    00445                 csay = say;
    00446                 for (y = 0; y < dst->h; y++) {
    00447                         csp = sp;
    00448                         csax = sax;
    00449                         for (x = 0; x < dst->w; x++) {
    00450                                 /*
    00451                                 * Draw
    00452                                 */
    00453                                 *dp = *sp;
    00454
    00455                                 /*
    00456                                 * Advance source pointer x
    00457                                 */
    00458                                 salast = csax;
    00459                                 csax++;
    00460                                 sstep = (*csax >> 16) - (*salast >> 16);
    00461                                 if (flipx) sstep = -sstep;
    00462                                 sp += sstep;
    00463
    00464                                 /*
    00465                                 * Advance destination pointer x
    00466                                 */
    00467                                 dp++;
    00468                         }
    00469                         /*
    00470                         * Advance source pointer y
    00471                         */
    00472                         salast = csay;
    00473                         csay++;
    00474                         sstep = (*csay >> 16) - (*salast >> 16);
    00475                         sstep *= spixelgap;
    00476                         if (flipy) sstep = -sstep;
    00477                         sp = csp + sstep;
    00478
    00479                         /*
    00480                         * Advance destination pointer y
    00481                         */
    00482                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
    00483                 }
    00484         }
    00485
    00486         /*
    00487         * Remove temp arrays
    00488         */
    00489         free(sax);
    00490         free(say);
    00491
    00492         return (0);
    00493 }
    00494
    00510 int _zoomSurfaceY(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy)
    00511 {
    00512         int x, y;
    00513         Uint32 *sax, *say, *csax, *csay;
    00514         int csx, csy;
    00515         Uint8 *sp, *dp, *csp;
    00516         int dgap;
    00517
    00518         /*
    00519         * Allocate memory for row increments
    00520         */
    00521         if ((sax = (Uint32 *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
    00522                 return (-1);
    00523         }
    00524         if ((say = (Uint32 *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
    00525                 free(sax);
    00526                 return (-1);
    00527         }
    00528
    00529         /*
    00530         * Pointer setup
    00531         */
    00532         sp = csp = (Uint8 *) src->pixels;
    00533         dp = (Uint8 *) dst->pixels;
    00534         dgap = dst->pitch - dst->w;
    00535
    00536         if (flipx) csp += (src->w-1);
    00537         if (flipy) csp  = ( (Uint8*)csp + src->pitch*(src->h-1) );
    00538
    00539         /*
    00540         * Precalculate row increments
    00541         */
    00542         csx = 0;
    00543         csax = sax;
    00544         for (x = 0; x < dst->w; x++) {
    00545                 csx += src->w;
    00546                 *csax = 0;
    00547                 while (csx >= dst->w) {
    00548                         csx -= dst->w;
    00549                         (*csax)++;
    00550                 }
    00551                 (*csax) = (*csax) * (flipx ? -1 : 1);
    00552                 csax++;
    00553         }
    00554         csy = 0;
    00555         csay = say;
    00556         for (y = 0; y < dst->h; y++) {
    00557                 csy += src->h;
    00558                 *csay = 0;
    00559                 while (csy >= dst->h) {
    00560                         csy -= dst->h;
    00561                         (*csay)++;
    00562                 }
    00563                 (*csay) = (*csay) * (flipy ? -1 : 1);
    00564                 csay++;
    00565         }
    00566
    00567         /*
    00568         * Draw
    00569         */
    00570         csay = say;
    00571         for (y = 0; y < dst->h; y++) {
    00572                 csax = sax;
    00573                 sp = csp;
    00574                 for (x = 0; x < dst->w; x++) {
    00575                         /*
    00576                         * Draw
    00577                         */
    00578                         *dp = *sp;
    00579                         /*
    00580                         * Advance source pointers
    00581                         */
    00582                         sp += (*csax);
    00583                         csax++;
    00584                         /*
    00585                         * Advance destination pointer
    00586                         */
    00587                         dp++;
    00588                 }
    00589                 /*
    00590                 * Advance source pointer (for row)
    00591                 */
    00592                 csp += ((*csay) * src->pitch);
    00593                 csay++;
    00594
    00595                 /*
    00596                 * Advance destination pointers
    00597                 */
    00598                 dp += dgap;
    00599         }
    00600
    00601         /*
    00602         * Remove temp arrays
    00603         */
    00604         free(sax);
    00605         free(say);
    00606
    00607         return (0);
    00608 }
    00609
    00629 void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
    00630 {
    00631         int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
    00632         tColorRGBA c00, c01, c10, c11, cswap;
    00633         tColorRGBA *pc, *sp;
    00634         int gap;
    00635
    00636         /*
    00637         * Variable setup
    00638         */
    00639         xd = ((src->w - dst->w) << 15);
    00640         yd = ((src->h - dst->h) << 15);
    00641         ax = (cx << 16) - (icos * cx);
    00642         ay = (cy << 16) - (isin * cx);
    00643         sw = src->w - 1;
    00644         sh = src->h - 1;
    00645         pc = (tColorRGBA*) dst->pixels;
    00646         gap = dst->pitch - dst->w * 4;
    00647
    00648         /*
    00649         * Switch between interpolating and non-interpolating code
    00650         */
    00651         if (smooth) {
    00652                 for (y = 0; y < dst->h; y++) {
    00653                         dy = cy - y;
    00654                         sdx = (ax + (isin * dy)) + xd;
    00655                         sdy = (ay - (icos * dy)) + yd;
    00656                         for (x = 0; x < dst->w; x++) {
    00657                                 dx = (sdx >> 16);
    00658                                 dy = (sdy >> 16);
    00659                                 if (flipx) dx = sw - dx;
    00660                                 if (flipy) dy = sh - dy;
    00661                                 if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
    00662                                         sp = (tColorRGBA *)src->pixels;;
    00663                                         sp += ((src->pitch/4) * dy);
    00664                                         sp += dx;
    00665                                         c00 = *sp;
    00666                                         sp += 1;
    00667                                         c01 = *sp;
    00668                                         sp += (src->pitch/4);
    00669                                         c11 = *sp;
    00670                                         sp -= 1;
    00671                                         c10 = *sp;
    00672                                         if (flipx) {
    00673                                                 cswap = c00; c00=c01; c01=cswap;
    00674                                                 cswap = c10; c10=c11; c11=cswap;
    00675                                         }
    00676                                         if (flipy) {
    00677                                                 cswap = c00; c00=c10; c10=cswap;
    00678                                                 cswap = c01; c01=c11; c11=cswap;
    00679                                         }
    00680                                         /*
    00681                                         * Interpolate colors
    00682                                         */
    00683                                         ex = (sdx & 0xffff);
    00684                                         ey = (sdy & 0xffff);
    00685                                         t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
    00686                                         t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
    00687                                         pc->r = (((t2 - t1) * ey) >> 16) + t1;
    00688                                         t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
    00689                                         t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
    00690                                         pc->g = (((t2 - t1) * ey) >> 16) + t1;
    00691                                         t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
    00692                                         t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
    00693                                         pc->b = (((t2 - t1) * ey) >> 16) + t1;
    00694                                         t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
    00695                                         t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
    00696                                         pc->a = (((t2 - t1) * ey) >> 16) + t1;
    00697                                 }
    00698                                 sdx += icos;
    00699                                 sdy += isin;
    00700                                 pc++;
    00701                         }
    00702                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
    00703                 }
    00704         } else {
    00705                 for (y = 0; y < dst->h; y++) {
    00706                         dy = cy - y;
    00707                         sdx = (ax + (isin * dy)) + xd;
    00708                         sdy = (ay - (icos * dy)) + yd;
    00709                         for (x = 0; x < dst->w; x++) {
    00710                                 dx = (short) (sdx >> 16);
    00711                                 dy = (short) (sdy >> 16);
    00712                                 if (flipx) dx = (src->w-1)-dx;
    00713                                 if (flipy) dy = (src->h-1)-dy;
    00714                                 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
    00715                                         sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
    00716                                         sp += dx;
    00717                                         *pc = *sp;
    00718                                 }
    00719                                 sdx += icos;
    00720                                 sdy += isin;
    00721                                 pc++;
    00722                         }
    00723                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
    00724                 }
    00725         }
    00726 }
    00727
    00746 void transformSurfaceY(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
    00747 {
    00748         int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay;
    00749         tColorY *pc, *sp;
    00750         int gap;
    00751
    00752         /*
    00753         * Variable setup
    00754         */
    00755         xd = ((src->w - dst->w) << 15);
    00756         yd = ((src->h - dst->h) << 15);
    00757         ax = (cx << 16) - (icos * cx);
    00758         ay = (cy << 16) - (isin * cx);
    00759         pc = (tColorY*) dst->pixels;
    00760         gap = dst->pitch - dst->w;
    00761         /*
    00762         * Clear surface to colorkey
    00763         */
    00764         memset(pc, (int)(_colorkey(src) & 0xff), dst->pitch * dst->h);
    00765         /*
    00766         * Iterate through destination surface
    00767         */
    00768         for (y = 0; y < dst->h; y++) {
    00769                 dy = cy - y;
    00770                 sdx = (ax + (isin * dy)) + xd;
    00771                 sdy = (ay - (icos * dy)) + yd;
    00772                 for (x = 0; x < dst->w; x++) {
    00773                         dx = (short) (sdx >> 16);
    00774                         dy = (short) (sdy >> 16);
    00775                         if (flipx) dx = (src->w-1)-dx;
    00776                         if (flipy) dy = (src->h-1)-dy;
    00777                         if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
    00778                                 sp = (tColorY *) (src->pixels);
    00779                                 sp += (src->pitch * dy + dx);
    00780                                 *pc = *sp;
    00781                         }
    00782                         sdx += icos;
    00783                         sdy += isin;
    00784                         pc++;
    00785                 }
    00786                 pc += gap;
    00787         }
    00788 }
    00789
    00803 SDL_Surface* rotateSurface90Degrees(SDL_Surface* src, int numClockwiseTurns)
    00804 {
    00805         int row, col, newWidth, newHeight;
    00806         int bpp;
    00807         SDL_Surface* dst;
    00808         Uint8* srcBuf;
    00809         Uint8* dstBuf;
    00810
    00811         /* Has to be a valid surface pointer and be a 8/16/24/32-bit surface */
    00812         if (!src || !src->format ||
    00813                  !(src->format->BitsPerPixel == 8) ||
    00814                   (src->format->BitsPerPixel == 16) ||
    00815                   (src->format->BitsPerPixel == 24) ||
    00816                   (src->format->BitsPerPixel == 32)) { return NULL; }
    00817
    00818         /* normalize numClockwiseTurns */
    00819         while(numClockwiseTurns < 0) { numClockwiseTurns += 4; }
    00820         numClockwiseTurns = (numClockwiseTurns % 4);
    00821
    00822         /* if it's even, our new width will be the same as the source surface */
    00823         newWidth = (numClockwiseTurns % 2) ? (src->h) : (src->w);
    00824         newHeight = (numClockwiseTurns % 2) ? (src->w) : (src->h);
    00825         dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
    00826                 src->format->Rmask,
    00827                 src->format->Gmask,
    00828                 src->format->Bmask,
    00829                 src->format->Amask);
    00830         if(!dst) {
    00831                 return NULL;
    00832         }
    00833
    00834         if (SDL_MUSTLOCK(src)) {
    00835                 SDL_LockSurface(src);
    00836         }
    00837         if (SDL_MUSTLOCK(dst)) {
    00838                 SDL_LockSurface(dst);
    00839         }
    00840
    00841         /* Calculate byte-per-pixel */
    00842         bpp = src->format->BitsPerPixel / 8;
    00843
    00844         switch(numClockwiseTurns) {
    00845         case 0: /* Make a copy of the surface */
    00846                 {
    00847                         /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
    00848                         since it does not preserve alpha. */
    00849
    00850                         if (src->pitch == dst->pitch) {
    00851                                 /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
    00852                                 memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
    00853                         }
    00854                         else
    00855                         {
    00856                                 /* If the pitch differs, copy each row separately */
    00857                                 srcBuf = (Uint8*)(src->pixels);
    00858                                 dstBuf = (Uint8*)(dst->pixels);
    00859                                 for (row = 0; row < src->h; row++) {
    00860                                         memcpy(dstBuf, srcBuf, dst->w * bpp);
    00861                                         srcBuf += src->pitch;
    00862                                         dstBuf += dst->pitch;
    00863                                 } /* end for(col) */
    00864                         } /* end for(row) */
    00865                 }
    00866                 break;
    00867
    00868                 /* rotate clockwise */
    00869         case 1: /* rotated 90 degrees clockwise */
    00870                 {
    00871                         for (row = 0; row < src->h; ++row) {
    00872                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
    00873                                 dstBuf = (Uint8*)(dst->pixels) + (dst->w - row - 1) * bpp;
    00874                                 for (col = 0; col < src->w; ++col) {
    00875                                         memcpy (dstBuf, srcBuf, bpp);
    00876                                         srcBuf += bpp;
    00877                                         dstBuf += dst->pitch;
    00878                                 }
    00879                         }
    00880                 }
    00881                 break;
    00882
    00883         case 2: /* rotated 180 degrees clockwise */
    00884                 {
    00885                         for (row = 0; row < src->h; ++row) {
    00886                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
    00887                                 dstBuf = (Uint8*)(dst->pixels) + ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
    00888                                 for (col = 0; col < src->w; ++col) {
    00889                                         memcpy (dstBuf, srcBuf, bpp);
    00890                                         srcBuf += bpp;
    00891                                         dstBuf -= bpp;
    00892                                 }
    00893                         }
    00894                 }
    00895                 break;
    00896
    00897         case 3: /* rotated 270 degrees clockwise */
    00898                 {
    00899                         for (row = 0; row < src->h; ++row) {
    00900                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
    00901                                 dstBuf = (Uint8*)(dst->pixels) + row + ((dst->h - 1) * dst->pitch);
    00902                                 for (col = 0; col < src->w; ++col) {
    00903                                         *dstBuf = *srcBuf;
    00904                                         srcBuf += bpp;
    00905                                         dstBuf -= dst->pitch;
    00906                                 }
    00907                         }
    00908                 }
    00909                 break;
    00910         }
    00911         /* end switch */
    00912
    00913         if (SDL_MUSTLOCK(src)) {
    00914                 SDL_UnlockSurface(src);
    00915         }
    00916         if (SDL_MUSTLOCK(dst)) {
    00917                 SDL_UnlockSurface(dst);
    00918         }
    00919
    00920         return dst;
    00921 }
    00922
    00923
    00938 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
    00939         int *dstwidth, int *dstheight,
    00940         double *canglezoom, double *sanglezoom)
    00941 {
    00942         double x, y, cx, cy, sx, sy;
    00943         double radangle;
    00944         int dstwidthhalf, dstheighthalf;
    00945
    00946         /*
    00947         * Determine destination width and height by rotating a centered source box
    00948         */
    00949         radangle = angle * (M_PI / 180.0);
    00950         *sanglezoom = sin(radangle);
    00951         *canglezoom = cos(radangle);
    00952         *sanglezoom *= zoomx;
    00953         *canglezoom *= zoomx;
    00954         x = (double)(width / 2);
    00955         y = (double)(height / 2);
    00956         cx = *canglezoom * x;
    00957         cy = *canglezoom * y;
    00958         sx = *sanglezoom * x;
    00959         sy = *sanglezoom * y;
    00960
    00961         dstwidthhalf = MAX((int)
    00962                 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
    00963         dstheighthalf = MAX((int)
    00964                 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
    00965         *dstwidth = 2 * dstwidthhalf;
    00966         *dstheight = 2 * dstheighthalf;
    00967 }
    00968
    00980 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
    00981 {
    00982         double dummy_sanglezoom, dummy_canglezoom;
    00983
    00984         _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
    00985 }
    00986
    00997 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
    00998 {
    00999         double dummy_sanglezoom, dummy_canglezoom;
    01000
    01001         _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
    01002 }
    01003
    01019 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
    01020 {
    01021         return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
    01022 }
    01023
    01040 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
    01041 {
    01042         SDL_Surface *rz_src;
    01043         SDL_Surface *rz_dst;
    01044         double zoominv;
    01045         double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
    01046         int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
    01047         int is32bit;
    01048         int i, src_converted;
    01049         int flipx,flipy;
    01050
    01051         /*
    01052         * Sanity check
    01053         */
    01054         if (src == NULL) {
    01055                 return (NULL);
    01056         }
    01057
    01058         /*
    01059         * Determine if source surface is 32bit or 8bit
    01060         */
    01061         is32bit = (src->format->BitsPerPixel == 32);
    01062         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01063                 /*
    01064                 * Use source surface 'as is'
    01065                 */
    01066                 rz_src = src;
    01067                 src_converted = 0;
    01068         } else {
    01069                 /*
    01070                 * New source surface is 32bit with a defined RGBA ordering
    01071                 */
    01072                 rz_src =
    01073                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01074 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01075                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01076 #else
    01077                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01078 #endif
    01079                         );
    01080
    01081                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01082
    01083                 src_converted = 1;
    01084                 is32bit = 1;
    01085         }
    01086
    01087         /*
    01088         * Sanity check zoom factor
    01089         */
    01090         flipx = (zoomx<0.0);
    01091         if (flipx) zoomx=-zoomx;
    01092         flipy = (zoomy<0.0);
    01093         if (flipy) zoomy=-zoomy;
    01094         if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
    01095         if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
    01096         zoominv = 65536.0 / (zoomx * zoomx);
    01097
    01098         /*
    01099         * Check if we have a rotozoom or just a zoom
    01100         */
    01101         if (fabs(angle) > VALUE_LIMIT) {
    01102
    01103                 /*
    01104                 * Angle!=0: full rotozoom
    01105                 */
    01106                 /*
    01107                 * -----------------------
    01108                 */
    01109
    01110                 /* Determine target size */
    01111                 _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
    01112
    01113                 /*
    01114                 * Calculate target factors from sin/cos and zoom
    01115                 */
    01116                 sanglezoominv = sanglezoom;
    01117                 canglezoominv = canglezoom;
    01118                 sanglezoominv *= zoominv;
    01119                 canglezoominv *= zoominv;
    01120
    01121                 /* Calculate half size */
    01122                 dstwidthhalf = dstwidth / 2;
    01123                 dstheighthalf = dstheight / 2;
    01124
    01125                 /*
    01126                 * Alloc space to completely contain the rotated surface
    01127                 */
    01128                 rz_dst = NULL;
    01129                 if (is32bit) {
    01130                         /*
    01131                         * Target surface is 32bit with source RGBA/ABGR ordering
    01132                         */
    01133                         rz_dst =
    01134                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01135                                 rz_src->format->Rmask, rz_src->format->Gmask,
    01136                                 rz_src->format->Bmask, rz_src->format->Amask);
    01137                 } else {
    01138                         /*
    01139                         * Target surface is 8bit
    01140                         */
    01141                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01142                 }
    01143
    01144                 /* Check target */
    01145                 if (rz_dst == NULL)
    01146                         return NULL;
    01147
    01148                 /* Adjust for guard rows */
    01149                 rz_dst->h = dstheight;
    01150
    01151                 /*
    01152                 * Lock source surface
    01153                 */
    01154                 if (SDL_MUSTLOCK(rz_src)) {
    01155                         SDL_LockSurface(rz_src);
    01156                 }
    01157
    01158                 /*
    01159                 * Check which kind of surface we have
    01160                 */
    01161                 if (is32bit) {
    01162                         /*
    01163                         * Call the 32bit transformation routine to do the rotation (using alpha)
    01164                         */
    01165                         _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
    01166                                 (int) (sanglezoominv), (int) (canglezoominv),
    01167                                 flipx, flipy,
    01168                                 smooth);
    01169                 } else {
    01170                         /*
    01171                         * Copy palette and colorkey info
    01172                         */
    01173                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01174                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01175                         }
    01176                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01177                         /*
    01178                         * Call the 8bit transformation routine to do the rotation
    01179                         */
    01180                         transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
    01181                                 (int) (sanglezoominv), (int) (canglezoominv),
    01182                                 flipx, flipy);
    01183                 }
    01184                 /*
    01185                 * Unlock source surface
    01186                 */
    01187                 if (SDL_MUSTLOCK(rz_src)) {
    01188                         SDL_UnlockSurface(rz_src);
    01189                 }
    01190
    01191         } else {
    01192
    01193                 /*
    01194                 * Angle=0: Just a zoom
    01195                 */
    01196                 /*
    01197                 * --------------------
    01198                 */
    01199
    01200                 /*
    01201                 * Calculate target size
    01202                 */
    01203                 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
    01204
    01205                 /*
    01206                 * Alloc space to completely contain the zoomed surface
    01207                 */
    01208                 rz_dst = NULL;
    01209                 if (is32bit) {
    01210                         /*
    01211                         * Target surface is 32bit with source RGBA/ABGR ordering
    01212                         */
    01213                         rz_dst =
    01214                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01215                                 rz_src->format->Rmask, rz_src->format->Gmask,
    01216                                 rz_src->format->Bmask, rz_src->format->Amask);
    01217                 } else {
    01218                         /*
    01219                         * Target surface is 8bit
    01220                         */
    01221                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01222                 }
    01223
    01224                 /* Check target */
    01225                 if (rz_dst == NULL)
    01226                         return NULL;
    01227
    01228                 /* Adjust for guard rows */
    01229                 rz_dst->h = dstheight;
    01230
    01231                 /*
    01232                 * Lock source surface
    01233                 */
    01234                 if (SDL_MUSTLOCK(rz_src)) {
    01235                         SDL_LockSurface(rz_src);
    01236                 }
    01237
    01238                 /*
    01239                 * Check which kind of surface we have
    01240                 */
    01241                 if (is32bit) {
    01242                         /*
    01243                         * Call the 32bit transformation routine to do the zooming (using alpha)
    01244                         */
    01245                         _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
    01246
    01247                 } else {
    01248                         /*
    01249                         * Copy palette and colorkey info
    01250                         */
    01251                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01252                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01253                         }
    01254                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01255
    01256                         /*
    01257                         * Call the 8bit transformation routine to do the zooming
    01258                         */
    01259                         _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
    01260                 }
    01261
    01262                 /*
    01263                 * Unlock source surface
    01264                 */
    01265                 if (SDL_MUSTLOCK(rz_src)) {
    01266                         SDL_UnlockSurface(rz_src);
    01267                 }
    01268         }
    01269
    01270         /*
    01271         * Cleanup temp surface
    01272         */
    01273         if (src_converted) {
    01274                 SDL_FreeSurface(rz_src);
    01275         }
    01276
    01277         /*
    01278         * Return destination surface
    01279         */
    01280         return (rz_dst);
    01281 }
    01282
    01295 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
    01296 {
    01297         /*
    01298         * Make zoom factors positive
    01299         */
    01300         int flipx, flipy;
    01301         flipx = (zoomx<0.0);
    01302         if (flipx) zoomx = -zoomx;
    01303         flipy = (zoomy<0.0);
    01304         if (flipy) zoomy = -zoomy;
    01305
    01306         /*
    01307         * Sanity check zoom factors
    01308         */
    01309         if (zoomx < VALUE_LIMIT) {
    01310                 zoomx = VALUE_LIMIT;
    01311         }
    01312         if (zoomy < VALUE_LIMIT) {
    01313                 zoomy = VALUE_LIMIT;
    01314         }
    01315
    01316         /*
    01317         * Calculate target size
    01318         */
    01319         *dstwidth = (int) floor(((double) width * zoomx) + 0.5);
    01320         *dstheight = (int) floor(((double) height * zoomy) + 0.5);
    01321         if (*dstwidth < 1) {
    01322                 *dstwidth = 1;
    01323         }
    01324         if (*dstheight < 1) {
    01325                 *dstheight = 1;
    01326         }
    01327 }
    01328
    01345 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
    01346 {
    01347         SDL_Surface *rz_src;
    01348         SDL_Surface *rz_dst;
    01349         int dstwidth, dstheight;
    01350         int is32bit;
    01351         int i, src_converted;
    01352         int flipx, flipy;
    01353
    01354         /*
    01355         * Sanity check
    01356         */
    01357         if (src == NULL)
    01358                 return (NULL);
    01359
    01360         /*
    01361         * Determine if source surface is 32bit or 8bit
    01362         */
    01363         is32bit = (src->format->BitsPerPixel == 32);
    01364         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01365                 /*
    01366                 * Use source surface 'as is'
    01367                 */
    01368                 rz_src = src;
    01369                 src_converted = 0;
    01370         } else {
    01371                 /*
    01372                 * New source surface is 32bit with a defined RGBA ordering
    01373                 */
    01374                 rz_src =
    01375                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01376 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01377                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01378 #else
    01379                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01380 #endif
    01381                         );
    01382                 if (rz_src == NULL) {
    01383                         return NULL;
    01384                 }
    01385                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01386                 src_converted = 1;
    01387                 is32bit = 1;
    01388         }
    01389
    01390         flipx = (zoomx<0.0);
    01391         if (flipx) zoomx = -zoomx;
    01392         flipy = (zoomy<0.0);
    01393         if (flipy) zoomy = -zoomy;
    01394
    01395         /* Get size if target */
    01396         zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
    01397
    01398         /*
    01399         * Alloc space to completely contain the zoomed surface
    01400         */
    01401         rz_dst = NULL;
    01402         if (is32bit) {
    01403                 /*
    01404                 * Target surface is 32bit with source RGBA/ABGR ordering
    01405                 */
    01406                 rz_dst =
    01407                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01408                         rz_src->format->Rmask, rz_src->format->Gmask,
    01409                         rz_src->format->Bmask, rz_src->format->Amask);
    01410         } else {
    01411                 /*
    01412                 * Target surface is 8bit
    01413                 */
    01414                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01415         }
    01416
    01417         /* Check target */
    01418         if (rz_dst == NULL) {
    01419                 /*
    01420                 * Cleanup temp surface
    01421                 */
    01422                 if (src_converted) {
    01423                         SDL_FreeSurface(rz_src);
    01424                 }
    01425                 return NULL;
    01426         }
    01427
    01428         /* Adjust for guard rows */
    01429         rz_dst->h = dstheight;
    01430
    01431         /*
    01432         * Lock source surface
    01433         */
    01434         if (SDL_MUSTLOCK(rz_src)) {
    01435                 SDL_LockSurface(rz_src);
    01436         }
    01437
    01438         /*
    01439         * Check which kind of surface we have
    01440         */
    01441         if (is32bit) {
    01442                 /*
    01443                 * Call the 32bit transformation routine to do the zooming (using alpha)
    01444                 */
    01445                 _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
    01446         } else {
    01447                 /*
    01448                 * Copy palette and colorkey info
    01449                 */
    01450                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01451                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01452                 }
    01453                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01454                 /*
    01455                 * Call the 8bit transformation routine to do the zooming
    01456                 */
    01457                 _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
    01458         }
    01459         /*
    01460         * Unlock source surface
    01461         */
    01462         if (SDL_MUSTLOCK(rz_src)) {
    01463                 SDL_UnlockSurface(rz_src);
    01464         }
    01465
    01466         /*
    01467         * Cleanup temp surface
    01468         */
    01469         if (src_converted) {
    01470                 SDL_FreeSurface(rz_src);
    01471         }
    01472
    01473         /*
    01474         * Return destination surface
    01475         */
    01476         return (rz_dst);
    01477 }
    01478
    01495 /*@null@*/
    01496 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
    01497 {
    01498         int result;
    01499         SDL_Surface *rz_src;
    01500         SDL_Surface *rz_dst = NULL;
    01501         int dstwidth, dstheight;
    01502         int is32bit;
    01503         int i, src_converted;
    01504         int haveError = 0;
    01505
    01506         /*
    01507         * Sanity check
    01508         */
    01509         if (src == NULL) {
    01510                 return (NULL);
    01511         }
    01512
    01513         /*
    01514         * Determine if source surface is 32bit or 8bit
    01515         */
    01516         is32bit = (src->format->BitsPerPixel == 32);
    01517         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01518                 /*
    01519                 * Use source surface 'as is'
    01520                 */
    01521                 rz_src = src;
    01522                 src_converted = 0;
    01523         } else {
    01524                 /*
    01525                 * New source surface is 32bit with a defined RGBA ordering
    01526                 */
    01527                 rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01528 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01529                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01530 #else
    01531                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01532 #endif
    01533                         );
    01534                 if (rz_src==NULL) {
    01535                         haveError = 1;
    01536                         goto exitShrinkSurface;
    01537                 }
    01538
    01539                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01540                 src_converted = 1;
    01541                 is32bit = 1;
    01542         }
    01543
    01544         /*
    01545         * Lock the surface
    01546         */
    01547         if (SDL_MUSTLOCK(rz_src)) {
    01548                 if (SDL_LockSurface(rz_src) < 0) {
    01549                         haveError = 1;
    01550                         goto exitShrinkSurface;
    01551                 }
    01552         }
    01553
    01554         /* Get size for target */
    01555         dstwidth=rz_src->w/factorx;
    01556         while (dstwidth*factorx>rz_src->w) { dstwidth--; }
    01557         dstheight=rz_src->h/factory;
    01558         while (dstheight*factory>rz_src->h) { dstheight--; }
    01559
    01560         /*
    01561         * Alloc space to completely contain the shrunken surface
    01562         * (with added guard rows)
    01563         */
    01564         if (is32bit==1) {
    01565                 /*
    01566                 * Target surface is 32bit with source RGBA/ABGR ordering
    01567                 */
    01568                 rz_dst =
    01569                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01570                         rz_src->format->Rmask, rz_src->format->Gmask,
    01571                         rz_src->format->Bmask, rz_src->format->Amask);
    01572         } else {
    01573                 /*
    01574                 * Target surface is 8bit
    01575                 */
    01576                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01577         }
    01578
    01579         /* Check target */
    01580         if (rz_dst == NULL) {
    01581                 haveError = 1;
    01582                 goto exitShrinkSurface;
    01583         }
    01584
    01585         /* Adjust for guard rows */
    01586         rz_dst->h = dstheight;
    01587
    01588         /*
    01589         * Check which kind of surface we have
    01590         */
    01591         if (is32bit==1) {
    01592                 /*
    01593                 * Call the 32bit transformation routine to do the shrinking (using alpha)
    01594                 */
    01595                 result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
    01596                 if ((result!=0) || (rz_dst==NULL)) {
    01597                         haveError = 1;
    01598                         goto exitShrinkSurface;
    01599                 }
    01600         } else {
    01601                 /*
    01602                 * Copy palette and colorkey info
    01603                 */
    01604                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01605                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01606                 }
    01607                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01608                 /*
    01609                 * Call the 8bit transformation routine to do the shrinking
    01610                 */
    01611                 result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
    01612                 if (result!=0) {
    01613                         haveError = 1;
    01614                         goto exitShrinkSurface;
    01615                 }
    01616         }
    01617
    01618 exitShrinkSurface:
    01619         if (rz_src!=NULL) {
    01620                 /*
    01621                 * Unlock source surface
    01622                 */
    01623                 if (SDL_MUSTLOCK(rz_src)) {
    01624                         SDL_UnlockSurface(rz_src);
    01625                 }
    01626
    01627                 /*
    01628                 * Cleanup temp surface
    01629                 */
    01630                 if (src_converted==1) {
    01631                         SDL_FreeSurface(rz_src);
    01632                 }
    01633         }
    01634
    01635         /* Check error state; maybe need to cleanup destination */
    01636         if (haveError==1) {
    01637                 if (rz_dst!=NULL) {
    01638                         SDL_FreeSurface(rz_dst);
    01639                 }
    01640                 rz_dst=NULL;
    01641         }
    01642
    01643         /*
    01644         * Return destination surface
    01645         */
    01646         return (rz_dst);
    01647 }