Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1788 lines
59 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: tranblt.cxx
  3. *
  4. * Transparent BLT
  5. *
  6. * Created: 21-Jun-1996
  7. * Author: Mark Enstrom [marke]
  8. *
  9. * Copyright (c) 1996-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. #pragma hdrstop
  13. #if !(_WIN32_WINNT >= 0x500)
  14. PBYTE pAlphaMulTable;
  15. ALPHAPIX aPalHalftone[256] =
  16. {
  17. {0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x00,0x80,0x00,0x00},{0x80,0x80,0x00,0x00},
  18. {0x00,0x00,0x80,0x00},{0x80,0x00,0x80,0x00},{0x00,0x80,0x80,0x00},{0xc0,0xc0,0xc0,0x00},
  19. {0xc0,0xdc,0xc0,0x00},{0xa6,0xca,0xf0,0x00},{0x04,0x04,0x04,0x04},{0x08,0x08,0x08,0x04},
  20. {0x0c,0x0c,0x0c,0x04},{0x11,0x11,0x11,0x04},{0x16,0x16,0x16,0x04},{0x1c,0x1c,0x1c,0x04},
  21. //10
  22. {0x22,0x22,0x22,0x04},{0x29,0x29,0x29,0x04},{0x55,0x55,0x55,0x04},{0x4d,0x4d,0x4d,0x04},
  23. {0x42,0x42,0x42,0x04},{0x39,0x39,0x39,0x04},{0xFF,0x7C,0x80,0x04},{0xFF,0x50,0x50,0x04},
  24. {0xD6,0x00,0x93,0x04},{0xCC,0xEC,0xFF,0x04},{0xEF,0xD6,0xC6,0x04},{0xE7,0xE7,0xD6,0x04},
  25. {0xAD,0xA9,0x90,0x04},{0x33,0x00,0x00,0x04},{0x66,0x00,0x00,0x04},{0x99,0x00,0x00,0x04},
  26. //2
  27. {0xcc,0x00,0x00,0x04},{0x00,0x33,0x00,0x04},{0x33,0x33,0x00,0x04},{0x66,0x33,0x00,0x04},
  28. {0x99,0x33,0x00,0x04},{0xcc,0x33,0x00,0x04},{0xff,0x33,0x00,0x04},{0x00,0x66,0x00,0x04},
  29. {0x33,0x66,0x00,0x04},{0x66,0x66,0x00,0x04},{0x99,0x66,0x00,0x04},{0xcc,0x66,0x00,0x04},
  30. {0xff,0x66,0x00,0x04},{0x00,0x99,0x00,0x04},{0x33,0x99,0x00,0x04},{0x66,0x99,0x00,0x04},
  31. //3
  32. {0x99,0x99,0x00,0x04},{0xcc,0x99,0x00,0x04},{0xff,0x99,0x00,0x04},{0x00,0xcc,0x00,0x04},
  33. {0x33,0xcc,0x00,0x04},{0x66,0xcc,0x00,0x04},{0x99,0xcc,0x00,0x04},{0xcc,0xcc,0x00,0x04},
  34. {0xff,0xcc,0x00,0x04},{0x66,0xff,0x00,0x04},{0x99,0xff,0x00,0x04},{0xcc,0xff,0x00,0x04},
  35. {0x00,0x00,0x33,0x04},{0x33,0x00,0x33,0x04},{0x66,0x00,0x33,0x04},{0x99,0x00,0x33,0x04},
  36. //4
  37. {0xcc,0x00,0x33,0x04},{0xff,0x00,0x33,0x04},{0x00,0x33,0x33,0x04},{0x33,0x33,0x33,0x04},
  38. {0x66,0x33,0x33,0x04},{0x99,0x33,0x33,0x04},{0xcc,0x33,0x33,0x04},{0xff,0x33,0x33,0x04},
  39. {0x00,0x66,0x33,0x04},{0x33,0x66,0x33,0x04},{0x66,0x66,0x33,0x04},{0x99,0x66,0x33,0x04},
  40. {0xcc,0x66,0x33,0x04},{0xff,0x66,0x33,0x04},{0x00,0x99,0x33,0x04},{0x33,0x99,0x33,0x04},
  41. //5
  42. {0x66,0x99,0x33,0x04},{0x99,0x99,0x33,0x04},{0xcc,0x99,0x33,0x04},{0xff,0x99,0x33,0x04},
  43. {0x00,0xcc,0x33,0x04},{0x33,0xcc,0x33,0x04},{0x66,0xcc,0x33,0x04},{0x99,0xcc,0x33,0x04},
  44. {0xcc,0xcc,0x33,0x04},{0xff,0xcc,0x33,0x04},{0x33,0xff,0x33,0x04},{0x66,0xff,0x33,0x04},
  45. {0x99,0xff,0x33,0x04},{0xcc,0xff,0x33,0x04},{0xff,0xff,0x33,0x04},{0x00,0x00,0x66,0x04},
  46. //6
  47. {0x33,0x00,0x66,0x04},{0x66,0x00,0x66,0x04},{0x99,0x00,0x66,0x04},{0xcc,0x00,0x66,0x04},
  48. {0xff,0x00,0x66,0x04},{0x00,0x33,0x66,0x04},{0x33,0x33,0x66,0x04},{0x66,0x33,0x66,0x04},
  49. {0x99,0x33,0x66,0x04},{0xcc,0x33,0x66,0x04},{0xff,0x33,0x66,0x04},{0x00,0x66,0x66,0x04},
  50. {0x33,0x66,0x66,0x04},{0x66,0x66,0x66,0x04},{0x99,0x66,0x66,0x04},{0xcc,0x66,0x66,0x04},
  51. //7
  52. {0x00,0x99,0x66,0x04},{0x33,0x99,0x66,0x04},{0x66,0x99,0x66,0x04},{0x99,0x99,0x66,0x04},
  53. {0xcc,0x99,0x66,0x04},{0xff,0x99,0x66,0x04},{0x00,0xcc,0x66,0x04},{0x33,0xcc,0x66,0x04},
  54. {0x99,0xcc,0x66,0x04},{0xcc,0xcc,0x66,0x04},{0xff,0xcc,0x66,0x04},{0x00,0xff,0x66,0x04},
  55. {0x33,0xff,0x66,0x04},{0x99,0xff,0x66,0x04},{0xcc,0xff,0x66,0x04},{0xff,0x00,0xcc,0x04},
  56. //8
  57. {0xcc,0x00,0xff,0x04},{0x00,0x99,0x99,0x04},{0x99,0x33,0x99,0x04},{0x99,0x00,0x99,0x04},
  58. {0xcc,0x00,0x99,0x04},{0x00,0x00,0x99,0x04},{0x33,0x33,0x99,0x04},{0x66,0x00,0x99,0x04},
  59. {0xcc,0x33,0x99,0x04},{0xff,0x00,0x99,0x04},{0x00,0x66,0x99,0x04},{0x33,0x66,0x99,0x04},
  60. {0x66,0x33,0x99,0x04},{0x99,0x66,0x99,0x04},{0xcc,0x66,0x99,0x04},{0xff,0x33,0x99,0x04},
  61. //9
  62. {0x33,0x99,0x99,0x04},{0x66,0x99,0x99,0x04},{0x99,0x99,0x99,0x04},{0xcc,0x99,0x99,0x04},
  63. {0xff,0x99,0x99,0x04},{0x00,0xcc,0x99,0x04},{0x33,0xcc,0x99,0x04},{0x66,0xcc,0x66,0x04},
  64. {0x99,0xcc,0x99,0x04},{0xcc,0xcc,0x99,0x04},{0xff,0xcc,0x99,0x04},{0x00,0xff,0x99,0x04},
  65. {0x33,0xff,0x99,0x04},{0x66,0xcc,0x99,0x04},{0x99,0xff,0x99,0x04},{0xcc,0xff,0x99,0x04},
  66. //a
  67. {0xff,0xff,0x99,0x04},{0x00,0x00,0xcc,0x04},{0x33,0x00,0x99,0x04},{0x66,0x00,0xcc,0x04},
  68. {0x99,0x00,0xcc,0x04},{0xcc,0x00,0xcc,0x04},{0x00,0x33,0x99,0x04},{0x33,0x33,0xcc,0x04},
  69. {0x66,0x33,0xcc,0x04},{0x99,0x33,0xcc,0x04},{0xcc,0x33,0xcc,0x04},{0xff,0x33,0xcc,0x04},
  70. {0x00,0x66,0xcc,0x04},{0x33,0x66,0xcc,0x04},{0x66,0x66,0x99,0x04},{0x99,0x66,0xcc,0x04},
  71. //b
  72. {0xcc,0x66,0xcc,0x04},{0xff,0x66,0x99,0x04},{0x00,0x99,0xcc,0x04},{0x33,0x99,0xcc,0x04},
  73. {0x66,0x99,0xcc,0x04},{0x99,0x99,0xcc,0x04},{0xcc,0x99,0xcc,0x04},{0xff,0x99,0xcc,0x04},
  74. {0x00,0xcc,0xcc,0x04},{0x33,0xcc,0xcc,0x04},{0x66,0xcc,0xcc,0x04},{0x99,0xcc,0xcc,0x04},
  75. {0xcc,0xcc,0xcc,0x04},{0xff,0xcc,0xcc,0x04},{0x00,0xff,0xcc,0x04},{0x33,0xff,0xcc,0x04},
  76. //c
  77. {0x66,0xff,0x99,0x04},{0x99,0xff,0xcc,0x04},{0xcc,0xff,0xcc,0x04},{0xff,0xff,0xcc,0x04},
  78. {0x33,0x00,0xcc,0x04},{0x66,0x00,0xff,0x04},{0x99,0x00,0xff,0x04},{0x00,0x33,0xcc,0x04},
  79. {0x33,0x33,0xff,0x04},{0x66,0x33,0xff,0x04},{0x99,0x33,0xff,0x04},{0xcc,0x33,0xff,0x04},
  80. {0xff,0x33,0xff,0x04},{0x00,0x66,0xff,0x04},{0x33,0x66,0xff,0x04},{0x66,0x66,0xcc,0x04},
  81. //d
  82. {0x99,0x66,0xff,0x04},{0xcc,0x66,0xff,0x04},{0xff,0x66,0xcc,0x04},{0x00,0x99,0xff,0x04},
  83. {0x33,0x99,0xff,0x04},{0x66,0x99,0xff,0x04},{0x99,0x99,0xff,0x04},{0xcc,0x99,0xff,0x04},
  84. {0xff,0x99,0xff,0x04},{0x00,0xcc,0xff,0x04},{0x33,0xcc,0xff,0x04},{0x66,0xcc,0xff,0x04},
  85. {0x99,0xcc,0xff,0x04},{0xcc,0xcc,0xff,0x04},{0xff,0xcc,0xff,0x04},{0x33,0xff,0xff,0x04},
  86. //e
  87. {0x66,0xff,0xcc,0x04},{0x99,0xff,0xff,0x04},{0xcc,0xff,0xff,0x04},{0xff,0x66,0x66,0x04},
  88. {0x66,0xff,0x66,0x04},{0xff,0xff,0x66,0x04},{0x66,0x66,0xff,0x04},{0xff,0x66,0xff,0x04},
  89. {0x66,0xff,0xff,0x04},{0xA5,0x00,0x21,0x04},{0x5f,0x5f,0x5f,0x04},{0x77,0x77,0x77,0x04},
  90. {0x86,0x86,0x86,0x04},{0x96,0x96,0x96,0x04},{0xcb,0xcb,0xcb,0x04},{0xb2,0xb2,0xb2,0x04},
  91. //f
  92. {0xd7,0xd7,0xd7,0x04},{0xdd,0xdd,0xdd,0x04},{0xe3,0xe3,0xe3,0x04},{0xea,0xea,0xea,0x04},
  93. {0xf1,0xf1,0xf1,0x04},{0xf8,0xf8,0xf8,0x04},{0xff,0xfb,0xf0,0x00},{0xa0,0xa0,0xa4,0x00},
  94. {0x80,0x80,0x80,0x00},{0xff,0x00,0x00,0x00},{0x00,0xff,0x00,0x00},{0xff,0xff,0x00,0x00},
  95. {0x00,0x00,0xff,0x00},{0xff,0x00,0xff,0x00},{0x00,0xff,0xff,0x00},{0xff,0xff,0xff,0x00}
  96. };
  97. //
  98. // translate RGB [3 3 2] into halftone palette index
  99. //
  100. BYTE gHalftoneColorXlate332[] = {
  101. 0x00,0x5f,0x85,0xfc,0x21,0x65,0xa6,0xfc,0x21,0x65,0xa6,0xcd,0x27,0x6b,0x8a,0xcd,
  102. 0x2d,0x70,0x81,0xd3,0x33,0x76,0x95,0xd9,0x33,0x76,0x95,0xd9,0xfa,0x7b,0x9b,0xfe,
  103. 0x1d,0x60,0xa2,0xfc,0x22,0x66,0x86,0xc8,0x22,0x66,0x86,0xc8,0x28,0x6c,0x8b,0xce,
  104. 0x2e,0x71,0x90,0xd4,0x34,0x77,0x96,0xda,0x34,0x77,0x96,0xda,0xfa,0x7c,0x9c,0xdf,
  105. 0x1d,0x60,0xa2,0xc5,0x22,0x66,0x86,0xc8,0x22,0x13,0x86,0xc8,0x28,0x12,0x8b,0xce,
  106. 0x2e,0x71,0x90,0xd4,0x34,0x77,0x96,0xda,0x34,0x77,0x96,0xda,0x39,0x7c,0x9c,0xdf,
  107. 0x1e,0x61,0x87,0xc5,0x23,0x67,0x8c,0xc9,0x23,0x12,0x8c,0xc9,0x29,0x6d,0xae,0xe6,
  108. 0x2f,0x72,0x91,0xd5,0x35,0x97,0x9d,0xdb,0x35,0x97,0x9d,0xdb,0x39,0xe4,0xc0,0xe8,
  109. 0x1f,0x62,0x83,0xc6,0x24,0x68,0x82,0xca,0x24,0x68,0x82,0xca,0x2a,0x6e,0x8d,0xd0,
  110. 0x30,0x73,0x92,0xd6,0x36,0x78,0xf7,0xdc,0x36,0x78,0x98,0xdc,0x3a,0x7d,0x9e,0xe1,
  111. 0x20,0x63,0x84,0x80,0x25,0x69,0x88,0xcb,0x25,0x69,0x88,0xcb,0x2b,0x6f,0x8e,0xd1,
  112. 0x31,0x74,0xf7,0xd7,0x37,0x79,0xef,0x09,0x37,0x79,0x08,0xdd,0x3b,0x7e,0x9f,0xe2,
  113. 0x20,0x63,0x84,0x80,0x25,0x69,0x88,0xcb,0x25,0x69,0x88,0xcb,0x2b,0x6f,0x8e,0xd1,
  114. 0x31,0x74,0x93,0xd7,0x37,0x79,0x99,0xdd,0x37,0x79,0x99,0xdd,0x3b,0x7e,0x9f,0xe2,
  115. 0xf9,0x64,0x89,0xfd,0x26,0x6a,0x8f,0xcc,0x26,0x17,0x8f,0xcc,0x2c,0xe3,0xb1,0xe7,
  116. 0x32,0x75,0x94,0xd8,0x38,0x7a,0x9a,0xde,0x38,0x7a,0x9a,0xde,0xfb,0xe5,0xa0,0xff
  117. };
  118. /**************************************************************************\
  119. * BLEND MACROS
  120. *
  121. *
  122. * Arguments:
  123. *
  124. *
  125. *
  126. * Return Value:
  127. *
  128. *
  129. *
  130. * History:
  131. *
  132. * 3/11/1997 Mark Enstrom [marke]
  133. *
  134. \**************************************************************************/
  135. #define INT_MULT(a,b,t) \
  136. t = ((a)*(b)) + 0x80; \
  137. t = ((((t) >> 8) + t) >> 8);
  138. #define INT_LERP(a,s,d,t) \
  139. INT_MULT((a),((s)-(d)),t); \
  140. t = t + (d);
  141. #define INT_PRELERP(a,s,d,t) \
  142. INT_MULT((a),(d),t); \
  143. t = (s) + (d) - t;
  144. /******************************Public*Routine******************************\
  145. * vPixelGeneralBlend
  146. * blend scan line of two PIXEL32 values based on BLENDFUNCTION
  147. *
  148. * This is the general case, arbitrary and non-optimized blend
  149. * functions
  150. *
  151. * Arguments:
  152. * ppixDst - address of dst pixel
  153. * ppixSrc - address of src pixel
  154. * cx - number of pixels in scan line
  155. * BlendFunction - blend to be done on each pixel
  156. * pwrMask - set each byte to 0 for pixel that doesn't
  157. * need to be written back to destination
  158. *
  159. * Return Value:
  160. *
  161. * nont
  162. *
  163. * History:
  164. *
  165. * 10/28/1996 Mark Enstrom [marke]
  166. *
  167. \**************************************************************************/
  168. VOID
  169. vPixelGeneralBlend(
  170. ALPHAPIX *ppixDst,
  171. ALPHAPIX *ppixSrc,
  172. LONG cx,
  173. BLENDFUNCTION BlendFunction,
  174. PBYTE pwrMask
  175. )
  176. {
  177. ALPHAPIX pixRet;
  178. ALPHAPIX pixSrc;
  179. ALPHAPIX pixDst;
  180. BYTE sR,sG,sB,sA;
  181. BYTE dR,dG,dB,dA;
  182. int iTmp;
  183. while (cx--)
  184. {
  185. pixSrc = *ppixSrc;
  186. pixDst = *ppixDst;
  187. switch (BlendFunction.SourceBlend)
  188. {
  189. case AC_ZERO:
  190. sR = 0;
  191. sG = 0;
  192. sB = 0;
  193. sA = 0;
  194. break;
  195. case AC_ONE:
  196. sR = pixSrc.pix.r;
  197. sG = pixSrc.pix.g;
  198. sB = pixSrc.pix.b;
  199. sA = pixSrc.pix.a;
  200. break;
  201. case AC_SRC_ALPHA:
  202. if (pixSrc.pix.a == 0)
  203. {
  204. sR = 0;
  205. sG = 0;
  206. sB = 0;
  207. sA = 0;
  208. }
  209. else if (pixSrc.pix.a == 255)
  210. {
  211. sR = pixSrc.pix.r;
  212. sG = pixSrc.pix.g;
  213. sB = pixSrc.pix.b;
  214. sA = 255;
  215. }
  216. else
  217. {
  218. int Temp;
  219. INT_MULT(pixSrc.pix.r,pixSrc.pix.a,Temp);
  220. sR = Temp;
  221. INT_MULT(pixSrc.pix.g,pixSrc.pix.a,Temp);
  222. sG = Temp;
  223. INT_MULT(pixSrc.pix.b,pixSrc.pix.a,Temp);
  224. sB = Temp;
  225. INT_MULT(pixSrc.pix.a,pixSrc.pix.a,Temp);
  226. sA = Temp;
  227. }
  228. break;
  229. case AC_DST_COLOR:
  230. case AC_ONE_MINUS_DST_COLOR:
  231. {
  232. ALPHAPIX paltDst = pixDst;
  233. int Temp;
  234. if (BlendFunction.SourceBlend == AC_ONE_MINUS_DST_COLOR)
  235. {
  236. paltDst.pix.r = 255 - pixDst.pix.r;
  237. paltDst.pix.g = 255 - pixDst.pix.g;
  238. paltDst.pix.b = 255 - pixDst.pix.b;
  239. paltDst.pix.a = 255 - pixDst.pix.a;
  240. }
  241. INT_MULT(pixDst.pix.r,pixSrc.pix.r,Temp);
  242. sR = Temp;
  243. INT_MULT(pixDst.pix.g,pixSrc.pix.g,Temp);
  244. sG = Temp;
  245. INT_MULT(pixDst.pix.b,pixSrc.pix.b,Temp);
  246. sB = Temp;
  247. INT_MULT(pixDst.pix.a,pixSrc.pix.a,Temp);
  248. sA = Temp;
  249. }
  250. break;
  251. case AC_SRC_OVER:
  252. case AC_SRC_UNDER:
  253. WARNING("General blend doesn't operate on OVER and UNDER\n");
  254. break;
  255. default:
  256. RIP("Error in source alpha blend function\n");
  257. }
  258. //
  259. // destination blend
  260. //
  261. switch (BlendFunction.DestinationBlend)
  262. {
  263. case AC_ZERO:
  264. dR = 0;
  265. dG = 0;
  266. dB = 0;
  267. dA = 0;
  268. break;
  269. case AC_ONE:
  270. dR = pixDst.pix.r;
  271. dG = pixDst.pix.g;
  272. dB = pixDst.pix.b;
  273. dA = pixDst.pix.a;
  274. break;
  275. case AC_SRC_ALPHA:
  276. case AC_ONE_MINUS_SRC_ALPHA:
  277. {
  278. BYTE Alpha = pixSrc.pix.a;
  279. int Temp;
  280. if (BlendFunction.DestinationBlend == AC_ONE_MINUS_SRC_ALPHA)
  281. {
  282. Alpha = 255 - Alpha;
  283. }
  284. INT_MULT(pixDst.pix.r,Alpha,Temp);
  285. dR = Temp;
  286. INT_MULT(pixDst.pix.g,Alpha,Temp);
  287. dG = Temp;
  288. INT_MULT(pixDst.pix.b,Alpha,Temp);
  289. dB = Temp;
  290. INT_MULT(pixDst.pix.a,Alpha,Temp);
  291. dA = Temp;
  292. }
  293. break;
  294. case AC_SRC_COLOR:
  295. case AC_ONE_MINUS_SRC_COLOR:
  296. {
  297. ALPHAPIX paltSrc = pixSrc;
  298. int Temp;
  299. if (BlendFunction.DestinationBlend == AC_ONE_MINUS_SRC_COLOR)
  300. {
  301. paltSrc.pix.r = 255 - pixSrc.pix.r;
  302. paltSrc.pix.g = 255 - pixSrc.pix.g;
  303. paltSrc.pix.b = 255 - pixSrc.pix.b;
  304. paltSrc.pix.a = 255 - pixSrc.pix.a;
  305. }
  306. INT_MULT(pixDst.pix.r,paltSrc.pix.r,Temp);
  307. dR = Temp;
  308. INT_MULT(pixDst.pix.g,paltSrc.pix.g,Temp);
  309. dG = Temp;
  310. INT_MULT(pixDst.pix.b,paltSrc.pix.b,Temp);
  311. dB = Temp;
  312. INT_MULT(pixDst.pix.a,paltSrc.pix.a,Temp);
  313. dA = Temp;
  314. }
  315. break;
  316. case AC_SRC_OVER:
  317. case AC_SRC_UNDER:
  318. WARNING("General blend doesn't operate on OVER and UNDER\n");
  319. break;
  320. default:
  321. RIP("Error in source alpha blend function\n");
  322. }
  323. pixRet.pix.r = sR + dR;
  324. pixRet.pix.g = sG + dG;
  325. pixRet.pix.b = sB + dB;
  326. pixRet.pix.a = sA + dA;
  327. *ppixDst = pixRet;
  328. ppixSrc++;
  329. ppixDst++;
  330. }
  331. }
  332. /**************************************************************************\
  333. * vPixelOver
  334. *
  335. * optimized routine used when the blend function is SRC_OVER and the
  336. * SourceConstantAlpha is 255.
  337. *
  338. * Dst = Src + (1-SrcAlpha) * Dst
  339. *
  340. * Arguments:
  341. *
  342. * ppixDst - address of dst pixel
  343. * ppixSrc - address of src pixel
  344. * cx - number of pixels in scan line
  345. * BlendFunction - blend to be done on each pixel
  346. * pwrMask - set each byte to 0 for pixel that doesn't need
  347. * to be written to dst
  348. *
  349. * Return Value:
  350. *
  351. * none
  352. *
  353. * History:
  354. *
  355. * 1/23/1997 Mark Enstrom [marke]
  356. *
  357. \**************************************************************************/
  358. #if !defined(_X86_)
  359. VOID
  360. vPixelOver(
  361. ALPHAPIX *ppixDst,
  362. ALPHAPIX *ppixSrc,
  363. LONG cx,
  364. BLENDFUNCTION BlendFunction,
  365. PBYTE pwrMask
  366. )
  367. {
  368. ALPHAPIX pixSrc;
  369. ALPHAPIX pixDst;
  370. while (cx--)
  371. {
  372. pixSrc = *ppixSrc;
  373. if (pixSrc.pix.a != 0)
  374. {
  375. pixDst = *ppixDst;
  376. if (pixSrc.pix.a == 255)
  377. {
  378. pixDst = pixSrc;
  379. }
  380. else
  381. {
  382. //
  383. // Dst = Src + (1-SrcAlpha) * Dst
  384. //
  385. ULONG Multa = 255 - pixSrc.pix.a;
  386. ULONG _D1_00AA00GG = (pixDst.ul & 0xff00ff00) >> 8;
  387. ULONG _D1_00RR00BB = (pixDst.ul & 0x00ff00ff);
  388. ULONG _D2_AAAAGGGG = _D1_00AA00GG * Multa + 0x00800080;
  389. ULONG _D2_RRRRBBBB = _D1_00RR00BB * Multa + 0x00800080;
  390. ULONG _D3_00AA00GG = (_D2_AAAAGGGG & 0xff00ff00) >> 8;
  391. ULONG _D3_00RR00BB = (_D2_RRRRBBBB & 0xff00ff00) >> 8;
  392. ULONG _D4_AA00GG00 = (_D2_AAAAGGGG + _D3_00AA00GG) & 0xFF00FF00;
  393. ULONG _D4_00RR00BB = ((_D2_RRRRBBBB + _D3_00RR00BB) & 0xFF00FF00) >> 8;
  394. pixDst.ul = pixSrc.ul + _D4_AA00GG00 + _D4_00RR00BB;
  395. }
  396. *ppixDst = pixDst;
  397. }
  398. else
  399. {
  400. *pwrMask = 0;
  401. }
  402. pwrMask++;
  403. ppixSrc++;
  404. ppixDst++;
  405. }
  406. }
  407. #endif
  408. /**************************************************************************\
  409. * vPixelBlendOrDissolveOver
  410. *
  411. * Blend routine when the blend function is SRC_OVER, but when
  412. * SourceConstantAlpah != 255 and The source bitmap does have alpha values
  413. *
  414. * if SrcAlpha == 255 then
  415. * (Blend)
  416. * Dst = Dst + ConstAlpha * (Src - Dst)
  417. *
  418. * else
  419. * (Dissolve)
  420. * Src = Src * ConstAlpha
  421. * (Over)
  422. * Dst = Src + (1 - SrcAlpha) Dst
  423. *
  424. * Arguments:
  425. *
  426. * ppixDst - address of dst pixel
  427. * ppixSrc - address of src pixel
  428. * cx - number of pixels in scan line
  429. * BlendFunction - blend to be done on each pixel
  430. * pwrMask - set each byte to 0 for pixel that doesn't need
  431. * to be written to dst
  432. *
  433. * Return Value:
  434. *
  435. * None
  436. *
  437. * History:
  438. *
  439. * 3/12/1997 Mark Enstrom [marke]
  440. *
  441. \**************************************************************************/
  442. VOID
  443. vPixelBlendOrDissolveOver(
  444. ALPHAPIX *ppixDst,
  445. ALPHAPIX *ppixSrc,
  446. LONG cx,
  447. BLENDFUNCTION BlendFunction,
  448. PBYTE pwrMask
  449. )
  450. {
  451. ALPHAPIX pixSrc;
  452. ALPHAPIX pixDst;
  453. BYTE ConstAlpha = BlendFunction.SourceConstantAlpha;
  454. while (cx--)
  455. {
  456. pixSrc = *ppixSrc;
  457. if (pixSrc.pix.a != 0)
  458. {
  459. pixDst = *ppixDst;
  460. if (pixSrc.pix.a == 255)
  461. {
  462. //
  463. // Blend: D = sA * S + (1-sA) * D
  464. //
  465. // red and blue
  466. //
  467. ULONG uB00rr00bb = pixDst.ul & 0x00ff00ff;
  468. ULONG uF00rr00bb = pixSrc.ul & 0x00ff00ff;
  469. ULONG uMrrrrbbbb = ((uB00rr00bb<<8)-uB00rr00bb) +
  470. (ConstAlpha * (uF00rr00bb - uB00rr00bb)) + 0x00800080;
  471. ULONG uM00rr00bb = (uMrrrrbbbb & 0xff00ff00) >> 8;
  472. ULONG uD00rr00bb = ((uMrrrrbbbb+uM00rr00bb) & 0xff00ff00)>>8;
  473. //
  474. // alpha and green
  475. //
  476. ULONG uB00aa00gg = (pixDst.ul >> 8) & 0xff00ff;
  477. ULONG uF00aa00gg = (pixSrc.ul >> 8) & 0xff00ff;
  478. ULONG uMaaaagggg = ((uB00aa00gg <<8)-uB00aa00gg) +
  479. (ConstAlpha * (uF00aa00gg-uB00aa00gg)) + 0x00800080;
  480. ULONG uM00aa00gg = (uMaaaagggg & 0xff00ff00)>>8;
  481. ULONG uDaa00gg00 = (uMaaaagggg + uM00aa00gg) & 0xff00ff00;
  482. pixDst.ul = uD00rr00bb + uDaa00gg00;
  483. }
  484. else
  485. {
  486. //
  487. // disolve
  488. //
  489. ULONG ul_B_00AA00GG = (pixSrc.ul & 0xff00ff00) >> 8;
  490. ULONG ul_B_00RR00BB = (pixSrc.ul & 0x00ff00ff);
  491. ULONG ul_T_AAAAGGGG = ul_B_00AA00GG * ConstAlpha + 0x00800080;
  492. ULONG ul_T_RRRRBBBB = ul_B_00RR00BB * ConstAlpha + 0x00800080;
  493. ULONG ul_T_00AA00GG = (ul_T_AAAAGGGG & 0xFF00FF00) >> 8;
  494. ULONG ul_T_00RR00BB = (ul_T_RRRRBBBB & 0xFF00FF00) >> 8;
  495. ULONG ul_C_AA00GG00 = ((ul_T_AAAAGGGG + ul_T_00AA00GG) & 0xFF00FF00);
  496. ULONG ul_C_00RR00BB = ((ul_T_RRRRBBBB + ul_T_00RR00BB) & 0xFF00FF00) >> 8;
  497. pixSrc.ul = (ul_C_AA00GG00 | ul_C_00RR00BB);
  498. //
  499. // over
  500. //
  501. ULONG Multa = 255 - pixSrc.pix.a;
  502. ULONG _D1_00AA00GG = (pixDst.ul & 0xff00ff00) >> 8;
  503. ULONG _D1_00RR00BB = (pixDst.ul & 0x00ff00ff);
  504. ULONG _D2_AAAAGGGG = _D1_00AA00GG * Multa + 0x00800080;
  505. ULONG _D2_RRRRBBBB = _D1_00RR00BB * Multa + 0x00800080;
  506. ULONG _D3_00AA00GG = (_D2_AAAAGGGG & 0xff00ff00) >> 8;
  507. ULONG _D3_00RR00BB = (_D2_RRRRBBBB & 0xff00ff00) >> 8;
  508. ULONG _D4_AA00GG00 = (_D2_AAAAGGGG + _D3_00AA00GG) & 0xFF00FF00;
  509. ULONG _D4_00RR00BB = ((_D2_RRRRBBBB + _D3_00RR00BB) & 0xFF00FF00) >> 8;
  510. pixDst.ul = pixSrc.ul + _D4_AA00GG00 + _D4_00RR00BB;
  511. }
  512. *ppixDst = pixDst;
  513. }
  514. else
  515. {
  516. *pwrMask = 0;
  517. }
  518. pwrMask++;
  519. ppixSrc++;
  520. ppixDst++;
  521. }
  522. }
  523. #if !defined(_X86_)
  524. /******************************Public*Routine******************************\
  525. * vPixelBlend
  526. *
  527. * Blend function used then BlendFunction is SRC_OVER and
  528. * SourceConstantAlpha != 255, and Src image does NOT have
  529. * it's own alpha channel. (assume 255)
  530. *
  531. * Dst = Dst + ConstAlpha * (Src - Dst)
  532. *
  533. * Arguments:
  534. *
  535. * ppixDst - address of dst pixel
  536. * ppixSrc - address of src pixel
  537. * cx - number of pixels in scan line
  538. * BlendFunction - blend to be done on each pixel
  539. * pwrMask - set each byte to 0 for pixel that doesn't need
  540. * to be written to dst
  541. *
  542. * Return Value:
  543. *
  544. * None
  545. *
  546. * History:
  547. *
  548. * 12/2/1996 Mark Enstrom [marke]
  549. *
  550. \**************************************************************************/
  551. VOID
  552. vPixelBlend(
  553. ALPHAPIX *ppixDst,
  554. ALPHAPIX *ppixSrc,
  555. LONG cx,
  556. BLENDFUNCTION BlendFunction,
  557. PBYTE pwrMask
  558. )
  559. {
  560. PULONG pulSrc = (PULONG)ppixSrc;
  561. PULONG pulDst = (PULONG)ppixDst;
  562. PULONG pulSrcEnd = pulSrc + cx;
  563. BYTE ConstAlpha = BlendFunction.SourceConstantAlpha;
  564. //
  565. // Blend: D = sA * S + (1-sA) * D
  566. //
  567. while (pulSrc != pulSrcEnd)
  568. {
  569. ULONG ulDst = *pulDst;
  570. ULONG ulSrc = *pulSrc;
  571. ULONG uB00rr00bb = ulDst & 0x00ff00ff;
  572. ULONG uF00rr00bb = ulSrc & 0x00ff00ff;
  573. ULONG uMrrrrbbbb;
  574. ULONG uM00rr00bb;
  575. ULONG uD00rr00bb;
  576. ULONG uB00aa00gg;
  577. ULONG uF00aa00gg;
  578. ULONG uMaaaagggg;
  579. ULONG uM00aa00gg;
  580. ULONG uDaa00gg00;
  581. //
  582. // red and blue
  583. //
  584. uB00rr00bb = ulDst & 0x00ff00ff;
  585. uF00rr00bb = ulSrc & 0x00ff00ff;
  586. uMrrrrbbbb = ((uB00rr00bb<<8)-uB00rr00bb) +
  587. (ConstAlpha * (uF00rr00bb - uB00rr00bb)) + 0x00800080;
  588. uM00rr00bb = (uMrrrrbbbb & 0xff00ff00) >> 8;
  589. uD00rr00bb = ((uMrrrrbbbb+uM00rr00bb) & 0xff00ff00)>>8;
  590. //
  591. // alpha and green
  592. //
  593. uB00aa00gg = (ulDst >> 8) & 0xff00ff;
  594. uF00aa00gg = (ulSrc >> 8) & 0xff00ff;
  595. uMaaaagggg = ((uB00aa00gg <<8)-uB00aa00gg) +
  596. (ConstAlpha * (uF00aa00gg-uB00aa00gg)) + 0x00800080;
  597. uM00aa00gg = (uMaaaagggg & 0xff00ff00)>>8;
  598. uDaa00gg00 = (uMaaaagggg + uM00aa00gg) & 0xff00ff00;
  599. *pulDst = uD00rr00bb + uDaa00gg00;
  600. pulSrc++;
  601. pulDst++;
  602. }
  603. }
  604. #endif
  605. #if defined(_X86_)
  606. typedef unsigned __int64 QWORD;
  607. /**************************************************************************
  608. THIS FUNCTION DOES NOT DO ANY PARAMETER VALIDATION
  609. DO NOT CALL THIS FUNCTION WITH WIDTH == 0
  610. This function operates on 32 bit pixels (BGRA) in a row of a bitmap.
  611. This function performs the following:
  612. SrcTran = 255 - pixSrc.a
  613. pixDst.r = pixSrc.r + (((SrcTran * pixDst.r)+127)/255);
  614. pixDst.g = pixSrc.g + (((SrcTran * pixDst.g)+127)/255);
  615. pixDst.b = pixSrc.b + (((SrcTran * pixDst.b)+127)/255);
  616. pixDst.a = pixSrc.a + (((SrcTran * pixDst.a)+127)/255);
  617. pDst is assumed to be aligned to a DWORD boundary when passed to this function.
  618. Step 1:
  619. Check pDst for QWORD alignment. If aligned, do Step 2. If unaligned, do first pixel
  620. as a DWORD, then do Step 2.
  621. Step 2:
  622. QuadAligned
  623. pDst is QWORD aligned. If two pixels can be done as a QWORD, do Step 3. If only one
  624. pixel left, do as a DWORD.
  625. Step 3:
  626. Load two source pixels, S1 and S2. Get (255 - alpha value) for each source pixel, 255-S1a and 255-S2a.
  627. Copy 255-S1a as four words into an MMX register. Copy 255-S2a as four words into an MMX register.
  628. Load two destination pixels, D1 and D2. Expand each byte in D1 into four words
  629. of an MMX register. If at least four pixels can be done, do Step 4. If not, jump over
  630. FourPixelsPerPass and finish doing two pixels at TwoPixelsLeft, Step 5.
  631. Step 4:
  632. FourPixelsPerPass
  633. Expand each byte in D2 into four words of an MMX register. Multiply each byte
  634. of D1 by 255-S1a. Multiply each byte of D2 by 255-S2a. Add 128 to each intermediate result
  635. of both pixels. Copy the results of each pixel into an MMX register. Shift each result of
  636. both pixels by 8. Add the shifted results to the copied results. Shift these results by 8.
  637. Pack the results into one MMX register. Add the packed results to the source pixels. Store result
  638. over destination pixels. Stay in FourPixelsPerPass loop until there are less than four pixels to do.
  639. Step 5:
  640. TwoPixelsLeft
  641. Do same as Step 4 above; but do not loop.
  642. Step 6:
  643. OnePixelLeft
  644. If there is one pixel left (odd number of original pixels) do last pixel as a DWORD.
  645. **************************************************************************/
  646. VOID
  647. mmxPixelOver(
  648. ALPHAPIX *pDst,
  649. ALPHAPIX *pSrc,
  650. LONG Width,
  651. BLENDFUNCTION BlendFunction,
  652. PBYTE pwrMask)
  653. {
  654. static QWORD W128 = 0x0080008000800080;
  655. static QWORD AlphaMask = 0x000000FF000000FF;
  656. _asm
  657. {
  658. mov esi, pSrc
  659. mov edi, pDst
  660. movq mm7, W128 // | 0 | 128 | 0 | 128 | 0 | 128 | 0 | 128 |
  661. // This register never changes
  662. pxor mm6, mm6 // | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
  663. // This register never changes
  664. mov ecx, Width
  665. // Step 1:
  666. test edi, 7 // Test first pixel for QWORD alignment
  667. jz QuadAligned // if unaligned,
  668. jmp Do1Pixel // do first pixel only
  669. QuadAligned: // Step 2:
  670. mov eax, ecx // Save the width in eax for later (see OnePixelLeft:)
  671. shr ecx, 1 // Want to do 2 pixels (1 quad) at once, so make ecx even
  672. test ecx, ecx // Make sure there is at least 1 quad to do
  673. jz OnePixelLeft // If we take this jump, width was 1 (aligned) or 2 (unaligned)
  674. // Step 3:
  675. movq mm0, [esi] // | S2a | S2r | S2g | S2b | S1a | S1r | S1g | S1b |
  676. psrld mm0, 24 // | 0 | 0 | 0 | S2a | 0 | 0 | 0 | S1a |
  677. pxor mm0, AlphaMask // | 0 | 0 | 0 |255-S2a| 0 | 0 | 0 |255-S1a|
  678. movq mm1, mm0 // | 0 | 0 | 0 |255-S2a| 0 | 0 | 0 |255-S1a|
  679. punpcklwd mm0, mm0 // | 0 | 0 | 255-S1a | 255-S1a |
  680. movq mm2, [edi] // | D2a | D2r | D2g | D2b | D1a | D1r | D1g | D1b |
  681. punpckhwd mm1, mm1 // | 0 | 0 | 255-S2a | 255-S2a |
  682. movq mm3, mm2 // | D2a | D2r | D2g | D2b | D1a | D1r | D1g | D1b |
  683. punpckldq mm0, mm0 // | 255-S1a | 255-S1a | 255-S1a | 255-S1a |
  684. punpckldq mm1, mm1 // | 255-S2a | 255-S2a | 255-S2a | 255-S2a |
  685. punpcklbw mm2, mm6 // | 0 | D1a | 0 | D1r | 0 | D1g | 0 | D1b |
  686. dec ecx
  687. jz TwoPixelsLeft
  688. FourPixelsPerPass: // Step 4:
  689. // Indenting indicates operations on the next set of pixels
  690. // Within this loop, instructions will pair as shown for the Pentium processor
  691. // T1 = 255-S1a T2 = 255-S2a
  692. punpckhbw mm3, mm6 // | 0 | D2a | 0 | D2r | 0 | D2g | 0 | D2b |
  693. pmullw mm2, mm0 // | T1*D1a | T1*D1r | T1*D1g | T1*D1b |
  694. movq mm0, [esi+8] // | S2a | S2r | S2g | S2b | S1a | S1r | S1g | S1b |
  695. pmullw mm3, mm1 // | T2*D2a | T2*D2r | T2*D2g | T2*D2b |
  696. psrld mm0, 24 // | 0 | 0 | 0 | S2a | 0 | 0 | 0 | S1a |
  697. add esi, 8 // pSrc++;
  698. pxor mm0, AlphaMask // | 0 | 0 | 0 |255-S2a| 0 | 0 | 0 |255-S1a|
  699. paddusw mm2, mm7 // |T1*D1a+128 |T1*D1r+128 |T1*D1g+128 |T1*D1b+128 |
  700. paddusw mm3, mm7 // |T2*D2a+128 |T2*D2r+128 |T2*D2g+128 |T2*D2b+128 |
  701. movq mm1, mm0 // | 0 | 0 | 0 |255-S2a| 0 | 0 | 0 |255-S1a|
  702. movq mm4, mm2 // |T1*D1a+128 |T1*D1r+128 |T1*D1g+128 |T1*D1b+128 |
  703. punpcklwd mm0, mm0 // | 0 | 0 | 255-S1a | 255-S1a |
  704. movq mm5, mm3 // |T2*D2a+128 |T2*D2r+128 |T2*D2g+128 |T2*D2b+128 |
  705. punpckhwd mm1, mm1 // | 0 | 0 | 255-S2a | 255-S2a |
  706. // TDXx' = TX*DXx+128
  707. psrlw mm2, 8 // | TD1a'>>8 | TD1r'>>8 | TD1g'>>8 | TD1b'>>8 |
  708. // TDXx" = (TX*DXx+128)+(TDXx'>>8)
  709. psrlw mm3, 8 // | TD2a'>>8 | TD2r'>>8 | TD2g'>>8 | TD2b'>>8 |
  710. paddusw mm4, mm2 // | TD1a" | TD1r" | TD1g" | TD1b" |
  711. paddusw mm5, mm3 // | TD2a" | TD2r" | TD2g" | TD2b" |
  712. psrlw mm4, 8 // | TD1a">>8 | TD1r">>8 | TD1g">>8 | TD1b">>8 |
  713. movq mm2, [edi+8] // | D2a | D2r | D2g | D2b | D1a | D1r | D1g | D1b |
  714. psrlw mm5, 8 // | TD2a">>8 | TD2r">>8 | TD2g">>8 | TD2b">>8 |
  715. movq mm3, mm2 // | D2a | D2r | D2g | D2b | D1a | D1r | D1g | D1b |
  716. packuswb mm4, mm5 // |TD2a'"|TD2r'"|TD2g'"|TD2b'"|TD1a'"|TD1r'"|TD1g'"|TD1b'"|
  717. paddusb mm4, [esi-8]
  718. punpckldq mm0, mm0 // | 255-S1a | 255-S1a | 255-S1a | 255-S1a |
  719. movq [edi], mm4
  720. punpckldq mm1, mm1 // | 255-S2a | 255-S2a | 255-S2a | 255-S2a |
  721. punpcklbw mm2, mm6 // | 0 | D1a | 0 | D1r | 0 | D1g | 0 | D1b |
  722. add edi, 8 // pDst++;
  723. dec ecx
  724. jnz FourPixelsPerPass
  725. TwoPixelsLeft: // Step 5:
  726. punpckhbw mm3, mm6 // | 0 | D2a | 0 | D2r | 0 | D2g | 0 | D2b |
  727. pmullw mm2, mm0 // | T1*D1a | T1*D1r | T1*D1g | T1*D1b |
  728. pmullw mm3, mm1 // | T2*D2a | T2*D2r | T2*D2g | T2*D2b |
  729. paddusw mm2, mm7 // |T1*D1a+128 |T1*D1r+128 |T1*D1g+128 |T1*D1b+128 |
  730. paddusw mm3, mm7 // |T2*D2a+128 |T2*D2r+128 |T2*D2g+128 |T2*D2b+128 |
  731. movq mm4, mm2 // |T1*D1a+128 |T1*D1r+128 |T1*D1g+128 |T1*D1b+128 |
  732. movq mm5, mm3 // |T2*D2a+128 |T2*D2r+128 |T2*D2g+128 |T2*D2b+128 |
  733. psrlw mm2, 8 // | TD1a'>>8 | TD1r'>>8 | TD1g'>>8 | TD1b'>>8 |
  734. psrlw mm3, 8 // | TD2a'>>8 | TD2r'>>8 | TD2g'>>8 | TD2b'>>8 |
  735. paddusw mm4, mm2 // | TD1a" | TD1r" | TD1g" | TD1b" |
  736. paddusw mm5, mm3 // | TD2a" | TD2r" | TD2g" | TD2b" |
  737. psrlw mm4, 8 // | TD1a">>8 | TD1r">>8 | TD1g">>8 | TD1b">>8 |
  738. psrlw mm5, 8 // | TD2a">>8 | TD2r">>8 | TD2g">>8 | TD2b">>8 |
  739. packuswb mm4, mm5 // |TD2a'"|TD2r'"|TD2g'"|TD2b'"|TD1a'"|TD1r'"|TD1g'"|TD1b'"|
  740. paddusb mm4, [esi]
  741. movq [edi], mm4
  742. add edi, 8
  743. add esi, 8
  744. OnePixelLeft: // Step 6:
  745. // This tests for 0 or 1 pixel left in row - eax contains real width, not width/2
  746. // If 0, there were an even number of pixels and we're done
  747. // If 1, there is an odd number of pixels and we need to do one more
  748. test eax, 1
  749. jz Done
  750. Do1Pixel: // make as a macro if used in asm file
  751. // T = 255-S1x
  752. movd mm0, DWORD PTR[esi] // | 0 | 0 | 0 | 0 | S1a | S1r | S1g | S1b |
  753. psrld mm0, 24 // | 0 | 0 | 0 | 0 | 0 | 0 | 0 | S1a |
  754. pxor mm0, AlphaMask // | 0 | 0 | 0 | 255 | 0 | 0 | 0 |255-S1a|
  755. punpcklwd mm0, mm0 // | 0 | 0 | 255-S1a | 255-S1a |
  756. punpckldq mm0, mm0 // | 255-S1a | 255-S1a | 255-S1a | 255-S1a |
  757. movd mm1, [edi] // | 0 | 0 | 0 | 0 | D1a | D1r | D1g | D1b |
  758. punpcklbw mm1, mm6 // | 0 | D1a | 0 | D1r | 0 | D1g | 0 | D1b |
  759. pmullw mm0, mm1 // | T*D1a | T*D1r | T*D1g | T*D1b |
  760. paddusw mm0, mm7 // | T*D1a+128 | T*D1r+128 | T*D1g+128 | T*D1b+128 |
  761. movq mm1, mm0 // | T*D1a+128 | T*D1r+128 | T*D1g+128 | T*D1b+128 |
  762. psrlw mm0, 8 // | TD1a'>>8 | TD1r'>>8 | TD1g'>>8 | TD1b'>>8 |
  763. paddusw mm0, mm1 // | TD1a" | TD1r" | TD1g" | TD1b" |
  764. psrlw mm0, 8 // | TD1a">>8 | TD1r">>8 | TD1g">>8 | TD1b">>8 |
  765. movd mm1, [esi]
  766. packuswb mm0, mm0 // |TD2a'"|TD2r'"|TD2g'"|TD2b'"|TD1a'"|TD1r'"|TD1g'"|TD1b'"|
  767. paddusb mm0, mm1
  768. movd [edi], mm0
  769. add edi, 4 // pDst++;
  770. add esi, 4 // pSrc++;
  771. test ecx, ecx
  772. jz Done // just processed the last pixel of the row
  773. dec ecx
  774. jmp QuadAligned // just processed the first pixel of the row
  775. Done:
  776. emms // remove for optimizations, have calling function do emms
  777. }
  778. }
  779. /**************************************************************************\
  780. * mmxPixelBlendOrDissolveOver
  781. *
  782. * Blend routine when the blend function is SRC_OVER, but when
  783. * SourceConstantAlpah != 255 and The source bitmap does have alpha values
  784. *
  785. * if SrcAlpha == 255 then
  786. *
  787. * Dst = Dst + ConstAlpha * (Src - Dst)
  788. *
  789. * else
  790. *
  791. * Src = Src * ConstAlpha
  792. * Dst = Src + (1 - SrcAlpha) Dst
  793. *
  794. * Arguments:
  795. *
  796. * ppixDst - address of dst pixel
  797. * ppixSrc - address of src pixel
  798. * cx - number of pixels in scan line
  799. * BlendFunction - blend to be done on each pixel
  800. * pwrMask - set each byte to 0 for pixel that doesn't need
  801. * to be written to dst
  802. *
  803. * Return Value:
  804. *
  805. * None
  806. *
  807. * History:
  808. *
  809. * 3/12/1997 Mark Enstrom [marke]
  810. *
  811. \**************************************************************************/
  812. /**************************************************************************
  813. THIS FUNCTION DOES NOT DO ANY PARAMETER VALIDATION
  814. DO NOT CALL THIS FUNCTION WITH WIDTH == 0
  815. This function operates on 32 bit pixels (BGRA) in a row of a bitmap.
  816. This function performs the following:
  817. first,
  818. pixSrc.r = (((ConstAlpha * pixSrc.r)+127)/255);
  819. pixSrc.g = (((ConstAlpha * pixSrc.g)+127)/255);
  820. pixSrc.b = (((ConstAlpha * pixSrc.b)+127)/255);
  821. pixSrc.a = (((ConstAlpha * pixSrc.a)+127)/255);
  822. then,
  823. SrcTran = 255 - pixSrc.a
  824. pixDst.r = pixSrc.r + (((SrcTran * pixDst.r)+127)/255);
  825. pixDst.g = pixSrc.g + (((SrcTran * pixDst.g)+127)/255);
  826. pixDst.b = pixSrc.b + (((SrcTran * pixDst.b)+127)/255);
  827. pixDst.a = pixSrc.a + (((SrcTran * pixDst.a)+127)/255);
  828. pDst is assumed to be aligned to a DWORD boundary when passed to this function.
  829. Step 1:
  830. Check pDst for QWORD alignment. If aligned, do Step 2. If unaligned, do first pixel
  831. as a DWORD, then do Step 2.
  832. Step 2:
  833. QuadAligned
  834. pDst is QWORD aligned. If two pixels can be done as a QWORD, do Step 3. If only one
  835. pixel left, do as a DWORD.
  836. Step 3:
  837. Load two source pixels, S1 and S2, as one QWORD. Expand S1 and S2 as four words into two MMX registers.
  838. Multiply each word in S1 and S2 by ConstAlpha. Add 128 to each result of both pixels. Copy the results
  839. of each pixel into an MMX register. Shift each result of both pixels by 8. Add the shifted results
  840. to the copied results. Shift these results by 8. Pack the results into one MMX register...this will
  841. be used later.
  842. Shift the packed results by 24 to get only the alpha value for each pixel.
  843. Step 4:
  844. Get (255 - new alpha value) for each pixel, 255-S1a and 255-S2a.
  845. Copy 255-S1a as four words into an MMX register. Copy 255-S2a as four words into an MMX register.
  846. Load two destination pixels, D1 and D2. Expand D1 and D2 as four words into two MMX registers.
  847. Multiply each byte of D1 by 255-S1a. Multiply each byte of D2 by 255-S2a. Add 128 to each intermediate
  848. result of both pixels. Copy the results of each pixel into an MMX register. Shift each result of
  849. both pixels by 8. Add the shifted results to the copied results. Shift these results by 8.
  850. Pack the results into one MMX register. Add the packed results to the new source pixels saved from
  851. above. Store result over destination pixels. Stay in TwoPixelsAtOnceLoop loop until there is less than
  852. two pixels to do.
  853. Step 5:
  854. OnePixelLeft
  855. If there is one pixel left (odd number of original pixels) do last pixel as a DWORD.
  856. **************************************************************************/
  857. VOID
  858. mmxPixelBlendOrDissolveOver(
  859. ALPHAPIX *pDst,
  860. ALPHAPIX *pSrc,
  861. LONG Width,
  862. BLENDFUNCTION BlendFunction,
  863. PBYTE pwrMask
  864. )
  865. {
  866. BYTE ConstAlpha = BlendFunction.SourceConstantAlpha;
  867. static QWORD W128 = 0x0080008000800080;
  868. static QWORD AlphaMask = 0x000000FF000000FF;
  869. static QWORD Zeros = 0;
  870. _asm
  871. {
  872. mov esi, pSrc
  873. mov edi, pDst
  874. movq mm7, W128 // This register never changes
  875. pxor mm4, mm4 // This register never changes
  876. xor eax, eax
  877. mov al, ConstAlpha
  878. movd mm5, eax // | | | | CA |
  879. punpcklwd mm5, mm5 // | | | CA | CA |
  880. punpcklwd mm5, mm5 // | CA | CA | CA | CA |
  881. // This register never changes
  882. mov ecx, Width
  883. // Step 1:
  884. test edi, 7 // Test first pixel for QWORD alignment
  885. jz QuadAligned // if unaligned,
  886. jmp Do1Pixel // do first pixel only
  887. QuadAligned: // Step 2:
  888. mov eax, ecx // Save the width in eax for later (see OnePixelLeft:)
  889. shr ecx, 1 // Want to do 2 pixels (1 quad) at once, so make ecx even
  890. test ecx, ecx // Make sure there is at least 1 quad to do
  891. jz OnePixelLeft // If we take this jump, width was 1 (aligned) or 2 (unaligned)
  892. TwoPixelsAtOnceLoop: // Step 3:
  893. // Within this loop, instructions will pair as shown for the Pentium processor
  894. /* Dissolve
  895. pixSrc.r = (((ConstAlpha * pixSrc.r)+127)/255);
  896. pixSrc.g = (((ConstAlpha * pixSrc.g)+127)/255);
  897. pixSrc.b = (((ConstAlpha * pixSrc.b)+127)/255);
  898. pixSrc.a = (((ConstAlpha * pixSrc.a)+127)/255);
  899. */
  900. movq mm0, [esi] // | S2a | S2r | S2g | S2b | S1a | S1r | S1g | S1b |
  901. movq mm1, mm0 // | S2a | S2r | S2g | S2b | S1a | S1r | S1g | S1b |
  902. punpcklbw mm0, mm4 // | 0 | S1a | 0 | S1r | 0 | S1g | 0 | S1b |
  903. punpckhbw mm1, mm4 // | 0 | S2a | 0 | S2r | 0 | S2g | 0 | S2b |
  904. pmullw mm0, mm5 // | CA*S1a | CA*S1r | CA*S1g | CA*S1b |
  905. add esi, 8 // pSrc++;
  906. pmullw mm1, mm5 // | CA*S2a | CA*S2r | CA*S2g | CA*S2b |
  907. paddusw mm1, mm7 // |CA*S2a+128 |CA*S2r+128 |CA*S2g+128 |CA*S2b+128 |
  908. paddusw mm0, mm7 // |CA*S1a+128 |CA*S1r+128 |CA*S1g+128 |CA*S1b+128 |
  909. movq mm2, mm0 // |CA*S1a+128 |CA*S1r+128 |CA*S1g+128 |CA*S1b+128 |
  910. psrlw mm0, 8 // | S1a'>>8 | S1r'>>8 | S1g'>>8 | S1b'>>8 |
  911. // S1x' = CA*S1x+128 S2x' = CA*S2x+128
  912. movq mm3, mm1 // |CA*S2a+128 |CA*S2r+128 |CA*S2g+128 |CA*S2b+128 |
  913. psrlw mm1, 8 // | S2a'>>8 | S2r'>>8 | S2g'>>8 | S2b'>>8 |
  914. // S1x" = (CA*S1x+128)>>8 S2x" = (CA*S2x+128)>>8
  915. paddusw mm0, mm2 // | S1a" | S1r" | S1g" | S1b" |
  916. paddusw mm1, mm3 // | S2a" | S2r" | S2g" | S2b" |
  917. psrlw mm0, 8 // | S1a">>8 | S1r">>8 | S1g">>8 | S1b">>8 |
  918. // SXx'" = ((CA*SXx+128)>>8)>>8)
  919. psrlw mm1, 8 // | S2a">>8 | S2r">>8 | S2g">>8 | S2b">>8 |
  920. packuswb mm0, mm1 // |S2a'"|S2r'"|S2g'"|S2b'"|S1a'"|S1r'"|S1g'"|S1b'"|
  921. movq mm6, mm0
  922. psrld mm0, 24 // | 0 | 0 | 0 | S2a | 0 | 0 | 0 | S1a |
  923. /* Over
  924. SrcTran = 255 - pixSrc.a
  925. pixDst.r = pixSrc.r + (((SrcTran * pixDst.r)+128)/255);
  926. pixDst.g = pixSrc.g + (((SrcTran * pixDst.g)+128)/255);
  927. pixDst.b = pixSrc.b + (((SrcTran * pixDst.b)+128)/255);
  928. pixDst.a = pixSrc.a + (((SrcTran * pixDst.a)+128)/255);
  929. */
  930. // Step 4:
  931. pxor mm0, AlphaMask // | 0 | 0 | 0 |255-S2a| 0 | 0 | 0 |255-S1a|
  932. movq mm1, mm0 // | 0 | 0 | 0 |255-S2a| 0 | 0 | 0 |255-S1a|
  933. punpcklwd mm0, mm0 // | 0 | 0 | 255-S1a | 255-S1a |
  934. movq mm2, [edi] // | D2a | D2r | D2g | D2b | D1a | D1r | D1g | D1b |
  935. punpcklwd mm0, mm0 // | 255-S1a | 255-S1a | 255-S1a | 255-S1a |
  936. movq mm3, mm2 // | D2a | D2r | D2g | D2b | D1a | D1r | D1g | D1b |
  937. punpckhwd mm1, mm1 // | 0 | 0 | 255-S2a | 255-S2a |
  938. punpcklwd mm1, mm1 // | 255-S2a | 255-S2a | 255-S2a | 255-S2a |
  939. punpckhbw mm3, mm4 // | 0 | D2a | 0 | D2r | 0 | D2g | 0 | D2b |
  940. // T1 = 255-S1a T2 = 255-S2a
  941. punpcklbw mm2, mm4 // | 0 | D1a | 0 | D1r | 0 | D1g | 0 | D1b |
  942. pmullw mm1, mm3 // | T2*D2a | T2*D2r | T2*D2g | T2*D2b |
  943. add edi, 8 // pDst++;
  944. pmullw mm0, mm2 // | T1*D1a | T1*D1r | T1*D1g | T1*D1b |
  945. paddusw mm0, mm7 // |T1*D1a+128 |T1*D1r+128 |T1*D1g+128 |T1*D1b+128 |
  946. paddusw mm1, mm7 // |T2*D2a+128 |T2*D2r+128 |T2*D2g+128 |T2*D2b+128 |
  947. movq mm3, mm1 // |T2*D2a+128 |T2*D2r+128 |T2*D2g+128 |T2*D2b+128 |
  948. // TDXx' = TX*DXx+128
  949. psrlw mm1, 8 // | TD2a'>>8 | TD2r'>>8 | TD2g'>>8 | TD2b'>>8 |
  950. movq mm2, mm0 // |T1*D1a+128 |T1*D1r+128 |T1*D1g+128 |T1*D1b+128 |
  951. psrlw mm0, 8 // | TD1a'>>8 | TD1r'>>8 | TD1g'>>8 | TD1b'>>8 |
  952. // TDXx" = (TX*DXx+128)+(TDXx'>>8)
  953. paddusw mm1, mm3 // | TD2a" | TD2r" | TD2g" | TD2b" |
  954. paddusw mm0, mm2 // | TD1a" | TD1r" | TD1g" | TD1b" |
  955. psrlw mm1, 8 // | TD2a">>8 | TD2r">>8 | TD2g">>8 | TD2b">>8 |
  956. psrlw mm0, 8 // | TD1a">>8 | TD1r">>8 | TD1g">>8 | TD1b">>8 |
  957. packuswb mm0, mm1 // |TD2a'"|TD2r'"|TD2g'"|TD2b'"|TD1a'"|TD1r'"|TD1g'"|TD1b'"|
  958. // SXx = SXx'" TDXx = TDXx'"
  959. paddusb mm0, mm6// |S2a+TD2a|S2r+TD2r|S2g+TD2g|S2b+TD2b|S1a+TD1a|S1r+TD1r|S1g+TD1g|S1b+TD1b|
  960. movq [edi-8], mm0
  961. dec ecx
  962. jnz TwoPixelsAtOnceLoop
  963. OnePixelLeft: // Step 5:
  964. // This tests for 0 or 1 pixel left in row - eax contains real width, not width/2
  965. // If 0, there were an even number of pixels and we're done
  966. // If 1, there is an odd number of pixels and we need to do one more
  967. test eax, 1
  968. jz Done
  969. Do1Pixel: // make as a macro if used in asm file
  970. /* Dissolve
  971. pixSrc.r = (((ConstAlpha * pixSrc.r)+127)/255);
  972. pixSrc.g = (((ConstAlpha * pixSrc.g)+127)/255);
  973. pixSrc.b = (((ConstAlpha * pixSrc.b)+127)/255);
  974. pixSrc.a = (((ConstAlpha * pixSrc.a)+127)/255);
  975. */
  976. movd mm0, [esi] // | S2a | S2r | S2g | S2b | S1a | S1r | S1g | S1b |
  977. punpcklbw mm0, mm4 // | 0 | S1a | 0 | S1r | 0 | S1g | 0 | S1b |
  978. pmullw mm0, mm5 // | CA*S1a | CA*S1r | CA*S1g | CA*S1b |
  979. paddusw mm0, mm7 // |CA*S1a+128 |CA*S1r+128 |CA*S1g+128 |CA*S1b+128 |
  980. movq mm2, mm0 // |CA*S1a+128 |CA*S1r+128 |CA*S1g+128 |CA*S1b+128 |
  981. // S1x' = CA*S1x+128 S2x' = CA*S2x+128
  982. psrlw mm0, 8 // | S1a'>>8 | S1r'>>8 | S1g'>>8 | S1b'>>8 |
  983. // S1x" = (CA*S1x+128)>>8 S2x" = (CA*S2x+128)>>8
  984. paddusw mm0, mm2 // | S1a" | S1r" | S1g" | S1b" |
  985. psrlw mm0, 8 // | S1a">>8 | S1r">>8 | S1g">>8 | S1b">>8 |
  986. packuswb mm0, mm0 // |S2a'"|S2r'"|S2g'"|S2b'"|S1a'"|S1r'"|S1g'"|S1b'"|
  987. movq mm6, mm0
  988. psrld mm0, 24 // | 0 | 0 | 0 | S2a | 0 | 0 | 0 | S1a |
  989. /* Over
  990. SrcTran = 255 - pixSrc.a
  991. pixDst.r = pixSrc.r + (((SrcTran * pixDst.r)+128)/255);
  992. pixDst.g = pixSrc.g + (((SrcTran * pixDst.g)+128)/255);
  993. pixDst.b = pixSrc.b + (((SrcTran * pixDst.b)+128)/255);
  994. pixDst.a = pixSrc.a + (((SrcTran * pixDst.a)+128)/255);
  995. */
  996. pxor mm0, AlphaMask // | 0 | 0 | 0 |255-S2a| 0 | 0 | 0 |255-S1a|
  997. punpcklwd mm0, mm0 // | 0 | 0 | 0 | 0 | 0 | 0 |255-S1a|255-S1a|
  998. punpckldq mm0, mm0 // | 255-S1a| 255-S1a| 255-S1a| 255-S1a|
  999. movd mm2, [edi] // | 0 | 0 | 0 | 0 | D1a | D1r | D1g | D1b |
  1000. punpcklbw mm2, mm4 // | D1a | D1r | D1g | D1b |
  1001. // T = 255-S1x
  1002. pmullw mm0, mm2 // | T*D1a | T*D1r | T*D1g | T*D1b |
  1003. paddusw mm0, mm7 // | T*D1a+128 | T*D1r+128 | T*D1g+128 | T*D1b+128 |
  1004. movq mm1, mm0 // | T*D1a+128 | T*D1r+128 | T*D1g+128 | T*D1b+128 |
  1005. psrlw mm0, 8 // | TD1a'>>8 | TD1r'>>8 | TD1g'>>8 | TD1b'>>8 |
  1006. paddusw mm0, mm1 // | TD1a" | TD1r" | TD1g" | TD1b" |
  1007. psrlw mm0, 8
  1008. packuswb mm0, mm0 // |TD2a'"|TD2r'"|TD2g'"|TD2b'"|TD1a'"|TD1r'"|TD1g'"|TD1b'"|
  1009. paddusb mm0, mm6
  1010. movd [edi], mm0
  1011. add edi, 4 // pDst++;
  1012. add esi, 4 // pSrc++;
  1013. test ecx, ecx
  1014. jz Done // just processed the last pixel of the row
  1015. dec ecx
  1016. jmp QuadAligned // just processed the first pixel of the row
  1017. Done:
  1018. emms // remove for optimizations, have calling function do emms
  1019. }
  1020. }
  1021. #endif
  1022. /******************************Public*Routine******************************\
  1023. * AlphaScanLineBlend
  1024. *
  1025. * Blends source and destionation surfaces one scan line at a time.
  1026. *
  1027. * Allocate a scan line buffer for xlate of src to 32BGRA if needed.
  1028. * Allocate a scan line buffer for xlate of dst to 32BGRA if needed.
  1029. * Blend scan line using blend function from pAlphaDispatch
  1030. * Write scan line back to dst (if needed)
  1031. *
  1032. * Arguments:
  1033. *
  1034. * pDst - pointer to dst surface
  1035. * pDstRect - Dst output rect
  1036. * DeltaDst - dst scan line delat
  1037. * pSrc - pointer to src surface
  1038. * DeltaSrc - src scan line delta
  1039. * pptlSrc - src offset
  1040. * pxloSrcTo32 - xlateobj from src to 32BGR
  1041. * pxlo32ToDst - xlateobj from 32BGR to dst
  1042. * palDst - destination palette
  1043. * palSrc - source palette
  1044. * pAlphaDispatch - blend data and function pointers
  1045. *
  1046. * Return Value:
  1047. *
  1048. * Status
  1049. *
  1050. * History:
  1051. *
  1052. * 10/14/1996 Mark Enstrom [marke]
  1053. *
  1054. \**************************************************************************/
  1055. BOOL
  1056. AlphaScanLineBlend(
  1057. PBYTE pDst,
  1058. PRECTL pDstRect,
  1059. ULONG DeltaDst,
  1060. PBYTE pSrc,
  1061. ULONG DeltaSrc,
  1062. PPOINTL pptlSrc,
  1063. PPALINFO ppalInfoDst,
  1064. PPALINFO ppalInfoSrc,
  1065. PALPHA_DISPATCH_FORMAT pAlphaDispatch
  1066. )
  1067. {
  1068. //
  1069. // get two scanlines of RGBA data, blend pixels, store
  1070. //
  1071. LONG cx = pDstRect->right - pDstRect->left;
  1072. LONG cy = pDstRect->bottom - pDstRect->top;
  1073. LONG ScanBufferWidth = cx * 4;
  1074. LONG WriteMaskSize = cx;
  1075. LONG AllocationSize = 0;
  1076. ULONG ulSrcBytesPerPixel = pAlphaDispatch->ulSrcBitsPerPixel/8;
  1077. ULONG ulDstBytesPerPixel = pAlphaDispatch->ulDstBitsPerPixel/8;
  1078. PBYTE pjSrcTempScanBuffer = NULL;
  1079. PBYTE pjDstTempScanBuffer = NULL;
  1080. PBYTE pjAlloc = NULL;
  1081. PBYTE pjDstTmp;
  1082. PBYTE pjSrcTmp;
  1083. PBYTE pWriteMask;
  1084. //
  1085. // calculate destination starting address
  1086. //
  1087. if (ulDstBytesPerPixel)
  1088. {
  1089. pjDstTmp = pDst + ulDstBytesPerPixel * pDstRect->left + DeltaDst * pDstRect->top;
  1090. }
  1091. else if (pAlphaDispatch->ulDstBitsPerPixel == 1)
  1092. {
  1093. pjDstTmp = pDst + pDstRect->left/8 + DeltaDst * pDstRect->top;
  1094. }
  1095. else
  1096. {
  1097. pjDstTmp = pDst + pDstRect->left/2 + DeltaDst * pDstRect->top;
  1098. }
  1099. //
  1100. // calculate source starting address
  1101. //
  1102. if (ulSrcBytesPerPixel)
  1103. {
  1104. pjSrcTmp = pSrc + ulSrcBytesPerPixel * pptlSrc->x + DeltaSrc * pptlSrc->y;
  1105. }
  1106. else if (pAlphaDispatch->ulSrcBitsPerPixel == 1)
  1107. {
  1108. pjSrcTmp = pSrc + pptlSrc->x/8 + DeltaSrc * pptlSrc->y;
  1109. }
  1110. else
  1111. {
  1112. pjSrcTmp = pSrc + pptlSrc->x/2 + DeltaSrc * pptlSrc->y;
  1113. }
  1114. //
  1115. // calculate size of needed scan line buffer
  1116. //
  1117. if (pAlphaDispatch->pfnLoadSrcAndConvert != NULL)
  1118. {
  1119. AllocationSize += ScanBufferWidth;
  1120. }
  1121. if (pAlphaDispatch->pfnLoadDstAndConvert != NULL)
  1122. {
  1123. AllocationSize += ScanBufferWidth;
  1124. }
  1125. AllocationSize += WriteMaskSize;
  1126. //
  1127. // allocate scan line buffer memory
  1128. //
  1129. pWriteMask = (PBYTE)LOCALALLOC(AllocationSize);
  1130. if (pWriteMask == NULL)
  1131. {
  1132. return(FALSE);
  1133. }
  1134. PBYTE pjTemp = pWriteMask + WriteMaskSize;
  1135. if (pAlphaDispatch->pfnLoadSrcAndConvert != NULL)
  1136. {
  1137. pjSrcTempScanBuffer = pjTemp;
  1138. pjTemp += ScanBufferWidth;
  1139. }
  1140. if (pAlphaDispatch->pfnLoadDstAndConvert != NULL)
  1141. {
  1142. pjDstTempScanBuffer = pjTemp;
  1143. }
  1144. //
  1145. // Blend scan lines
  1146. //
  1147. while (cy--)
  1148. {
  1149. PBYTE pjSource = pjSrcTmp;
  1150. PBYTE pjDest = pjDstTmp;
  1151. //
  1152. // get src scan line if needed
  1153. //
  1154. if (pjSrcTempScanBuffer)
  1155. {
  1156. (*pAlphaDispatch->pfnLoadSrcAndConvert)(
  1157. (PULONG)pjSrcTempScanBuffer,
  1158. pjSrcTmp,
  1159. 0,
  1160. cx,
  1161. (PVOID)ppalInfoSrc);
  1162. pjSource = pjSrcTempScanBuffer;
  1163. }
  1164. //
  1165. // get dst scan line if needed
  1166. //
  1167. if (pjDstTempScanBuffer)
  1168. {
  1169. (*pAlphaDispatch->pfnLoadDstAndConvert)(
  1170. (PULONG)pjDstTempScanBuffer,
  1171. pjDstTmp,
  1172. 0,
  1173. cx,
  1174. (PVOID)ppalInfoDst);
  1175. pjDest = pjDstTempScanBuffer;
  1176. }
  1177. //
  1178. // blend
  1179. //
  1180. memset(pWriteMask,1,WriteMaskSize);
  1181. (*pAlphaDispatch->pfnGeneralBlend)(
  1182. (PALPHAPIX)pjDest,
  1183. (PALPHAPIX)pjSource,
  1184. cx,
  1185. pAlphaDispatch->BlendFunction,
  1186. pWriteMask
  1187. );
  1188. //
  1189. // write buffer back if needed
  1190. //
  1191. if (pjDstTempScanBuffer)
  1192. {
  1193. (*pAlphaDispatch->pfnConvertAndStore)(
  1194. pjDstTmp,
  1195. (PULONG)pjDstTempScanBuffer,
  1196. cx,
  1197. 0,
  1198. (PVOID)ppalInfoDst,
  1199. pWriteMask
  1200. );
  1201. }
  1202. pjDstTmp += DeltaDst;
  1203. pjSrcTmp += DeltaSrc;
  1204. }
  1205. //
  1206. // free any temp buffer memory
  1207. //
  1208. LOCALFREE(pWriteMask);
  1209. return(TRUE);
  1210. }
  1211. /**************************************************************************\
  1212. * bIsHalftonePalette
  1213. *
  1214. *
  1215. * Arguments:
  1216. *
  1217. *
  1218. *
  1219. * Return Value:
  1220. *
  1221. *
  1222. *
  1223. * History:
  1224. *
  1225. * 12/19/1996 Mark Enstrom [marke]
  1226. *
  1227. \**************************************************************************/
  1228. BOOL
  1229. bIsHalftonePalette(ULONG *pPalette)
  1230. {
  1231. BOOL bRet = FALSE;
  1232. if (pPalette)
  1233. {
  1234. ULONG ulIndex;
  1235. for (ulIndex=0;ulIndex<256;ulIndex++)
  1236. {
  1237. ALPHAPIX Pix;
  1238. BYTE Temp;
  1239. Pix.ul = aPalHalftone[ulIndex].ul;
  1240. //
  1241. // jsut store ht palette in rgbquad!!!
  1242. //
  1243. Temp = Pix.pix.r;
  1244. Pix.pix.r = Pix.pix.b;
  1245. Pix.pix.b = Temp;
  1246. Pix.pix.a = 0;
  1247. if ((pPalette[ulIndex] & 0x00ffffff) != Pix.ul)
  1248. {
  1249. break;
  1250. }
  1251. }
  1252. if (ulIndex == 256)
  1253. {
  1254. bRet = TRUE;
  1255. }
  1256. }
  1257. return(bRet);
  1258. }
  1259. /**************************************************************************\
  1260. * vInitializePalinfo
  1261. *
  1262. *
  1263. * Arguments:
  1264. *
  1265. *
  1266. *
  1267. * Return Value:
  1268. *
  1269. *
  1270. *
  1271. * History:
  1272. *
  1273. * 12/19/1996 Mark Enstrom [marke]
  1274. *
  1275. \**************************************************************************/
  1276. BOOL
  1277. bInitializePALINFO(
  1278. PPALINFO ppalInfo
  1279. )
  1280. {
  1281. //
  1282. // based on pmbi, set palette color flag and set translation
  1283. // routines
  1284. //
  1285. BOOL bRet = FALSE;
  1286. PBITMAPINFO pbmi = ppalInfo->pBitmapInfo;
  1287. if (pbmi == NULL)
  1288. {
  1289. return(FALSE);
  1290. }
  1291. PULONG pulColors = (PULONG)&pbmi->bmiColors[0];
  1292. ppalInfo->pxlate332 = NULL;
  1293. switch (pbmi->bmiHeader.biBitCount)
  1294. {
  1295. case 1:
  1296. {
  1297. //
  1298. // make color xlate vector
  1299. //
  1300. ULONG NumPalEntries = 2;
  1301. PBYTE pxlate = NULL;
  1302. pxlate = pGenColorXform332((PULONG)(&pbmi->bmiColors[0]),NumPalEntries);
  1303. if (pxlate)
  1304. {
  1305. ppalInfo->flPal = XPAL_1PAL;
  1306. ppalInfo->pxlate332 = pxlate;
  1307. bRet = TRUE;
  1308. }
  1309. }
  1310. break;
  1311. case 4:
  1312. {
  1313. //
  1314. // make color xlate vector
  1315. //
  1316. ULONG NumPalEntries = 16;
  1317. PBYTE pxlate = NULL;
  1318. if ((pbmi->bmiHeader.biClrUsed > 0) &&
  1319. (pbmi->bmiHeader.biClrUsed < 16))
  1320. {
  1321. NumPalEntries = pbmi->bmiHeader.biClrUsed;
  1322. }
  1323. pxlate = pGenColorXform332((PULONG)(&pbmi->bmiColors[0]),NumPalEntries);
  1324. if (pxlate)
  1325. {
  1326. ppalInfo->flPal = XPAL_4PAL;
  1327. ppalInfo->pxlate332 = pxlate;
  1328. bRet = TRUE;
  1329. }
  1330. }
  1331. break;
  1332. case 8:
  1333. {
  1334. //
  1335. // make color xlate vector
  1336. //
  1337. ULONG NumPalEntries = 256;
  1338. PBYTE pxlate = NULL;
  1339. if ((pbmi->bmiHeader.biClrUsed > 0) &&
  1340. (pbmi->bmiHeader.biClrUsed < 256))
  1341. {
  1342. NumPalEntries = pbmi->bmiHeader.biClrUsed;
  1343. }
  1344. pxlate = pGenColorXform332((PULONG)(&pbmi->bmiColors[0]),NumPalEntries);
  1345. if (pxlate)
  1346. {
  1347. ppalInfo->flPal = XPAL_8PAL;
  1348. ppalInfo->pxlate332 = pxlate;
  1349. bRet = TRUE;
  1350. }
  1351. }
  1352. break;
  1353. case 16:
  1354. //
  1355. // look for 565 RGB or 555 RGB
  1356. //
  1357. if (
  1358. (pulColors[0] == 0xf800) &&
  1359. (pulColors[1] == 0x07e0) &&
  1360. (pulColors[2] == 0x001f)
  1361. )
  1362. {
  1363. ppalInfo->flPal = XPAL_RGB16_565;
  1364. bRet = TRUE;
  1365. }
  1366. else if (
  1367. (pulColors[0] == 0x7c00) &&
  1368. (pulColors[1] == 0x03e0) &&
  1369. (pulColors[2] == 0x001f)
  1370. )
  1371. {
  1372. ppalInfo->flPal = XPAL_RGB16_555;
  1373. bRet = TRUE;
  1374. }
  1375. else
  1376. {
  1377. ppalInfo->flPal = XPAL_RGB16_555;
  1378. bRet = TRUE;
  1379. }
  1380. break;
  1381. case 24:
  1382. ppalInfo->flPal = XPAL_RGB24;
  1383. bRet = TRUE;
  1384. break;
  1385. case 32:
  1386. if (
  1387. (pbmi->bmiHeader.biCompression == BI_BGRA) || // NT 5 only
  1388. (
  1389. (pbmi->bmiHeader.biCompression == BI_BITFIELDS) &&
  1390. (
  1391. (pulColors[0] == 0xff0000) &&
  1392. (pulColors[1] == 0x00ff00) &&
  1393. (pulColors[2] == 0x0000ff)
  1394. ) ||
  1395. (
  1396. (pulColors[0] == 0) &&
  1397. (pulColors[1] == 0) &&
  1398. (pulColors[2] == 0)
  1399. )
  1400. )
  1401. )
  1402. {
  1403. ppalInfo->flPal = XPAL_BGRA;
  1404. bRet = TRUE;
  1405. }
  1406. else if (
  1407. (pbmi->bmiHeader.biCompression == BI_RGB) ||
  1408. (pbmi->bmiHeader.biCompression == BI_BITFIELDS) &&
  1409. (
  1410. (pulColors[0] == 0x0000ff) &&
  1411. (pulColors[1] == 0x00ff00) &&
  1412. (pulColors[2] == 0xff0000)
  1413. )
  1414. )
  1415. {
  1416. ppalInfo->flPal = XPAL_RGB32;
  1417. bRet = TRUE;
  1418. }
  1419. else
  1420. {
  1421. ppalInfo->flPal = XPAL_RGB32;
  1422. bRet = TRUE;
  1423. }
  1424. }
  1425. return(bRet);
  1426. }
  1427. /**************************************************************************\
  1428. * vCleanupPALINFO
  1429. *
  1430. *
  1431. * Arguments:
  1432. *
  1433. *
  1434. *
  1435. * Return Value:
  1436. *
  1437. *
  1438. *
  1439. * History:
  1440. *
  1441. * 2/13/1997 Mark Enstrom [marke]
  1442. *
  1443. \**************************************************************************/
  1444. VOID
  1445. vCleanupPALINFO(
  1446. PPALINFO ppalInfo
  1447. )
  1448. {
  1449. if ((ppalInfo->pxlate332 != NULL) &&
  1450. (ppalInfo->pxlate332 != gHalftoneColorXlate332))
  1451. {
  1452. LOCALFREE(ppalInfo->pxlate332);
  1453. }
  1454. }
  1455. #endif