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