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.

242 lines
6.0 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. int IntSqrt(unsigned long dwNum)
  4. {
  5. // We will keep shifting dwNum left and look at the top two bits.
  6. // initialize sqrt and remainder to 0.
  7. DWORD dwSqrt = 0, dwRemain = 0, dwTry;
  8. int i;
  9. // We iterate 16 times, once for each pair of bits.
  10. for (i=0; i<16; ++i)
  11. {
  12. // Mask off the top two bits of dwNum and rotate them into the
  13. // bottom of the remainder
  14. dwRemain = (dwRemain<<2) | (dwNum>>30);
  15. // Now we shift the sqrt left; next we'll determine whether the
  16. // new bit is a 1 or a 0.
  17. dwSqrt <<= 1;
  18. // This is where we double what we already have, and try a 1 in
  19. // the lowest bit.
  20. dwTry = dwSqrt*2 + 1;
  21. if (dwRemain >= dwTry)
  22. {
  23. // The remainder was big enough, so subtract dwTry from
  24. // the remainder and tack a 1 onto the sqrt.
  25. dwRemain -= dwTry;
  26. dwSqrt |= 0x01;
  27. }
  28. // Shift dwNum to the left by 2 so we can work on the next few
  29. // bits.
  30. dwNum <<= 2;
  31. }
  32. return(dwSqrt);
  33. }
  34. STDAPI_(VOID) DrawPie(HDC hDC, LPCRECT lprcItem, UINT uPctX10, BOOL TrueZr100,
  35. UINT uOffset, const COLORREF *lpColors)
  36. {
  37. int cx, cy, rx, ry, x, y;
  38. int uQPctX10;
  39. RECT rcItem;
  40. HRGN hEllRect, hEllipticRgn, hRectRgn;
  41. HBRUSH hBrush, hOldBrush;
  42. HPEN hPen, hOldPen;
  43. DWORD dwOldLayout;
  44. rcItem = *lprcItem;
  45. rcItem.left = lprcItem->left;
  46. rcItem.top = lprcItem->top;
  47. rcItem.right = lprcItem->right - rcItem.left;
  48. rcItem.bottom = lprcItem->bottom - rcItem.top - uOffset;
  49. rx = rcItem.right / 2;
  50. cx = rcItem.left + rx - 1;
  51. ry = rcItem.bottom / 2;
  52. cy = rcItem.top + ry - 1;
  53. if (rx<=10 || ry<=10)
  54. {
  55. return;
  56. }
  57. dwOldLayout = SET_DC_LAYOUT(hDC, 0);
  58. rcItem.right = rcItem.left+2*rx;
  59. rcItem.bottom = rcItem.top+2*ry;
  60. if (uPctX10 > 1000)
  61. {
  62. uPctX10 = 1000;
  63. }
  64. /* Translate to first quadrant of a Cartesian system
  65. */
  66. uQPctX10 = (uPctX10 % 500) - 250;
  67. if (uQPctX10 < 0)
  68. {
  69. uQPctX10 = -uQPctX10;
  70. }
  71. /* Calc x and y. I am trying to make the area be the right percentage.
  72. ** I don't know how to calculate the area of a pie slice exactly, so I
  73. ** approximate it by using the triangle area instead.
  74. */
  75. if (uQPctX10 < 120)
  76. {
  77. x = IntSqrt(((DWORD)rx*(DWORD)rx*(DWORD)uQPctX10*(DWORD)uQPctX10)
  78. /((DWORD)uQPctX10*(DWORD)uQPctX10+(250L-(DWORD)uQPctX10)*(250L-(DWORD)uQPctX10)));
  79. y = IntSqrt(((DWORD)rx*(DWORD)rx-(DWORD)x*(DWORD)x)*(DWORD)ry*(DWORD)ry/((DWORD)rx*(DWORD)rx));
  80. }
  81. else
  82. {
  83. y = IntSqrt((DWORD)ry*(DWORD)ry*(250L-(DWORD)uQPctX10)*(250L-(DWORD)uQPctX10)
  84. /((DWORD)uQPctX10*(DWORD)uQPctX10+(250L-(DWORD)uQPctX10)*(250L-(DWORD)uQPctX10)));
  85. x = IntSqrt(((DWORD)ry*(DWORD)ry-(DWORD)y*(DWORD)y)*(DWORD)rx*(DWORD)rx/((DWORD)ry*(DWORD)ry));
  86. }
  87. /* Switch on the actual quadrant
  88. */
  89. switch (uPctX10 / 250)
  90. {
  91. case 1:
  92. y = -y;
  93. break;
  94. case 2:
  95. break;
  96. case 3:
  97. x = -x;
  98. break;
  99. default: // case 0 and case 4
  100. x = -x;
  101. y = -y;
  102. break;
  103. }
  104. /* Now adjust for the center.
  105. */
  106. x += cx;
  107. y += cy;
  108. // Hack to get around bug in NTGDI
  109. x = x < 0 ? 0 : x;
  110. /* Draw the shadows using regions (to reduce flicker).
  111. */
  112. hEllipticRgn = CreateEllipticRgnIndirect(&rcItem);
  113. OffsetRgn(hEllipticRgn, 0, uOffset);
  114. hEllRect = CreateRectRgn(rcItem.left, cy, rcItem.right, cy+uOffset);
  115. hRectRgn = CreateRectRgn(0, 0, 0, 0);
  116. CombineRgn(hRectRgn, hEllipticRgn, hEllRect, RGN_OR);
  117. OffsetRgn(hEllipticRgn, 0, -(int)uOffset);
  118. CombineRgn(hEllRect, hRectRgn, hEllipticRgn, RGN_DIFF);
  119. /* Always draw the whole area in the free shadow/
  120. */
  121. hBrush = CreateSolidBrush(lpColors[DP_FREESHADOW]);
  122. if (hBrush)
  123. {
  124. FillRgn(hDC, hEllRect, hBrush);
  125. DeleteObject(hBrush);
  126. }
  127. /* Draw the used shadow only if the disk is at least half used.
  128. */
  129. if (uPctX10>500 && (hBrush=CreateSolidBrush(lpColors[DP_USEDSHADOW]))!=NULL)
  130. {
  131. DeleteObject(hRectRgn);
  132. hRectRgn = CreateRectRgn(x, cy, rcItem.right, lprcItem->bottom);
  133. CombineRgn(hEllipticRgn, hEllRect, hRectRgn, RGN_AND);
  134. FillRgn(hDC, hEllipticRgn, hBrush);
  135. DeleteObject(hBrush);
  136. }
  137. DeleteObject(hRectRgn);
  138. DeleteObject(hEllipticRgn);
  139. DeleteObject(hEllRect);
  140. hPen = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME));
  141. hOldPen = SelectObject(hDC, hPen);
  142. if((uPctX10 < 100) && (cy == y))
  143. {
  144. hBrush = CreateSolidBrush(lpColors[DP_FREECOLOR]);
  145. hOldBrush = SelectObject(hDC, hBrush);
  146. if((TrueZr100 == FALSE) || (uPctX10 != 0))
  147. {
  148. Pie(hDC, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom,
  149. rcItem.left, cy, x, y);
  150. }
  151. else
  152. {
  153. Ellipse(hDC, rcItem.left, rcItem.top, rcItem.right,
  154. rcItem.bottom);
  155. }
  156. }
  157. else if((uPctX10 > (1000 - 100)) && (cy == y))
  158. {
  159. hBrush = CreateSolidBrush(lpColors[DP_USEDCOLOR]);
  160. hOldBrush = SelectObject(hDC, hBrush);
  161. if((TrueZr100 == FALSE) || (uPctX10 != 1000))
  162. {
  163. Pie(hDC, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom,
  164. rcItem.left, cy, x, y);
  165. }
  166. else
  167. {
  168. Ellipse(hDC, rcItem.left, rcItem.top, rcItem.right,
  169. rcItem.bottom);
  170. }
  171. }
  172. else
  173. {
  174. hBrush = CreateSolidBrush(lpColors[DP_USEDCOLOR]);
  175. hOldBrush = SelectObject(hDC, hBrush);
  176. Ellipse(hDC, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom);
  177. SelectObject(hDC, hOldBrush);
  178. DeleteObject(hBrush);
  179. hBrush = CreateSolidBrush(lpColors[DP_FREECOLOR]);
  180. hOldBrush = SelectObject(hDC, hBrush);
  181. Pie(hDC, rcItem.left, rcItem.top, rcItem.right, rcItem.bottom,
  182. rcItem.left, cy, x, y);
  183. }
  184. SelectObject(hDC, hOldBrush);
  185. DeleteObject(hBrush);
  186. /* Do not draw the lines if the %age is truely 0 or 100 (completely
  187. ** empty disk or completly full disk)
  188. */
  189. if((TrueZr100 == FALSE) || ((uPctX10 != 0) && (uPctX10 != 1000)))
  190. {
  191. Arc(hDC, rcItem.left, rcItem.top+uOffset, rcItem.right, rcItem.bottom+uOffset,
  192. rcItem.left, cy+uOffset, rcItem.right, cy+uOffset-1);
  193. MoveToEx(hDC, rcItem.left, cy, NULL);
  194. LineTo(hDC, rcItem.left, cy+uOffset);
  195. MoveToEx(hDC, rcItem.right-1, cy, NULL);
  196. LineTo(hDC, rcItem.right-1, cy+uOffset);
  197. if (uPctX10 > 500)
  198. {
  199. MoveToEx(hDC, x, y, NULL);
  200. LineTo(hDC, x, y+uOffset);
  201. }
  202. }
  203. SelectObject(hDC, hOldPen);
  204. DeleteObject(hPen);
  205. SET_DC_LAYOUT(hDC, dwOldLayout);
  206. }