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.

373 lines
10 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: fillddi.cxx
  3. *
  4. * Contains filling simulations code and help functions.
  5. *
  6. * Created: 04-Apr-1991 17:30:35
  7. * Author: Wendy Wu [wendywu]
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. /******************************Member*Function*****************************\
  13. * EngFillPath
  14. *
  15. * This routine first converts the given pathobj to rgnmemobj then
  16. * calls EngPaint to fill.
  17. *
  18. * History:
  19. * 07-Mar-1992 -by- Donald Sidoroff [donalds]
  20. * Rewrote to call (Drv/Eng)Paint
  21. *
  22. * 13-Feb-1991 -by- Wendy Wu [wendywu]
  23. * Wrote it.
  24. \**************************************************************************/
  25. BOOL EngFillPath(
  26. SURFOBJ *pso,
  27. PATHOBJ *ppo,
  28. CLIPOBJ *pco,
  29. BRUSHOBJ *pbo,
  30. PPOINTL pptlBrushOrg,
  31. MIX mix,
  32. FLONG flOptions
  33. )
  34. {
  35. GDIFunctionID(EngFillPath);
  36. ASSERTGDI(pso != (SURFOBJ *) NULL, "pso is NULL\n");
  37. ASSERTGDI(ppo != (PATHOBJ *) NULL, "ppo is NULL\n");
  38. ASSERTGDI(pco != (CLIPOBJ *) NULL, "pco is NULL\n");
  39. PSURFACE pSurf = SURFOBJ_TO_SURFACE(pso);
  40. PDEVOBJ po(pSurf->hdev());
  41. SUSPENDWATCH sw(po);
  42. ASSERTGDI(pco->iMode == TC_RECTANGLES, "Invalid clip object iMode");
  43. // Check if we have to flatten any Beziers:
  44. if (ppo->fl & PO_BEZIERS)
  45. if (!((EPATHOBJ*) ppo)->bFlatten())
  46. return(FALSE);
  47. // Before we touch any bits, make sure the device is happy about it.
  48. po.vSync(pso,&pco->rclBounds,0);
  49. // check if we can try the fast fill.
  50. if (!( pSurf->flags() & HOOK_PAINT) &&
  51. (pco->iDComplexity != DC_COMPLEX))
  52. {
  53. PRECTL prclClip = NULL;
  54. if ((pco->iDComplexity == DC_RECT) ||
  55. (pco->fjOptions & OC_BANK_CLIP))
  56. {
  57. RECTFX rcfx = ((EPATHOBJ*)ppo)->rcfxBoundBox();
  58. // check the bound box, maybe it really is unclipped
  59. if ((pco->rclBounds.left > (rcfx.xLeft >> 4)) ||
  60. (pco->rclBounds.right < ((rcfx.xRight + 15) >> 4)) ||
  61. (pco->rclBounds.top > (rcfx.yTop >> 4)) ||
  62. (pco->rclBounds.bottom < ((rcfx.yBottom + 15) >> 4)))
  63. {
  64. prclClip = &pco->rclBounds;
  65. }
  66. }
  67. // -1 - couldn't handle, 0 error, 1 success
  68. LONG lRes = EngFastFill(pso,ppo,prclClip,pbo,pptlBrushOrg,mix,flOptions);
  69. if (lRes >= 0)
  70. return(lRes);
  71. }
  72. // Convert path to region.
  73. RECTL Bounds,*pBounds;
  74. if( pco->iDComplexity != DC_TRIVIAL )
  75. {
  76. Bounds.top = (pco->rclBounds.top) << 4;
  77. Bounds.bottom = (pco->rclBounds.bottom) << 4;
  78. pBounds = &Bounds;
  79. }
  80. else
  81. {
  82. pBounds = NULL;
  83. }
  84. RGNMEMOBJTMP rmo(*((EPATHOBJ *)ppo), flOptions, pBounds);
  85. if (!rmo.bValid())
  86. {
  87. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  88. return(FALSE);
  89. }
  90. if (rmo.iComplexity() == NULLREGION)
  91. return(TRUE);
  92. // CLIPOBJ_bEnum will do the clipping if clipping is not complex.
  93. ERECTL erclClip(pco->rclBounds);
  94. if (pco->iDComplexity == DC_TRIVIAL)
  95. {
  96. ECLIPOBJ ecoPath(rmo.prgnGet(), erclClip);
  97. if (ecoPath.erclExclude().bEmpty())
  98. return(TRUE);
  99. if (ecoPath.iDComplexity == DC_TRIVIAL)
  100. ecoPath.iDComplexity = DC_RECT;
  101. // Inc the target surface uniqueness
  102. INC_SURF_UNIQ(pSurf);
  103. BOOL bRet;
  104. sw.Resume();
  105. bRet = EngPaint(
  106. pso, // Destination surface.
  107. &ecoPath, // Clip object.
  108. pbo, // Realized brush.
  109. pptlBrushOrg, // Brush origin.
  110. mix); // Mix mode.
  111. return(bRet);
  112. }
  113. // Create a RGNMEMOBJ for bMerge since it will trash the target.
  114. RGNMEMOBJTMP rmoTrg;
  115. if (!rmoTrg.bValid())
  116. {
  117. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  118. return(FALSE);
  119. }
  120. // Merge the region we just constructed with the clip region.
  121. if (!rmoTrg.bMerge(rmo, *((ECLIPOBJ *)pco), gafjRgnOp[RGN_AND]))
  122. return(FALSE);
  123. ERECTL ercl;
  124. rmoTrg.vGet_rcl(&ercl);
  125. ercl *= ((ECLIPOBJ *)pco)->erclExclude();
  126. ECLIPOBJ co(rmoTrg.prgnGet(), ercl);
  127. if (co.erclExclude().bEmpty())
  128. return(TRUE);
  129. if (co.iDComplexity == DC_TRIVIAL)
  130. co.iDComplexity = DC_RECT;
  131. // Inc the target surface uniqueness
  132. INC_SURF_UNIQ(pSurf);
  133. sw.Resume();
  134. sw.Resume();
  135. return(EngPaint(
  136. pso, // Destination surface.
  137. &co, // Clip object.
  138. pbo, // Realized brush.
  139. pptlBrushOrg, // Brush origin.
  140. mix)); // Mix mode.
  141. }
  142. /******************************Member*Function*****************************\
  143. * EngStrokeAndFillPath
  144. *
  145. * Engine simulation for stroking and filling the given path.
  146. *
  147. * History:
  148. * 06-Apr-1992 -by- J. Andrew Goossen [andrewgo]
  149. * Re-wrote it to do region subtraction.
  150. *
  151. * 02-Oct-1991 -by- Wendy Wu [wendywu]
  152. * Wrote it.
  153. \**************************************************************************/
  154. BOOL EngStrokeAndFillPath(
  155. SURFOBJ *pso,
  156. PATHOBJ *ppo,
  157. CLIPOBJ *pco,
  158. XFORMOBJ *pxo,
  159. BRUSHOBJ *pboStroke,
  160. LINEATTRS *pla,
  161. BRUSHOBJ *pboFill,
  162. POINTL *pptlBrushOrg,
  163. MIX mix,
  164. FLONG flOptions)
  165. {
  166. BOOL bRet = FALSE;
  167. PSURFACE pSurf = SURFOBJ_TO_SURFACE(pso);
  168. MIX mixFill, mixStroke;
  169. mixFill = mixStroke = mix;
  170. if (!((EBRUSHOBJ *)pboFill)->bIsMasking())
  171. {
  172. mixFill = (mix & 0xff) | ((mix & 0xff) << 8);
  173. }
  174. if (!((EBRUSHOBJ *)pboStroke)->bIsMasking())
  175. {
  176. mixStroke = (mix & 0xff) | ((mix & 0xff) << 8);
  177. }
  178. ERECTL ercl;
  179. // If we're not doing a wide-line, or if we're doing a wide-line and
  180. // the mix is overwrite so we don't care about re-lighting pixels,
  181. // make two calls out of it:
  182. if (!(pla->fl & LA_GEOMETRIC) || ((mix & 0xFF) == R2_COPYPEN))
  183. {
  184. bRet = EngFillPath(pso,
  185. ppo,
  186. pco,
  187. pboFill,
  188. pptlBrushOrg,
  189. mixFill,
  190. flOptions) &&
  191. EngStrokePath(pso,
  192. ppo,
  193. pco,
  194. pxo,
  195. pboStroke,
  196. pptlBrushOrg,
  197. pla,
  198. mixStroke);
  199. return(bRet);
  200. }
  201. // Okay, we have a wideline call with a weird mix mode. Because part
  202. // of the wide-line overlaps part of the fill, we will convert both to
  203. // regions, and subtract them so that they won't overlap.
  204. // Convert the widened outline to a region. We have to widen the path
  205. // before flattening it (for the fill) because the widener will produce
  206. // better looking wide curves that way:
  207. PATHMEMOBJ pmoStroke;
  208. if (!pmoStroke.bValid() ||
  209. !pmoStroke.bComputeWidenedBounds(*(EPATHOBJ*) ppo, pxo, pla) ||
  210. !pmoStroke.bWiden(*(EPATHOBJ*) ppo, pxo, pla))
  211. {
  212. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  213. return(bRet);
  214. }
  215. // First flatten any curves and then convert the interior to a region:
  216. if (ppo->fl & PO_BEZIERS)
  217. {
  218. if (!((EPATHOBJ*) ppo)->bFlatten())
  219. {
  220. return(bRet);
  221. }
  222. }
  223. // Create the regions:
  224. RGNMEMOBJTMP rmoStroke(pmoStroke, WINDING);
  225. RGNMEMOBJTMP rmoFill(*((EPATHOBJ *)ppo), flOptions);
  226. RGNMEMOBJTMP rmoNewFill;
  227. if (rmoFill.bValid() &&
  228. rmoStroke.bValid() &&
  229. rmoNewFill.bValid() &&
  230. rmoNewFill.bMerge(rmoFill, rmoStroke, gafjRgnOp[RGN_DIFF]))
  231. {
  232. // Create a RGNMEMOBJ for bMerge since it will trash the target.
  233. RGNMEMOBJTMP rmoTrg;
  234. if (rmoTrg.bValid())
  235. {
  236. PDEVOBJ pdo(pSurf->hdev());
  237. // Paint the stroked outline:
  238. if (rmoStroke.iComplexity() != NULLREGION)
  239. {
  240. // Merge the outline region with the clip region:
  241. if (!rmoTrg.bMerge(rmoStroke, *((ECLIPOBJ *)pco), gafjRgnOp[RGN_AND]))
  242. {
  243. bRet = FALSE;
  244. }
  245. else
  246. {
  247. rmoTrg.vGet_rcl(&ercl);
  248. ECLIPOBJ co(rmoTrg.prgnGet(), ercl);
  249. if (co.erclExclude().bEmpty())
  250. {
  251. bRet = TRUE;
  252. }
  253. else
  254. {
  255. INC_SURF_UNIQ(pSurf);
  256. bRet = EngPaint(
  257. pso,
  258. &co,
  259. pboStroke,
  260. pptlBrushOrg,
  261. mixStroke);
  262. }
  263. }
  264. }
  265. // Paint the filled interior:
  266. if ((bRet == TRUE) &&
  267. rmoNewFill.iComplexity() != NULLREGION)
  268. {
  269. // Merge the inside region with the clip region.
  270. if (!rmoTrg.bMerge(rmoNewFill, *((ECLIPOBJ *)pco), gafjRgnOp[RGN_AND]))
  271. {
  272. bRet = FALSE;
  273. }
  274. else
  275. {
  276. rmoTrg.vGet_rcl(&ercl);
  277. ECLIPOBJ co(rmoTrg.prgnGet(), ercl);
  278. if (co.erclExclude().bEmpty())
  279. {
  280. bRet = TRUE;
  281. }
  282. else
  283. {
  284. INC_SURF_UNIQ(pSurf);
  285. bRet = EngPaint(pso,
  286. &co,
  287. pboFill,
  288. pptlBrushOrg,
  289. mixFill);
  290. }
  291. }
  292. }
  293. }
  294. }
  295. return(bRet);
  296. }