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.

246 lines
6.4 KiB

  1. #include "stdafx.h"
  2. #include "Base.h"
  3. #include "GfxHelp.h"
  4. /***************************************************************************\
  5. *
  6. * GdDrawBlendRect
  7. *
  8. * GdDrawBlendRect draws a alpha-blended rectangle using the current brush
  9. * and specified alpha level
  10. *
  11. \***************************************************************************/
  12. BOOL GdDrawBlendRect(HDC hdcDest, const RECT * prcDest, HBRUSH hbrFill, BYTE bAlpha, int wBrush, int hBrush)
  13. {
  14. HBITMAP hbmpSrc = NULL, hbmpOld = NULL;
  15. HDC hdcSrc = NULL;
  16. HBRUSH hbrOld;
  17. BOOL fSuccess = FALSE;
  18. if ((wBrush == 0) || (hBrush == 0)) {
  19. wBrush = 100;
  20. hBrush = 100;
  21. }
  22. hbmpSrc = CreateCompatibleBitmap(hdcDest, wBrush, hBrush);
  23. if (hbmpSrc == NULL) {
  24. goto cleanup;
  25. }
  26. hdcSrc = CreateCompatibleDC(hdcDest);
  27. if (hdcSrc == NULL) {
  28. goto cleanup;
  29. }
  30. hbmpOld = (HBITMAP) SelectObject(hdcSrc, hbmpSrc);
  31. hbrOld = (HBRUSH) SelectObject(hdcSrc, hbrFill);
  32. PatBlt(hdcSrc, 0, 0, wBrush, hBrush, PATCOPY);
  33. SelectObject(hdcSrc, hbrOld);
  34. BLENDFUNCTION blend;
  35. blend.BlendOp = AC_SRC_OVER;
  36. blend.BlendFlags = 0;
  37. blend.AlphaFormat = 0;
  38. blend.SourceConstantAlpha = bAlpha;
  39. AlphaBlend(hdcDest, prcDest->left, prcDest->top,
  40. prcDest->right - prcDest->left, prcDest->bottom - prcDest->top,
  41. hdcSrc, 0, 0, wBrush, hBrush, blend);
  42. fSuccess = TRUE;
  43. cleanup:
  44. if (hdcSrc != NULL) {
  45. SelectObject(hdcSrc, hbmpOld);
  46. DeleteDC(hdcSrc);
  47. }
  48. DeleteObject(hbmpSrc);
  49. return fSuccess;
  50. }
  51. /***************************************************************************\
  52. *
  53. * GetSignFromMappingMode
  54. *
  55. * For the current mapping mode, find out the sign of x from left to right,
  56. * and the sign of y from top to bottom.
  57. *
  58. * History:
  59. * 2000-04-22 JStall Ported from NT-USER
  60. *
  61. \***************************************************************************/
  62. BOOL GetSignFromMappingMode (
  63. HDC hdc,
  64. PPOINT pptSign)
  65. {
  66. SIZE sizeViewPortExt;
  67. SIZE sizeWindowExt;
  68. if (!GetViewportExtEx(hdc, &sizeViewPortExt)
  69. || !GetWindowExtEx(hdc, &sizeWindowExt)) {
  70. return FALSE;
  71. }
  72. pptSign->x = ((sizeViewPortExt.cx ^ sizeWindowExt.cx) < 0) ? -1 : 1;
  73. pptSign->y = ((sizeViewPortExt.cy ^ sizeWindowExt.cy) < 0) ? -1 : 1;
  74. return TRUE;
  75. }
  76. BOOL
  77. GdDrawOutlineRect(Gdiplus::Graphics * pgpgr, const RECT * prcPxl, Gdiplus::Brush * pgpbr, int nThickness)
  78. {
  79. Gdiplus::RectF rc(
  80. (float) prcPxl->left,
  81. (float) prcPxl->top,
  82. (float) (prcPxl->right - prcPxl->left),
  83. (float) (prcPxl->bottom - prcPxl->top));
  84. if ((rc.Width < 0) || (rc.Height < 0)) {
  85. return FALSE;
  86. }
  87. Gdiplus::RectF rcPxl(rc);
  88. /*
  89. * Factor in the thickness of the rectangle to be drawn. This will
  90. * automatically offset the edges so that the actual rectangle gets filled
  91. * "in" as it becomes thicker.
  92. */
  93. Gdiplus::PointF ptEdge((float) nThickness, (float) nThickness);
  94. Gdiplus::RectF rcFill;
  95. BOOL fSuccess = TRUE;
  96. // Top border
  97. rcFill.X = rc.X;
  98. rcFill.Y = rc.Y;
  99. rcFill.Width = rc.Width;
  100. rcFill.Height = ptEdge.Y;
  101. pgpgr->FillRectangle(pgpbr, rcFill);
  102. // Bottom border
  103. rc.Y = rcPxl.Y + rcPxl.Height - ptEdge.Y;
  104. rcFill.X = rc.X;
  105. rcFill.Y = rc.Y;
  106. rcFill.Width = rc.Width;
  107. rcFill.Height = ptEdge.Y;
  108. pgpgr->FillRectangle(pgpbr, rcFill);
  109. /*
  110. * Left Border
  111. * Don't xor the corners twice
  112. */
  113. rc.Y = rcPxl.Y + ptEdge.Y;
  114. rc.Height -= 2 * ptEdge.Y;
  115. rcFill.X = rc.X;
  116. rcFill.Y = rc.Y;
  117. rcFill.Width = ptEdge.X;
  118. rcFill.Height = rc.Height;
  119. pgpgr->FillRectangle(pgpbr, rcFill);
  120. // Right Border
  121. rc.X = rcPxl.X + rcPxl.Width - ptEdge.X;
  122. rcFill.X = rc.X;
  123. rcFill.Y = rc.Y;
  124. rcFill.Width = ptEdge.X;
  125. rcFill.Height = rc.Height;
  126. pgpgr->FillRectangle(pgpbr, rcFill);
  127. return fSuccess;
  128. }
  129. /***************************************************************************\
  130. *
  131. * GdDrawOutlineRect
  132. *
  133. * GdDrawOutlineRect draws the outline of a rectange using the specified
  134. * brush. This function uses the same "off-by-1" errors as GDI.
  135. *
  136. \***************************************************************************/
  137. BOOL
  138. GdDrawOutlineRect(HDC hdc, const RECT * prcPxl, HBRUSH hbrDraw, int nThickness)
  139. {
  140. int w;
  141. int h;
  142. POINT point;
  143. POINT ptEdge;
  144. if (!GetSignFromMappingMode(hdc, &ptEdge))
  145. return FALSE;
  146. h = prcPxl->bottom - (point.y = prcPxl->top);
  147. if (h < 0) {
  148. return FALSE;
  149. }
  150. w = prcPxl->right - (point.x = prcPxl->left);
  151. /*
  152. * Check width and height signs
  153. */
  154. if (((w ^ ptEdge.x) < 0) || ((h ^ ptEdge.y) < 0))
  155. return FALSE;
  156. /*
  157. * Factor in the thickness of the rectangle to be drawn. This will
  158. * automatically offset the edges so that the actual rectangle gets filled
  159. * "in" as it becomes thicker.
  160. */
  161. ptEdge.x *= nThickness;
  162. ptEdge.y *= nThickness;
  163. RECT rcFill;
  164. BOOL fSuccess = TRUE;
  165. // Top border
  166. rcFill.left = point.x;
  167. rcFill.top = point.y;
  168. rcFill.right = point.x + w;
  169. rcFill.bottom = point.y + ptEdge.y;
  170. fSuccess &= FillRect(hdc, &rcFill, hbrDraw);
  171. // Bottom border
  172. point.y = prcPxl->bottom - ptEdge.y;
  173. rcFill.left = point.x;
  174. rcFill.top = point.y;
  175. rcFill.right = point.x + w;
  176. rcFill.bottom = point.y + ptEdge.y;
  177. fSuccess &= FillRect(hdc, &rcFill, hbrDraw);
  178. /*
  179. * Left Border
  180. * Don't xor the corners twice
  181. */
  182. point.y = prcPxl->top + ptEdge.y;
  183. h -= 2 * ptEdge.y;
  184. rcFill.left = point.x;
  185. rcFill.top = point.y;
  186. rcFill.right = point.x + ptEdge.x;
  187. rcFill.bottom = point.y + h;
  188. fSuccess &= FillRect(hdc, &rcFill, hbrDraw);
  189. // Right Border
  190. point.x = prcPxl->right - ptEdge.x;
  191. rcFill.left = point.x;
  192. rcFill.top = point.y;
  193. rcFill.right = point.x + ptEdge.x;
  194. rcFill.bottom = point.y + h;
  195. fSuccess &= FillRect(hdc, &rcFill, hbrDraw);
  196. return fSuccess;
  197. }