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.

399 lines
12 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module name:
  6. *
  7. * The "Dither" scan operation.
  8. *
  9. * Abstract:
  10. *
  11. * See Gdiplus\Specs\ScanOperation.doc for an overview.
  12. *
  13. * Notes:
  14. *
  15. * Revision History:
  16. *
  17. * 01/19/2000 andrewgo
  18. * Created it.
  19. *
  20. \**************************************************************************/
  21. #include "precomp.hpp"
  22. /**************************************************************************\
  23. *
  24. * Operation Description:
  25. *
  26. * Dither: Dither from 32bpp ARGB to 16bpp.
  27. *
  28. * Arguments:
  29. *
  30. * dst - The destination scan
  31. * src - The source scan (32bpp ARGB)
  32. * count - The length of the scan, in pixels
  33. * otherParams - Additional data. (We use X and Y.)
  34. *
  35. * Return Value:
  36. *
  37. * None
  38. *
  39. * Notes:
  40. *
  41. * Special cases which alpha-blend and dither in one step, should probably
  42. * go in this file, but be named e.g. Blend_sRGB_565_Dithered.
  43. *
  44. * History:
  45. *
  46. * 01/19/2000 andrewgo
  47. * Created it.
  48. * 01/19/2000 agodfrey
  49. * Stashed it here for the time being.
  50. *
  51. \**************************************************************************/
  52. UINT32 Saturate5Bit[] = { 0, 1, 2, 3, 4, 5, 6, 7,
  53. 8, 9, 10, 11, 12, 13, 14, 15,
  54. 16, 17, 18, 19, 20, 21, 22, 23,
  55. 24, 25, 26, 27, 28, 29, 30, 31,
  56. 31 };
  57. UINT32 Saturate6Bit[] = { 0, 1, 2, 3, 4, 5, 6, 7,
  58. 8, 9, 10, 11, 12, 13, 14, 15,
  59. 16, 17, 18, 19, 20, 21, 22, 23,
  60. 24, 25, 26, 27, 28, 29, 30, 31,
  61. 32, 33, 34, 35, 36, 37, 38, 39,
  62. 40, 41, 42, 43, 44, 45, 46, 47,
  63. 48, 49, 50, 51, 52, 53, 54, 55,
  64. 56, 57, 58, 59, 60, 61, 62, 63,
  65. 63 };
  66. UINT32 Dither5BitR[16] = { 0x00000000, 0x00040000, 0x00010000, 0x00050000,
  67. 0x00060000, 0x00020000, 0x00070000, 0x00030000,
  68. 0x00010000, 0x00050000, 0x00000000, 0x00040000,
  69. 0x00070000, 0x00030000, 0x00060000, 0x00020000 };
  70. UINT32 Dither5BitG[16] = { 0x00000000, 0x00000400, 0x00000100, 0x00000500,
  71. 0x00000600, 0x00000200, 0x00000700, 0x00000300,
  72. 0x00000100, 0x00000500, 0x00000000, 0x00000400,
  73. 0x00000700, 0x00000300, 0x00000600, 0x00000200 };
  74. UINT32 Dither6BitG[16] = { 0x00000000, 0x00000200, 0x00000000, 0x00000200,
  75. 0x00000300, 0x00000100, 0x00000300, 0x00000100,
  76. 0x00000000, 0x00000200, 0x00000000, 0x00000200,
  77. 0x00000300, 0x00000100, 0x00000300, 0x00000100 };
  78. UINT32 Dither5BitB[16] = { 0x00000000, 0x00000004, 0x00000001, 0x00000005,
  79. 0x00000006, 0x00000002, 0x00000007, 0x00000003,
  80. 0x00000001, 0x00000005, 0x00000000, 0x00000004,
  81. 0x00000007, 0x00000003, 0x00000006, 0x00000002 };
  82. // The following 'Dither565' and 'Dither555' matrices are 4 by 4
  83. // arrays for adding straight to an ARGB dword value. Every row
  84. // is repeated to allow us to do 128-bit reads with wrapping.
  85. UINT32 Dither565[32] = { 0x00000000, 0x00040204, 0x00010001, 0x00050205,
  86. 0x00000000, 0x00040204, 0x00010001, 0x00050205,
  87. 0x00060306, 0x00020102, 0x00070307, 0x00030103,
  88. 0x00060306, 0x00020102, 0x00070307, 0x00030103,
  89. 0x00010001, 0x00050205, 0x00000000, 0x00040204,
  90. 0x00010001, 0x00050205, 0x00000000, 0x00040204,
  91. 0x00070307, 0x00030103, 0x00060306, 0x00020102,
  92. 0x00070307, 0x00030103, 0x00060306, 0x00020102 };
  93. UINT32 Dither555[32] = { 0x00000000, 0x00040404, 0x00010101, 0x00050505,
  94. 0x00000000, 0x00040404, 0x00010101, 0x00050505,
  95. 0x00060606, 0x00020202, 0x00070707, 0x00030303,
  96. 0x00060606, 0x00020202, 0x00070707, 0x00030303,
  97. 0x00010101, 0x00050505, 0x00000000, 0x00040404,
  98. 0x00010101, 0x00050505, 0x00000000, 0x00040404,
  99. 0x00070707, 0x00030303, 0x00060606, 0x00020202,
  100. 0x00070707, 0x00030303, 0x00060606, 0x00020202 };
  101. // The 'DitherNone' matrix allows us to disable dithering in a dithering
  102. // routine:
  103. UINT32 DitherNone[4] = { 0, 0, 0, 0 };
  104. // Dither to 16bpp 565
  105. VOID FASTCALL
  106. ScanOperation::Dither_sRGB_565(
  107. VOID *dst,
  108. const VOID *src,
  109. INT count,
  110. const OtherParams *otherParams
  111. )
  112. {
  113. // Since the MMX versions easily handle both dithering and non-dithering,
  114. // it makes it simpler if all the 16bpp functions handle both.
  115. if (!otherParams->DoingDither)
  116. {
  117. Quantize_sRGB_565(dst, src, count, otherParams);
  118. return;
  119. }
  120. DEFINE_POINTERS(ARGB, WORD);
  121. ASSERT(count != 0);
  122. ASSERT(otherParams);
  123. INT x = otherParams->X;
  124. INT y = otherParams->Y;
  125. // !!![andrewgo] Are we getting the window-relative (x, y)? (Don't think so!)
  126. INT startDitherIndex = (y & 3) * 4;
  127. do {
  128. UINT32 src = *s;
  129. x = (x & 3) + startDitherIndex;
  130. *d = (WORD)
  131. (Saturate5Bit[((src & 0xff0000) + Dither5BitR[x]) >> 19] << 11) +
  132. (Saturate6Bit[((src & 0x00ff00) + Dither6BitG[x]) >> 10] << 5) +
  133. (Saturate5Bit[((src & 0x0000ff) + Dither5BitB[x]) >> 3]);
  134. s++;
  135. d++;
  136. x++;
  137. } while (--count != 0);
  138. }
  139. // Dither to 16bpp 555
  140. VOID FASTCALL
  141. ScanOperation::Dither_sRGB_555(
  142. VOID *dst,
  143. const VOID *src,
  144. INT count,
  145. const OtherParams *otherParams
  146. )
  147. {
  148. // Since the MMX versions easily handle both dithering and non-dithering,
  149. // it makes it simpler if all the 16bpp functions handle both.
  150. if (!otherParams->DoingDither)
  151. {
  152. Quantize_sRGB_555(dst, src, count, otherParams);
  153. return;
  154. }
  155. DEFINE_POINTERS(ARGB, WORD);
  156. ASSERT(count != 0);
  157. ASSERT(otherParams);
  158. INT x = otherParams->X;
  159. INT y = otherParams->Y;
  160. INT startDitherIndex = (y & 3) * 4;
  161. do {
  162. UINT32 src = *s;
  163. x = (x & 3) + startDitherIndex;
  164. *d = (WORD)
  165. (Saturate5Bit[((src & 0xff0000) + Dither5BitR[x]) >> 19] << 10) +
  166. (Saturate5Bit[((src & 0x00ff00) + Dither5BitG[x]) >> 11] << 5) +
  167. (Saturate5Bit[((src & 0x0000ff) + Dither5BitB[x]) >> 3]);
  168. s++;
  169. d++;
  170. x++;
  171. } while (--count != 0);
  172. }
  173. // Blend from sRGB to 16bpp 565, with dithering.
  174. VOID FASTCALL
  175. ScanOperation::Dither_Blend_sRGB_565(
  176. VOID *dst,
  177. const VOID *src,
  178. INT count,
  179. const OtherParams *otherParams
  180. )
  181. {
  182. // Since the MMX versions easily handle both dithering and non-dithering,
  183. // it makes it simpler if all the 16bpp functions handle both.
  184. if (!otherParams->DoingDither)
  185. {
  186. Blend_sRGB_565(dst, src, count, otherParams);
  187. return;
  188. }
  189. DEFINE_POINTERS(UINT16, UINT16)
  190. DEFINE_BLEND_POINTER(ARGB)
  191. ASSERT(count>0);
  192. INT x = otherParams->X;
  193. INT y = otherParams->Y;
  194. INT startDitherIndex = (y & 3) * 4;
  195. do {
  196. UINT32 blendPixel = *bl;
  197. UINT32 alpha = blendPixel >> 24;
  198. x = (x & 3) + startDitherIndex;
  199. if (alpha != 0)
  200. {
  201. UINT32 srcPixel;
  202. UINT r, g, b;
  203. r = blendPixel & 0xff0000;
  204. g = blendPixel & 0x00ff00;
  205. b = blendPixel & 0x0000ff;
  206. if (alpha != 255)
  207. {
  208. srcPixel = *s;
  209. UINT sr = (srcPixel >> 11) & 0x1f;
  210. UINT sg = (srcPixel >> 5) & 0x3f;
  211. UINT sb = (srcPixel ) & 0x1f;
  212. sr = (sr << 3) | (sr >> 2);
  213. sg = (sg << 2) | (sg >> 4);
  214. sb = (sb << 3) | (sb >> 2);
  215. //
  216. // Dst = B + (1-Alpha) * S
  217. //
  218. ULONG Multa = 255 - alpha;
  219. ULONG _D1_000000GG = sg;
  220. ULONG _D1_00RR00BB = sb | (sr << 16);
  221. ULONG _D2_0000GGGG = _D1_000000GG * Multa + 0x00000080;
  222. ULONG _D2_RRRRBBBB = _D1_00RR00BB * Multa + 0x00800080;
  223. ULONG _D3_000000GG = (_D2_0000GGGG & 0x0000ff00) >> 8;
  224. ULONG _D3_00RR00BB = (_D2_RRRRBBBB & 0xff00ff00) >> 8;
  225. ULONG _D4_0000GG00 = (_D2_0000GGGG + _D3_000000GG) & 0x0000FF00;
  226. ULONG _D4_00RR00BB = ((_D2_RRRRBBBB + _D3_00RR00BB) & 0xFF00FF00) >> 8;
  227. r += _D4_00RR00BB; // The BB part will be shifted off
  228. g += _D4_0000GG00;
  229. b += _D4_00RR00BB & 0x0000ff;
  230. }
  231. *d = (WORD)
  232. (Saturate5Bit[(r + Dither5BitR[x]) >> 19] << 11) +
  233. (Saturate6Bit[(g + Dither6BitG[x]) >> 10] << 5) +
  234. (Saturate5Bit[(b + Dither5BitB[x]) >> 3]);
  235. }
  236. bl++;
  237. s++;
  238. d++;
  239. x++;
  240. } while (--count != 0);
  241. }
  242. // Blend from sRGB to 16bpp 555, with dithering.
  243. VOID FASTCALL
  244. ScanOperation::Dither_Blend_sRGB_555(
  245. VOID *dst,
  246. const VOID *src,
  247. INT count,
  248. const OtherParams *otherParams
  249. )
  250. {
  251. // Since the MMX versions easily handle both dithering and non-dithering,
  252. // it makes it simpler if all the 16bpp functions handle both.
  253. if (!otherParams->DoingDither)
  254. {
  255. Blend_sRGB_555(dst, src, count, otherParams);
  256. return;
  257. }
  258. DEFINE_POINTERS(UINT16, UINT16)
  259. DEFINE_BLEND_POINTER(ARGB)
  260. ASSERT(count>0);
  261. INT x = otherParams->X;
  262. INT y = otherParams->Y;
  263. INT startDitherIndex = (y & 3) * 4;
  264. do {
  265. UINT32 blendPixel = *bl;
  266. UINT32 alpha = blendPixel >> 24;
  267. x = (x & 3) + startDitherIndex;
  268. if (alpha != 0)
  269. {
  270. UINT32 srcPixel;
  271. UINT r, g, b;
  272. r = blendPixel & 0xff0000;
  273. g = blendPixel & 0x00ff00;
  274. b = blendPixel & 0x0000ff;
  275. if (alpha != 255)
  276. {
  277. srcPixel = *s;
  278. UINT sr = (srcPixel >> 10) & 0x1f;
  279. UINT sg = (srcPixel >> 5) & 0x1f;
  280. UINT sb = (srcPixel ) & 0x1f;
  281. sr = (sr << 3) | (sr >> 2);
  282. sg = (sg << 3) | (sg >> 2);
  283. sb = (sb << 3) | (sb >> 2);
  284. //
  285. // Dst = B + (1-Alpha) * S
  286. //
  287. ULONG Multa = 255 - alpha;
  288. ULONG _D1_000000GG = sg;
  289. ULONG _D1_00RR00BB = sb | (sr << 16);
  290. ULONG _D2_0000GGGG = _D1_000000GG * Multa + 0x00000080;
  291. ULONG _D2_RRRRBBBB = _D1_00RR00BB * Multa + 0x00800080;
  292. ULONG _D3_000000GG = (_D2_0000GGGG & 0x0000ff00) >> 8;
  293. ULONG _D3_00RR00BB = (_D2_RRRRBBBB & 0xff00ff00) >> 8;
  294. ULONG _D4_0000GG00 = (_D2_0000GGGG + _D3_000000GG) & 0x0000FF00;
  295. ULONG _D4_00RR00BB = ((_D2_RRRRBBBB + _D3_00RR00BB) & 0xFF00FF00) >> 8;
  296. r += _D4_00RR00BB; // The BB part will be shifted off
  297. g += _D4_0000GG00;
  298. b += _D4_00RR00BB & 0x0000ff;
  299. }
  300. *d = (WORD)
  301. (Saturate5Bit[(r + Dither5BitR[x]) >> 19] << 10) +
  302. (Saturate5Bit[(g + Dither5BitG[x]) >> 11] << 5) +
  303. (Saturate5Bit[(b + Dither5BitB[x]) >> 3]);
  304. }
  305. bl++;
  306. s++;
  307. d++;
  308. x++;
  309. } while (--count != 0);
  310. }
  311. // Generate 555 versions of the routines defined in 'sodither.inc'
  312. #define DITHER_BLEND_555 1
  313. #include "SODither.inc"
  314. // Generate 565 versions of the routines defined in 'sodither.inc'
  315. #undef DITHER_BLEND_555
  316. #define DITHER_BLEND_555 0
  317. #include "SODither.inc"