Source code of Windows XP (NT5)
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.

305 lines
8.4 KiB

  1. /*
  2. ** CUTILS.C
  3. **
  4. ** Common utilities for common controls
  5. **
  6. */
  7. #include "ctlspriv.h"
  8. #include <shfusion.h>
  9. #define ARGB(a,r,g,b) ((COLORREF)(( \
  10. ((BYTE)(r)) | \
  11. ((WORD) ((BYTE)(g))<< 8)) | \
  12. (((DWORD)((BYTE)(b))<<16)) | \
  13. (((DWORD)((BYTE)(a))<<24))))
  14. #define PREMULTIPLY(c, alpha) ((( ((c) * (alpha)) + 128) >> 8) + 1)
  15. typedef struct tagCCBUFFER
  16. {
  17. HDC hdc;
  18. HBITMAP hbmp;
  19. HBITMAP hbmpOld;
  20. RGBQUAD* prgb;
  21. } CCBUFFER;
  22. BOOL Buffer_CreateBuffer(HDC hdc, int cx, int cy, CCBUFFER* pbuf)
  23. {
  24. BOOL fRet = FALSE;
  25. BITMAPINFO bi = {0};
  26. bi.bmiHeader.biSize = sizeof(bi.bmiHeader);
  27. bi.bmiHeader.biWidth = cx;
  28. bi.bmiHeader.biHeight = cy;
  29. bi.bmiHeader.biPlanes = 1;
  30. bi.bmiHeader.biBitCount = 32;
  31. bi.bmiHeader.biCompression = BI_RGB;
  32. pbuf->hdc = CreateCompatibleDC(hdc);
  33. if (pbuf->hdc)
  34. {
  35. pbuf->hbmp = CreateDIBSection(pbuf->hdc, &bi, DIB_RGB_COLORS, (VOID**)&pbuf->prgb, NULL, 0);
  36. if (!pbuf->hbmp)
  37. {
  38. DeleteDC(pbuf->hdc);
  39. ZeroMemory(pbuf, sizeof(CCBUFFER));
  40. }
  41. else
  42. {
  43. pbuf->hbmpOld = (HBITMAP)SelectObject(pbuf->hdc, pbuf->hbmp);
  44. fRet = TRUE;
  45. }
  46. }
  47. return fRet;
  48. }
  49. void Buffer_DestroyBuffer(CCBUFFER* pbuf)
  50. {
  51. if (pbuf->hdc)
  52. {
  53. SelectObject(pbuf->hdc, pbuf->hbmpOld);
  54. DeleteDC(pbuf->hdc);
  55. DeleteObject(pbuf->hbmp);
  56. }
  57. }
  58. void BlurBitmapNormal(ULONG* prgb, int cx, int cy, COLORREF crFill)
  59. {
  60. BYTE r = GetRValue(crFill);
  61. BYTE g = GetGValue(crFill);
  62. BYTE b = GetBValue(crFill);
  63. int cxMax = cx - 5;
  64. int cyMax = cy - 5;
  65. int iOffset;
  66. int y;
  67. for (y=0, iOffset = 0; y < cy; y++, iOffset += cx)
  68. {
  69. ULONG* p = &prgb[iOffset];
  70. int Accum = ((*p)) +
  71. ((*(p + 1))) +
  72. ((*(p + 2))) +
  73. ((*(p + 3)));
  74. for (int x=0; x< cxMax; x++)
  75. {
  76. Accum = Accum - ((*p)) + ((*(p + 4)));
  77. *p++ = (Accum >> 2);
  78. }
  79. }
  80. int cx2 = cx << 1;
  81. int cx3 = cx + cx + cx;
  82. int cx4 = cx << 2;
  83. for (iOffset = 0, y=0; y < cyMax; y++, iOffset += cx)
  84. {
  85. ULONG* p = &prgb[iOffset];
  86. for (int x=0; x < cx; x++)
  87. {
  88. DWORD Alpha = (((*p) ) +
  89. (*(p + cx) ) +
  90. (*(p + cx2) ) +
  91. (*(p + cx3) ) +
  92. (*(p + cx4) )) >> 2;
  93. if (Alpha > 255)
  94. Alpha = 255;
  95. *p = (ULONG)ARGB(Alpha, PREMULTIPLY(r, Alpha), PREMULTIPLY(g, Alpha), PREMULTIPLY(b, Alpha));
  96. p++;
  97. }
  98. }
  99. }
  100. #ifdef _X86_
  101. QWORD qw128 = 0x0000008000800080;
  102. QWORD qw1 = 0x0000000100010001;
  103. void BlurBitmapMMX(ULONG* prgb, int cx, int cy, COLORREF crFill)
  104. {
  105. RGBQUAD rgbFill; // ColorRef is opposite of RGBQUAD
  106. rgbFill.rgbRed = GetRValue(crFill);
  107. rgbFill.rgbGreen = GetGValue(crFill);
  108. rgbFill.rgbBlue = GetBValue(crFill);
  109. int cxMax = cx - 5;
  110. int cyMax = cy - 5;
  111. int iOffset;
  112. int y;
  113. for (y=0, iOffset = 0; y < cy; y++, iOffset += cx)
  114. {
  115. ULONG* p = &prgb[iOffset];
  116. int Accum = ((*p)) +
  117. ((*(p + 1))) +
  118. ((*(p + 2))) +
  119. ((*(p + 3)));
  120. for (int x=0; x< cxMax; x++)
  121. {
  122. Accum = Accum - ((*p)) + ((*(p + 4)));
  123. *p++ = (Accum >> 2);
  124. }
  125. }
  126. int cx2 = cx << 1;
  127. int cx3 = cx + cx + cx;
  128. int cx4 = cx << 2;
  129. _asm
  130. {
  131. pxor mm0, mm0
  132. pxor mm1, mm1
  133. pxor mm5, mm5
  134. movd mm4, dword ptr [rgbFill]
  135. movq mm6, qw128 // mm6 is filled with 128
  136. movq mm7, qw1 // mm7 is filled with 1
  137. }
  138. for (iOffset = 0, y=0; y < cyMax; y++, iOffset += cx)
  139. {
  140. ULONG* p = &prgb[iOffset];
  141. for (int x=0; x < cx; x++)
  142. {
  143. DWORD Alpha = (((*p) ) +
  144. (*(p + cx) ) +
  145. (*(p + cx2) ) +
  146. (*(p + cx3) ) +
  147. (*(p + cx4) )) >> 2;
  148. if (Alpha > 255)
  149. Alpha = 255;
  150. *p = ((BYTE)Alpha);
  151. _asm
  152. {
  153. mov edx, dword ptr [p]
  154. mov ebx, dword ptr [edx]
  155. mov eax, ebx // a -> b
  156. or eax, eax
  157. jz EarlyOut
  158. shl ebx, 8 // b << 8
  159. or eax, ebx // a |= b
  160. shl ebx, 8 // b << 8
  161. or eax, ebx // a |= b
  162. shl ebx, 8 // b << 8
  163. // Note high byte of alpha is zero.
  164. movd mm0, eax // a -> mm0
  165. movq mm1, mm4 // Load the pixel
  166. punpcklbw mm0,mm5 // mm0 -> Expands <- mm0 Contains the Alpha channel for this multiply
  167. punpcklbw mm1, mm5 // Unpack the pixel
  168. pmullw mm1, mm0 // Multiply by the alpha channel <- mm1 contains c * alpha
  169. paddusw mm1, mm6 // perform the (c * alpha) + 128
  170. psrlw mm1, 8 // Divide by 255
  171. paddusw mm1, mm7 // Add 1 to finish the divide by 255
  172. packuswb mm1, mm5
  173. movd eax, mm1
  174. or eax, ebx // Transfer alpha channel
  175. EarlyOut:
  176. mov dword ptr [edx], eax
  177. }
  178. p++;
  179. }
  180. }
  181. _asm emms
  182. }
  183. void BlurBitmap(ULONG* plBitmapBits, int cx, int cy, COLORREF crFill)
  184. {
  185. if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
  186. BlurBitmapMMX(plBitmapBits, cx, cy, crFill);
  187. else
  188. BlurBitmapNormal(plBitmapBits, cx, cy, crFill);
  189. }
  190. #else
  191. void BlurBitmap(ULONG* plBitmapBits, int cx, int cy, COLORREF crFill)
  192. {
  193. BlurBitmapNormal(plBitmapBits, cx, cy, crFill);
  194. }
  195. #endif
  196. int DrawShadowText(HDC hdc, LPCTSTR pszText, UINT cch, RECT* prc, DWORD dwFlags, COLORREF crText,
  197. COLORREF crShadow, int ixOffset, int iyOffset)
  198. {
  199. int iRet = -1;
  200. if (dwFlags & DT_CALCRECT)
  201. {
  202. iRet = DrawText(hdc, pszText, cch, prc, dwFlags | DT_CALCRECT);
  203. }
  204. else
  205. {
  206. if (GetLayout(hdc) == LAYOUT_RTL)
  207. {
  208. COLORREF crTextSave = SetTextColor(hdc, crShadow);
  209. int iMode = SetBkMode(hdc, TRANSPARENT);
  210. RECT rc = *prc;
  211. OffsetRect(&rc, ixOffset, iyOffset);
  212. DrawText(hdc, pszText, cch, &rc, dwFlags);
  213. SetBkMode(hdc, iMode);
  214. SetTextColor(hdc, crTextSave);
  215. }
  216. else
  217. {
  218. RECT rc = *prc;
  219. CCBUFFER buf;
  220. int cx = RECTWIDTH(rc) + 10;
  221. int cy = RECTHEIGHT(rc) + 10;
  222. if (Buffer_CreateBuffer(hdc, cx, cy, &buf))
  223. {
  224. OffsetRect(&rc, 5, 5);
  225. RECT rcMem = {5, 5, RECTWIDTH(rc) + 5, RECTHEIGHT(rc) + 5};
  226. HFONT hFontOldhdc = (HFONT)SelectObject(hdc, GetStockObject(SYSTEM_FONT));
  227. HFONT hFontOldhdcMem = (HFONT)SelectObject(buf.hdc, hFontOldhdc);
  228. SetTextColor(buf.hdc, crText);
  229. SetBkColor(buf.hdc, crShadow);
  230. SetBkMode(buf.hdc, TRANSPARENT);
  231. DrawText(buf.hdc, pszText, cch, &rcMem, dwFlags);
  232. int Total = cx * cy;
  233. for (int z = 0; z < Total; z++)
  234. {
  235. if (((PULONG)buf.prgb)[z] != 0)
  236. ((PULONG)buf.prgb)[z] = 0x000000ff;
  237. }
  238. BlurBitmap((ULONG*)buf.prgb, cx, cy, crShadow);
  239. BLENDFUNCTION bf = {0};
  240. bf.BlendOp = AC_SRC_OVER;
  241. bf.SourceConstantAlpha = 255;
  242. bf.AlphaFormat = AC_SRC_ALPHA;
  243. GdiAlphaBlend(hdc, prc->left - 4 + ixOffset, prc->top - 8 + iyOffset, cx, cy, buf.hdc, 0, 0, cx, cy, bf);
  244. SelectObject(buf.hdc, hFontOldhdcMem);
  245. SelectObject(hdc, hFontOldhdc);
  246. Buffer_DestroyBuffer(&buf);
  247. }
  248. }
  249. int iMode = SetBkMode(hdc, TRANSPARENT);
  250. COLORREF crTextSave = SetTextColor(hdc, crText);
  251. iRet = DrawText(hdc, pszText, cch, prc, dwFlags);
  252. SetTextColor(hdc, crTextSave);
  253. SetBkMode(hdc, iMode);
  254. }
  255. return iRet;
  256. }