surface.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. pygame - Python Game Library
  3. Copyright (C) 2000-2001 Pete Shinners
  4. Copyright (C) 2007 Marcus von Appen
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Library General Public
  7. License as published by the Free Software Foundation; either
  8. version 2 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Library General Public License for more details.
  13. You should have received a copy of the GNU Library General Public
  14. License along with this library; if not, write to the Free
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. Pete Shinners
  17. pete@shinners.org
  18. */
  19. #ifndef SURFACE_H
  20. #define SURFACE_H
  21. #include <SDL.h>
  22. #include "pygame.h"
  23. #define PYGAME_BLEND_ADD 0x1
  24. #define PYGAME_BLEND_SUB 0x2
  25. #define PYGAME_BLEND_MULT 0x3
  26. #define PYGAME_BLEND_MIN 0x4
  27. #define PYGAME_BLEND_MAX 0x5
  28. #define PYGAME_BLEND_RGB_ADD 0x1
  29. #define PYGAME_BLEND_RGB_SUB 0x2
  30. #define PYGAME_BLEND_RGB_MULT 0x3
  31. #define PYGAME_BLEND_RGB_MIN 0x4
  32. #define PYGAME_BLEND_RGB_MAX 0x5
  33. #define PYGAME_BLEND_RGBA_ADD 0x6
  34. #define PYGAME_BLEND_RGBA_SUB 0x7
  35. #define PYGAME_BLEND_RGBA_MULT 0x8
  36. #define PYGAME_BLEND_RGBA_MIN 0x9
  37. #define PYGAME_BLEND_RGBA_MAX 0x10
  38. #if SDL_BYTEORDER == SDL_LIL_ENDIAN
  39. #define GET_PIXEL_24(b) (b[0] + (b[1] << 8) + (b[2] << 16))
  40. #else
  41. #define GET_PIXEL_24(b) (b[2] + (b[1] << 8) + (b[0] << 16))
  42. #endif
  43. #define GET_PIXEL(pxl, bpp, source) \
  44. switch (bpp) \
  45. { \
  46. case 2: \
  47. pxl = *((Uint16 *) (source)); \
  48. break; \
  49. case 4: \
  50. pxl = *((Uint32 *) (source)); \
  51. break; \
  52. default: \
  53. { \
  54. Uint8 *b = (Uint8 *) source; \
  55. pxl = GET_PIXEL_24(b); \
  56. } \
  57. break; \
  58. }
  59. #define GET_PIXELVALS(_sR, _sG, _sB, _sA, px, fmt, ppa) \
  60. _sR = ((px & fmt->Rmask) >> fmt->Rshift); \
  61. _sR = (_sR << fmt->Rloss) + (_sR >> (8 - (fmt->Rloss << 1))); \
  62. _sG = ((px & fmt->Gmask) >> fmt->Gshift); \
  63. _sG = (_sG << fmt->Gloss) + (_sG >> (8 - (fmt->Gloss << 1))); \
  64. _sB = ((px & fmt->Bmask) >> fmt->Bshift); \
  65. _sB = (_sB << fmt->Bloss) + (_sB >> (8 - (fmt->Bloss << 1))); \
  66. if (ppa) \
  67. { \
  68. _sA = ((px & fmt->Amask) >> fmt->Ashift); \
  69. _sA = (_sA << fmt->Aloss) + (_sA >> (8 - (fmt->Aloss << 1))); \
  70. } \
  71. else \
  72. { \
  73. _sA = 255; \
  74. }
  75. #define GET_PIXELVALS_1(sr, sg, sb, sa, _src, _fmt) \
  76. sr = _fmt->palette->colors[*((Uint8 *) (_src))].r; \
  77. sg = _fmt->palette->colors[*((Uint8 *) (_src))].g; \
  78. sb = _fmt->palette->colors[*((Uint8 *) (_src))].b; \
  79. sa = 255;
  80. #if SDL_BYTEORDER == SDL_LIL_ENDIAN
  81. #define SET_OFFSETS_24(or, og, ob, fmt) \
  82. { \
  83. or = (fmt->Rshift == 0 ? 0 : \
  84. fmt->Rshift == 8 ? 1 : \
  85. 2 ); \
  86. og = (fmt->Gshift == 0 ? 0 : \
  87. fmt->Gshift == 8 ? 1 : \
  88. 2 ); \
  89. ob = (fmt->Bshift == 0 ? 0 : \
  90. fmt->Bshift == 8 ? 1 : \
  91. 2 ); \
  92. }
  93. #define SET_OFFSETS_32(or, og, ob, fmt) \
  94. { \
  95. or = (fmt->Rshift == 0 ? 0 : \
  96. fmt->Rshift == 8 ? 1 : \
  97. fmt->Rshift == 16 ? 2 : \
  98. 3 ); \
  99. og = (fmt->Gshift == 0 ? 0 : \
  100. fmt->Gshift == 8 ? 1 : \
  101. fmt->Gshift == 16 ? 2 : \
  102. 3 ); \
  103. ob = (fmt->Bshift == 0 ? 0 : \
  104. fmt->Bshift == 8 ? 1 : \
  105. fmt->Bshift == 16 ? 2 : \
  106. 3 ); \
  107. }
  108. #else
  109. #define SET_OFFSETS_24(or, og, ob, fmt) \
  110. { \
  111. or = (fmt->Rshift == 0 ? 2 : \
  112. fmt->Rshift == 8 ? 1 : \
  113. 0 ); \
  114. og = (fmt->Gshift == 0 ? 2 : \
  115. fmt->Gshift == 8 ? 1 : \
  116. 0 ); \
  117. ob = (fmt->Bshift == 0 ? 2 : \
  118. fmt->Bshift == 8 ? 1 : \
  119. 0 ); \
  120. }
  121. #define SET_OFFSETS_32(or, og, ob, fmt) \
  122. { \
  123. or = (fmt->Rshift == 0 ? 3 : \
  124. fmt->Rshift == 8 ? 2 : \
  125. fmt->Rshift == 16 ? 1 : \
  126. 0 ); \
  127. og = (fmt->Gshift == 0 ? 3 : \
  128. fmt->Gshift == 8 ? 2 : \
  129. fmt->Gshift == 16 ? 1 : \
  130. 0 ); \
  131. ob = (fmt->Bshift == 0 ? 3 : \
  132. fmt->Bshift == 8 ? 2 : \
  133. fmt->Bshift == 16 ? 1 : \
  134. 0 ); \
  135. }
  136. #endif
  137. #define CREATE_PIXEL(buf, r, g, b, a, bp, ft) \
  138. switch (bp) \
  139. { \
  140. case 2: \
  141. *((Uint16 *) (buf)) = \
  142. ((r >> ft->Rloss) << ft->Rshift) | \
  143. ((g >> ft->Gloss) << ft->Gshift) | \
  144. ((b >> ft->Bloss) << ft->Bshift) | \
  145. ((a >> ft->Aloss) << ft->Ashift); \
  146. break; \
  147. case 4: \
  148. *((Uint32 *) (buf)) = \
  149. ((r >> ft->Rloss) << ft->Rshift) | \
  150. ((g >> ft->Gloss) << ft->Gshift) | \
  151. ((b >> ft->Bloss) << ft->Bshift) | \
  152. ((a >> ft->Aloss) << ft->Ashift); \
  153. break; \
  154. }
  155. /* Pretty good idea from Tom Duff :-). */
  156. #define LOOP_UNROLLED4(code, n, width) \
  157. n = (width + 3) / 4; \
  158. switch (width & 3) \
  159. { \
  160. case 0: do { code; \
  161. case 3: code; \
  162. case 2: code; \
  163. case 1: code; \
  164. } while (--n > 0); \
  165. }
  166. /* Used in the srcbpp == dstbpp == 1 blend functions */
  167. #define REPEAT_3(code) \
  168. code; \
  169. code; \
  170. code;
  171. #define REPEAT_4(code) \
  172. code; \
  173. code; \
  174. code; \
  175. code;
  176. #define BLEND_ADD(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
  177. tmp = dR + sR; dR = (tmp <= 255 ? tmp : 255); \
  178. tmp = dG + sG; dG = (tmp <= 255 ? tmp : 255); \
  179. tmp = dB + sB; dB = (tmp <= 255 ? tmp : 255);
  180. #define BLEND_SUB(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
  181. tmp = dR - sR; dR = (tmp >= 0 ? tmp : 0); \
  182. tmp = dG - sG; dG = (tmp >= 0 ? tmp : 0); \
  183. tmp = dB - sB; dB = (tmp >= 0 ? tmp : 0);
  184. #define BLEND_MULT(sR, sG, sB, sA, dR, dG, dB, dA) \
  185. dR = (dR && sR) ? (dR * sR) >> 8 : 0; \
  186. dG = (dG && sG) ? (dG * sG) >> 8 : 0; \
  187. dB = (dB && sB) ? (dB * sB) >> 8 : 0;
  188. #define BLEND_MIN(sR, sG, sB, sA, dR, dG, dB, dA) \
  189. if(sR < dR) { dR = sR; } \
  190. if(sG < dG) { dG = sG; } \
  191. if(sB < dB) { dB = sB; }
  192. #define BLEND_MAX(sR, sG, sB, sA, dR, dG, dB, dA) \
  193. if(sR > dR) { dR = sR; } \
  194. if(sG > dG) { dG = sG; } \
  195. if(sB > dB) { dB = sB; }
  196. #define BLEND_RGBA_ADD(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
  197. tmp = dR + sR; dR = (tmp <= 255 ? tmp : 255); \
  198. tmp = dG + sG; dG = (tmp <= 255 ? tmp : 255); \
  199. tmp = dB + sB; dB = (tmp <= 255 ? tmp : 255); \
  200. tmp = dA + sA; dA = (tmp <= 255 ? tmp : 255);
  201. #define BLEND_RGBA_SUB(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
  202. tmp = dR - sR; dR = (tmp >= 0 ? tmp : 0); \
  203. tmp = dG - sG; dG = (tmp >= 0 ? tmp : 0); \
  204. tmp = dB - sB; dB = (tmp >= 0 ? tmp : 0); \
  205. tmp = dA - sA; dA = (tmp >= 0 ? tmp : 0);
  206. #define BLEND_RGBA_MULT(sR, sG, sB, sA, dR, dG, dB, dA) \
  207. dR = (dR && sR) ? (dR * sR) >> 8 : 0; \
  208. dG = (dG && sG) ? (dG * sG) >> 8 : 0; \
  209. dB = (dB && sB) ? (dB * sB) >> 8 : 0; \
  210. dA = (dA && sA) ? (dA * sA) >> 8 : 0;
  211. #define BLEND_RGBA_MIN(sR, sG, sB, sA, dR, dG, dB, dA) \
  212. if(sR < dR) { dR = sR; } \
  213. if(sG < dG) { dG = sG; } \
  214. if(sB < dB) { dB = sB; } \
  215. if(sA < dA) { dA = sA; }
  216. #define BLEND_RGBA_MAX(sR, sG, sB, sA, dR, dG, dB, dA) \
  217. if(sR > dR) { dR = sR; } \
  218. if(sG > dG) { dG = sG; } \
  219. if(sB > dB) { dB = sB; } \
  220. if(sA > dA) { dA = sA; }
  221. #if 1
  222. /* Choose an alpha blend equation. If the sign is preserved on a right shift
  223. * then use a specialized, faster, equation. Otherwise a more general form,
  224. * where all additions are done before the shift, is needed.
  225. */
  226. #if (-1 >> 1) < 0
  227. #define ALPHA_BLEND_COMP(sC, dC, sA) ((((sC - dC) * sA + sC) >> 8) + dC)
  228. #else
  229. #define ALPHA_BLEND_COMP(sC, dC, sA) (((dC << 8) + (sC - dC) * sA + sC) >> 8)
  230. #endif
  231. #define ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB, dA) \
  232. do { \
  233. if (dA) \
  234. { \
  235. dR = ALPHA_BLEND_COMP(sR, dR, sA); \
  236. dG = ALPHA_BLEND_COMP(sG, dG, sA); \
  237. dB = ALPHA_BLEND_COMP(sB, dB, sA); \
  238. dA = sA + dA - ((sA * dA) / 255); \
  239. } \
  240. else \
  241. { \
  242. dR = sR; \
  243. dG = sG; \
  244. dB = sB; \
  245. dA = sA; \
  246. } \
  247. } while(0)
  248. #elif 0
  249. #define ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB, dA) \
  250. do { \
  251. if(sA){ \
  252. if(dA && sA < 255){ \
  253. int dContrib = dA*(255 - sA)/255; \
  254. dA = sA+dA - ((sA*dA)/255); \
  255. dR = (dR*dContrib + sR*sA)/dA; \
  256. dG = (dG*dContrib + sG*sA)/dA; \
  257. dB = (dB*dContrib + sB*sA)/dA; \
  258. }else{ \
  259. dR = sR; \
  260. dG = sG; \
  261. dB = sB; \
  262. dA = sA; \
  263. } \
  264. } \
  265. } while(0)
  266. #endif
  267. int
  268. surface_fill_blend (SDL_Surface *surface, SDL_Rect *rect, Uint32 color,
  269. int blendargs);
  270. int
  271. pygame_AlphaBlit (SDL_Surface * src, SDL_Rect * srcrect,
  272. SDL_Surface * dst, SDL_Rect * dstrect, int the_args);
  273. int
  274. pygame_Blit (SDL_Surface * src, SDL_Rect * srcrect,
  275. SDL_Surface * dst, SDL_Rect * dstrect, int the_args);
  276. #endif /* SURFACE_H */