Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

rotozoom.cpp

Go to the documentation of this file.
00001 /*
00002     pgrotozoom.cpp
00003  
00004     Copyright (C) A. Schiffler, July 2001
00005  
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010  
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015  
00016     You should have received a copy of the GNU Lesser General Public
00017     License along with this library; if not, write to the Free Software
00018     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  
00020     The code here within is based on the LGPL SDL_Rotozoom package by
00021     A. Schiffler <aschiffler@home.com>. The only changes made are
00022     cosmetical (interface and naming) to fit the ParaGUI library.
00023  
00024     Last Update:      $Author: mbickel $
00025     Update Date:      $Date: 2007-04-13 16:16:01 $
00026     Source File:      $Source: /home/cvspsrv/cvsroot/games/asc/source/libs/paragui/src/draw/rotozoom.cpp,v $
00027     CVS/RCS Revision: $Revision: 1.2 $
00028     Status:           $State: Exp $
00029 */
00030 
00031 #include "paragui.h"
00032 #include "pgdraw.h"
00033 
00034 #include <cstdlib>
00035 #include <cstring>
00036 #include <cmath>
00037 
00038 #define MAX(a,b)    (((a) > (b)) ? (a) : (b))
00039 
00040 /* ---- Structures */
00041 
00042 typedef struct tColorRGBA {
00043         tColorRGBA() : r(0), g(0), b(0), a(0) {}
00044         ;
00045         Uint8 r;
00046         Uint8 g;
00047         Uint8 b;
00048         Uint8 a;
00049 }
00050 tColorRGBA;
00051 
00052 typedef struct tColorY {
00053         Uint8 y;
00054 }
00055 tColorY;
00056 
00057 // 32bit Zoomer with optional anti-aliasing by bilinear interpolation.
00058 // Zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
00059 static int zoomSurfaceRGBA (SDL_Surface * src, SDL_Surface * dst, bool smooth) {
00060         int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep;
00061         tColorRGBA *c00, *c01, *c10, *c11;
00062         tColorRGBA *sp, *csp, *dp;
00063         int sgap, dgap, orderRGBA;
00064 
00065         /* Variable setup */
00066         if (smooth) {
00067                 /* For interpolation: assume source dimension is one pixel */
00068                 /* smaller to avoid overflow on right and bottom edge.     */
00069                 sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
00070                 sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
00071         } else {
00072                 sx = (int) (65536.0 * (float) src->w / (float) dst->w);
00073                 sy = (int) (65536.0 * (float) src->h / (float) dst->h);
00074         }
00075 
00076         /* Allocate memory for row increments */
00077         if ((sax = (int *) malloc ((dst->w + 1) * sizeof (Uint32))) == NULL) {
00078                 return (-1);
00079         }
00080         if ((say = (int *) malloc ((dst->h + 1) * sizeof (Uint32))) == NULL) {
00081                 free (sax);
00082                 return (-1);
00083         }
00084 
00085         /* Precalculate row increments */
00086         csx = 0;
00087         csax = sax;
00088         for (x = 0; x <= dst->w; x++) {
00089                 *csax = csx;
00090                 csax++;
00091                 csx &= 0xffff;
00092                 csx += sx;
00093         }
00094         csy = 0;
00095         csay = say;
00096         for (y = 0; y <= dst->h; y++) {
00097                 *csay = csy;
00098                 csay++;
00099                 csy &= 0xffff;
00100                 csy += sy;
00101         }
00102 
00103         /* Pointer setup */
00104         sp = csp = (tColorRGBA *) src->pixels;
00105         dp = (tColorRGBA *) dst->pixels;
00106         sgap = src->pitch - src->w * 4;
00107         dgap = dst->pitch - dst->w * 4;
00108         orderRGBA = (src->format->Rmask == 0x000000ff);
00109 
00110         /* Switch between interpolating and non-interpolating code */
00111         if (smooth) {
00112 
00113                 /* Interpolating Zoom */
00114 
00115                 /* Scan destination */
00116                 csay = say;
00117                 for (y = 0; y < dst->h; y++) {
00118                         /* Setup color source pointers */
00119                         c00 = csp;
00120                         c01 = csp;
00121                         c01++;
00122                         c10 = (tColorRGBA *) ((Uint8 *) csp + src->pitch);
00123                         c11 = c10;
00124                         c11++;
00125                         csax = sax;
00126                         for (x = 0; x < dst->w; x++) {
00127                                 /* ABGR ordering */
00128                                 /* Interpolate colors */
00129                                 ex = (*csax & 0xffff);
00130                                 ey = (*csay & 0xffff);
00131                                 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
00132                                 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
00133                                 dp->r = (((t2 - t1) * ey) >> 16) + t1;
00134                                 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
00135                                 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
00136                                 dp->g = (((t2 - t1) * ey) >> 16) + t1;
00137                                 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
00138                                 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
00139                                 dp->b = (((t2 - t1) * ey) >> 16) + t1;
00140                                 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
00141                                 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
00142                                 dp->a = (((t2 - t1) * ey) >> 16) + t1;
00143                                 /* Advance source pointers */
00144                                 csax++;
00145                                 sstep = (*csax >> 16);
00146                                 c00 += sstep;
00147                                 c01 += sstep;
00148                                 c10 += sstep;
00149                                 c11 += sstep;
00150                                 /* Advance destination pointer */
00151                                 dp++;
00152                         }
00153                         /* Advance source pointer */
00154                         csay++;
00155                         csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
00156                         /* Advance destination pointers */
00157                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00158                 }
00159 
00160         } else {
00161 
00162                 /* Non-Interpolating Zoom */
00163 
00164                 csay = say;
00165                 for (y = 0; y < dst->h; y++) {
00166                         sp = csp;
00167                         csax = sax;
00168                         for (x = 0; x < dst->w; x++) {
00169                                 /* Draw */
00170                                 *dp = *sp;
00171                                 /* Advance source pointers */
00172                                 csax++;
00173                                 sp += (*csax >> 16);
00174                                 /* Advance destination pointer */
00175                                 dp++;
00176                         }
00177                         /* Advance source pointer */
00178                         csay++;
00179                         csp = (tColorRGBA *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
00180                         /* Advance destination pointers */
00181                         dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
00182                 }
00183 
00184         }
00185 
00186         /* Remove temp arrays */
00187         free (sax);
00188         free (say);
00189 
00190         return (0);
00191 }
00192 
00193 // 8bit Zoomer without smoothing.
00194 // Zoomes 8bit palette/Y 'src' surface to 'dst' surface.
00195 
00196 static int zoomSurfaceY (SDL_Surface * src, SDL_Surface * dst) {
00197         Uint32  sx, sy, *sax, *say, *csax, *csay, csx, csy;
00198         Sint32 x, y;
00199         Uint8 *sp, *dp, *csp;
00200         int dgap;
00201 
00202         /* Variable setup */
00203         sx = (Uint32) (65536.0 * (float) src->w / (float) dst->w);
00204         sy = (Uint32) (65536.0 * (float) src->h / (float) dst->h);
00205 
00206         /* Allocate memory for row increments */
00207         if ((sax = (Uint32 *) malloc (dst->w * sizeof (Uint32))) == NULL) {
00208                 return (-1);
00209         }
00210         if ((say = (Uint32 *) malloc (dst->h * sizeof (Uint32))) == NULL) {
00211                 if (sax != NULL) {
00212                         free (sax);
00213                 }
00214                 return (-1);
00215         }
00216 
00217         /* Precalculate row increments */
00218         csx = 0;
00219         csax = sax;
00220         for (x = 0; x < dst->w; x++) {
00221                 csx += sx;
00222                 *csax = (csx >> 16);
00223                 csx &= 0xffff;
00224                 csax++;
00225         }
00226         csy = 0;
00227         csay = say;
00228         for (y = 0; y < dst->h; y++) {
00229                 csy += sy;
00230                 *csay = (csy >> 16);
00231                 csy &= 0xffff;
00232                 csay++;
00233         }
00234 
00235         csx = 0;
00236         csax = sax;
00237         for (x = 0; x < dst->w; x++) {
00238                 csx += (*csax);
00239                 csax++;
00240         }
00241         csy = 0;
00242         csay = say;
00243         for (y = 0; y < dst->h; y++) {
00244                 csy += (*csay);
00245                 csay++;
00246         }
00247 
00248         /* Pointer setup */
00249         sp = csp = (Uint8 *) src->pixels;
00250         dp = (Uint8 *) dst->pixels;
00251         dgap = dst->pitch - dst->w;
00252 
00253         /* Draw */
00254         csay = say;
00255         for (y = 0; y < dst->h; y++) {
00256                 csax = sax;
00257                 sp = csp;
00258                 for (x = 0; x < dst->w; x++) {
00259                         /* Draw */
00260                         *dp = *sp;
00261                         /* Advance source pointers */
00262                         sp += (*csax);
00263                         csax++;
00264                         /* Advance destination pointer */
00265                         dp++;
00266                 }
00267                 /* Advance source pointer (for row) */
00268                 csp += ((*csay) * src->pitch);
00269                 csay++;
00270                 /* Advance destination pointers */
00271                 dp += dgap;
00272         }
00273 
00274         /* Remove temp arrays */
00275         free (sax);
00276         free (say);
00277 
00278         return (0);
00279 }
00280 
00281 // 32bit Rotozoomer with optional anti-aliasing by bilinear interpolation.
00282 // Rotates and zoomes 32bit RGBA/ABGR 'src' surface to 'dst' surface.
00283 
00284 static void transformSurfaceRGBA (SDL_Surface * src, SDL_Surface * dst, int cx,
00285                                   int cy, int isin, int icos, bool smooth) {
00286         int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
00287         tColorRGBA c00, c01, c10, c11;
00288         tColorRGBA *pc, *sp;
00289         int gap, orderRGBA;
00290 
00291         /* Variable setup */
00292         xd = ((src->w - dst->w) << 15);
00293         yd = ((src->h - dst->h) << 15);
00294         ax = (cx << 16) - (icos * cx);
00295         ay = (cy << 16) - (isin * cx);
00296         sw = src->w - 1;
00297         sh = src->h - 1;
00298         pc = reinterpret_cast<tColorRGBA*>(dst->pixels);
00299         gap = dst->pitch - dst->w * 4;
00300         orderRGBA = (src->format->Rmask == 0x000000ff);
00301 
00302         /* Switch between interpolating and non-interpolating code */
00303         if (smooth) {
00304                 for (y = 0; y < dst->h; y++) {
00305                         dy = cy - y;
00306                         sdx = (ax + (isin * dy)) + xd;
00307                         sdy = (ay - (icos * dy)) + yd;
00308                         for (x = 0; x < dst->w; x++) {
00309                                 dx = (sdx >> 16);
00310                                 dy = (sdy >> 16);
00311                                 if ((dx >= -1) && (dy >= -1) && (dx < src->w) && (dy < src->h)) {
00312                                         if ((dx >= 0) && (dy >= 0) && (dx < sw) && (dy < sh)) {
00313                                                 sp =
00314                                                     (tColorRGBA *) ((Uint8 *) src->pixels +
00315                                                                     src->pitch * dy);
00316                                                 sp += dx;
00317                                                 c00 = *sp;
00318                                                 sp += 1;
00319                                                 c01 = *sp;
00320                                                 sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
00321                                                 sp -= 1;
00322                                                 c10 = *sp;
00323                                                 sp += 1;
00324                                                 c11 = *sp;
00325                                         } else if ((dx == sw) && (dy == sh)) {
00326                                                 sp =
00327                                                     (tColorRGBA *) ((Uint8 *) src->pixels +
00328                                                                     src->pitch * dy);
00329                                                 sp += dx;
00330                                                 c00 = *sp;
00331                                                 c01 = *pc;
00332                                                 c10 = *pc;
00333                                                 c11 = *pc;
00334                                         } else if ((dx == -1) && (dy == -1)) {
00335                                                 sp = (tColorRGBA *) (src->pixels);
00336                                                 c00 = *pc;
00337                                                 c01 = *pc;
00338                                                 c10 = *pc;
00339                                                 c11 = *sp;
00340                                         } else if ((dx == -1) && (dy == sh)) {
00341                                                 sp = (tColorRGBA *) (src->pixels);
00342                                                 sp =
00343                                                     (tColorRGBA *) ((Uint8 *) src->pixels +
00344                                                                     src->pitch * dy);
00345                                                 c00 = *pc;
00346                                                 c01 = *sp;
00347                                                 c10 = *pc;
00348                                                 c11 = *pc;
00349                                         } else if ((dx == sw) && (dy == -1)) {
00350                                                 sp = (tColorRGBA *) (src->pixels);
00351                                                 sp += dx;
00352                                                 c00 = *pc;
00353                                                 c01 = *pc;
00354                                                 c10 = *sp;
00355                                                 c11 = *pc;
00356                                         } else if (dx == -1) {
00357                                                 sp =
00358                                                     (tColorRGBA *) ((Uint8 *) src->pixels +
00359                                                                     src->pitch * dy);
00360                                                 c00 = *pc;
00361                                                 c01 = *sp;
00362                                                 c10 = *pc;
00363                                                 sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
00364                                                 c11 = *sp;
00365                                         } else if (dy == -1) {
00366                                                 sp = (tColorRGBA *) (src->pixels);
00367                                                 sp += dx;
00368                                                 c00 = *pc;
00369                                                 c01 = *pc;
00370                                                 c10 = *sp;
00371                                                 sp += 1;
00372                                                 c11 = *sp;
00373                                         } else if (dx == sw) {
00374                                                 sp =
00375                                                     (tColorRGBA *) ((Uint8 *) src->pixels +
00376                                                                     src->pitch * dy);
00377                                                 sp += dx;
00378                                                 c00 = *sp;
00379                                                 c01 = *pc;
00380                                                 sp = (tColorRGBA *) ((Uint8 *) sp + src->pitch);
00381                                                 c10 = *sp;
00382                                                 c11 = *pc;
00383                                         } else if (dy == sh) {
00384                                                 sp =
00385                                                     (tColorRGBA *) ((Uint8 *) src->pixels +
00386                                                                     src->pitch * dy);
00387                                                 sp += dx;
00388                                                 c00 = *sp;
00389                                                 sp += 1;
00390                                                 c01 = *sp;
00391                                                 c10 = *pc;
00392                                                 c11 = *pc;
00393                                         }
00394                                         /* Interpolate colors */
00395                                         ex = (sdx & 0xffff);
00396                                         ey = (sdy & 0xffff);
00397                                         t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
00398                                         t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
00399                                         pc->r = (((t2 - t1) * ey) >> 16) + t1;
00400                                         t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
00401                                         t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
00402                                         pc->g = (((t2 - t1) * ey) >> 16) + t1;
00403                                         t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
00404                                         t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
00405                                         pc->b = (((t2 - t1) * ey) >> 16) + t1;
00406                                         t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
00407                                         t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
00408                                         pc->a = (((t2 - t1) * ey) >> 16) + t1;
00409 
00410                                 }
00411                                 sdx += icos;
00412                                 sdy += isin;
00413                                 pc++;
00414                         }
00415                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
00416                 }
00417         } else {
00418                 for (y = 0; y < dst->h; y++) {
00419                         dy = cy - y;
00420                         sdx = (ax + (isin * dy)) + xd;
00421                         sdy = (ay - (icos * dy)) + yd;
00422                         for (x = 0; x < dst->w; x++) {
00423                                 dx = (short) (sdx >> 16);
00424                                 dy = (short) (sdy >> 16);
00425                                 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
00426                                         sp =
00427                                             (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
00428                                         sp += dx;
00429                                         *pc = *sp;
00430                                 }
00431                                 sdx += icos;
00432                                 sdy += isin;
00433                                 pc++;
00434                         }
00435                         pc = (tColorRGBA *) ((Uint8 *) pc + gap);
00436                 }
00437         }
00438 }
00439 
00440 // 8bit Rotozoomer without smoothing
00441 // Rotates and zoomes 8bit palette/Y 'src' surface to 'dst' surface.
00442 
00443 static void transformSurfaceY (SDL_Surface * src, SDL_Surface * dst,
00444                                int cx, int cy, int isin, int icos) {
00445         int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay, sw, sh;
00446         tColorY *pc, *sp;
00447         int gap;
00448 
00449         /* Variable setup */
00450         xd = ((src->w - dst->w) << 15);
00451         yd = ((src->h - dst->h) << 15);
00452         ax = (cx << 16) - (icos * cx);
00453         ay = (cy << 16) - (isin * cx);
00454         sw = src->w - 1;
00455         sh = src->h - 1;
00456         pc = reinterpret_cast<tColorY*>(dst->pixels);
00457         gap = dst->pitch - dst->w;
00458         /* Clear surface to colorkey */
00459         memset (pc, (unsigned char) (src->format->colorkey & 0xff),
00460                 dst->pitch * dst->h);
00461         /* Iterate through destination surface */
00462         for (y = 0; y < dst->h; y++) {
00463                 dy = cy - y;
00464                 sdx = (ax + (isin * dy)) + xd;
00465                 sdy = (ay - (icos * dy)) + yd;
00466                 for (x = 0; x < dst->w; x++) {
00467                         dx = (short) (sdx >> 16);
00468                         dy = (short) (sdy >> 16);
00469                         if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
00470                                 sp = (tColorY *) (src->pixels);
00471                                 sp += (src->pitch * dy + dx);
00472                                 *pc = *sp;
00473                         }
00474                         sdx += icos;
00475                         sdy += isin;
00476                         pc++;
00477                 }
00478                 pc += gap;
00479         }
00480 }
00481 
00482 
00483 
00484 // Rotates and zoomes a 32bit or 8bit 'src' surface to newly created
00485 // 'dst' surface.  'angle' is the rotation in degrees. 'zoom' a
00486 // scaling factor. If 'smooth' is 1 then the destination 32bit surface
00487 // is anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it
00488 // will be converted into a 32bit RGBA format on the fly.
00489 
00490 #define VALUE_LIMIT     0.001
00491 
00492 SDL_Surface* PG_Draw::RotoScaleSurface(SDL_Surface *src, double angle,
00493                                        double zoom, bool smooth) {
00494         SDL_Surface *rz_src;
00495         SDL_Surface *rz_dst;
00496         double zoominv;
00497         double radangle, sanglezoom, canglezoom, sanglezoominv, canglezoominv;
00498         int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
00499         double x,y,cx,cy,sx,sy;
00500         int is32bit;
00501         int i,src_converted;
00502 
00503         /* Sanity check */
00504         if (src==NULL)
00505                 return(NULL);
00506 
00507         /* Determine if source surface is 32bit or 8bit */
00508         is32bit=(src->format->BitsPerPixel==32);
00509         if ( (is32bit) || (src->format->BitsPerPixel==8)) {
00510                 /* Use source surface 'as is' */
00511                 rz_src=src;
00512                 src_converted=0;
00513         } else {
00514                 /* New source surface is 32bit with a defined RGBA ordering */
00515                 rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
00516                 SDL_BlitSurface(src,NULL,rz_src,NULL);
00517                 src_converted=1;
00518                 is32bit=1;
00519         }
00520 
00521         /* Sanity check zoom factor */
00522         if (zoom<VALUE_LIMIT) {
00523                 zoom=VALUE_LIMIT;
00524         }
00525         zoominv=65536.0/zoom;
00526 
00527         /* Check if we have a rotozoom or just a zoom */
00528         if (fabs(angle)>VALUE_LIMIT) {
00529 
00530                 /* Angle!=0: full rotozoom */
00531                 /* ----------------------- */
00532 
00533                 /* Calculate target factors from sin/cos and zoom */
00534                 radangle=angle*(M_PI/180.0);
00535                 sanglezoom=sanglezoominv=sin(radangle);
00536                 canglezoom=canglezoominv=cos(radangle);
00537                 sanglezoom *= zoom;
00538                 canglezoom *= zoom;
00539                 sanglezoominv *= zoominv;
00540                 canglezoominv *= zoominv;
00541 
00542                 /* Determine destination width and height by rotating a centered source box */
00543                 x=rz_src->w/2;
00544                 y=rz_src->h/2;
00545                 cx=canglezoom*x;
00546                 cy=canglezoom*y;
00547                 sx=sanglezoom*x;
00548                 sy=sanglezoom*y;
00549                 dstwidthhalf =MAX((int)ceil(MAX(MAX(MAX(fabs(cx+sy),fabs(cx-sy)),fabs(-cx+sy)),fabs(-cx-sy))),1);
00550                 dstheighthalf=MAX((int)ceil(MAX(MAX(MAX(fabs(sx+cy),fabs(sx-cy)),fabs(-sx+cy)),fabs(-sx-cy))),1);
00551                 dstwidth=2*dstwidthhalf;
00552                 dstheight=2*dstheighthalf;
00553 
00554                 /* Alloc space to completely contain the rotated surface */
00555                 rz_dst=NULL;
00556                 if (is32bit) {
00557                         /* Target surface is 32bit with source RGBA/ABGR ordering */
00558                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask);
00559                 } else {
00560                         /* Target surface is 8bit */
00561                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
00562                 }
00563 
00564                 /* Lock source surface */
00565                 SDL_LockSurface(rz_src);
00566                 /* Check which kind of surface we have */
00567                 if (is32bit) {
00568                         /* Call the 32bit transformation routine to do the rotation (using alpha) */
00569                         transformSurfaceRGBA(rz_src,rz_dst,dstwidthhalf,dstheighthalf,
00570                                              (int)(sanglezoominv),
00571                                              (int)(canglezoominv),
00572                                              smooth);
00573                         /* Turn on source-alpha support */
00574                         SDL_SetAlpha(rz_dst, SDL_SRCALPHA , 255);
00575                 } else {
00576                         /* Copy palette and colorkey info */
00577                         for (i=0; i<rz_src->format->palette->ncolors; i++) {
00578                                 rz_dst->format->palette->colors[i]=rz_src->format->palette->colors[i];
00579                         }
00580                         rz_dst->format->palette->ncolors=rz_src->format->palette->ncolors;
00581                         /* Call the 8bit transformation routine to do the rotation */
00582                         transformSurfaceY(rz_src,rz_dst,dstwidthhalf,dstheighthalf,
00583                                           (int)(sanglezoominv),
00584                                           (int)(canglezoominv));
00585                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
00586                 }
00587                 /* Unlock source surface */
00588                 SDL_UnlockSurface(rz_src);
00589 
00590         } else {
00591 
00592                 /* Angle=0: Just a zoom */
00593                 /* -------------------- */
00594 
00595                 /* Calculate target size and set rect */
00596                 dstwidth=(int)((double)rz_src->w*zoom);
00597                 dstheight=(int)((double)rz_src->h*zoom);
00598                 if (dstwidth<1) {
00599                         dstwidth=1;
00600                 }
00601                 if (dstheight<1) {
00602                         dstheight=1;
00603                 }
00604 
00605                 /* Alloc space to completely contain the zoomed surface */
00606                 rz_dst=NULL;
00607                 if (is32bit) {
00608                         /* Target surface is 32bit with source RGBA/ABGR ordering */
00609                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask);
00610                 } else {
00611                         /* Target surface is 8bit */
00612                         rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
00613                 }
00614 
00615                 /* Lock source surface */
00616                 SDL_LockSurface(rz_src);
00617                 /* Check which kind of surface we have */
00618                 if (is32bit) {
00619                         /* Call the 32bit transformation routine to do the zooming (using alpha) */
00620                         zoomSurfaceRGBA(rz_src,rz_dst,smooth);
00621                         /* Turn on source-alpha support */
00622                         SDL_SetAlpha(rz_dst, SDL_SRCALPHA , 255);
00623                 } else {
00624                         /* Copy palette and colorkey info */
00625                         for (i=0; i<rz_src->format->palette->ncolors; i++) {
00626                                 rz_dst->format->palette->colors[i]=rz_src->format->palette->colors[i];
00627                         }
00628                         rz_dst->format->palette->ncolors=rz_src->format->palette->ncolors;
00629                         /* Call the 8bit transformation routine to do the zooming */
00630                         zoomSurfaceY(rz_src,rz_dst);
00631                         SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
00632                 }
00633                 /* Unlock source surface */
00634                 SDL_UnlockSurface(rz_src);
00635         }
00636 
00637         /* Cleanup temp surface */
00638         if (src_converted) {
00639                 SDL_FreeSurface(rz_src);
00640         }
00641 
00642         /* Return destination surface */
00643         return(rz_dst);
00644 }
00645 
00646 // Zoomes a 32bit or 8bit 'src' surface to newly created 'dst'
00647 // surface.  'zoomx' and 'zoomy' are scaling factors for width and
00648 // height. If 'smooth' is 1 then the destination 32bit surface is
00649 // anti-aliased. If the surface is not 8bit or 32bit RGBA/ABGR it will
00650 // be converted into a 32bit RGBA format on the fly.
00651 
00652 #define VALUE_LIMIT     0.001
00653 
00654 SDL_Surface* PG_Draw::ScaleSurface(SDL_Surface *src,
00655                                    double zoomx, double zoomy, bool smooth) {
00656         SDL_Surface *rz_src;
00657         SDL_Surface *rz_dst;
00658         int dstwidth, dstheight;
00659         int is32bit;
00660         int i,src_converted;
00661 
00662         /* Sanity check */
00663         if (src==NULL)
00664                 return(NULL);
00665 
00666         /* Determine if source surface is 32bit or 8bit */
00667         is32bit=(src->format->BitsPerPixel==32);
00668         if ( (is32bit) || (src->format->BitsPerPixel==8)) {
00669                 /* Use source surface 'as is' */
00670                 rz_src=src;
00671                 src_converted=0;
00672         } else {
00673                 /* New source surface is 32bit with a defined RGBA ordering */
00674                 rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
00675                 SDL_BlitSurface(src,NULL,rz_src,NULL);
00676                 src_converted=1;
00677                 is32bit=1;
00678         }
00679 
00680         /* Sanity check zoom factors */
00681         if (zoomx<VALUE_LIMIT) {
00682                 zoomx=VALUE_LIMIT;
00683         }
00684         if (zoomy<VALUE_LIMIT) {
00685                 zoomy=VALUE_LIMIT;
00686         }
00687 
00688         /* Calculate target size and set rect */
00689         dstwidth=(int)((double)rz_src->w*zoomx);
00690         dstheight=(int)((double)rz_src->h*zoomy);
00691         if (dstwidth<1) {
00692                 dstwidth=1;
00693         }
00694         if (dstheight<1) {
00695                 dstheight=1;
00696         }
00697 
00698         /* Alloc space to completely contain the zoomed surface */
00699         rz_dst=NULL;
00700         if (is32bit) {
00701                 /* Target surface is 32bit with source RGBA/ABGR ordering */
00702                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 32, rz_src->format->Rmask, rz_src->format->Gmask, rz_src->format->Bmask, rz_src->format->Amask);
00703         } else {
00704                 /* Target surface is 8bit */
00705                 rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth, dstheight, 8, 0, 0, 0, 0);
00706         }
00707 
00708         /* Lock source surface */
00709         SDL_LockSurface(rz_src);
00710         /* Check which kind of surface we have */
00711         if (is32bit) {
00712                 /* Call the 32bit transformation routine to do the zooming (using alpha) */
00713                 zoomSurfaceRGBA(rz_src,rz_dst,smooth);
00714                 /* Turn on source-alpha support */
00715                 SDL_SetAlpha(rz_dst, SDL_SRCALPHA , 255);
00716         } else {
00717                 /* Copy palette and colorkey info */
00718                 for (i=0; i<rz_src->format->palette->ncolors; i++) {
00719                         rz_dst->format->palette->colors[i]=rz_src->format->palette->colors[i];
00720                 }
00721                 rz_dst->format->palette->ncolors=rz_src->format->palette->ncolors;
00722                 /* Call the 8bit transformation routine to do the zooming */
00723                 zoomSurfaceY(rz_src,rz_dst);
00724                 SDL_SetColorKey(rz_dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, rz_src->format->colorkey);
00725         }
00726         /* Unlock source surface */
00727         SDL_UnlockSurface(rz_src);
00728 
00729         /* Cleanup temp surface */
00730         if (src_converted) {
00731                 SDL_FreeSurface(rz_src);
00732         }
00733 
00734         /* Return destination surface */
00735         return(rz_dst);
00736 }
00737 
00738 void PG_Draw::BlitScale(SDL_Surface *src, SDL_Surface *dst, bool smooth) {
00739         SDL_Surface *tmp = ScaleSurface(src,
00740                                         static_cast<double>(dst->w) / src->w,
00741                                         static_cast<double>(dst->h) / src->h,
00742                                         smooth);
00743         SDL_BlitSurface(tmp, 0, dst, 0);
00744         SDL_FreeSurface(tmp);
00745 }
00746 
00747 
00748 /*
00749  * Local Variables:
00750  * c-basic-offset: 8
00751  * End:
00752  */
00753 

Generated on Tue Jun 24 01:27:51 2008 for Advanced Strategic Command by  doxygen 1.4.2