ManaPlus
SDL2_rotozoom.cpp
Go to the documentation of this file.
1 /*
2 
3 SDL2_rotozoom.c: rotozoomer, zoomer and shrinker for 32bit or 8bit surfaces
4 
5 Copyright (C) 2012-2014 Andreas Schiffler
6 
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any damages
9 arising from the use of this software.
10 
11 Permission is granted to anyone to use this software for any purpose,
12 including commercial applications, and to alter it and redistribute it
13 freely, subject to the following restrictions:
14 
15 1. The origin of this software must not be misrepresented; you must not
16 claim that you wrote the original software. If you use this software
17 in a product, an acknowledgment in the product documentation would be
18 appreciated but is not required.
19 
20 2. Altered source versions must be plainly marked as such, and must not be
21 misrepresented as being the original software.
22 
23 3. This notice may not be removed or altered from any source
24 distribution.
25 
26 Andreas Schiffler -- aschiffler at ferzkopp dot net
27 
28 Changed for ManaPlus (C) 2013-2017 ManaPlus developers
29 
30 */
31 
32 #ifdef WIN32
33 #include <windows.h>
34 #endif
35 
36 #include <stdlib.h>
37 #include <string.h>
38 
39 #include "sdl2gfx/SDL2_rotozoom.h"
40 
41 #include "debug.h"
42 
43 /* ---- Internally used structures */
44 
48 typedef struct tColorRGBA
49 {
50  Uint8 r;
51  Uint8 g;
52  Uint8 b;
53  Uint8 a;
55 
59 typedef struct tColorY
60 {
61  Uint8 y;
63 
67 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
68 
79 #define GUARD_ROWS (2)
80 
84 #define VALUE_LIMIT 0.001
85 
89 static Uint32 _colorkey(SDL_Surface *src)
90 {
91  Uint32 key = 0;
92  SDL_GetColorKey(src, &key);
93  return key;
94 }
95 
96 
112 static int _shrinkSurfaceRGBA(SDL_Surface *src,
113  SDL_Surface *dst,
114  int factorx,
115  int factory)
116 {
117  int x, y, dx, dy, dgap, ra, ga, ba, aa;
118  int n_average;
119  tColorRGBA *sp, *osp, *oosp;
120  tColorRGBA *dp;
121 
122  /*
123  * Averaging integer shrink
124  */
125 
126  /* Precalculate division factor */
127  n_average = factorx*factory;
128 
129  /*
130  * Scan destination
131  */
132  sp = static_cast<tColorRGBA *>(src->pixels);
133 
134  dp = static_cast<tColorRGBA *>(dst->pixels);
135  dgap = dst->pitch - dst->w * 4;
136 
137  for (y = 0; y < dst->h; y++)
138  {
139  osp=sp;
140  for (x = 0; x < dst->w; x++)
141  {
142  /* Trace out source box and accumulate */
143  oosp=sp;
144  ra=ga=ba=aa=0;
145  for (dy=0; dy < factory; dy++)
146  {
147  for (dx=0; dx < factorx; dx++)
148  {
149  ra += sp->r;
150  ga += sp->g;
151  ba += sp->b;
152  aa += sp->a;
153 
154  sp++;
155  }
156  /* src dx loop */
157  sp = reinterpret_cast<tColorRGBA *>(
158  reinterpret_cast<Uint8*>(sp) +
159  (src->pitch - 4*factorx)); // next y
160  }
161  /* src dy loop */
162 
163  /* next box-x */
164  sp = reinterpret_cast<tColorRGBA *>(
165  reinterpret_cast<Uint8*>(oosp) + 4*factorx);
166 
167  /* Store result in destination */
168  dp->r = ra/n_average;
169  dp->g = ga/n_average;
170  dp->b = ba/n_average;
171  dp->a = aa/n_average;
172 
173  /*
174  * Advance destination pointer
175  */
176  dp++;
177  }
178  /* dst x loop */
179 
180  /* next box-y */
181  sp = reinterpret_cast<tColorRGBA *>(reinterpret_cast<Uint8*>(osp) +
182  src->pitch*factory);
183 
184  /*
185  * Advance destination pointers
186  */
187  dp = reinterpret_cast<tColorRGBA *>(reinterpret_cast<Uint8*>(dp) +
188  dgap);
189  }
190  /* dst y loop */
191 
192  return (0);
193 }
194 
210 static int _shrinkSurfaceY(SDL_Surface *src,
211  SDL_Surface *dst,
212  int factorx,
213  int factory)
214 {
215  int x, y, dx, dy, dgap, a;
216  int n_average;
217  Uint8 *sp, *osp, *oosp;
218  Uint8 *dp;
219 
220  /*
221  * Averaging integer shrink
222  */
223 
224  /* Precalculate division factor */
225  n_average = factorx*factory;
226 
227  /*
228  * Scan destination
229  */
230  sp = static_cast<Uint8*>(src->pixels);
231 
232  dp = static_cast<Uint8*>(dst->pixels);
233  dgap = dst->pitch - dst->w;
234 
235  for (y = 0; y < dst->h; y++)
236  {
237  osp=sp;
238  for (x = 0; x < dst->w; x++)
239  {
240  /* Trace out source box and accumulate */
241  oosp=sp;
242  a=0;
243  for (dy=0; dy < factory; dy++)
244  {
245  for (dx=0; dx < factorx; dx++)
246  {
247  a += (*sp);
248  /* next x */
249  sp++;
250  }
251  /* end src dx loop */
252  /* next y */
253  sp = static_cast<Uint8*>(static_cast<Uint8*>(sp) +
254  (src->pitch - factorx));
255  }
256  /* end src dy loop */
257 
258  /* next box-x */
259  sp = static_cast<Uint8*>(static_cast<Uint8*>(oosp) + factorx);
260 
261  /* Store result in destination */
262  *dp = a/n_average;
263 
264  /*
265  * Advance destination pointer
266  */
267  dp++;
268  }
269  /* end dst x loop */
270 
271  /* next box-y */
272  sp = static_cast<Uint8*>(static_cast<Uint8*>(osp) +
273  src->pitch*factory);
274 
275  /*
276  * Advance destination pointers
277  */
278  dp = static_cast<Uint8*>(static_cast<Uint8*>(dp) + dgap);
279  }
280  /* end dst y loop */
281 
282  return (0);
283 }
284 
300 static int _zoomSurfaceRGBA(SDL_Surface *src,
301  SDL_Surface *dst,
302  int flipx,
303  int flipy,
304  int smooth)
305 {
306  int x, y, sx, sy, ssx, ssy;
307  int *sax, *say, *csax, *csay, *salast;
308  int csx, csy, ex, ey, cx, cy, sstep, sstepx, sstepy;
309  tColorRGBA *c00, *c01, *c10, *c11;
310  tColorRGBA *sp, *csp, *dp;
311  int spixelgap, spixelw, spixelh, dgap, t1, t2;
312 
313  /*
314  * Allocate memory for row/column increments
315  */
316  if ((sax = static_cast<int *>(malloc((dst->w + 1) * sizeof(Uint32)))) == nullptr)
317  {
318  return (-1);
319  }
320  if ((say = static_cast<int *>(malloc((dst->h + 1) * sizeof(Uint32)))) == nullptr)
321  {
322  free(sax);
323  return (-1);
324  }
325 
326  /*
327  * Precalculate row increments
328  */
329  spixelw = (src->w - 1);
330  spixelh = (src->h - 1);
331  if (smooth)
332  {
333  sx = static_cast<int>(65536.0 * static_cast<float>(spixelw) /
334  static_cast<float>(dst->w - 1));
335  sy = static_cast<int>(65536.0 * static_cast<float>(spixelh) /
336  static_cast<float>(dst->h - 1));
337  }
338  else
339  {
340  sx = static_cast<int>(65536.0 * static_cast<float>(src->w) /
341  static_cast<float>(dst->w));
342  sy = static_cast<int>(65536.0 * static_cast<float>(src->h) /
343  static_cast<float>(dst->h));
344  }
345 
346  /* Maximum scaled source size */
347  ssx = (src->w << 16) - 1;
348  ssy = (src->h << 16) - 1;
349 
350  /* Precalculate horizontal row increments */
351  csx = 0;
352  csax = sax;
353  for (x = 0; x <= dst->w; x++)
354  {
355  *csax = csx;
356  csax++;
357  csx += sx;
358 
359  /* Guard from overflows */
360  if (csx > ssx)
361  {
362  csx = ssx;
363  }
364  }
365 
366  /* Precalculate vertical row increments */
367  csy = 0;
368  csay = say;
369  for (y = 0; y <= dst->h; y++)
370  {
371  *csay = csy;
372  csay++;
373  csy += sy;
374 
375  /* Guard from overflows */
376  if (csy > ssy)
377  {
378  csy = ssy;
379  }
380  }
381 
382  sp = static_cast<tColorRGBA *>(src->pixels);
383  dp = static_cast<tColorRGBA *>(dst->pixels);
384  dgap = dst->pitch - dst->w * 4;
385  spixelgap = src->pitch/4;
386 
387  if (flipx) sp += spixelw;
388  if (flipy) sp += (spixelgap * spixelh);
389 
390  /*
391  * Switch between interpolating and non-interpolating code
392  */
393  if (smooth)
394  {
395  /*
396  * Interpolating Zoom
397  */
398  csay = say;
399  for (y = 0; y < dst->h; y++)
400  {
401  csp = sp;
402  csax = sax;
403  for (x = 0; x < dst->w; x++)
404  {
405  /*
406  * Setup color source pointers
407  */
408  ex = (*csax & 0xffff);
409  ey = (*csay & 0xffff);
410  cx = (*csax >> 16);
411  cy = (*csay >> 16);
412  sstepx = cx < spixelw;
413  sstepy = cy < spixelh;
414  c00 = sp;
415  c01 = sp;
416  c10 = sp;
417  if (sstepy)
418  {
419  if (flipy)
420  {
421  c10 -= spixelgap;
422  }
423  else
424  {
425  c10 += spixelgap;
426  }
427  }
428  c11 = c10;
429  if (sstepx)
430  {
431  if (flipx)
432  {
433  c01--;
434  c11--;
435  }
436  else
437  {
438  c01++;
439  c11++;
440  }
441  }
442 
443  /*
444  * Draw and interpolate colors
445  */
446  t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff;
447  t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff;
448  dp->r = (((t2 - t1) * ey) >> 16) + t1;
449  t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff;
450  t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff;
451  dp->g = (((t2 - t1) * ey) >> 16) + t1;
452  t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff;
453  t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff;
454  dp->b = (((t2 - t1) * ey) >> 16) + t1;
455  t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff;
456  t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff;
457  dp->a = (((t2 - t1) * ey) >> 16) + t1;
458  /*
459  * Advance source pointer x
460  */
461  salast = csax;
462  csax++;
463  sstep = (*csax >> 16) - (*salast >> 16);
464  if (flipx)
465  {
466  sp -= sstep;
467  }
468  else
469  {
470  sp += sstep;
471  }
472 
473  /*
474  * Advance destination pointer x
475  */
476  dp++;
477  }
478  /*
479  * Advance source pointer y
480  */
481  salast = csay;
482  csay++;
483  sstep = (*csay >> 16) - (*salast >> 16);
484  sstep *= spixelgap;
485  if (flipy)
486  {
487  sp = csp - sstep;
488  }
489  else
490  {
491  sp = csp + sstep;
492  }
493 
494  /*
495  * Advance destination pointer y
496  */
497  dp = reinterpret_cast<tColorRGBA *>(
498  reinterpret_cast<Uint8*>(dp) + dgap);
499  }
500  }
501  else
502  {
503  /*
504  * Non-Interpolating Zoom
505  */
506  csay = say;
507  for (y = 0; y < dst->h; y++)
508  {
509  csp = sp;
510  csax = sax;
511  for (x = 0; x < dst->w; x++)
512  {
513  /*
514  * Draw
515  */
516  *dp = *sp;
517 
518  /*
519  * Advance source pointer x
520  */
521  salast = csax;
522  csax++;
523  sstep = (*csax >> 16) - (*salast >> 16);
524  if (flipx) sstep = -sstep;
525  sp += sstep;
526 
527  /*
528  * Advance destination pointer x
529  */
530  dp++;
531  }
532  /*
533  * Advance source pointer y
534  */
535  salast = csay;
536  csay++;
537  sstep = (*csay >> 16) - (*salast >> 16);
538  sstep *= spixelgap;
539  if (flipy) sstep = -sstep;
540  sp = csp + sstep;
541 
542  /*
543  * Advance destination pointer y
544  */
545  dp = reinterpret_cast<tColorRGBA *>(
546  reinterpret_cast<Uint8*>(dp) + dgap);
547  }
548  }
549 
550  /*
551  * Remove temp arrays
552  */
553  free(sax);
554  free(say);
555 
556  return (0);
557 }
558 
574 static int _zoomSurfaceY(SDL_Surface *src,
575  SDL_Surface *dst,
576  int flipx,
577  int flipy)
578 {
579  int x, y;
580  Uint32 *sax, *say, *csax, *csay;
581  int csx, csy;
582  Uint8 *sp, *dp, *csp;
583  int dgap;
584 
585  /*
586  * Allocate memory for row increments
587  */
588  if ((sax = static_cast<Uint32 *>(malloc((dst->w + 1) *
589  sizeof(Uint32)))) == nullptr)
590  {
591  return (-1);
592  }
593  if ((say = static_cast<Uint32 *>(malloc((dst->h + 1) *
594  sizeof(Uint32)))) == nullptr)
595  {
596  free(sax);
597  return (-1);
598  }
599 
600  /*
601  * Pointer setup
602  */
603  sp = csp = static_cast<Uint8*>(src->pixels);
604  dp = static_cast<Uint8*>(dst->pixels);
605  dgap = dst->pitch - dst->w;
606 
607  if (flipx) csp += (src->w-1);
608  if (flipy) csp = (static_cast<Uint8*>(csp) + src->pitch*(src->h-1));
609 
610  /*
611  * Precalculate row increments
612  */
613  csx = 0;
614  csax = sax;
615  for (x = 0; x < dst->w; x++)
616  {
617  csx += src->w;
618  *csax = 0;
619  while (csx >= dst->w)
620  {
621  csx -= dst->w;
622  (*csax)++;
623  }
624  (*csax) = (*csax) * (flipx ? -1 : 1);
625  csax++;
626  }
627  csy = 0;
628  csay = say;
629  for (y = 0; y < dst->h; y++)
630  {
631  csy += src->h;
632  *csay = 0;
633  while (csy >= dst->h)
634  {
635  csy -= dst->h;
636  (*csay)++;
637  }
638  (*csay) = (*csay) * (flipy ? -1 : 1);
639  csay++;
640  }
641 
642  /*
643  * Draw
644  */
645  csay = say;
646  for (y = 0; y < dst->h; y++)
647  {
648  csax = sax;
649  sp = csp;
650  for (x = 0; x < dst->w; x++)
651  {
652  /*
653  * Draw
654  */
655  *dp = *sp;
656  /*
657  * Advance source pointers
658  */
659  sp += (*csax);
660  csax++;
661  /*
662  * Advance destination pointer
663  */
664  dp++;
665  }
666  /*
667  * Advance source pointer (for row)
668  */
669  csp += ((*csay) * src->pitch);
670  csay++;
671 
672  /*
673  * Advance destination pointers
674  */
675  dp += dgap;
676  }
677 
678  /*
679  * Remove temp arrays
680  */
681  free(sax);
682  free(say);
683 
684  return (0);
685 }
686 
706 static void _transformSurfaceRGBA(SDL_Surface *src,
707  SDL_Surface *dst,
708  int cx,
709  int cy,
710  int isin,
711  int icos,
712  int flipx,
713  int flipy,
714  int smooth)
715 {
716  int x, y, t1, t2, dx, dy, xd, yd, sdx, sdy, ax, ay, ex, ey, sw, sh;
717  tColorRGBA c00, c01, c10, c11, cswap;
718  tColorRGBA *pc, *sp;
719  int gap;
720 
721  /*
722  * Variable setup
723  */
724  xd = ((src->w - dst->w) << 15);
725  yd = ((src->h - dst->h) << 15);
726  ax = (cx << 16) - (icos * cx);
727  ay = (cy << 16) - (isin * cx);
728  sw = src->w - 1;
729  sh = src->h - 1;
730  pc = static_cast<tColorRGBA*>(dst->pixels);
731  gap = dst->pitch - dst->w * 4;
732 
733  /*
734  * Switch between interpolating and non-interpolating code
735  */
736  if (smooth)
737  {
738  for (y = 0; y < dst->h; y++)
739  {
740  dy = cy - y;
741  sdx = (ax + (isin * dy)) + xd;
742  sdy = (ay - (icos * dy)) + yd;
743  for (x = 0; x < dst->w; x++)
744  {
745  dx = (sdx >> 16);
746  dy = (sdy >> 16);
747  if (flipx) dx = sw - dx;
748  if (flipy) dy = sh - dy;
749  if ((dx > -1) && (dy > -1) &&
750  (dx < (src->w-1)) && (dy < (src->h-1)))
751  {
752  sp = static_cast<tColorRGBA *>(src->pixels);
753  sp += ((src->pitch/4) * dy);
754  sp += dx;
755  c00 = *sp;
756  sp += 1;
757  c01 = *sp;
758  sp += (src->pitch/4);
759  c11 = *sp;
760  sp -= 1;
761  c10 = *sp;
762  if (flipx)
763  {
764  cswap = c00; c00=c01; c01=cswap;
765  cswap = c10; c10=c11; c11=cswap;
766  }
767  if (flipy)
768  {
769  cswap = c00; c00=c10; c10=cswap;
770  cswap = c01; c01=c11; c11=cswap;
771  }
772  /*
773  * Interpolate colors
774  */
775  ex = (sdx & 0xffff);
776  ey = (sdy & 0xffff);
777  t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff;
778  t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff;
779  pc->r = (((t2 - t1) * ey) >> 16) + t1;
780  t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff;
781  t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff;
782  pc->g = (((t2 - t1) * ey) >> 16) + t1;
783  t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff;
784  t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff;
785  pc->b = (((t2 - t1) * ey) >> 16) + t1;
786  t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff;
787  t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff;
788  pc->a = (((t2 - t1) * ey) >> 16) + t1;
789  }
790  sdx += icos;
791  sdy += isin;
792  pc++;
793  }
794  pc = reinterpret_cast<tColorRGBA *>(
795  reinterpret_cast<Uint8*>(pc) + gap);
796  }
797  }
798  else
799  {
800  for (y = 0; y < dst->h; y++)
801  {
802  dy = cy - y;
803  sdx = (ax + (isin * dy)) + xd;
804  sdy = (ay - (icos * dy)) + yd;
805  for (x = 0; x < dst->w; x++)
806  {
807  dx = static_cast<short>(sdx >> 16);
808  dy = static_cast<short>(sdy >> 16);
809  if (flipx) dx = (src->w-1)-dx;
810  if (flipy) dy = (src->h-1)-dy;
811  if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h))
812  {
813  sp = reinterpret_cast<tColorRGBA *>(
814  reinterpret_cast<Uint8*>(src->pixels) +
815  src->pitch * dy);
816  sp += dx;
817  *pc = *sp;
818  }
819  sdx += icos;
820  sdy += isin;
821  pc++;
822  }
823  pc = reinterpret_cast<tColorRGBA *>(
824  reinterpret_cast<Uint8*>(pc) + gap);
825  }
826  }
827 }
828 
847 static void transformSurfaceY(SDL_Surface *src,
848  SDL_Surface *dst,
849  int cx,
850  int cy,
851  int isin,
852  int icos,
853  int flipx,
854  int flipy)
855 {
856  int x, y, dx, dy, xd, yd, sdx, sdy, ax, ay;
857  tColorY *pc, *sp;
858  int gap;
859 
860  /*
861  * Variable setup
862  */
863  xd = ((src->w - dst->w) << 15);
864  yd = ((src->h - dst->h) << 15);
865  ax = (cx << 16) - (icos * cx);
866  ay = (cy << 16) - (isin * cx);
867  pc = static_cast<tColorY*>(dst->pixels);
868  gap = dst->pitch - dst->w;
869  /*
870  * Clear surface to colorkey
871  */
872  memset(pc, static_cast<int>(_colorkey(src) & 0xff), dst->pitch * dst->h);
873  /*
874  * Iterate through destination surface
875  */
876  for (y = 0; y < dst->h; y++)
877  {
878  dy = cy - y;
879  sdx = (ax + (isin * dy)) + xd;
880  sdy = (ay - (icos * dy)) + yd;
881  for (x = 0; x < dst->w; x++)
882  {
883  dx = static_cast<short>(sdx >> 16);
884  dy = static_cast<short>(sdy >> 16);
885  if (flipx) dx = (src->w-1)-dx;
886  if (flipy) dy = (src->h-1)-dy;
887  if ((dx >= 0) && (dy >= 0) && (dx < src->w) && (dy < src->h))
888  {
889  sp = static_cast<tColorY *>(src->pixels);
890  sp += (src->pitch * dy + dx);
891  *pc = *sp;
892  }
893  sdx += icos;
894  sdy += isin;
895  pc++;
896  }
897  pc += gap;
898  }
899 }
900 
914 SDL_Surface* rotateSurface90Degrees(SDL_Surface *src,
915  int numClockwiseTurns)
916 {
917  int row, col, newWidth, newHeight;
918  int bpp, bpr;
919  SDL_Surface* dst;
920  Uint8* srcBuf;
921  Uint8* dstBuf;
922  int normalizedClockwiseTurns;
923 
924  /* Has to be a valid surface pointer and be a Nbit surface where n is divisible by 8 */
925  if (!src ||
926  !src->format)
927  {
928  SDL_SetError("NULL source surface or source surface format");
929  return nullptr;
930  }
931 
932  if ((src->format->BitsPerPixel % 8) != 0)
933  {
934  SDL_SetError("Invalid source surface bit depth");
935  return nullptr;
936  }
937 
938  /* normalize numClockwiseTurns */
939  normalizedClockwiseTurns = (numClockwiseTurns % 4);
940  if (normalizedClockwiseTurns < 0)
941  {
942  normalizedClockwiseTurns += 4;
943  }
944 
945  /* If turns are even, our new width/height will be the same as the source surface */
946  if (normalizedClockwiseTurns % 2)
947  {
948  newWidth = src->h;
949  newHeight = src->w;
950  }
951  else
952  {
953  newWidth = src->w;
954  newHeight = src->h;
955  }
956 
957  dst = SDL_CreateRGBSurface(src->flags,
958  newWidth,
959  newHeight,
960  src->format->BitsPerPixel,
961  src->format->Rmask,
962  src->format->Gmask,
963  src->format->Bmask,
964  src->format->Amask);
965  if (!dst)
966  {
967  SDL_SetError("Could not create destination surface");
968  return nullptr;
969  }
970 
971  if (SDL_MUSTLOCK(src))
972  {
973  SDL_LockSurface(src);
974  }
975  if (SDL_MUSTLOCK(dst))
976  {
977  SDL_LockSurface(dst);
978  }
979 
980  /* Calculate byte-per-pixel */
981  bpp = src->format->BitsPerPixel / 8;
982 
983  switch (normalizedClockwiseTurns)
984  {
985  case 0: /* Make a copy of the surface */
986  {
987  /* Unfortunately SDL_BlitSurface cannot be used to
988  make a copy of the surface
989  since it does not preserve alpha. */
990 
991  if (src->pitch == dst->pitch)
992  {
993  /* If the pitch is the same for both surfaces,
994  the memory can be copied all at once. */
995  memcpy(dst->pixels, src->pixels, (src->h * src->pitch));
996  }
997  else
998  {
999  /* If the pitch differs, copy each row separately */
1000  srcBuf = static_cast<Uint8*>(src->pixels);
1001  dstBuf = static_cast<Uint8*>(dst->pixels);
1002  bpr = src->w * bpp;
1003  for (row = 0; row < src->h; row++)
1004  {
1005  memcpy(dstBuf, srcBuf, bpr);
1006  srcBuf += src->pitch;
1007  dstBuf += dst->pitch;
1008  }
1009  }
1010  }
1011  break;
1012 
1013  /* rotate clockwise */
1014  case 1: /* rotated 90 degrees clockwise */
1015  {
1016  for (row = 0; row < src->h; ++row)
1017  {
1018  srcBuf = static_cast<Uint8*>(src->pixels) +
1019  (row * src->pitch);
1020  dstBuf = static_cast<Uint8*>(dst->pixels) +
1021  (dst->w - row - 1) * bpp;
1022  for (col = 0; col < src->w; ++col)
1023  {
1024  memcpy (dstBuf, srcBuf, bpp);
1025  srcBuf += bpp;
1026  dstBuf += dst->pitch;
1027  }
1028  }
1029  }
1030  break;
1031 
1032  case 2: /* rotated 180 degrees clockwise */
1033  {
1034  for (row = 0; row < src->h; ++row)
1035  {
1036  srcBuf = static_cast<Uint8*>(src->pixels) +
1037  (row * src->pitch);
1038  dstBuf = static_cast<Uint8*>(dst->pixels) +
1039  ((dst->h - row - 1) * dst->pitch) + (dst->w - 1) * bpp;
1040  for (col = 0; col < src->w; ++col)
1041  {
1042  memcpy (dstBuf, srcBuf, bpp);
1043  srcBuf += bpp;
1044  dstBuf -= bpp;
1045  }
1046  }
1047  }
1048  break;
1049 
1050  case 3: /* rotated 270 degrees clockwise */
1051  {
1052  for (row = 0; row < src->h; ++row)
1053  {
1054  srcBuf = static_cast<Uint8*>(src->pixels) + (row * src->pitch);
1055  dstBuf = static_cast<Uint8*>(dst->pixels) +
1056  (row * bpp) + (dst->h * dst->pitch);
1057  for (col = 0; col < src->w; ++col)
1058  {
1059  memcpy (dstBuf, srcBuf, bpp);
1060  srcBuf += bpp;
1061  dstBuf -= dst->pitch;
1062  }
1063  }
1064  }
1065  break;
1066  default:
1067  break;
1068  }
1069  /* end switch */
1070 
1071  if (SDL_MUSTLOCK(src))
1072  {
1073  SDL_UnlockSurface(src);
1074  }
1075  if (SDL_MUSTLOCK(dst))
1076  {
1077  SDL_UnlockSurface(dst);
1078  }
1079 
1080  return dst;
1081 }
1082 
1083 
1099 static void _rotozoomSurfaceSizeTrig(int width,
1100  int height,
1101  double angle,
1102  double zoomx,
1103  double zoomy,
1104  int *dstwidth,
1105  int *dstheight,
1106  double *canglezoom,
1107  double *sanglezoom)
1108 {
1109  double x, y, cx, cy, sx, sy;
1110  double radangle;
1111  int dstwidthhalf, dstheighthalf;
1112 
1113  /*
1114  * Determine destination width and height by rotating a centered source box
1115  */
1116  radangle = angle * (M_PI / 180.0);
1117  *sanglezoom = sin(radangle);
1118  *canglezoom = cos(radangle);
1119  *sanglezoom *= zoomx;
1120  *canglezoom *= zoomy;
1121  x = static_cast<double>(width / 2);
1122  y = static_cast<double>(height / 2);
1123  cx = *canglezoom * x;
1124  cy = *canglezoom * y;
1125  sx = *sanglezoom * x;
1126  sy = *sanglezoom * y;
1127 
1128  dstwidthhalf = MAX(static_cast<int>(
1129  ceil(MAX(MAX(MAX(fabs(cx + sy), fabs(cx - sy)),
1130  fabs(-cx + sy)), fabs(-cx - sy)))), 1);
1131  dstheighthalf = MAX(static_cast<int>(
1132  ceil(MAX(MAX(MAX(fabs(sx + cy), fabs(sx - cy)),
1133  fabs(-sx + cy)), fabs(-sx - cy)))), 1);
1134  *dstwidth = 2 * dstwidthhalf;
1135  *dstheight = 2 * dstheighthalf;
1136 }
1137 
1150 void rotozoomSurfaceSizeXY(int width,
1151  int height,
1152  double angle,
1153  double zoomx,
1154  double zoomy,
1155  int *dstwidth,
1156  int *dstheight)
1157 {
1158  double dummy_sanglezoom, dummy_canglezoom;
1159 
1160  _rotozoomSurfaceSizeTrig(width, height, angle, zoomx, zoomy,
1161  dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
1162 }
1163 
1175 void rotozoomSurfaceSize(int width,
1176  int height,
1177  double angle,
1178  double zoom,
1179  int *dstwidth,
1180  int *dstheight)
1181 {
1182  double dummy_sanglezoom, dummy_canglezoom;
1183 
1184  _rotozoomSurfaceSizeTrig(width, height, angle, zoom, zoom,
1185  dstwidth, dstheight, &dummy_sanglezoom, &dummy_canglezoom);
1186 }
1187 
1204 SDL_Surface *rotozoomSurface(SDL_Surface *src,
1205  double angle,
1206  double zoom,
1207  int smooth)
1208 {
1209  return rotozoomSurfaceXY(src, angle, zoom, zoom, smooth);
1210 }
1211 
1230 SDL_Surface *rotozoomSurfaceXY(SDL_Surface *src,
1231  double angle,
1232  double zoomx,
1233  double zoomy,
1234  int smooth)
1235 {
1236  SDL_Surface *rz_src;
1237  SDL_Surface *rz_dst;
1238  double zoominv;
1239  double sanglezoom, canglezoom, sanglezoominv, canglezoominv;
1240  int dstwidthhalf, dstwidth, dstheighthalf, dstheight;
1241  int is32bit;
1242  int i, src_converted;
1243  int flipx,flipy;
1244 
1245  /*
1246  * Sanity check
1247  */
1248  if (src == nullptr)
1249  {
1250  return (nullptr);
1251  }
1252 
1253  /*
1254  * Determine if source surface is 32bit or 8bit
1255  */
1256  is32bit = (src->format->BitsPerPixel == 32);
1257  if ((is32bit) || (src->format->BitsPerPixel == 8))
1258  {
1259  /*
1260  * Use source surface 'as is'
1261  */
1262  rz_src = src;
1263  src_converted = 0;
1264  }
1265  else
1266  {
1267  /*
1268  * New source surface is 32bit with a defined RGBA ordering
1269  */
1270  rz_src =
1271  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1272 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1273  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1274 #else
1275  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1276 #endif
1277  );
1278 
1279  SDL_BlitSurface(src, nullptr, rz_src, nullptr);
1280 
1281  src_converted = 1;
1282  is32bit = 1;
1283  }
1284 
1285  /*
1286  * Sanity check zoom factor
1287  */
1288  flipx = (zoomx<0.0);
1289  if (flipx) zoomx=-zoomx;
1290  flipy = (zoomy<0.0);
1291  if (flipy) zoomy=-zoomy;
1292  if (zoomx < VALUE_LIMIT) zoomx = VALUE_LIMIT;
1293  if (zoomy < VALUE_LIMIT) zoomy = VALUE_LIMIT;
1294  zoominv = 65536.0 / (zoomx * zoomx);
1295 
1296  /*
1297  * Check if we have a rotozoom or just a zoom
1298  */
1299  if (fabs(angle) > VALUE_LIMIT)
1300  {
1301 
1302  /*
1303  * Angle!=0: full rotozoom
1304  */
1305  /*
1306  * -----------------------
1307  */
1308 
1309  /* Determine target size */
1310  _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, zoomx, zoomy,
1311  &dstwidth, &dstheight, &canglezoom, &sanglezoom);
1312 
1313  /*
1314  * Calculate target factors from sin/cos and zoom
1315  */
1316  sanglezoominv = sanglezoom;
1317  canglezoominv = canglezoom;
1318  sanglezoominv *= zoominv;
1319  canglezoominv *= zoominv;
1320 
1321  /* Calculate half size */
1322  dstwidthhalf = dstwidth / 2;
1323  dstheighthalf = dstheight / 2;
1324 
1325  /*
1326  * Alloc space to completely contain the rotated surface
1327  */
1328  rz_dst = nullptr;
1329  if (is32bit)
1330  {
1331  /*
1332  * Target surface is 32bit with source RGBA/ABGR ordering
1333  */
1334  rz_dst =
1335  SDL_CreateRGBSurface(SDL_SWSURFACE,
1336  dstwidth, dstheight + GUARD_ROWS, 32,
1337  rz_src->format->Rmask, rz_src->format->Gmask,
1338  rz_src->format->Bmask, rz_src->format->Amask);
1339  }
1340  else
1341  {
1342  /*
1343  * Target surface is 8bit
1344  */
1345  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE, dstwidth,
1346  dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1347  }
1348 
1349  /* Check target */
1350  if (rz_dst == nullptr)
1351  return nullptr;
1352 
1353  /* Adjust for guard rows */
1354  rz_dst->h = dstheight;
1355 
1356  /*
1357  * Lock source surface
1358  */
1359  if (SDL_MUSTLOCK(rz_src))
1360  {
1361  SDL_LockSurface(rz_src);
1362  }
1363 
1364  /*
1365  * Check which kind of surface we have
1366  */
1367  if (is32bit)
1368  {
1369  /*
1370  * Call the 32bit transformation routine to do the rotation
1371  * (using alpha)
1372  */
1373  _transformSurfaceRGBA(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1374  static_cast<int>(sanglezoominv),
1375  static_cast<int>(canglezoominv),
1376  flipx, flipy,
1377  smooth);
1378  }
1379  else
1380  {
1381  /*
1382  * Copy palette and colorkey info
1383  */
1384  for (i = 0; i < rz_src->format->palette->ncolors; i++)
1385  {
1386  rz_dst->format->palette->colors[i] =
1387  rz_src->format->palette->colors[i];
1388  }
1389  rz_dst->format->palette->ncolors =
1390  rz_src->format->palette->ncolors;
1391  /*
1392  * Call the 8bit transformation routine to do the rotation
1393  */
1394  transformSurfaceY(rz_src, rz_dst, dstwidthhalf, dstheighthalf,
1395  static_cast<int>(sanglezoominv),
1396  static_cast<int>(canglezoominv),
1397  flipx, flipy);
1398  }
1399  /*
1400  * Unlock source surface
1401  */
1402  if (SDL_MUSTLOCK(rz_src))
1403  {
1404  SDL_UnlockSurface(rz_src);
1405  }
1406 
1407  }
1408  else
1409  {
1410  /*
1411  * Angle=0: Just a zoom
1412  */
1413  /*
1414  * --------------------
1415  */
1416 
1417  /*
1418  * Calculate target size
1419  */
1420  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy,
1421  &dstwidth, &dstheight);
1422 
1423  /*
1424  * Alloc space to completely contain the zoomed surface
1425  */
1426  rz_dst = nullptr;
1427  if (is32bit)
1428  {
1429  /*
1430  * Target surface is 32bit with source RGBA/ABGR ordering
1431  */
1432  rz_dst =
1433  SDL_CreateRGBSurface(SDL_SWSURFACE,
1434  dstwidth, dstheight + GUARD_ROWS, 32,
1435  rz_src->format->Rmask, rz_src->format->Gmask,
1436  rz_src->format->Bmask, rz_src->format->Amask);
1437  }
1438  else
1439  {
1440  /*
1441  * Target surface is 8bit
1442  */
1443  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
1444  dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1445  }
1446 
1447  /* Check target */
1448  if (rz_dst == nullptr)
1449  return nullptr;
1450 
1451  /* Adjust for guard rows */
1452  rz_dst->h = dstheight;
1453 
1454  /*
1455  * Lock source surface
1456  */
1457  if (SDL_MUSTLOCK(rz_src))
1458  {
1459  SDL_LockSurface(rz_src);
1460  }
1461 
1462  /*
1463  * Check which kind of surface we have
1464  */
1465  if (is32bit)
1466  {
1467  /*
1468  * Call the 32bit transformation routine to do the zooming
1469  * (using alpha)
1470  */
1471  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1472 
1473  }
1474  else
1475  {
1476  /*
1477  * Copy palette and colorkey info
1478  */
1479  for (i = 0; i < rz_src->format->palette->ncolors; i++)
1480  {
1481  rz_dst->format->palette->colors[i] =
1482  rz_src->format->palette->colors[i];
1483  }
1484  rz_dst->format->palette->ncolors =
1485  rz_src->format->palette->ncolors;
1486 
1487  /*
1488  * Call the 8bit transformation routine to do the zooming
1489  */
1490  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1491  }
1492 
1493  /*
1494  * Unlock source surface
1495  */
1496  if (SDL_MUSTLOCK(rz_src))
1497  {
1498  SDL_UnlockSurface(rz_src);
1499  }
1500  }
1501 
1502  /*
1503  * Cleanup temp surface
1504  */
1505  if (src_converted)
1506  {
1507  SDL_FreeSurface(rz_src);
1508  }
1509 
1510  /*
1511  * Return destination surface
1512  */
1513  return (rz_dst);
1514 }
1515 
1531 void zoomSurfaceSize(int width, int height,
1532  double zoomx, double zoomy,
1533  int *dstwidth, int *dstheight)
1534 {
1535  /*
1536  * Make zoom factors positive
1537  */
1538  int flipx, flipy;
1539  flipx = (zoomx<0.0);
1540  if (flipx) zoomx = -zoomx;
1541  flipy = (zoomy<0.0);
1542  if (flipy) zoomy = -zoomy;
1543 
1544  /*
1545  * Sanity check zoom factors
1546  */
1547  if (zoomx < VALUE_LIMIT)
1548  {
1549  zoomx = VALUE_LIMIT;
1550  }
1551  if (zoomy < VALUE_LIMIT)
1552  {
1553  zoomy = VALUE_LIMIT;
1554  }
1555 
1556  /*
1557  * Calculate target size
1558  */
1559  *dstwidth = static_cast<int>(floor((static_cast<double>(
1560  width) * zoomx) + 0.5));
1561  *dstheight = static_cast<int>(floor((static_cast<double>(
1562  height) * zoomy) + 0.5));
1563  if (*dstwidth < 1)
1564  {
1565  *dstwidth = 1;
1566  }
1567  if (*dstheight < 1)
1568  {
1569  *dstheight = 1;
1570  }
1571 }
1572 
1590 SDL_Surface *zoomSurface(SDL_Surface *src,
1591  double zoomx,
1592  double zoomy,
1593  int smooth)
1594 {
1595  SDL_Surface *rz_src;
1596  SDL_Surface *rz_dst;
1597  int dstwidth, dstheight;
1598  int is32bit;
1599  int i, src_converted;
1600  int flipx, flipy;
1601 
1602  /*
1603  * Sanity check
1604  */
1605  if (src == nullptr)
1606  return (nullptr);
1607 
1608  /*
1609  * Determine if source surface is 32bit or 8bit
1610  */
1611  is32bit = (src->format->BitsPerPixel == 32);
1612  if ((is32bit) || (src->format->BitsPerPixel == 8))
1613  {
1614  /*
1615  * Use source surface 'as is'
1616  */
1617  rz_src = src;
1618  src_converted = 0;
1619  }
1620  else
1621  {
1622  /*
1623  * New source surface is 32bit with a defined RGBA ordering
1624  */
1625  rz_src =
1626  SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1627 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1628  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1629 #else
1630  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1631 #endif
1632  );
1633  if (rz_src == nullptr)
1634  {
1635  return nullptr;
1636  }
1637  SDL_BlitSurface(src, nullptr, rz_src, nullptr);
1638  src_converted = 1;
1639  is32bit = 1;
1640  }
1641 
1642  flipx = (zoomx<0.0);
1643  if (flipx) zoomx = -zoomx;
1644  flipy = (zoomy<0.0);
1645  if (flipy) zoomy = -zoomy;
1646 
1647  /* Get size if target */
1648  zoomSurfaceSize(rz_src->w, rz_src->h, zoomx, zoomy, &dstwidth, &dstheight);
1649 
1650  /*
1651  * Alloc space to completely contain the zoomed surface
1652  */
1653  rz_dst = nullptr;
1654  if (is32bit)
1655  {
1656  /*
1657  * Target surface is 32bit with source RGBA/ABGR ordering
1658  */
1659  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
1660  dstwidth, dstheight + GUARD_ROWS, 32,
1661  rz_src->format->Rmask, rz_src->format->Gmask,
1662  rz_src->format->Bmask, rz_src->format->Amask);
1663  }
1664  else
1665  {
1666  /*
1667  * Target surface is 8bit
1668  */
1669  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
1670  dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1671  }
1672 
1673  /* Check target */
1674  if (rz_dst == nullptr)
1675  {
1676  /*
1677  * Cleanup temp surface
1678  */
1679  if (src_converted)
1680  {
1681  SDL_FreeSurface(rz_src);
1682  }
1683  return nullptr;
1684  }
1685 
1686  /* Adjust for guard rows */
1687  rz_dst->h = dstheight;
1688 
1689  /*
1690  * Lock source surface
1691  */
1692  if (SDL_MUSTLOCK(rz_src))
1693  {
1694  SDL_LockSurface(rz_src);
1695  }
1696 
1697  /*
1698  * Check which kind of surface we have
1699  */
1700  if (is32bit)
1701  {
1702  /*
1703  * Call the 32bit transformation routine to do the zooming (using alpha)
1704  */
1705  _zoomSurfaceRGBA(rz_src, rz_dst, flipx, flipy, smooth);
1706  }
1707  else
1708  {
1709  /*
1710  * Copy palette and colorkey info
1711  */
1712  for (i = 0; i < rz_src->format->palette->ncolors; i++)
1713  {
1714  rz_dst->format->palette->colors[i] =
1715  rz_src->format->palette->colors[i];
1716  }
1717  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1718  /*
1719  * Call the 8bit transformation routine to do the zooming
1720  */
1721  _zoomSurfaceY(rz_src, rz_dst, flipx, flipy);
1722  }
1723  /*
1724  * Unlock source surface
1725  */
1726  if (SDL_MUSTLOCK(rz_src))
1727  {
1728  SDL_UnlockSurface(rz_src);
1729  }
1730 
1731  /*
1732  * Cleanup temp surface
1733  */
1734  if (src_converted)
1735  {
1736  SDL_FreeSurface(rz_src);
1737  }
1738 
1739  /*
1740  * Return destination surface
1741  */
1742  return (rz_dst);
1743 }
1744 
1761 /*@nullptr@*/
1762 SDL_Surface *shrinkSurface(SDL_Surface *src,
1763  int factorx,
1764  int factory)
1765 {
1766  int result;
1767  SDL_Surface *rz_src;
1768  SDL_Surface *rz_dst = nullptr;
1769  int dstwidth, dstheight;
1770  int is32bit;
1771  int i, src_converted = 0;
1772  int haveError = 0;
1773 
1774  /*
1775  * Sanity check
1776  */
1777  if (src == nullptr)
1778  {
1779  return (nullptr);
1780  }
1781 
1782  /*
1783  * Determine if source surface is 32bit or 8bit
1784  */
1785  is32bit = (src->format->BitsPerPixel == 32);
1786  if ((is32bit) || (src->format->BitsPerPixel == 8))
1787  {
1788  /*
1789  * Use source surface 'as is'
1790  */
1791  rz_src = src;
1792  src_converted = 0;
1793  }
1794  else
1795  {
1796  /*
1797  * New source surface is 32bit with a defined RGBA ordering
1798  */
1799  rz_src = SDL_CreateRGBSurface(SDL_SWSURFACE, src->w, src->h, 32,
1800 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
1801  0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
1802 #else
1803  0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
1804 #endif
1805  );
1806  if (rz_src==nullptr)
1807  {
1808  haveError = 1;
1809  goto exitShrinkSurface;
1810  }
1811 
1812  SDL_BlitSurface(src, nullptr, rz_src, nullptr);
1813  src_converted = 1;
1814  is32bit = 1;
1815  }
1816 
1817  /*
1818  * Lock the surface
1819  */
1820  if (SDL_MUSTLOCK(rz_src))
1821  {
1822  if (SDL_LockSurface(rz_src) < 0)
1823  {
1824  haveError = 1;
1825  goto exitShrinkSurface;
1826  }
1827  }
1828 
1829  /* Get size for target */
1830  dstwidth=rz_src->w/factorx;
1831  while (dstwidth*factorx>rz_src->w)
1832  {
1833  dstwidth--;
1834  }
1835  dstheight=rz_src->h/factory;
1836  while (dstheight*factory>rz_src->h)
1837  {
1838  dstheight--;
1839  }
1840 
1841  /*
1842  * Alloc space to completely contain the shrunken surface
1843  * (with added guard rows)
1844  */
1845  if (is32bit==1)
1846  {
1847  /*
1848  * Target surface is 32bit with source RGBA/ABGR ordering
1849  */
1850  rz_dst = SDL_CreateRGBSurface(
1851  SDL_SWSURFACE, dstwidth, dstheight + GUARD_ROWS, 32,
1852  rz_src->format->Rmask, rz_src->format->Gmask,
1853  rz_src->format->Bmask, rz_src->format->Amask);
1854  }
1855  else
1856  {
1857  /*
1858  * Target surface is 8bit
1859  */
1860  rz_dst = SDL_CreateRGBSurface(SDL_SWSURFACE,
1861  dstwidth, dstheight + GUARD_ROWS, 8, 0, 0, 0, 0);
1862  }
1863 
1864  /* Check target */
1865  if (rz_dst == nullptr)
1866  {
1867  haveError = 1;
1868  goto exitShrinkSurface;
1869  }
1870 
1871  /* Adjust for guard rows */
1872  rz_dst->h = dstheight;
1873 
1874  /*
1875  * Check which kind of surface we have
1876  */
1877  if (is32bit==1)
1878  {
1879  /*
1880  * Call the 32bit transformation routine to do the shrinking (using alpha)
1881  */
1882  result = _shrinkSurfaceRGBA(rz_src, rz_dst, factorx, factory);
1883  if ((result!=0) || (rz_dst==nullptr))
1884  {
1885  haveError = 1;
1886  goto exitShrinkSurface;
1887  }
1888  }
1889  else
1890  {
1891  /*
1892  * Copy palette and colorkey info
1893  */
1894  for (i = 0; i < rz_src->format->palette->ncolors; i++)
1895  {
1896  rz_dst->format->palette->colors[i] = rz_src->format->palette->colors[i];
1897  }
1898  rz_dst->format->palette->ncolors = rz_src->format->palette->ncolors;
1899  /*
1900  * Call the 8bit transformation routine to do the shrinking
1901  */
1902  result = _shrinkSurfaceY(rz_src, rz_dst, factorx, factory);
1903  if (result!=0)
1904  {
1905  haveError = 1;
1906  goto exitShrinkSurface;
1907  }
1908  }
1909 
1910 exitShrinkSurface:
1911  if (rz_src!=nullptr)
1912  {
1913  /*
1914  * Unlock source surface
1915  */
1916  if (SDL_MUSTLOCK(rz_src))
1917  {
1918  SDL_UnlockSurface(rz_src);
1919  }
1920 
1921  /*
1922  * Cleanup temp surface
1923  */
1924  if (src_converted==1)
1925  {
1926  SDL_FreeSurface(rz_src);
1927  }
1928  }
1929 
1930  /* Check error state; maybe need to cleanup destination */
1931  if (haveError==1)
1932  {
1933  if (rz_dst!=nullptr)
1934  {
1935  SDL_FreeSurface(rz_dst);
1936  }
1937  rz_dst=nullptr;
1938  }
1939 
1940  /*
1941  * Return destination surface
1942  */
1943  return (rz_dst);
1944 }
#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 Uint32 _colorkey(SDL_Surface *src)
Returns colorkey info for a surface.
static int _shrinkSurfaceY(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 8 bit integer-factor averaging shrinker.
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.
struct tColorRGBA tColorRGBA
A 32 bit RGBA pixel.
static int _shrinkSurfaceRGBA(SDL_Surface *src, SDL_Surface *dst, int factorx, int factory)
Internal 32 bit integer-factor averaging Shrinker.
SDL_Surface * rotozoomSurface(SDL_Surface *src, double angle, double zoom, int smooth)
Rotates and zooms a surface and optional anti-aliasing.
SDL_Surface * rotateSurface90Degrees(SDL_Surface *src, int numClockwiseTurns)
Rotates a 8/16/24/32 bit surface in increments of 90 degrees.
static int _zoomSurfaceY(SDL_Surface *src, SDL_Surface *dst, int flipx, int flipy)
Internal 8 bit Zoomer without smoothing.
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.
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-...
SDL_Surface * shrinkSurface(SDL_Surface *src, int factorx, int factory)
Shrink a surface by an integer ratio using averaging.
static void transformSurfaceY(SDL_Surface *src, SDL_Surface *dst, int cx, int cy, int isin, int icos, int flipx, int flipy)
Rotates and zooms 8 bit palette/Y 'src' surface to 'dst' surface without smoothing.
SDL_Surface * zoomSurface(SDL_Surface *src, double zoomx, double zoomy, int smooth)
Zoom a surface by independent horizontal and vertical factors with optional smoothing.
struct tColorY tColorY
A 8bit Y/palette pixel.
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.
A 32 bit RGBA pixel.
A 8bit Y/palette pixel.