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.

228 lines
8.1 KiB

  1. //---------------------------------------------------------------------------
  2. // TextFade.cpp - text fading code (removed from taskbar)
  3. //---------------------------------------------------------------------------
  4. // BEGIN fade-text drawing functions and friends
  5. //---------------------------------------------------------------------------
  6. #include "stdafx.h"
  7. //---------------------------------------------------------------------------
  8. static HBITMAP CreateDibSection32Bit(int w, int h, void** ppv)
  9. {
  10. HBITMAP bitmap;
  11. BITMAPINFO bmi;
  12. memset(&bmi, 0, sizeof(BITMAPINFO));
  13. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  14. bmi.bmiHeader.biWidth = w;
  15. bmi.bmiHeader.biHeight = h;
  16. bmi.bmiHeader.biPlanes = 1;
  17. bmi.bmiHeader.biBitCount = 32;
  18. bmi.bmiHeader.biCompression = BI_RGB;
  19. bmi.bmiHeader.biSizeImage = 0;
  20. bitmap = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, ppv, NULL, 0);
  21. if (bitmap)
  22. memset(*ppv, 0xff, w*h*4); //32bpp=4bytes
  23. return bitmap;
  24. }
  25. //---------------------------------------------------------------------------
  26. static void SetupAlphaChannel(DWORD* pdw, int w, int h, BYTE bstart, BYTE bend, int nExtra)
  27. {
  28. //nExtra is extra space that we want to fill with the final value
  29. int i,j;
  30. w -= nExtra;
  31. if (bstart > bend)
  32. {
  33. BYTE bdiff = bstart - bend;
  34. for (j=0;j<h;j++)
  35. {
  36. for (i=0;i<w;i++)
  37. {
  38. BYTE a = bstart - bdiff * i/w; //alpha
  39. BYTE r = (GetRValue(*pdw)*a)/256;
  40. BYTE g = (GetGValue(*pdw)*a)/256;
  41. BYTE b = (GetBValue(*pdw)*a)/256;
  42. *pdw = (a<<24)|RGB(r,g,b);
  43. pdw++;
  44. }
  45. for (i=w;i<w+nExtra;i++)
  46. {
  47. BYTE a = bend; //alpha
  48. BYTE r = (GetRValue(*pdw)*a)/256;
  49. BYTE g = (GetGValue(*pdw)*a)/256;
  50. BYTE b = (GetBValue(*pdw)*a)/256;
  51. *pdw = (a<<24)|RGB(r,g,b);
  52. pdw++;
  53. }
  54. }
  55. }
  56. else
  57. {
  58. BYTE bdiff = bend - bstart;
  59. for (j=0;j<h;j++)
  60. {
  61. for (i=0;i<w;i++)
  62. {
  63. BYTE a = bstart + bdiff * i/w; //alpha
  64. BYTE r = (GetRValue(*pdw)*a)/256;
  65. BYTE g = (GetGValue(*pdw)*a)/256;
  66. BYTE b = (GetBValue(*pdw)*a)/256;
  67. *pdw = (a<<24)|RGB(r,g,b);
  68. pdw++;
  69. }
  70. for (i=w;i<w+nExtra;i++)
  71. {
  72. BYTE a = bend; //alpha
  73. BYTE r = (GetRValue(*pdw)*a)/256;
  74. BYTE g = (GetGValue(*pdw)*a)/256;
  75. BYTE b = (GetBValue(*pdw)*a)/256;
  76. *pdw = (a<<24)|RGB(r,g,b);
  77. pdw++;
  78. }
  79. }
  80. }
  81. }
  82. //---------------------------------------------------------------------------
  83. int ExtTextOutAlpha(HDC dc, int X, int Y, UINT fuOptions, CONST RECT *lprc,
  84. LPCTSTR lpsz, UINT nCount, CONST INT *lpDx)
  85. {
  86. BOOL bEffects = FALSE;
  87. SystemParametersInfo(SPI_GETUIEFFECTS, 0, (void*)&bEffects, 0);
  88. // don't alpha blend if ui effects off or number of colors <= 256
  89. if (!bEffects ||
  90. (GetDeviceCaps(dc, BITSPIXEL) * GetDeviceCaps(dc, PLANES) <= 8))
  91. {
  92. return ExtTextOut(dc, X, Y, fuOptions, lprc, lpsz, nCount, lpDx);
  93. }
  94. if (lprc == NULL)
  95. return ExtTextOut(dc, X, Y, fuOptions, lprc, lpsz, nCount, lpDx);
  96. RECT rc = *lprc;
  97. int nwidth = rc.right -rc.left;
  98. int nheight = rc.bottom - rc.top;
  99. int nLen = (nCount == -1) ? lstrlen(lpsz) : nCount;
  100. int nFit=0;
  101. int* pFit = new int[nLen];
  102. if (pFit == NULL)
  103. return 0;
  104. pFit[0] = 0;
  105. SIZE size;
  106. GetTextExtentExPoint(dc, lpsz, nLen, nwidth, &nFit, pFit, &size);
  107. if (nFit >= nLen)
  108. return ExtTextOut(dc, X, Y, fuOptions, lprc, lpsz, nCount, lpDx);
  109. // too small, let's alpha blend it
  110. if ((nwidth <= 0) || (nheight <= 0))
  111. return 1;
  112. TEXTMETRIC tm;
  113. GetTextMetrics(dc, &tm);
  114. int nPix = tm.tmAveCharWidth*5;
  115. //don't fade out more than half the text
  116. if (nPix > nwidth)
  117. nPix = nwidth/2;
  118. //Create a 32bpp dibsection to store the background
  119. void* pv = NULL;
  120. HDC dcbitmap = CreateCompatibleDC(dc);
  121. int nRet = 0;
  122. if (dcbitmap != NULL)
  123. {
  124. HBITMAP bitmap = CreateDibSection32Bit(nPix, nheight, &pv);
  125. if (bitmap != NULL)
  126. {
  127. HBITMAP tmpbmp = (HBITMAP) SelectObject(dcbitmap, bitmap);
  128. BitBlt(dcbitmap, 0, 0, nPix, nheight, dc, rc.right-nPix, rc.top, SRCCOPY);
  129. //Setup the per-pixel alpha blending values
  130. SetupAlphaChannel((DWORD*)pv, nPix, nheight, 0x00, 0xdf, 0);
  131. //Draw the text onto the display DC
  132. ExtTextOut(dc, X, Y, fuOptions, lprc, lpsz, nLen, lpDx);
  133. //Blend the background back into the display
  134. BLENDFUNCTION blend = {AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA};
  135. GdiAlphaBlend(dc, rc.right-nPix, rc.top, nPix, nheight, dcbitmap, 0, 0, nPix, nheight, blend);
  136. ::SelectObject(dcbitmap, tmpbmp);
  137. DeleteObject(bitmap);
  138. nRet = 1;
  139. }
  140. DeleteDC(dcbitmap);
  141. }
  142. return nRet;
  143. }
  144. //---------------------------------------------------------------------------
  145. int DrawTextAlpha(HDC hdc, LPCTSTR lpsz, int nCount, RECT* prc, UINT uFormat)
  146. {
  147. BOOL bEffects = FALSE;
  148. SystemParametersInfo(SPI_GETUIEFFECTS, 0, (void*)&bEffects, 0);
  149. // don't alpha blend if ui effects off or number of colors <= 256
  150. if (!bEffects ||
  151. (GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES) <= 8))
  152. {
  153. return DrawText(hdc, lpsz, nCount, prc, uFormat);
  154. }
  155. UINT nEllipsis = (DT_END_ELLIPSIS|DT_WORD_ELLIPSIS|DT_WORD_ELLIPSIS);
  156. if (!(uFormat & DT_SINGLELINE) || !(uFormat & DT_END_ELLIPSIS) || (uFormat & DT_CALCRECT))
  157. return ::DrawText(hdc, lpsz, nCount, prc, uFormat);
  158. //we are single line and ellipses are requested
  159. //we are going to alpha blend though
  160. uFormat &= ~nEllipsis; //turn all ellipsis flags off
  161. if (nCount == -1)
  162. nCount = lstrlen(lpsz);
  163. RECT rc;
  164. CopyRect(&rc, prc);
  165. ::DrawText(hdc, (TCHAR*)lpsz, nCount, &rc, uFormat | DT_CALCRECT);
  166. if (rc.right <= prc->right) //not truncated
  167. return ::DrawText(hdc, lpsz, nCount, prc, uFormat);
  168. // DT_CENTER is effectively ignored when ellipses flags are on,
  169. // because text is clipped to fit in rectangle. With fading, we
  170. // need to justify the text.
  171. uFormat &= ~DT_CENTER;
  172. CopyRect(&rc, prc);
  173. int nwidth = RECTWIDTH(&rc);
  174. int nheight = RECTHEIGHT(&rc);
  175. if ((nwidth <= 0) || (nheight <= 0))
  176. return 1;
  177. // Figure out how much of the background to stash away
  178. TEXTMETRIC tm;
  179. GetTextMetrics(hdc, &tm);
  180. int nPix = tm.tmAveCharWidth*5; //five characters worth
  181. if (nPix > nwidth/2)
  182. nPix = nwidth/2;
  183. //Adjust by one max char width because DrawText can draw up to
  184. //one extra character outside the clip rect.
  185. nPix += tm.tmMaxCharWidth;
  186. rc.right += tm.tmMaxCharWidth;
  187. //Create a 32bpp dibsection to store the background
  188. void* pv = NULL;
  189. HDC dcbitmap = CreateCompatibleDC(hdc);
  190. int nRet = 0;
  191. if (dcbitmap != NULL)
  192. {
  193. HBITMAP bitmap = CreateDibSection32Bit(nPix, nheight, &pv);
  194. if (bitmap != NULL)
  195. {
  196. HBITMAP tmpbmp = (HBITMAP) SelectObject(dcbitmap, bitmap);
  197. BitBlt(dcbitmap, 0, 0, nPix, nheight, hdc, rc.right-nPix, rc.top, SRCCOPY);
  198. //Setup the per-pixel alpha blending values
  199. SetupAlphaChannel((DWORD*)pv, nPix, nheight, 0x00, 0xdf, tm.tmMaxCharWidth);
  200. //Draw the text onto the display DC
  201. ::DrawText(hdc, lpsz, nCount, prc, uFormat);
  202. //Blend the background back into the display
  203. BLENDFUNCTION blend = {AC_SRC_OVER, 0, 0xff, AC_SRC_ALPHA};
  204. GdiAlphaBlend(hdc, rc.right-nPix, rc.top, nPix, nheight, dcbitmap, 0, 0, nPix, nheight, blend);
  205. ::SelectObject(dcbitmap, tmpbmp);
  206. DeleteObject(bitmap);
  207. nRet = 1;
  208. }
  209. DeleteDC(dcbitmap);
  210. }
  211. return nRet;
  212. }
  213. //---------------------------------------------------------------------------