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.

248 lines
7.5 KiB

  1. //---------------------------------------------------------------------------
  2. // Gradient.cpp - gradient drawing support
  3. //---------------------------------------------------------------------------
  4. #include "stdafx.h"
  5. #include "Render.h"
  6. #include "Utils.h"
  7. #include "gradient.h"
  8. //---------------------------------------------------------------------------
  9. HRESULT PaintGradientRadialRect(HDC hdc, RECT &rcBand, int iPartCount,
  10. GRADIENTPART *pGradientParts)
  11. {
  12. if (iPartCount < 2)
  13. return MakeError32(E_INVALIDARG);
  14. int width = WIDTH(rcBand);
  15. int height = HEIGHT(rcBand);
  16. int radius = width;
  17. if (height > width)
  18. radius = height;
  19. radius = radius/2;
  20. int radiusOffset = 0;
  21. int ratioTotal = 0;
  22. UCHAR ratio;
  23. bool firstColor = true;
  24. COLORREF color, prevcolor = 0;
  25. for (int i=0; i <= iPartCount; i++) // go thru 1 extra time at end
  26. {
  27. if (i == iPartCount) // solid part of last color for remaining ratio
  28. {
  29. color = prevcolor;
  30. ratio = static_cast<UCHAR>(255 - ratioTotal);
  31. }
  32. else
  33. {
  34. color = RGBA2WINCOLOR(pGradientParts[i].Color);
  35. ratio = pGradientParts[i].Ratio;
  36. }
  37. if (firstColor)
  38. {
  39. prevcolor = color;
  40. firstColor = false;
  41. }
  42. int radius2 = radius*ratio/255;
  43. if (radius2)
  44. PaintGradientRadialBand(hdc, rcBand, radiusOffset, radius2, prevcolor, color);
  45. radiusOffset += radius2;
  46. prevcolor = color;
  47. ratioTotal += ratio;
  48. }
  49. return S_OK;
  50. }
  51. //---------------------------------------------------------------------------
  52. HRESULT PaintHorzGradient(HDC hdc, RECT &rcBand, int iPartCount,
  53. GRADIENTPART *pGradientParts)
  54. {
  55. if (iPartCount < 2)
  56. return MakeError32(E_INVALIDARG);
  57. int width = WIDTH(rcBand);
  58. int xoffset = rcBand.left;
  59. int ratioTotal = 0;
  60. UCHAR ratio;
  61. bool firstColor = true;
  62. COLORREF color, prevcolor = 0;
  63. for (int i=0; i <= iPartCount; i++) // go thru 1 extra time at end
  64. {
  65. if (i == iPartCount) // solid part of last color for remaining ratio
  66. {
  67. color = prevcolor;
  68. ratio = static_cast<UCHAR>(255 - ratioTotal);
  69. }
  70. else
  71. {
  72. color = RGBA2WINCOLOR(pGradientParts[i].Color);
  73. ratio = pGradientParts[i].Ratio;
  74. }
  75. if (firstColor)
  76. {
  77. prevcolor = color;
  78. firstColor = false;
  79. }
  80. int width2 = width*ratio/255;
  81. if (width2)
  82. {
  83. RECT rect2 = {xoffset, rcBand.top, xoffset+width2, rcBand.bottom};
  84. PaintGradientHorzBand(hdc, rect2, prevcolor, color);
  85. }
  86. xoffset += width2;
  87. prevcolor = color;
  88. ratioTotal += ratio;
  89. }
  90. return S_OK;
  91. }
  92. //---------------------------------------------------------------------------
  93. HRESULT PaintVertGradient(HDC hdc, RECT &rcBounds, int iPartCount,
  94. GRADIENTPART *pGradientParts)
  95. {
  96. if (iPartCount < 2)
  97. return MakeError32(E_INVALIDARG);
  98. int iHeight = HEIGHT(rcBounds);
  99. int yoffset = rcBounds.top;
  100. int ratioTotal = 0;
  101. UCHAR ratio;
  102. bool firstColor = true;
  103. COLORREF color, prevcolor = 0;
  104. for (int i=0; i <= iPartCount; i++) // go thru 1 extra time at end
  105. {
  106. if (i == iPartCount) // solid part of last color for remaining ratio
  107. {
  108. color = prevcolor;
  109. ratio = static_cast<UCHAR>(255 - ratioTotal);
  110. }
  111. else
  112. {
  113. color = RGBA2WINCOLOR(pGradientParts[i].Color);
  114. ratio = pGradientParts[i].Ratio;
  115. }
  116. if (firstColor)
  117. {
  118. prevcolor = color;
  119. firstColor = false;
  120. }
  121. int iHeight2 = iHeight*ratio/255;
  122. if (iHeight2)
  123. {
  124. RECT rect2 = {rcBounds.left, yoffset, rcBounds.right, yoffset+iHeight2};
  125. PaintGradientVertBand(hdc, rect2, prevcolor, color);
  126. }
  127. yoffset += iHeight2;
  128. prevcolor = color;
  129. ratioTotal += ratio;
  130. }
  131. return S_OK;
  132. }
  133. //---------------------------------------------------------------------------
  134. void DrawGradient(HDC hdc, RECT &rcBand, COLORREF color1, COLORREF color2, BOOL fHorz)
  135. {
  136. TRIVERTEX vert[2];
  137. GRADIENT_RECT gRect;
  138. vert[0].x = rcBand.left;
  139. vert[0].y = rcBand.top;
  140. vert[1].x = rcBand.right;
  141. vert[1].y = rcBand.bottom;
  142. // first vertex
  143. vert[0].Red = (USHORT)(GetRValue(color1) << 8);
  144. vert[0].Green = (USHORT)(GetGValue(color1) << 8);
  145. vert[0].Blue = (USHORT)(GetBValue(color1) << 8);
  146. vert[0].Alpha = 0x0000;
  147. // second vertex
  148. vert[1].Red = (USHORT)(GetRValue(color2) << 8);
  149. vert[1].Green = (USHORT)(GetGValue(color2) << 8);
  150. vert[1].Blue = (USHORT)(GetBValue(color2) << 8);
  151. vert[1].Alpha = 0x0000;
  152. gRect.UpperLeft = 0;
  153. gRect.LowerRight = 1;
  154. GdiGradientFill(hdc, vert, 2, &gRect, 1, fHorz ? GRADIENT_FILL_RECT_H : GRADIENT_FILL_RECT_V);
  155. }
  156. //---------------------------------------------------------------------------
  157. void PaintGradientHorzBand(HDC hdc, RECT &rcBand, COLORREF color1, COLORREF color2)
  158. {
  159. DrawGradient(hdc, rcBand, color1, color2, TRUE);
  160. }
  161. //---------------------------------------------------------------------------
  162. void PaintGradientVertBand(HDC hdc, RECT &rcBand, COLORREF color1, COLORREF color2)
  163. {
  164. DrawGradient(hdc, rcBand, color1, color2, FALSE);
  165. }
  166. //---------------------------------------------------------------------------
  167. void PaintGradientRadialBand(HDC hdc, RECT &rcBand, int radiusOffset,
  168. int radius, COLORREF color1, COLORREF color2)
  169. {
  170. int red1 = RED(color1);
  171. int red2 = RED(color2);
  172. int green1 = GREEN(color1);
  173. int green2 = GREEN(color2);
  174. int blue1 = BLUE(color1);
  175. int blue2 = BLUE(color2);
  176. int maxcolors = abs(red1 - red2);
  177. int cnt = abs(green1 - green2);
  178. if (cnt > maxcolors)
  179. maxcolors = cnt;
  180. cnt = abs(blue1 - blue2);
  181. if (cnt > maxcolors)
  182. maxcolors = cnt;
  183. int linewidth;
  184. if (color1 == color2) // just do solid color1
  185. linewidth = radius;
  186. else if (radius > maxcolors)
  187. linewidth = radius/maxcolors;
  188. else
  189. linewidth = 1;
  190. POINT center = {rcBand.left + WIDTH(rcBand)/2, rcBand.top + HEIGHT(rcBand)/2};
  191. radiusOffset += linewidth/2; // center pen within line
  192. for (int r=0; r < radius; r += linewidth)
  193. {
  194. int red = (red2*r + red1*(radius-r))/radius;
  195. int green = (green2*r + green1*(radius-r))/radius;
  196. int blue = (blue2*r + blue1*(radius-r))/radius;
  197. int radius2 = radiusOffset + r; // center pen within target line
  198. //---- calculate rcBand around "center" with "radius2" ----
  199. int left = center.x - radius2;
  200. int right = center.x + radius2;
  201. int top = center.y - radius2;
  202. int bottom = center.y + radius2;
  203. //---- overlap lines slightly so that bg doesn't leak thru ----
  204. HPEN pen = CreatePen(PS_SOLID, linewidth+2, RGB(red, green, blue));
  205. HPEN oldpen = (HPEN)SelectObject(hdc, pen);
  206. Arc(hdc, left, top, right, bottom, 0, 0, 0, 0);
  207. SelectObject(hdc, oldpen);
  208. DeleteObject(pen);
  209. }
  210. }
  211. //---------------------------------------------------------------------------