sdl_zoom_template.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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 void 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. sax = g_new(int, dst->w + 1);
  66. say = g_new(int, dst->h + 1);
  67. sp = csp = (SDL_TYPE *) src->pixels;
  68. dp = (SDL_TYPE *) (dst->pixels + dst_rect->y * dst->pitch +
  69. dst_rect->x * dst->format->BytesPerPixel);
  70. csx = 0;
  71. csax = sax;
  72. for (x = 0; x <= dst->w; x++) {
  73. *csax = csx;
  74. csax++;
  75. csx &= 0xffff;
  76. csx += sx;
  77. }
  78. csy = 0;
  79. csay = say;
  80. for (y = 0; y <= dst->h; y++) {
  81. *csay = csy;
  82. csay++;
  83. csy &= 0xffff;
  84. csy += sy;
  85. }
  86. d_gap = dst->pitch - dst_rect->w * dst->format->BytesPerPixel;
  87. if (smooth) {
  88. csay = say;
  89. for (y = 0; y < dst_rect->y; y++) {
  90. csay++;
  91. sstep = (*csay >> 16) * src->pitch;
  92. csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  93. }
  94. /* Calculate sstep_jump */
  95. csax = sax;
  96. sstep_jump = 0;
  97. for (x = 0; x < dst_rect->x; x++) {
  98. csax++;
  99. sstep = (*csax >> 16);
  100. sstep_jump += sstep;
  101. }
  102. for (y = 0; y < dst_rect->h ; y++) {
  103. /* Setup colour source pointers */
  104. c00 = csp + sstep_jump;
  105. c01 = c00 + 1;
  106. c10 = (SDL_TYPE *) ((Uint8 *) csp + src->pitch) + sstep_jump;
  107. c11 = c10 + 1;
  108. csax = sax + dst_rect->x;
  109. for (x = 0; x < dst_rect->w; x++) {
  110. /* Interpolate colours */
  111. ex = (*csax & 0xffff);
  112. ey = (*csay & 0xffff);
  113. t1 = ((((getRed(*c01) - getRed(*c00)) * ex) >> 16) +
  114. getRed(*c00)) & (dpf->Rmask >> dpf->Rshift);
  115. t2 = ((((getRed(*c11) - getRed(*c10)) * ex) >> 16) +
  116. getRed(*c10)) & (dpf->Rmask >> dpf->Rshift);
  117. setRed((((t2 - t1) * ey) >> 16) + t1, dp);
  118. t1 = ((((getGreen(*c01) - getGreen(*c00)) * ex) >> 16) +
  119. getGreen(*c00)) & (dpf->Gmask >> dpf->Gshift);
  120. t2 = ((((getGreen(*c11) - getGreen(*c10)) * ex) >> 16) +
  121. getGreen(*c10)) & (dpf->Gmask >> dpf->Gshift);
  122. setGreen((((t2 - t1) * ey) >> 16) + t1, dp);
  123. t1 = ((((getBlue(*c01) - getBlue(*c00)) * ex) >> 16) +
  124. getBlue(*c00)) & (dpf->Bmask >> dpf->Bshift);
  125. t2 = ((((getBlue(*c11) - getBlue(*c10)) * ex) >> 16) +
  126. getBlue(*c10)) & (dpf->Bmask >> dpf->Bshift);
  127. setBlue((((t2 - t1) * ey) >> 16) + t1, dp);
  128. t1 = ((((getAlpha(*c01) - getAlpha(*c00)) * ex) >> 16) +
  129. getAlpha(*c00)) & (dpf->Amask >> dpf->Ashift);
  130. t2 = ((((getAlpha(*c11) - getAlpha(*c10)) * ex) >> 16) +
  131. getAlpha(*c10)) & (dpf->Amask >> dpf->Ashift);
  132. setAlpha((((t2 - t1) * ey) >> 16) + t1, dp);
  133. /* Advance source pointers */
  134. csax++;
  135. sstep = (*csax >> 16);
  136. c00 += sstep;
  137. c01 += sstep;
  138. c10 += sstep;
  139. c11 += sstep;
  140. /* Advance destination pointer */
  141. dp++;
  142. }
  143. /* Advance source pointer */
  144. csay++;
  145. csp = (SDL_TYPE *) ((Uint8 *) csp + (*csay >> 16) * src->pitch);
  146. /* Advance destination pointers */
  147. dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
  148. }
  149. } else {
  150. csay = say;
  151. for (y = 0; y < dst_rect->y; y++) {
  152. csay++;
  153. sstep = (*csay >> 16) * src->pitch;
  154. csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  155. }
  156. /* Calculate sstep_jump */
  157. csax = sax;
  158. sstep_jump = 0;
  159. for (x = 0; x < dst_rect->x; x++) {
  160. csax++;
  161. sstep = (*csax >> 16);
  162. sstep_jump += sstep;
  163. }
  164. for (y = 0 ; y < dst_rect->h ; y++) {
  165. sp = csp + sstep_jump;
  166. csax = sax + dst_rect->x;
  167. for (x = 0; x < dst_rect->w; x++) {
  168. /* Draw */
  169. *dp = *sp;
  170. /* Advance source pointers */
  171. csax++;
  172. sstep = (*csax >> 16);
  173. sp += sstep;
  174. /* Advance destination pointer */
  175. dp++;
  176. }
  177. /* Advance source pointers */
  178. csay++;
  179. sstep = (*csay >> 16) * src->pitch;
  180. csp = (SDL_TYPE *) ((Uint8 *) csp + sstep);
  181. /* Advance destination pointer */
  182. dp = (SDL_TYPE *) ((Uint8 *) dp + d_gap);
  183. }
  184. }
  185. g_free(sax);
  186. g_free(say);
  187. }
  188. #undef SDL_TYPE