SDL2_gfx 1.0.1 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, bpr;
    00807         SDL_Surface* dst;
    00808         Uint8* srcBuf;
    00809         Uint8* dstBuf;
    00810         int normalizedClockwiseTurns;
    00811
    00812         /* Has to be a valid surface pointer and be a Nbit surface where n is divisible by 8 */
    00813         if (!src ||
    00814             !src->format) {
    00815                 SDL_SetError("NULL source surface or source surface format");
    00816             return NULL;
    00817         }
    00818
    00819         if ((src->format->BitsPerPixel % 8) != 0) {
    00820                 SDL_SetError("Invalid source surface bit depth");
    00821             return NULL;
    00822         }
    00823
    00824         /* normalize numClockwiseTurns */
    00825         normalizedClockwiseTurns = (numClockwiseTurns % 4);
    00826         if (normalizedClockwiseTurns < 0) {
    00827                 normalizedClockwiseTurns += 4;
    00828         }
    00829
    00830         /* If turns are even, our new width/height will be the same as the source surface */
    00831         if (normalizedClockwiseTurns % 2) {
    00832                 newWidth = src->h;
    00833                 newHeight = src->w;
    00834         } else {
    00835                 newWidth = src->w;
    00836                 newHeight = src->h;
    00837         }
    00838
    00839         dst = SDL_CreateRGBSurface( src->flags, newWidth, newHeight, src->format->BitsPerPixel,
    00840                 src->format->Rmask,
    00841                 src->format->Gmask,
    00842                 src->format->Bmask,
    00843                 src->format->Amask);
    00844         if(!dst) {
    00845                 SDL_SetError("Could not create destination surface");
    00846                 return NULL;
    00847         }
    00848
    00849         if (SDL_MUSTLOCK(src)) {
    00850                 SDL_LockSurface(src);
    00851         }
    00852         if (SDL_MUSTLOCK(dst)) {
    00853                 SDL_LockSurface(dst);
    00854         }
    00855
    00856         /* Calculate byte-per-pixel */
    00857         bpp = src->format->BitsPerPixel / 8;
    00858
    00859         switch(normalizedClockwiseTurns) {
    00860         case 0: /* Make a copy of the surface */
    00861                 {
    00862                         /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
    00863                         since it does not preserve alpha. */
    00864
    00865                         if (src->pitch == dst->pitch) {
    00866                                 /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
    00867                                 memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
    00868                         }
    00869                         else
    00870                         {
    00871                                 /* If the pitch differs, copy each row separately */
    00872                                 srcBuf = (Uint8*)(src->pixels);
    00873                                 dstBuf = (Uint8*)(dst->pixels);
    00874                                 bpr = src->w * bpp;
    00875                                 for (row = 0; row < src->h; row++) {
    00876                                         memcpy(dstBuf, srcBuf, bpr);
    00877                                         srcBuf += src->pitch;
    00878                                         dstBuf += dst->pitch;
    00879                                 }
    00880                         }
    00881                 }
    00882                 break;
    00883
    00884                 /* rotate clockwise */
    00885         case 1: /* rotated 90 degrees clockwise */
    00886                 {
    00887                         for (row = 0; row < src->h; ++row) {
    00888                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
    00889                                 dstBuf = (Uint8*)(dst->pixels) + (dst->w - row - 1) * bpp;
    00890                                 for (col = 0; col < src->w; ++col) {
    00891                                         memcpy (dstBuf, srcBuf, bpp);
    00892                                         srcBuf += bpp;
    00893                                         dstBuf += dst->pitch;
    00894                                 }
    00895                         }
    00896                 }
    00897                 break;
    00898
    00899         case 2: /* rotated 180 degrees clockwise */
    00900                 {
    00901                         for (row = 0; row < src->h; ++row) {
    00902                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
    00903                                 dstBuf = (Uint8*)(dst->pixels) + ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
    00904                                 for (col = 0; col < src->w; ++col) {
    00905                                         memcpy (dstBuf, srcBuf, bpp);
    00906                                         srcBuf += bpp;
    00907                                         dstBuf -= bpp;
    00908                                 }
    00909                         }
    00910                 }
    00911                 break;
    00912
    00913         case 3: /* rotated 270 degrees clockwise */
    00914                 {
    00915                         for (row = 0; row < src->h; ++row) {
    00916                                 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
    00917                                 dstBuf = (Uint8*)(dst->pixels) + (row * bpp) + (dst->h * dst->pitch);
    00918                                 for (col = 0; col < src->w; ++col) {
    00919                                         memcpy (dstBuf, srcBuf, bpp);
    00920                                         srcBuf += bpp;
    00921                                         dstBuf -= dst->pitch;
    00922                                 }
    00923                         }
    00924                 }
    00925                 break;
    00926         }
    00927         /* end switch */
    00928
    00929         if (SDL_MUSTLOCK(src)) {
    00930                 SDL_UnlockSurface(src);
    00931         }
    00932         if (SDL_MUSTLOCK(dst)) {
    00933                 SDL_UnlockSurface(dst);
    00934         }
    00935
    00936         return dst;
    00937 }
    00938
    00939
    00954 void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
    00955         int *dstwidth, int *dstheight,
    00956         double *canglezoom, double *sanglezoom)
    00957 {
    00958         double x, y, cx, cy, sx, sy;
    00959         double radangle;
    00960         int dstwidthhalf, dstheighthalf;
    00961
    00962         /*
    00963         * Determine destination width and height by rotating a centered source box
    00964         */
    00965         radangle = angle * (M_PI / 180.0);
    00966         *sanglezoom = sin(radangle);
    00967         *canglezoom = cos(radangle);
    00968         *sanglezoom *= zoomx;
    00969         *canglezoom *= zoomx;
    00970         x = (double)(width / 2);
    00971         y = (double)(height / 2);
    00972         cx = *canglezoom * x;
    00973         cy = *canglezoom * y;
    00974         sx = *sanglezoom * x;
    00975         sy = *sanglezoom * y;
    00976
    00977         dstwidthhalf = MAX((int)
    00978                 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
    00979         dstheighthalf = MAX((int)
    00980                 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
    00981         *dstwidth = 2 * dstwidthhalf;
    00982         *dstheight = 2 * dstheighthalf;
    00983 }
    00984
    00996 void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
    00997 {
    00998         double dummy_sanglezoom, dummy_canglezoom;
    00999
    01000         _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
    01001 }
    01002
    01013 void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
    01014 {
    01015         double dummy_sanglezoom, dummy_canglezoom;
    01016
    01017         _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom, dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
    01018 }
    01019
    01035 SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
    01036 {
    01037         return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
    01038 }
    01039
    01056 SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
    01057 {
    01058         SDL_Surface *rz_src;
    01059         SDL_Surface *rz_dst;
    01060         double zoominv;
    01061         double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
    01062         int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
    01063         int is32bit;
    01064         int i, src_converted;
    01065         int flipx,flipy;
    01066
    01067         /*
    01068         * Sanity check
    01069         */
    01070         if (src == NULL) {
    01071                 return (NULL);
    01072         }
    01073
    01074         /*
    01075         * Determine if source surface is 32bit or 8bit
    01076         */
    01077         is32bit = (src->format->BitsPerPixel == 32);
    01078         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01079                 /*
    01080                 * Use source surface 'as is'
    01081                 */
    01082                 rz_src = src;
    01083                 src_converted = 0;
    01084         } else {
    01085                 /*
    01086                 * New source surface is 32bit with a defined RGBA ordering
    01087                 */
    01088                 rz_src =
    01089                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01090 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01091                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01092 #else
    01093                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01094 #endif
    01095                         );
    01096
    01097                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01098
    01099                 src_converted = 1;
    01100                 is32bit = 1;
    01101         }
    01102
    01103         /*
    01104         * Sanity check zoom factor
    01105         */
    01106         flipx = (zoomx<0.0);
    01107         if (flipx) zoomx=-zoomx;
    01108         flipy = (zoomy<0.0);
    01109         if (flipy) zoomy=-zoomy;
    01110         if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
    01111         if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
    01112         zoominv = 65536.0 / (zoomx * zoomx);
    01113
    01114         /*
    01115         * Check if we have a rotozoom or just a zoom
    01116         */
    01117         if (fabs(angle) > VALUE_LIMIT) {
    01118
    01119                 /*
    01120                 * Angle!=0: full rotozoom
    01121                 */
    01122                 /*
    01123                 * -----------------------
    01124                 */
    01125
    01126                 /* Determine target size */
    01127                 _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy, &dstwidth, &dstheight, &canglezoom, &sanglezoom);
    01128
    01129                 /*
    01130                 * Calculate target factors from sin/cos and zoom
    01131                 */
    01132                 sanglezoominv = sanglezoom;
    01133                 canglezoominv = canglezoom;
    01134                 sanglezoominv *= zoominv;
    01135                 canglezoominv *= zoominv;
    01136
    01137                 /* Calculate half size */
    01138                 dstwidthhalf = dstwidth / 2;
    01139                 dstheighthalf = dstheight / 2;
    01140
    01141                 /*
    01142                 * Alloc space to completely contain the rotated surface
    01143                 */
    01144                 rz_dst = NULL;
    01145                 if (is32bit) {
    01146                         /*
    01147                         * Target surface is 32bit with source RGBA/ABGR ordering
    01148                         */
    01149                         rz_dst =
    01150                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01151                                 rz_src->format->Rmask, rz_src->format->Gmask,
    01152                                 rz_src->format->Bmask, rz_src->format->Amask);
    01153                 } else {
    01154                         /*
    01155                         * Target surface is 8bit
    01156                         */
    01157                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01158                 }
    01159
    01160                 /* Check target */
    01161                 if (rz_dst == NULL)
    01162                         return NULL;
    01163
    01164                 /* Adjust for guard rows */
    01165                 rz_dst->h = dstheight;
    01166
    01167                 /*
    01168                 * Lock source surface
    01169                 */
    01170                 if (SDL_MUSTLOCK(rz_src)) {
    01171                         SDL_LockSurface(rz_src);
    01172                 }
    01173
    01174                 /*
    01175                 * Check which kind of surface we have
    01176                 */
    01177                 if (is32bit) {
    01178                         /*
    01179                         * Call the 32bit transformation routine to do the rotation (using alpha)
    01180                         */
    01181                         _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
    01182                                 (int) (sanglezoominv), (int) (canglezoominv),
    01183                                 flipx, flipy,
    01184                                 smooth);
    01185                 } else {
    01186                         /*
    01187                         * Copy palette and colorkey info
    01188                         */
    01189                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01190                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01191                         }
    01192                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01193                         /*
    01194                         * Call the 8bit transformation routine to do the rotation
    01195                         */
    01196                         transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
    01197                                 (int) (sanglezoominv), (int) (canglezoominv),
    01198                                 flipx, flipy);
    01199                 }
    01200                 /*
    01201                 * Unlock source surface
    01202                 */
    01203                 if (SDL_MUSTLOCK(rz_src)) {
    01204                         SDL_UnlockSurface(rz_src);
    01205                 }
    01206
    01207         } else {
    01208
    01209                 /*
    01210                 * Angle=0: Just a zoom
    01211                 */
    01212                 /*
    01213                 * --------------------
    01214                 */
    01215
    01216                 /*
    01217                 * Calculate target size
    01218                 */
    01219                 zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
    01220
    01221                 /*
    01222                 * Alloc space to completely contain the zoomed surface
    01223                 */
    01224                 rz_dst = NULL;
    01225                 if (is32bit) {
    01226                         /*
    01227                         * Target surface is 32bit with source RGBA/ABGR ordering
    01228                         */
    01229                         rz_dst =
    01230                                 SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01231                                 rz_src->format->Rmask, rz_src->format->Gmask,
    01232                                 rz_src->format->Bmask, rz_src->format->Amask);
    01233                 } else {
    01234                         /*
    01235                         * Target surface is 8bit
    01236                         */
    01237                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01238                 }
    01239
    01240                 /* Check target */
    01241                 if (rz_dst == NULL)
    01242                         return NULL;
    01243
    01244                 /* Adjust for guard rows */
    01245                 rz_dst->h = dstheight;
    01246
    01247                 /*
    01248                 * Lock source surface
    01249                 */
    01250                 if (SDL_MUSTLOCK(rz_src)) {
    01251                         SDL_LockSurface(rz_src);
    01252                 }
    01253
    01254                 /*
    01255                 * Check which kind of surface we have
    01256                 */
    01257                 if (is32bit) {
    01258                         /*
    01259                         * Call the 32bit transformation routine to do the zooming (using alpha)
    01260                         */
    01261                         _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
    01262
    01263                 } else {
    01264                         /*
    01265                         * Copy palette and colorkey info
    01266                         */
    01267                         for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01268                                 rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01269                         }
    01270                         rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01271
    01272                         /*
    01273                         * Call the 8bit transformation routine to do the zooming
    01274                         */
    01275                         _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
    01276                 }
    01277
    01278                 /*
    01279                 * Unlock source surface
    01280                 */
    01281                 if (SDL_MUSTLOCK(rz_src)) {
    01282                         SDL_UnlockSurface(rz_src);
    01283                 }
    01284         }
    01285
    01286         /*
    01287         * Cleanup temp surface
    01288         */
    01289         if (src_converted) {
    01290                 SDL_FreeSurface(rz_src);
    01291         }
    01292
    01293         /*
    01294         * Return destination surface
    01295         */
    01296         return (rz_dst);
    01297 }
    01298
    01311 void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
    01312 {
    01313         /*
    01314         * Make zoom factors positive
    01315         */
    01316         int flipx, flipy;
    01317         flipx = (zoomx<0.0);
    01318         if (flipx) zoomx = -zoomx;
    01319         flipy = (zoomy<0.0);
    01320         if (flipy) zoomy = -zoomy;
    01321
    01322         /*
    01323         * Sanity check zoom factors
    01324         */
    01325         if (zoomx < VALUE_LIMIT) {
    01326                 zoomx = VALUE_LIMIT;
    01327         }
    01328         if (zoomy < VALUE_LIMIT) {
    01329                 zoomy = VALUE_LIMIT;
    01330         }
    01331
    01332         /*
    01333         * Calculate target size
    01334         */
    01335         *dstwidth = (int) floor(((double) width * zoomx) + 0.5);
    01336         *dstheight = (int) floor(((double) height * zoomy) + 0.5);
    01337         if (*dstwidth < 1) {
    01338                 *dstwidth = 1;
    01339         }
    01340         if (*dstheight < 1) {
    01341                 *dstheight = 1;
    01342         }
    01343 }
    01344
    01361 SDL_Surface *zoomSurface(SDL_Surface * src, double zoomx, double zoomy, int smooth)
    01362 {
    01363         SDL_Surface *rz_src;
    01364         SDL_Surface *rz_dst;
    01365         int dstwidth, dstheight;
    01366         int is32bit;
    01367         int i, src_converted;
    01368         int flipx, flipy;
    01369
    01370         /*
    01371         * Sanity check
    01372         */
    01373         if (src == NULL)
    01374                 return (NULL);
    01375
    01376         /*
    01377         * Determine if source surface is 32bit or 8bit
    01378         */
    01379         is32bit = (src->format->BitsPerPixel == 32);
    01380         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01381                 /*
    01382                 * Use source surface 'as is'
    01383                 */
    01384                 rz_src = src;
    01385                 src_converted = 0;
    01386         } else {
    01387                 /*
    01388                 * New source surface is 32bit with a defined RGBA ordering
    01389                 */
    01390                 rz_src =
    01391                         SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01392 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01393                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01394 #else
    01395                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01396 #endif
    01397                         );
    01398                 if (rz_src == NULL) {
    01399                         return NULL;
    01400                 }
    01401                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01402                 src_converted = 1;
    01403                 is32bit = 1;
    01404         }
    01405
    01406         flipx = (zoomx<0.0);
    01407         if (flipx) zoomx = -zoomx;
    01408         flipy = (zoomy<0.0);
    01409         if (flipy) zoomy = -zoomy;
    01410
    01411         /* Get size if target */
    01412         zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
    01413
    01414         /*
    01415         * Alloc space to completely contain the zoomed surface
    01416         */
    01417         rz_dst = NULL;
    01418         if (is32bit) {
    01419                 /*
    01420                 * Target surface is 32bit with source RGBA/ABGR ordering
    01421                 */
    01422                 rz_dst =
    01423                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01424                         rz_src->format->Rmask, rz_src->format->Gmask,
    01425                         rz_src->format->Bmask, rz_src->format->Amask);
    01426         } else {
    01427                 /*
    01428                 * Target surface is 8bit
    01429                 */
    01430                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01431         }
    01432
    01433         /* Check target */
    01434         if (rz_dst == NULL) {
    01435                 /*
    01436                 * Cleanup temp surface
    01437                 */
    01438                 if (src_converted) {
    01439                         SDL_FreeSurface(rz_src);
    01440                 }
    01441                 return NULL;
    01442         }
    01443
    01444         /* Adjust for guard rows */
    01445         rz_dst->h = dstheight;
    01446
    01447         /*
    01448         * Lock source surface
    01449         */
    01450         if (SDL_MUSTLOCK(rz_src)) {
    01451                 SDL_LockSurface(rz_src);
    01452         }
    01453
    01454         /*
    01455         * Check which kind of surface we have
    01456         */
    01457         if (is32bit) {
    01458                 /*
    01459                 * Call the 32bit transformation routine to do the zooming (using alpha)
    01460                 */
    01461                 _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
    01462         } else {
    01463                 /*
    01464                 * Copy palette and colorkey info
    01465                 */
    01466                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01467                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01468                 }
    01469                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01470                 /*
    01471                 * Call the 8bit transformation routine to do the zooming
    01472                 */
    01473                 _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
    01474         }
    01475         /*
    01476         * Unlock source surface
    01477         */
    01478         if (SDL_MUSTLOCK(rz_src)) {
    01479                 SDL_UnlockSurface(rz_src);
    01480         }
    01481
    01482         /*
    01483         * Cleanup temp surface
    01484         */
    01485         if (src_converted) {
    01486                 SDL_FreeSurface(rz_src);
    01487         }
    01488
    01489         /*
    01490         * Return destination surface
    01491         */
    01492         return (rz_dst);
    01493 }
    01494
    01511 /*@null@*/
    01512 SDL_Surface *shrinkSurface(SDL_Surface *src, int factorx, int factory)
    01513 {
    01514         int result;
    01515         SDL_Surface *rz_src;
    01516         SDL_Surface *rz_dst = NULL;
    01517         int dstwidth, dstheight;
    01518         int is32bit;
    01519         int i, src_converted;
    01520         int haveError = 0;
    01521
    01522         /*
    01523         * Sanity check
    01524         */
    01525         if (src == NULL) {
    01526                 return (NULL);
    01527         }
    01528
    01529         /*
    01530         * Determine if source surface is 32bit or 8bit
    01531         */
    01532         is32bit = (src->format->BitsPerPixel == 32);
    01533         if ((is32bit) || (src->format->BitsPerPixel == 8)) {
    01534                 /*
    01535                 * Use source surface 'as is'
    01536                 */
    01537                 rz_src = src;
    01538                 src_converted = 0;
    01539         } else {
    01540                 /*
    01541                 * New source surface is 32bit with a defined RGBA ordering
    01542                 */
    01543                 rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
    01544 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
    01545                         0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
    01546 #else
    01547                         0xff000000,  0x00ff0000, 0x0000ff00, 0x000000ff
    01548 #endif
    01549                         );
    01550                 if (rz_src==NULL) {
    01551                         haveError = 1;
    01552                         goto exitShrinkSurface;
    01553                 }
    01554
    01555                 SDL_BlitSurface(src, NULL, rz_src, NULL);
    01556                 src_converted = 1;
    01557                 is32bit = 1;
    01558         }
    01559
    01560         /*
    01561         * Lock the surface
    01562         */
    01563         if (SDL_MUSTLOCK(rz_src)) {
    01564                 if (SDL_LockSurface(rz_src) < 0) {
    01565                         haveError = 1;
    01566                         goto exitShrinkSurface;
    01567                 }
    01568         }
    01569
    01570         /* Get size for target */
    01571         dstwidth=rz_src->w/factorx;
    01572         while (dstwidth*factorx>rz_src->w) { dstwidth--; }
    01573         dstheight=rz_src->h/factory;
    01574         while (dstheight*factory>rz_src->h) { dstheight--; }
    01575
    01576         /*
    01577         * Alloc space to completely contain the shrunken surface
    01578         * (with added guard rows)
    01579         */
    01580         if (is32bit==1) {
    01581                 /*
    01582                 * Target surface is 32bit with source RGBA/ABGR ordering
    01583                 */
    01584                 rz_dst =
    01585                         SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
    01586                         rz_src->format->Rmask, rz_src->format->Gmask,
    01587                         rz_src->format->Bmask, rz_src->format->Amask);
    01588         } else {
    01589                 /*
    01590                 * Target surface is 8bit
    01591                 */
    01592                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
    01593         }
    01594
    01595         /* Check target */
    01596         if (rz_dst == NULL) {
    01597                 haveError = 1;
    01598                 goto exitShrinkSurface;
    01599         }
    01600
    01601         /* Adjust for guard rows */
    01602         rz_dst->h = dstheight;
    01603
    01604         /*
    01605         * Check which kind of surface we have
    01606         */
    01607         if (is32bit==1) {
    01608                 /*
    01609                 * Call the 32bit transformation routine to do the shrinking (using alpha)
    01610                 */
    01611                 result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
    01612                 if ((result!=0) || (rz_dst==NULL)) {
    01613                         haveError = 1;
    01614                         goto exitShrinkSurface;
    01615                 }
    01616         } else {
    01617                 /*
    01618                 * Copy palette and colorkey info
    01619                 */
    01620                 for (i = 0; i < rz_src->format->palette->ncolors; i++) {
    01621                         rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
    01622                 }
    01623                 rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
    01624                 /*
    01625                 * Call the 8bit transformation routine to do the shrinking
    01626                 */
    01627                 result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
    01628                 if (result!=0) {
    01629                         haveError = 1;
    01630                         goto exitShrinkSurface;
    01631                 }
    01632         }
    01633
    01634 exitShrinkSurface:
    01635         if (rz_src!=NULL) {
    01636                 /*
    01637                 * Unlock source surface
    01638                 */
    01639                 if (SDL_MUSTLOCK(rz_src)) {
    01640                         SDL_UnlockSurface(rz_src);
    01641                 }
    01642
    01643                 /*
    01644                 * Cleanup temp surface
    01645                 */
    01646                 if (src_converted==1) {
    01647                         SDL_FreeSurface(rz_src);
    01648                 }
    01649         }
    01650
    01651         /* Check error state; maybe need to cleanup destination */
    01652         if (haveError==1) {
    01653                 if (rz_dst!=NULL) {
    01654                         SDL_FreeSurface(rz_dst);
    01655                 }
    01656                 rz_dst=NULL;
    01657         }
    01658
    01659         /*
    01660         * Return destination surface
    01661         */
    01662         return (rz_dst);
    01663 }