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.

531 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. path.c
  5. Abstract:
  6. This module contains Functions related to drawing paths. The main stroke
  7. drawing entry poing DrvStrokePath, is implemented in this module.
  8. See also textout.c, bitblt.c: These two have copies of almost all the
  9. DrvStrokePath() code.
  10. Author:
  11. 17:30 on Wed 03 Apr 1991
  12. Created it
  13. 8/18/92 AP
  14. I have pretty much rewritten most of this. Some of the original
  15. code is left in, mainly to point out things that need to be added.
  16. 15-Nov-1993 Mon 19:40:18 updated
  17. clean up / debugging information
  18. 30-Nov-1993 Tue 22:32:12 updated
  19. style clean up, updated
  20. 01-Feb-1994 updated
  21. Added the ability to stroke styled lines through a complex
  22. clipping object
  23. [Environment:]
  24. GDI Device Driver - Plotter.
  25. [Notes:]
  26. Revision History:
  27. --*/
  28. #include "precomp.h"
  29. #pragma hdrstop
  30. #define DBG_PLOTFILENAME DbgPath
  31. #define DBG_STROKEPATH 0x00000001
  32. #define DBG_SELECTCOLOR 0x00000002
  33. #define DBG_STROKECLIPLINES 0x00000004
  34. #define DBG_MOVEPEN 0x00000008
  35. DEFINE_DBGVAR(0);
  36. BOOL
  37. DoStrokePathByEnumingClipLines(
  38. PPDEV pPDev,
  39. SURFOBJ *pso,
  40. CLIPOBJ *pco,
  41. PATHOBJ *ppo,
  42. PPOINTL pptlBrushOrg,
  43. BRUSHOBJ *pbo,
  44. ROP4 rop4,
  45. LINEATTRS *plineattrs
  46. )
  47. /*++
  48. Routine Description:
  49. Strokes a path through a complex clipping region by utilizing the
  50. engine helper functions. This is done because there is no way to
  51. fail a DrvStrokePath and have it come back in any simpler format by
  52. the NT graphics engine. In general, we can fail DrvXXX calls and the
  53. NT graphic engine will simply the object to draw, then call back into
  54. the driver. Stroking a path however cannot be simplified any more, so
  55. the best we can hope for is having the PATHOBJ converted to straight
  56. line segments (removing BEZIERS if present). We then must stroke the
  57. path ourselves, using the provided EngXXX helpers.
  58. Since helper functions exist that allow us to to enumerate the
  59. portions of a path as CLIPLINE segments that fall within the
  60. clipping region, we do that here, thus stroking the segments that lie
  61. inside of the passed CLIPOBJ.
  62. Arguments:
  63. pPDev Pointer to the current PDEV
  64. pso SURFOBJ to write to
  65. pco CLIPOBJ to use when enuming paths
  66. ppo PATHOBJ to stroke through clip path
  67. pptlBrushOrg BRUSH origin
  68. pbo BRUSH to stroke with
  69. rop4 ROP4 to use
  70. plineattrs LINEATTRS structure that describes the styling for the line
  71. Return Value:
  72. TRUE if sucessful FALSE if failed, If the path we are asked to stroke
  73. contains BEZIERS, this function will fail in order to allow the
  74. Engine to break the path down to line segments.
  75. Author:
  76. 2/01/94 JB
  77. Revision History:
  78. --*/
  79. {
  80. PLOT_CLIPLINE PlotClipLine;
  81. CLIPLINE *pCurClipLine;
  82. RUN *pCurRun;
  83. POINTFIX ptsfx[2];
  84. POINTL ptlCur;
  85. FIX iStartInFX;
  86. FIX iStopInFX;
  87. LONG dx;
  88. LONG dy;
  89. LONG i;
  90. BOOL bMore;
  91. BOOL bXordered;
  92. BOOL bFlipX;
  93. BOOL bFlipY;
  94. //
  95. // First check for Beziers and if we have them fail the call since we
  96. // want straight line segments to stroke, with the appropriate style
  97. //
  98. if (ppo->fl & PO_BEZIERS) {
  99. PLOTDBG(DBG_STROKECLIPLINES,
  100. ("DoStrokePathByEnumingClipLines:Path had BEZ returning FALSE"));
  101. return(FALSE);
  102. }
  103. if (NULL == pco) {
  104. PLOTDBG(DBG_STROKECLIPLINES,
  105. ("DoStrokePathByEnumingClipLines:CLIPOBJ is NULL."));
  106. return(FALSE);
  107. }
  108. //
  109. // Send out the line attributes , so the residue will be calculated
  110. // correctly
  111. //
  112. DoSetupOfStrokeAttributes(pPDev, pptlBrushOrg, pbo, rop4, NULL);
  113. //
  114. // Initiate enumeration of the CLIPLINES by calling the Engine helper
  115. //
  116. PATHOBJ_vEnumStartClipLines(ppo, pco, pso, plineattrs);
  117. //
  118. // Start a loop to enum through all the available CLIPLINE structures
  119. //
  120. pCurClipLine = (CLIPLINE *)&PlotClipLine;
  121. do {
  122. //
  123. // Get the first batch of CLIPLINE structures then go to work on them
  124. //
  125. bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(PlotClipLine), pCurClipLine);
  126. //
  127. // Calculate dx and dy in order to determine if the line is Xordered or
  128. // Yordered this is needed because of the way the engine passes us RUNS
  129. // if dx > dy then the line is said to be Xordered and thus any given
  130. // RUN iStart and iStop values is a projection on the x axis. Given this
  131. // informatino we can calculate the adjoining Y coordinate and draw the
  132. // line appropriately.
  133. //
  134. dx = pCurClipLine->ptfxB.x - pCurClipLine->ptfxA.x;
  135. dy = pCurClipLine->ptfxB.y - pCurClipLine->ptfxA.y;
  136. if ( bFlipX = (dx < 0 )) {
  137. dx = -dx;
  138. }
  139. if ( bFlipY = (dy < 0 )) {
  140. dy = -dy;
  141. }
  142. //
  143. // Now calculate if the line is x ordered or y ordered
  144. //
  145. bXordered = (dx >= dy);
  146. PLOTDBG(DBG_STROKECLIPLINES,
  147. ("DoStrokePathByEnumingClipLines:Compute ClipLine runs=%u, xordered %d",
  148. pCurClipLine->c, bXordered ));
  149. //
  150. // Enum through all the given RUNS drawing with the pen down between any
  151. // iStart and iStop value in each RUN
  152. //
  153. for (i = 0, pCurRun = &(pCurClipLine->arun[0]);
  154. i < (LONG)pCurClipLine->c;
  155. i++, pCurRun++) {
  156. //
  157. // The value of iStart and iStop are always positive!! so
  158. // we must handle it ourselves, so the correct thing happens
  159. //
  160. iStartInFX = LTOFX(pCurRun->iStart);
  161. iStopInFX = LTOFX(pCurRun->iStop);
  162. if (bFlipX ) {
  163. ptsfx[0].x = -iStartInFX;
  164. ptsfx[1].x = -iStopInFX;
  165. } else {
  166. ptsfx[0].x = iStartInFX;
  167. ptsfx[1].x = iStopInFX;
  168. }
  169. if (bFlipY ) {
  170. ptsfx[0].y = -iStartInFX;
  171. ptsfx[1].y = -iStopInFX;
  172. } else {
  173. ptsfx[0].y = iStartInFX;
  174. ptsfx[1].y = iStopInFX;
  175. }
  176. //
  177. // We must output the correct line attributes structure with the
  178. // correct calculated residue in order for this to work correctly
  179. //
  180. HandleLineAttributes(pPDev,
  181. plineattrs,
  182. &pCurClipLine->lStyleState,
  183. pCurRun->iStart);
  184. //
  185. // The calculations for the opposing coordinate varies based on the
  186. // ordering of the line. If the line is Xordered we calculate the
  187. // Y value, if itsYordered we calculate the X value. We do this
  188. // in order to determine the correct target coordinate. Since the
  189. // RUN is given to us as START and STOP, we must manually determine
  190. // what coordinate this represents inside the device coordinate
  191. // space. If the RUN is xordered, the x-coordinate is correct, and
  192. // the y-coordinate must be projected based on the ratio.
  193. //
  194. if (bXordered) {
  195. ptsfx[0].x += pCurClipLine->ptfxA.x;
  196. ptsfx[0].y = MulDiv( ptsfx[0].y, dy, dx) +
  197. pCurClipLine->ptfxA.y;
  198. ptsfx[1].x += pCurClipLine->ptfxA.x;
  199. ptsfx[1].y = MulDiv( ptsfx[1].y, dy, dx) +
  200. pCurClipLine->ptfxA.y;
  201. } else {
  202. ptsfx[0].x = MulDiv(ptsfx[0].x, dx, dy) +
  203. pCurClipLine->ptfxA.x;
  204. ptsfx[0].y += pCurClipLine->ptfxA.y;
  205. ptsfx[1].x = MulDiv(ptsfx[1].x, dx, dy) +
  206. pCurClipLine->ptfxA.x;
  207. ptsfx[1].y += pCurClipLine->ptfxA.y;
  208. }
  209. //
  210. // Do PE with pen up first, in order to move to the starting
  211. // position.
  212. //
  213. OutputString(pPDev, "PE<");
  214. if (!i) {
  215. //
  216. // If we are at first point then output that now.
  217. //
  218. ptlCur.x =
  219. ptlCur.y = 0;
  220. OutputString(pPDev, "=");
  221. }
  222. //
  223. // Stroke the segment with the pen down.
  224. //
  225. OutputXYParams(pPDev,
  226. (PPOINTL)ptsfx,
  227. (PPOINTL)NULL,
  228. (PPOINTL)&ptlCur,
  229. (UINT)2,
  230. (UINT)1,
  231. 'F');
  232. OutputString(pPDev, ";");
  233. }
  234. } while (bMore); // While we need to enum again..
  235. return(TRUE);
  236. }
  237. BOOL
  238. DrvStrokePath(
  239. SURFOBJ *pso,
  240. PATHOBJ *ppo,
  241. CLIPOBJ *pco,
  242. XFORMOBJ *pxo,
  243. BRUSHOBJ *pbo,
  244. PPOINTL pptlBrushOrg,
  245. LINEATTRS *plineattrs,
  246. MIX Mix
  247. )
  248. /*++
  249. Routine Description:
  250. The driver's function for the StrokePath
  251. Arguments:
  252. same as EngStrokePath
  253. Return Value:
  254. TRUE if sucessful FALSE if failed
  255. Author:
  256. 8/18/92 -- t-alip
  257. Rewrote it.
  258. 30-Nov-1993 Tue 22:21:51 updated
  259. updated by DC
  260. 04-Aug-1994 Thu 20:00:23 updated
  261. bug# 22348
  262. Revision History:
  263. 31-Jan-1994 Tue 22:21:51 updated
  264. Fixed dopolygon to pass in ROP4 not just MIX
  265. --*/
  266. {
  267. PPDEV pPDev;
  268. BOOL bRetVal;
  269. UNREFERENCED_PARAMETER(pxo);
  270. PLOTDBG(DBG_STROKEPATH, ("DrvStrokePath: Mix = %x", Mix));
  271. if (!(pPDev = SURFOBJ_GETPDEV(pso))) {
  272. PLOTERR(("DrvStrokePath: Invalid pPDev"));
  273. return(FALSE);
  274. }
  275. if (!(bRetVal = DoPolygon(pPDev,
  276. NULL,
  277. pco,
  278. ppo,
  279. pptlBrushOrg,
  280. NULL,
  281. pbo,
  282. MixToRop4(Mix),
  283. plineattrs,
  284. FPOLY_STROKE) )) {
  285. //
  286. // Since DoPolygon failed, it can only be because we had both a complex
  287. // clip and a pathobj, so the thing to here is do the stroke via another
  288. // method using some of the engine helpers.
  289. //
  290. // We will also failed when STYLE LINE + DC_RECT when raster plotter is
  291. // used
  292. //
  293. bRetVal = DoStrokePathByEnumingClipLines( pPDev,
  294. pso,
  295. pco,
  296. ppo,
  297. pptlBrushOrg,
  298. pbo,
  299. MixToRop4(Mix),
  300. plineattrs);
  301. }
  302. return(bRetVal);
  303. }
  304. BOOL
  305. MovePen(
  306. PPDEV pPDev,
  307. PPOINTFIX pPtNewPos,
  308. PPOINTL pPtDevPos
  309. )
  310. /*++
  311. Routine Description:
  312. This function sends the HPGL code for the requested pen.
  313. Arguments:
  314. pPDev - Pointer to the PDEV data structure
  315. pPtNewPos - The location pen will move to, this is in 28.4 fix notation
  316. pPtDevPos - The new device coordinate device position
  317. Return Value:
  318. TRUE if sucessful FALSE otherwise
  319. Author:
  320. 1:04 on Tue 7 Nov 1989
  321. Added this commentary, and area fill optimization code.
  322. 30-Nov-1993 Tue 22:05:32 updated
  323. Update, commented and clean up style
  324. 16-Feb-1994 Wed 17:10:54 updated
  325. Re-write to get rid of the physical position
  326. Revision History:
  327. --*/
  328. {
  329. POINTL ptDevPos;
  330. ptDevPos.x = FXTODEVL(pPDev, pPtNewPos->x);
  331. ptDevPos.y = FXTODEVL(pPDev, pPtNewPos->y);
  332. if (pPtDevPos) {
  333. *pPtDevPos = ptDevPos;
  334. }
  335. PLOTDBG( DBG_MOVEPEN,
  336. ("MovePen: Moving Absolute to FIX = [X=%d,%d] Device = [X=%d, Y=%d]",
  337. pPtNewPos->x,
  338. pPtNewPos->y,
  339. ptDevPos.x,
  340. ptDevPos.y ));
  341. return(OutputFormatStr(pPDev, "PE<=#D#D;", ptDevPos.x, ptDevPos.y));
  342. }