sdl_zoom_template.h 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * SDL_zoom_template - surface scaling
  3. *
  4. * Copyright (c) 2009 Citrix Systems, Inc.
  5. *
  6. * Derived from: SDL_rotozoom, LGPL (c) A. Schiffler from the SDL_gfx library.
  7. * Modifications by Stefano Stabellini.
  8. *
  9. * This work is licensed under the terms of the GNU GPL version 2.
  10. * See the COPYING file in the top-level directory.
  11. *
  12. */
  13. #if BPP == 16
  14. #define SDL_TYPE Uint16
  15. #elif BPP == 32
  16. #define SDL_TYPE Uint32
  17. #else
  18. #error unsupport depth
  19. #endif
  20. /*
  21. * Simple helper functions to make the code looks nicer
  22. *
  23. * Assume spf = source SDL_PixelFormat
  24. * dpf = dest SDL_PixelFormat
  25. *
  26. */
  27. #define getRed(color) (((color) & spf->Rmask) >> spf->Rshift)
  28. #define getGreen(color) (((color) & spf->Gmask) >> spf->Gshift)
  29. #define getBlue(color) (((color) & spf->Bmask) >> spf->Bshift)
  30. #define getAlpha(color) (((color) & spf->Amask) >> spf->Ashift)
  31. #define setRed(r, pcolor) do { \
  32. *pcolor = ((*pcolor) & (~(dpf->Rmask))) + \
  33. (((r) & (dpf->Rmask >> dpf->Rshift)) << dpf->Rshift); \
  34. } while (0);
  35. #define setGreen(g, pcolor) do { \
  36. *pcolor = ((*pcolor) & (~(dpf->Gmask))) + \
  37. (((g) & (dpf->Gmask >> dpf->Gshift)) << dpf->Gshift); \
  38. } while (0);
  39. #define setBlue(b, pcolor) do { \
  40. *pcolor = ((*pcolor) & (~(dpf->Bmask))) + \
  41. (((b) & (dpf->Bmask >> dpf->Bshift)) << dpf->Bshift); \
  42. } while (0);
  43. #define setAlpha(a, pcolor) do { \
  44. *pcolor = ((*pcolor) & (~(dpf->Amask))) + \
  45. (((a) & (dpf->Amask >> dpf->Ashift)) << dpf->Ashift); \
  46. } while (0);
  47. static int glue(sdl_zoom_rgb, BPP)(SDL_Surface *src, SDL_Surface *dst, int smooth,
  48. SDL_Rect *dst_rect)
  49. {
  50. int x, y, sx, sy, *sax, *say, *csax, *csay, csx, csy, ex, ey, t1, t2, sstep, sstep_jump;
  51. SDL_TYPE *c00, *c01, *c10, *c11, *sp, *csp, *dp;
  52. int d_gap;
  53. SDL_PixelFormat *spf = src->format;
  54. SDL_PixelFormat *dpf = dst->format;
  55. if (smooth) {
  56. /* For interpolation: assume source dimension is one pixel.
  57. * Smaller here to avoid overflow on right and bottom edge.
  58. */
  59. sx = (int) (65536.0 * (float) (src->w - 1) / (float) dst->w);
  60. sy = (int) (65536.0 * (float) (src->h - 1) / (float) dst->h);
  61. } else {
  62. sx = (int) (65536.0 * (float) src->w / (float) dst->w);
  63. sy = (int) (65536.0 * (float) src->h / (float) dst->h);
  64. }
  65. if ((sax = (int *) malloc((dst->w + 1) * sizeof(Uint32))) == NULL) {
  66. return (-1);
  67. }
  68. if ((say = (int *) malloc((dst->h + 1) * sizeof(Uint32))) == NULL) {
  69. free(sax);
  70. return (-1);
  71. }
  72. sp = csp = (SDL_TYPE *) src->pixels;
  73. dp = (SDL_TYPE *) (dst->pixels + dst_rect->y * dst->pitch +
  74. dst_rect->x * dst->format->BytesPerPixel);
  75. csx = 0;
  76. csax = sax;
  77. for (x = 0; x <= dst->w; x++) {
  78. *csax = csx;
  79. csax++;
  80. csx &= 0xffff;
  81. csx += sx;
  82. }
  83. csy = 0;
  84. csay = say;
  85. for (y = 0; y <= dst->h; y++) {
  86. *csay = csy;
  87. csay++;
  88. csy &= 0xffff;
  89. csy += sy;
  90. }
  91. d_gap = dst->pitch - dst_rect->w * dst->format->BytesPerPixel;
  92. if (smooth) {
  93. csay = say;
  94. for (y = 0; y < dst_rect->y; y++) {
  95. csay++;
  96. sstep = (*csay >> 16) * src->pitch;
  97. csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  98. }
  99. /* Calculate sstep_jump */
  100. csax = sax;
  101. sstep_jump = 0;
  102. for (x = 0; x < dst_rect->x; x++) {
  103. csax++;
  104. sstep = (*csax >> 16);
  105. sstep_jump += sstep;
  106. }
  107. for (y = 0; y < dst_rect->h ; y++) {
  108. /* Setup colour source pointers */
  109. c00 = csp + sstep_jump;
  110. c01 = c00 + 1;
  111. c10 = (SDL_TYPE *) ((Uint8 *) csp + src->pitch) + sstep_jump;
  112. c11 = c10 + 1;
  113. csax = sax + dst_rect->x;
  114. for (x = 0; x < dst_rect->w; x++) {
  115. /* Interpolate colours */
  116. ex = (*csax & 0xffff);
  117. ey = (*csay & 0xffff);
  118. t1 = ((((getRed(*c01) - getRed(*c00)) * ex) >> 16) +
  119. getRed(*c00)) & (dpf->Rmask >> dpf->Rshift);
  120. t2 = ((((getRed(*c11) - getRed(*c10)) * ex) >> 16) +
  121. getRed(*c10)) & (dpf->Rmask >> dpf->Rshift);
  122. setRed((((t2 - t1) * ey) >> 16) + t1, dp);
  123. t1 = ((((getGreen(*c01) - getGreen(*c00)) * ex) >> 16) +
  124. getGreen(*c00)) & (dpf->Gmask >> dpf->Gshift);
  125. t2 = ((((getGreen(*c11) - getGreen(*c10)) * ex) >> 16) +
  126. getGreen(*c10)) & (dpf->Gmask >> dpf->Gshift);
  127. setGreen((((t2 - t1) * ey) >> 16) + t1, dp);
  128. t1 = ((((getBlue(*c01) - getBlue(*c00)) * ex) >> 16) +
  129. getBlue(*c00)) & (dpf->Bmask >> dpf->Bshift);
  130. t2 = ((((getBlue(*c11) - getBlue(*c10)) * ex) >> 16) +
  131. getBlue(*c10)) & (dpf->Bmask >> dpf->Bshift);
  132. setBlue((((t2 - t1) * ey) >> 16) + t1, dp);
  133. t1 = ((((getAlpha(*c01) - getAlpha(*c00)) * ex) >> 16) +
  134. getAlpha(*c00)) & (dpf->Amask >> dpf->Ashift);
  135. t2 = ((((getAlpha(*c11) - getAlpha(*c10)) * ex) >> 16) +
  136. getAlpha(*c10)) & (dpf->Amask >> dpf->Ashift);
  137. setAlpha((((t2 - t1) * ey) >> 16) + t1, dp);
  138. /* Advance source pointers */
  139. csax++;
  140. sstep = (*csax >> 16);
  141. c00 += sstep;
  142. c01 += sstep;
  143. c10 += sstep;
  144. c11 += sstep;
  145. /* Advance destination pointer */
  146. dp++;
  147. }
  148. /* Advance source pointer */
  149. csay++;
  150. csp = (SDL_TYPE *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
  151. /* Advance destination pointers */
  152. dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
  153. }
  154. } else {
  155. csay = say;
  156. for (y = 0; y < dst_rect->y; y++) {
  157. csay++;
  158. sstep = (*csay >> 16) * src->pitch;
  159. csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  160. }
  161. /* Calculate sstep_jump */
  162. csax = sax;
  163. sstep_jump = 0;
  164. for (x = 0; x < dst_rect->x; x++) {
  165. csax++;
  166. sstep = (*csax >> 16);
  167. sstep_jump += sstep;
  168. }
  169. for (y = 0 ; y < dst_rect->h ; y++) {
  170. sp = csp + sstep_jump;
  171. csax = sax + dst_rect->x;
  172. for (x = 0; x < dst_rect->w; x++) {
  173. /* Draw */
  174. *dp = *sp;
  175. /* Advance source pointers */
  176. csax++;
  177. sstep = (*csax >> 16);
  178. sp += sstep;
  179. /* Advance destination pointer */
  180. dp++;
  181. }
  182. /* Advance source pointers */
  183. csay++;
  184. sstep = (*csay >> 16) * src->pitch;
  185. csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  186. /* Advance destination pointer */
  187. dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
  188. }
  189. }
  190. free(sax);
  191. free(say);
  192. return (0);
  193. }
  194. #undef SDL_TYPE