Freeciv-3.3
Loading...
Searching...
No Matches
SDL3_rotozoom.c
Go to the documentation of this file.
1/*
2
3SDL2_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
4
5Copyright (C) 2012-2014 Andreas Schiffler
6
7This software is provided 'as-is', without any express or implied
8warranty. In no event will the authors be held liable for any damages
9arising from the use of this software.
10
11Permission is granted to anyone to use this software for any purpose,
12including commercial applications, and to alter it and redistribute it
13freely, subject to the following restrictions:
14
151. The origin of this software must not be misrepresented; you must not
16claim that you wrote the original software. If you use this software
17in a product, an acknowledgment in the product documentation would be
18appreciated but is not required.
19
202. Altered source versions must be plainly marked as such, and must not be
21misrepresented as being the original software.
22
233. This notice may not be removed or altered from any source
24distribution.
25
26Andreas Schiffler -- aschiffler at ferzkopp dot net
27
28
29 ---
30
31 Adopted to freeciv usage as SDL3_rotozoom.c
32
33
34*/
35
36#ifdef WIN32
37#include <windows.h>
38#endif
39
40#include <stdlib.h>
41#include <string.h>
42
43#include "SDL3_rotozoom.h"
44
45/* ---- Internally used structures */
46
56
60typedef struct tColorY {
63
67#define MAX(a,b) (((a) > (b)) ? (a) : (b))
68
79#define GUARD_ROWS (2)
80
84#define VALUE_LIMIT 0.001
85
86
102static int _shrinkSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int factorx, int factory)
103{
104 int x, y, dx, dy, dgap, ra, ga, ba, aa;
105 int n_average;
106 tColorRGBA *sp, *osp, *oosp;
107 tColorRGBA *dp;
108
109 /*
110 * Averaging integer shrink
111 */
112
113 /* Precalculate division factor */
115
116 /*
117 * Scan destination
118 */
119 sp = (tColorRGBA *) src->pixels;
120
121 dp = (tColorRGBA *) dst->pixels;
122 dgap = dst->pitch - dst->w * 4;
123
124 for (y = 0; y < dst->h; y++) {
125
126 osp=sp;
127 for (x = 0; x < dst->w; x++) {
128
129 /* Trace out source box and accumulate */
130 oosp=sp;
131 ra=ga=ba=aa=0;
132 for (dy=0; dy < factory; dy++) {
133 for (dx=0; dx < factorx; dx++) {
134 ra += sp->r;
135 ga += sp->g;
136 ba += sp->b;
137 aa += sp->a;
138
139 sp++;
140 }
141 /* src dx loop */
142 sp = (tColorRGBA *)((Uint8*)sp + (src->pitch - 4*factorx)); // next y
143 }
144 /* src dy loop */
145
146 /* next box-x */
147 sp = (tColorRGBA *)((Uint8*)oosp + 4*factorx);
148
149 /* Store result in destination */
150 dp->r = ra/n_average;
151 dp->g = ga/n_average;
152 dp->b = ba/n_average;
153 dp->a = aa/n_average;
154
155 /*
156 * Advance destination pointer
157 */
158 dp++;
159 }
160 /* dst x loop */
161
162 /* next box-y */
163 sp = (tColorRGBA *)((Uint8*)osp + src->pitch*factory);
164
165 /*
166 * Advance destination pointers
167 */
168 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
169 }
170 /* dst y loop */
171
172 return (0);
173}
174
190static int _zoomSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int flipx, int flipy, int smooth)
191{
192 int x, y, sx, sy, ssx, ssy, *sax, *say, *csax, *csay, *salast, csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
193 tColorRGBA *c00, *c01, *c10, *c11;
194 tColorRGBA *sp, *csp, *dp;
195 int spixelgap, spixelw, spixelh, dgap, t1, t2;
196
197 /*
198 * Allocate memory for row/column increments
199 */
200 if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
201 return (-1);
202 }
203 if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
204 free(sax);
205 return (-1);
206 }
207
208 /*
209 * Precalculate row increments
210 */
211 spixelw = (src->w - 1);
212 spixelh = (src->h - 1);
213 if (smooth) {
214 sx = (int) (65536.0 * (float) spixelw / (float) (dst->w - 1));
215 sy = (int) (65536.0 * (float) spixelh / (float) (dst->h - 1));
216 } else {
217 sx = (int) (65536.0 * (float) (src->w) / (float) (dst->w));
218 sy = (int) (65536.0 * (float) (src->h) / (float) (dst->h));
219 }
220
221 /* Maximum scaled source size */
222 ssx = (src->w << 16) - 1;
223 ssy = (src->h << 16) - 1;
224
225 /* Precalculate horizontal row increments */
226 csx = 0;
227 csax = sax;
228 for (x = 0; x <= dst->w; x++) {
229 *csax = csx;
230 csax++;
231 csx += sx;
232
233 /* Guard from overflows */
234 if (csx > ssx) {
235 csx = ssx;
236 }
237 }
238
239 /* Precalculate vertical row increments */
240 csy = 0;
241 csay = say;
242 for (y = 0; y <= dst->h; y++) {
243 *csay = csy;
244 csay++;
245 csy += sy;
246
247 /* Guard from overflows */
248 if (csy > ssy) {
249 csy = ssy;
250 }
251 }
252
253 sp = (tColorRGBA *) src->pixels;
254 dp = (tColorRGBA *) dst->pixels;
255 dgap = dst->pitch - dst->w * 4;
256 spixelgap = src->pitch/4;
257
258 if (flipx) sp += spixelw;
259 if (flipy) sp += (spixelgap * spixelh);
260
261 /*
262 * Switch between interpolating and non-interpolating code
263 */
264 if (smooth) {
265
266 /*
267 * Interpolating Zoom
268 */
269 csay = say;
270 for (y = 0; y < dst->h; y++) {
271 csp = sp;
272 csax = sax;
273 for (x = 0; x < dst->w; x++) {
274 /*
275 * Setup color source pointers
276 */
277 ex = (*csax & 0xffff);
278 ey = (*csay & 0xffff);
279 cx = (*csax >> 16);
280 cy = (*csay >> 16);
281 sstepx = cx < spixelw;
282 sstepy = cy < spixelh;
283 c00 = sp;
284 c01 = sp;
285 c10 = sp;
286 if (sstepy) {
287 if (flipy) {
288 c10 -= spixelgap;
289 } else {
290 c10 += spixelgap;
291 }
292 }
293 c11 = c10;
294 if (sstepx) {
295 if (flipx) {
296 c01--;
297 c11--;
298 } else {
299 c01++;
300 c11++;
301 }
302 }
303
304 /*
305 * Draw and interpolate colors
306 */
307 t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
308 t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
309 dp->r = (((t2 - t1) * ey) >> 16) + t1;
310 t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
311 t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
312 dp->g = (((t2 - t1) * ey) >> 16) + t1;
313 t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
314 t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
315 dp->b = (((t2 - t1) * ey) >> 16) + t1;
316 t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
317 t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
318 dp->a = (((t2 - t1) * ey) >> 16) + t1;
319 /*
320 * Advance source pointer x
321 */
322 salast = csax;
323 csax++;
324 sstep = (*csax >> 16) - (*salast >> 16);
325 if (flipx) {
326 sp -= sstep;
327 } else {
328 sp += sstep;
329 }
330
331 /*
332 * Advance destination pointer x
333 */
334 dp++;
335 }
336 /*
337 * Advance source pointer y
338 */
339 salast = csay;
340 csay++;
341 sstep = (*csay >> 16) - (*salast >> 16);
342 sstep *= spixelgap;
343 if (flipy) {
344 sp = csp - sstep;
345 } else {
346 sp = csp + sstep;
347 }
348
349 /*
350 * Advance destination pointer y
351 */
352 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
353 }
354 } else {
355 /*
356 * Non-Interpolating Zoom
357 */
358 csay = say;
359 for (y = 0; y < dst->h; y++) {
360 csp = sp;
361 csax = sax;
362 for (x = 0; x < dst->w; x++) {
363 /*
364 * Draw
365 */
366 *dp = *sp;
367
368 /*
369 * Advance source pointer x
370 */
371 salast = csax;
372 csax++;
373 sstep = (*csax >> 16) - (*salast >> 16);
374 if (flipx) sstep = -sstep;
375 sp += sstep;
376
377 /*
378 * Advance destination pointer x
379 */
380 dp++;
381 }
382 /*
383 * Advance source pointer y
384 */
385 salast = csay;
386 csay++;
387 sstep = (*csay >> 16) - (*salast >> 16);
388 sstep *= spixelgap;
389 if (flipy) sstep = -sstep;
390 sp = csp + sstep;
391
392 /*
393 * Advance destination pointer y
394 */
395 dp = (tColorRGBA *) ((Uint8 *) dp + dgap);
396 }
397 }
398
399 /*
400 * Remove temp arrays
401 */
402 free(sax);
403 free(say);
404
405 return (0);
406}
407
427static void _transformSurfaceRGBA(SDL_Surface * src, SDL_Surface * dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
428{
429 int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
431 tColorRGBA *pc, *sp;
432 int gap;
433
434 /*
435 * Variable setup
436 */
437 xd = ((src->w - dst->w) << 15);
438 yd = ((src->h - dst->h) << 15);
439 ax = (cx << 16) - (icos * cx);
440 ay = (cy << 16) - (isin * cx);
441 sw = src->w - 1;
442 sh = src->h - 1;
443 pc = (tColorRGBA*) dst->pixels;
444 gap = dst->pitch - dst->w * 4;
445
446 /*
447 * Switch between interpolating and non-interpolating code
448 */
449 if (smooth) {
450 for (y = 0; y < dst->h; y++) {
451 dy = cy - y;
452 sdx = (ax + (isin * dy)) + xd;
453 sdy = (ay - (icos * dy)) + yd;
454 for (x = 0; x < dst->w; x++) {
455 dx = (sdx >> 16);
456 dy = (sdy >> 16);
457 if (flipx) dx = sw - dx;
458 if (flipy) dy = sh - dy;
459 if ((dx > -1) && (dy > -1) && (dx < (src->w-1)) && (dy < (src->h-1))) {
460 sp = (tColorRGBA *)src->pixels;;
461 sp += ((src->pitch/4) * dy);
462 sp += dx;
463 c00 = *sp;
464 sp += 1;
465 c01 = *sp;
466 sp += (src->pitch/4);
467 c11 = *sp;
468 sp -= 1;
469 c10 = *sp;
470 if (flipx) {
471 cswap = c00; c00=c01; c01=cswap;
472 cswap = c10; c10=c11; c11=cswap;
473 }
474 if (flipy) {
475 cswap = c00; c00=c10; c10=cswap;
476 cswap = c01; c01=c11; c11=cswap;
477 }
478 /*
479 * Interpolate colors
480 */
481 ex = (sdx & 0xffff);
482 ey = (sdy & 0xffff);
483 t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
484 t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
485 pc->r = (((t2 - t1) * ey) >> 16) + t1;
486 t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
487 t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
488 pc->g = (((t2 - t1) * ey) >> 16) + t1;
489 t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
490 t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
491 pc->b = (((t2 - t1) * ey) >> 16) + t1;
492 t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
493 t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
494 pc->a = (((t2 - t1) * ey) >> 16) + t1;
495 }
496 sdx += icos;
497 sdy += isin;
498 pc++;
499 }
500 pc = (tColorRGBA *) ((Uint8 *) pc + gap);
501 }
502 } else {
503 for (y = 0; y < dst->h; y++) {
504 dy = cy - y;
505 sdx = (ax + (isin * dy)) + xd;
506 sdy = (ay - (icos * dy)) + yd;
507 for (x = 0; x < dst->w; x++) {
508 dx = (short) (sdx >> 16);
509 dy = (short) (sdy >> 16);
510 if (flipx) dx = (src->w-1)-dx;
511 if (flipy) dy = (src->h-1)-dy;
512 if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h)) {
513 sp = (tColorRGBA *) ((Uint8 *) src->pixels + src->pitch * dy);
514 sp += dx;
515 *pc = *sp;
516 }
517 sdx += icos;
518 sdy += isin;
519 pc++;
520 }
521 pc = (tColorRGBA *) ((Uint8 *) pc + gap);
522 }
523 }
524}
525
540{
541 int row, col, newWidth, newHeight;
542 int bpp, bpr;
543 SDL_Surface* dst;
544 Uint8* srcBuf;
545 Uint8* dstBuf;
548
549 /* Has to be a valid surface pointer and be a Nbit surface where n is divisible by 8 */
550 if (!src) {
551 SDL_SetError("NULL source surface or source surface format");
552 return NULL;
553 }
554
555 details = SDL_GetPixelFormatDetails(src->format);
556
557 if ((details->bits_per_pixel % 8) != 0) {
558 SDL_SetError("Invalid source surface bit depth");
559 return NULL;
560 }
561
562 /* normalize numClockwiseTurns */
564 if (normalizedClockwiseTurns < 0) {
566 }
567
568 /* If turns are even, our new width/height will be the same as the source surface */
569 if (normalizedClockwiseTurns % 2) {
570 newWidth = src->h;
571 newHeight = src->w;
572 } else {
573 newWidth = src->w;
574 newHeight = src->h;
575 }
576
578 if(!dst) {
579 SDL_SetError("Could not create destination surface");
580 return NULL;
581 }
582
583 if (SDL_MUSTLOCK(src)) {
584 SDL_LockSurface(src);
585 }
586 if (SDL_MUSTLOCK(dst)) {
587 SDL_LockSurface(dst);
588 }
589
590 /* Calculate byte-per-pixel */
591 bpp = details->bits_per_pixel / 8;
592
594 case 0: /* Make a copy of the surface */
595 {
596 /* Unfortunately SDL_BlitSurface cannot be used to make a copy of the surface
597 since it does not preserve alpha. */
598
599 if (src->pitch == dst->pitch) {
600 /* If the pitch is the same for both surfaces, the memory can be copied all at once. */
601 memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
602 }
603 else
604 {
605 /* If the pitch differs, copy each row separately */
606 srcBuf = (Uint8*)(src->pixels);
607 dstBuf = (Uint8*)(dst->pixels);
608 bpr = src->w * bpp;
609 for (row = 0; row < src->h; row++) {
611 srcBuf += src->pitch;
612 dstBuf += dst->pitch;
613 }
614 }
615 }
616 break;
617
618 /* rotate clockwise */
619 case 1: /* rotated 90 degrees clockwise */
620 {
621 for (row = 0; row < src->h; ++row) {
622 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
623 dstBuf = (Uint8*)(dst->pixels) + (dst->w - row - 1) * bpp;
624 for (col = 0; col < src->w; ++col) {
626 srcBuf += bpp;
627 dstBuf += dst->pitch;
628 }
629 }
630 }
631 break;
632
633 case 2: /* rotated 180 degrees clockwise */
634 {
635 for (row = 0; row < src->h; ++row) {
636 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
637 dstBuf = (Uint8*)(dst->pixels) + ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
638 for (col = 0; col < src->w; ++col) {
640 srcBuf += bpp;
641 dstBuf -= bpp;
642 }
643 }
644 }
645 break;
646
647 case 3: /* rotated 270 degrees clockwise */
648 {
649 for (row = 0; row < src->h; ++row) {
650 srcBuf = (Uint8*)(src->pixels) + (row * src->pitch);
651 dstBuf = (Uint8*)(dst->pixels) + (row * bpp) + ((dst->h - 1) * dst->pitch);
652 for (col = 0; col < src->w; ++col) {
654 srcBuf += bpp;
655 dstBuf -= dst->pitch;
656 }
657 }
658 }
659 break;
660 }
661 /* end switch */
662
663 if (SDL_MUSTLOCK(src)) {
665 }
666 if (SDL_MUSTLOCK(dst)) {
668 }
669
670 return dst;
671}
672
673
688static void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy,
689 int *dstwidth, int *dstheight,
690 double *canglezoom, double *sanglezoom)
691{
692 double x, y, cx, cy, sx, sy;
693 double radangle;
695
696 /*
697 * Determine destination width and height by rotating a centered source box
698 */
699 radangle = angle * (M_PI / 180.0);
702 *sanglezoom *= zoomx;
703 *canglezoom *= zoomy;
704 x = (double)(width / 2);
705 y = (double)(height / 2);
706 cx = *canglezoom * x;
707 cy = *canglezoom * y;
708 sx = *sanglezoom * x;
709 sy = *sanglezoom * y;
710
711 dstwidthhalf = MAX((int)
712 ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)), fabs(-cx + sy)), fabs(-cx - sy))), 1);
713 dstheighthalf = MAX((int)
714 ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)), fabs(-sx + cy)), fabs(-sx - cy))), 1);
715 *dstwidth = 2 * dstwidthhalf;
717}
718
736
753
769SDL_Surface *rotozoomSurface(SDL_Surface * src, double angle, double zoom, int smooth)
770{
771 return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
772}
773
790SDL_Surface *rotozoomSurfaceXY(SDL_Surface * src, double angle, double zoomx, double zoomy, int smooth)
791{
794 double zoominv;
797 int src_converted;
798 int flipx,flipy;
800
801 /*
802 * Sanity check
803 */
804 if (src == NULL) {
805 return (NULL);
806 }
807
808 details = SDL_GetPixelFormatDetails(src->format);
809
810 /*
811 * Determine if source surface is 32bit or 8bit
812 */
813 if ((details->bits_per_pixel == 32)
814 || (details->bits_per_pixel == 8)) {
815 /*
816 * Use source surface 'as is'
817 */
818 rz_src = src;
819 src_converted = 0;
820 } else {
821 /*
822 * New source surface is 32bit with a defined RGBA ordering
823 */
824 rz_src =
826
828
829 src_converted = 1;
830 }
831
832 /*
833 * Sanity check zoom factor
834 */
835 flipx = (zoomx<0.0);
836 if (flipx) zoomx=-zoomx;
837 flipy = (zoomy<0.0);
838 if (flipy) zoomy=-zoomy;
841 zoominv = 65536.0 / (zoomx * zoomx);
842
843 /*
844 * Check if we have a rotozoom or just a zoom
845 */
846 if (fabs(angle) > VALUE_LIMIT) {
847
848 /*
849 * Angle!=0: full rotozoom
850 */
851 /*
852 * -----------------------
853 */
854
855 /* Determine target size */
857
858 /*
859 * Calculate target factors from sin/cos and zoom
860 */
865
866 /* Calculate half size */
869
870 /*
871 * Alloc space to completely contain the rotated surface
872 */
873 rz_dst = NULL;
874
875 /*
876 * Target surface is 32bit with source RGBA/ABGR ordering
877 */
878 rz_dst =
880 rz_src->format);
881
882 /* Check target */
883 if (rz_dst == NULL)
884 return NULL;
885
886 /* Adjust for guard rows */
887 rz_dst->h = dstheight;
888
889 /*
890 * Lock source surface
891 */
892 if (SDL_MUSTLOCK(rz_src)) {
894 }
895
896 /*
897 * Check which kind of surface we have
898 */
899
900 /*
901 * Call the 32bit transformation routine to do the rotation (using alpha)
902 */
904 (int) (sanglezoominv), (int) (canglezoominv),
905 flipx, flipy,
906 smooth);
907
908 /*
909 * Unlock source surface
910 */
911 if (SDL_MUSTLOCK(rz_src)) {
913 }
914
915 } else {
916
917 /*
918 * Angle=0: Just a zoom
919 */
920 /*
921 * --------------------
922 */
923
924 /*
925 * Calculate target size
926 */
928
929 /*
930 * Alloc space to completely contain the zoomed surface
931 */
932 rz_dst = NULL;
933
934 /*
935 * Target surface is 32bit with source RGBA/ABGR ordering
936 */
937 rz_dst =
939 rz_src->format);
940
941 /* Check target */
942 if (rz_dst == NULL)
943 return NULL;
944
945 /* Adjust for guard rows */
946 rz_dst->h = dstheight;
947
948 /*
949 * Lock source surface
950 */
951 if (SDL_MUSTLOCK(rz_src)) {
953 }
954
955 /*
956 * Check which kind of surface we have
957 */
958
959 /*
960 * Call the 32bit transformation routine to do the zooming (using alpha)
961 */
963
964 /*
965 * Unlock source surface
966 */
967 if (SDL_MUSTLOCK(rz_src)) {
969 }
970 }
971
972 /*
973 * Cleanup temp surface
974 */
975 if (src_converted) {
977 }
978
979 /*
980 * Return destination surface
981 */
982 return (rz_dst);
983}
984
997void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
998{
999 /*
1000 * Make zoom factors positive
1001 */
1002 int flipx, flipy;
1003 flipx = (zoomx<0.0);
1004 if (flipx) zoomx = -zoomx;
1005 flipy = (zoomy<0.0);
1006 if (flipy) zoomy = -zoomy;
1007
1008 /*
1009 * Sanity check zoom factors
1010 */
1011 if (zoomx < VALUE_LIMIT) {
1013 }
1014 if (zoomy < VALUE_LIMIT) {
1016 }
1017
1018 /*
1019 * Calculate target size
1020 */
1021 *dstwidth = (int) floor(((double) width * zoomx) + 0.5);
1022 *dstheight = (int) floor(((double) height * zoomy) + 0.5);
1023 if (*dstwidth < 1) {
1024 *dstwidth = 1;
1025 }
1026 if (*dstheight < 1) {
1027 *dstheight = 1;
1028 }
1029}
1030
1048{
1051 int dstwidth, dstheight;
1052 int src_converted;
1053 int flipx, flipy;
1055
1056 /*
1057 * Sanity check
1058 */
1059 if (src == NULL)
1060 return (NULL);
1061
1062 details = SDL_GetPixelFormatDetails(src->format);
1063
1064 /*
1065 * Determine if source surface is 32bit or 8bit
1066 */
1067 if ((details->bits_per_pixel == 32)
1068 || (details->bits_per_pixel == 8)) {
1069 /*
1070 * Use source surface 'as is'
1071 */
1072 rz_src = src;
1073 src_converted = 0;
1074 } else {
1075 /*
1076 * New source surface is 32bit with a defined RGBA ordering
1077 */
1078 rz_src =
1079 SDL_CreateSurface(src->w, src->h,
1081 if (rz_src == NULL) {
1082 return NULL;
1083 }
1085 src_converted = 1;
1086 }
1087
1088 flipx = (zoomx<0.0);
1089 if (flipx) zoomx = -zoomx;
1090 flipy = (zoomy<0.0);
1091 if (flipy) zoomy = -zoomy;
1092
1093 /* Get size if target */
1095
1096 /*
1097 * Alloc space to completely contain the zoomed surface
1098 */
1099 rz_dst = NULL;
1100
1101 /*
1102 * Target surface is 32bit with source RGBA/ABGR ordering
1103 */
1104 rz_dst =
1106 rz_src->format);
1107
1108 /* Check target */
1109 if (rz_dst == NULL) {
1110 /*
1111 * Cleanup temp surface
1112 */
1113 if (src_converted) {
1115 }
1116 return NULL;
1117 }
1118
1119 /* Adjust for guard rows */
1120 rz_dst->h = dstheight;
1121
1122 /*
1123 * Lock source surface
1124 */
1125 if (SDL_MUSTLOCK(rz_src)) {
1127 }
1128
1129 /*
1130 * Check which kind of surface we have
1131 */
1132
1133 /*
1134 * Call the 32bit transformation routine to do the zooming (using alpha)
1135 */
1137
1138 /*
1139 * Unlock source surface
1140 */
1141 if (SDL_MUSTLOCK(rz_src)) {
1143 }
1144
1145 /*
1146 * Cleanup temp surface
1147 */
1148 if (src_converted) {
1150 }
1151
1152 /*
1153 * Return destination surface
1154 */
1155 return (rz_dst);
1156}
1157
1174/*@null@*/
1176{
1177 int result;
1180 int dstwidth, dstheight;
1181 int src_converted;
1182 int haveError = 0;
1184
1185 /*
1186 * Sanity check
1187 */
1188 if (src == NULL) {
1189 return (NULL);
1190 }
1191
1192 details = SDL_GetPixelFormatDetails(src->format);
1193
1194 /*
1195 * Determine if source surface is 32bit or 8bit
1196 */
1197 if ((details->bits_per_pixel == 32)
1198 || (details->bits_per_pixel == 8)) {
1199 /*
1200 * Use source surface 'as is'
1201 */
1202 rz_src = src;
1203 src_converted = 0;
1204 } else {
1205 /*
1206 * New source surface is 32bit with a defined RGBA ordering
1207 */
1208 rz_src = SDL_CreateSurface(src->w, src->h,
1210 if (rz_src==NULL) {
1211 haveError = 1;
1212 goto exitShrinkSurface;
1213 }
1214
1216 src_converted = 1;
1217 }
1218
1219 /*
1220 * Lock the surface
1221 */
1222 if (SDL_MUSTLOCK(rz_src)) {
1223 if (!SDL_LockSurface(rz_src)) {
1224 haveError = 1;
1225 goto exitShrinkSurface;
1226 }
1227 }
1228
1229 /* Get size for target */
1231 while (dstwidth*factorx>rz_src->w) { dstwidth--; }
1233 while (dstheight*factory>rz_src->h) { dstheight--; }
1234
1235 /*
1236 * Alloc space to completely contain the shrunken surface
1237 * (with added guard rows)
1238 */
1239
1240 /*
1241 * Target surface is 32bit with source RGBA/ABGR ordering
1242 */
1243 rz_dst =
1245 rz_src->format);
1246
1247 /* Check target */
1248 if (rz_dst == NULL) {
1249 haveError = 1;
1250 goto exitShrinkSurface;
1251 }
1252
1253 /* Adjust for guard rows */
1254 rz_dst->h = dstheight;
1255
1256 /*
1257 * Check which kind of surface we have
1258 */
1259
1260 /*
1261 * Call the 32bit transformation routine to do the shrinking (using alpha)
1262 */
1264 if ((result!=0) || (rz_dst==NULL)) {
1265 haveError = 1;
1266 goto exitShrinkSurface;
1267 }
1268
1270 if (rz_src!=NULL) {
1271 /*
1272 * Unlock source surface
1273 */
1274 if (SDL_MUSTLOCK(rz_src)) {
1276 }
1277
1278 /*
1279 * Cleanup temp surface
1280 */
1281 if (src_converted==1) {
1283 }
1284 }
1285
1286 /* Check error state; maybe need to cleanup destination */
1287 if (haveError==1) {
1288 if (rz_dst!=NULL) {
1290 }
1291 rz_dst=NULL;
1292 }
1293
1294 /*
1295 * Return destination surface
1296 */
1297 return (rz_dst);
1298}
SDL_Surface * rotozoomSurfaceXY(SDL_Surface *src, double angle, double zoomx, double zoomy, int smooth)
Rotates and zooms a surface with different horizontal and vertival scaling factors and optional anti-...
#define GUARD_ROWS
Number of guard rows added to destination surfaces.
static void _transformSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int cx, int cy, int isin, int icos, int flipx, int flipy, int smooth)
Internal 32 bit rotozoomer with optional anti-aliasing.
static int _zoomSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int flipx, int flipy, int smooth)
Internal 32 bit Zoomer with optional anti-aliasing by bilinear interpolation.
SDL_Surface * rotozoomSurface(SDL_Surface *src, double angle, double zoom, int smooth)
Rotates and zooms a surface and optional anti-aliasing.
static int _shrinkSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 32 bit integer-factor averaging Shrinker.
SDL_Surface * rotateSurface90Degrees(SDL_Surface *src, int numClockwiseTurns)
Rotates a 8/16/24/32 bit surface in increments of 90 degrees.
SDL_Surface * zoomSurface(SDL_Surface *src, double zoomx, double zoomy, int smooth)
Zoom a surface by independent horizontal and vertical factors with optional smoothing.
SDL_Surface * shrinkSurface(SDL_Surface *src, int factorx, int factory)
Shrink a surface by an integer ratio using averaging.
void zoomSurfaceSize(int width, int height, double zoomx, double zoomy, int *dstwidth, int *dstheight)
Calculates the size of the target surface for a zoomSurface() call.
void rotozoomSurfaceSize(int width, int height, double angle, double zoom, int *dstwidth, int *dstheight)
Returns the size of the resulting target surface for a rotozoomSurface() call.
#define VALUE_LIMIT
Lower limit of absolute zoom factor or rotation degrees.
static void _rotozoomSurfaceSizeTrig(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight, double *canglezoom, double *sanglezoom)
Internal target surface sizing function for rotozooms with trig result return.
void rotozoomSurfaceSizeXY(int width, int height, double angle, double zoomx, double zoomy, int *dstwidth, int *dstheight)
Returns the size of the resulting target surface for a rotozoomSurfaceXY() call.
#define MAX(a, b)
Returns maximum of two numbers a and b.
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
char * incite_cost
Definition comments.c:76
#define M_PI
Definition plrdlg.c:53
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
A 32 bit RGBA pixel.
A 8bit Y/palette pixel.