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.

290 lines
7.6 KiB

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