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.

551 lines
18 KiB

  1. /******************************Module*Header***********************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: Stroke.c
  8. *
  9. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  10. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  11. ******************************************************************************/
  12. #include "precomp.h"
  13. #include "gdi.h"
  14. #include "log.h"
  15. PFNSTRIP gapfnStrip[] =
  16. {
  17. vSolidHorizontalLine,
  18. vSolidVerticalLine,
  19. vSolidDiagonalHorizontalLine,
  20. vSolidDiagonalVerticalLine,
  21. // Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
  22. vSolidHorizontalLine,
  23. vSolidVerticalLine,
  24. vSolidDiagonalHorizontalLine,
  25. vSolidDiagonalVerticalLine,
  26. // Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
  27. // solid lines, and the same number for non-solid lines:
  28. vStyledHorizontalLine,
  29. vStyledVerticalLine,
  30. vStyledVerticalLine, // Diagonal goes here
  31. vStyledVerticalLine, // Diagonal goes here
  32. vStyledHorizontalLine,
  33. vStyledVerticalLine,
  34. vStyledVerticalLine, // Diagonal goes here
  35. vStyledVerticalLine, // Diagonal goes here
  36. };
  37. // Style array for alternate style (alternates one pixel on, one pixel off):
  38. STYLEPOS gaspAlternateStyle[] = { 1 };
  39. //-----------------------------------------------------------------------------
  40. // BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrush, pla, mix)
  41. //
  42. // DrvStrokePath strokes a path when called by GDI. If the driver has hooked the
  43. // function, and if the appropriate GCAPs are set, GDI calls DrvStrokePath when
  44. // GDI draws a line or curve with any set of attributes.
  45. //
  46. // Parameters
  47. // pso----------Identifies the surface on which to draw.
  48. // ppo----------Points to a PATHOBJ structure. GDI PATHOBJ_Xxx service routines
  49. // are provided to enumerate the lines, Bezier curves, and other
  50. // data that make up the path. This indicates what is to be drawn.
  51. // pco----------Points to a CLIPOBJ structure. GDI CLIPOBJ_Xxx service routines
  52. // are provided to enumerate the clip region as a set of
  53. // rectangles. Optionally, all the lines in the path may be
  54. // enumerated preclipped by CLIPOBJ. This means that drivers can
  55. // have all their line clipping calculations done for them.
  56. // pxo----------Points to a XFORMOBJ. This is only needed when a geometric wide
  57. // line is to be drawn. It specifies the transform that maps world
  58. // coordinates to device coordinates. This is needed because the
  59. // path is provided in device coordinates but a geometric wide line
  60. // is actually widened in world coordinates.
  61. // The XFORMOBJ can be queried to find the transform.
  62. // pbo----------Specifies the brush to be used when drawing the path.
  63. // pptlBrushOrg-Points to the brush origin used to align the brush pattern on
  64. // the device.
  65. // pLineAttrs---Points to a LINEATTRS structure. Note that the elStyleState
  66. // member must be updated as part of this function if the line is
  67. // styled. Also note that the ptlLastPel member must be updated if
  68. // a single pixel width cosmetic line is being drawn.
  69. // mix----------Specifies how to combine the brush with the destination.
  70. //
  71. // Return Value
  72. // The return value is TRUE if the driver is able to stroke the path. If GDI
  73. // should stroke the path, the return value is FALSE, and an error code is not
  74. // logged. If the driver encounters an error, the return value is DDI_ERROR,
  75. // and an error code is reported.
  76. //
  77. // Comments
  78. // If a driver supports this entry point, it should also support the drawing of
  79. // cosmetic wide lines with arbitrary clipping. Using the provided GDI
  80. // functions, the call can be broken down into a set of single-pixel-width
  81. // lines with precomputed clipping.
  82. //
  83. // This function is required if any drawing is to be done on a device-managed
  84. // surface.
  85. //
  86. // Drivers for advanced devices can optionally receive this call to draw paths
  87. // containing Bezier curves and geometric wide lines. GDI will test the
  88. // GCAPS_BEZIERS and GCAPS_GEOMETRICWIDE flags of the flGraphicsCaps member of
  89. // the DEVINFO structure to decide whether it should call. (The four
  90. // combinations of the bits determine the four levels of functionality for
  91. // this call.) If the driver gets an advanced call containing Bezier curves or
  92. // geometric wide lines, it can decide not to handle the call, returning FALSE.
  93. // This might happen if the path or clipping is too complex for the device to
  94. // process. If the call does return FALSE, GDI breaks the call down into
  95. // simpler calls that can be handled easily.
  96. //
  97. // For device-managed surfaces, the function must minimally support
  98. // single-pixel-wide solid and styled cosmetic lines using a solid-colored
  99. // brush. The device can return FALSE if the line is geometric and the engine
  100. // will convert those calls to DrvFillPath or DrvPaint calls.
  101. //
  102. // The mix mode defines how the incoming pattern should be mixed with the data
  103. // already on the device surface. The MIX data type consists of two ROP2 values
  104. // packed into a single ULONG. The low-order byte defines the foreground raster
  105. // operation; the next byte defines the background raster operation. For more
  106. // information about raster operation codes, see the Platform SDK.
  107. //
  108. //-----------------------------------------------------------------------------
  109. BOOL
  110. DrvStrokePath(SURFOBJ* pso,
  111. PATHOBJ* ppo,
  112. CLIPOBJ* pco,
  113. XFORMOBJ* pxo,
  114. BRUSHOBJ* pbo,
  115. POINTL* pptlBrush,
  116. LINEATTRS* pLineAttrs,
  117. MIX mix)
  118. {
  119. STYLEPOS aspLtoR[STYLE_MAX_COUNT];
  120. STYLEPOS aspRtoL[STYLE_MAX_COUNT];
  121. LINESTATE lineState;
  122. PFNSTRIP* apfn;
  123. FLONG fl;
  124. PDev* ppdev;
  125. Surf* psurfDst;
  126. RECTL arclClip[4]; // For rectangular clipping
  127. BOOL bResetHW;
  128. BOOL bRet;
  129. DWORD logicOp;
  130. DBG_GDI((6, "DrvStrokePath called with mix =%x", mix));
  131. psurfDst = (Surf*)pso->dhsurf;
  132. //
  133. // Punt to engine if surface to draw is not in video memory
  134. //
  135. if ( psurfDst->flags & SF_SM )
  136. {
  137. goto puntIt;
  138. }
  139. ppdev = (PDev*)pso->dhpdev;
  140. //@@BEGIN_DDKSPLIT
  141. #if MULTITHREADED
  142. if(ppdev->ulLockCount)
  143. {
  144. DBG_GDI((MT_LOG_LEVEL, "DrvStrokePath: re-entered! %d", ppdev->ulLockCount));
  145. }
  146. EngAcquireSemaphore(ppdev->hsemLock);
  147. ppdev->ulLockCount++;
  148. #endif
  149. //@@END_DDKSPLIT
  150. vCheckGdiContext(ppdev);
  151. ppdev->psurf = psurfDst;
  152. fl = 0;
  153. //
  154. // Look after styling initialization:
  155. //
  156. if ( pLineAttrs->fl & LA_ALTERNATE )
  157. {
  158. //
  159. // LA_ALTERNATE: A special cosmetic line style; every other pixel is on
  160. //
  161. lineState.cStyle = 1;
  162. lineState.spTotal = 1;
  163. lineState.spTotal2 = 2;
  164. lineState.spRemaining = 1;
  165. lineState.aspRtoL = &gaspAlternateStyle[0];
  166. lineState.aspLtoR = &gaspAlternateStyle[0];
  167. lineState.spNext = HIWORD(pLineAttrs->elStyleState.l);
  168. lineState.xyDensity = 1;
  169. lineState.ulStartMask = 0L;
  170. fl |= FL_ARBITRARYSTYLED;
  171. }// Cosmetic line
  172. else if ( pLineAttrs->pstyle != (FLOAT_LONG*)NULL )
  173. {
  174. //
  175. // "pLineAttrs->pstyle" points to the style array. If this member is
  176. // null, the line style is solid
  177. //
  178. PFLOAT_LONG pStyle;
  179. STYLEPOS* pspDown;
  180. STYLEPOS* pspUp;
  181. //
  182. // "pLineAttrs->cstyle" specifies the number of entries in the style
  183. // array. So here we get the address of the last array first
  184. //
  185. pStyle = &pLineAttrs->pstyle[pLineAttrs->cstyle];
  186. lineState.xyDensity = STYLE_DENSITY;
  187. lineState.spTotal = 0;
  188. //
  189. // Loop through all the data array backworfds to get the sum of style
  190. // array
  191. //
  192. while ( pStyle-- > pLineAttrs->pstyle )
  193. {
  194. lineState.spTotal += pStyle->l;
  195. }
  196. lineState.spTotal *= STYLE_DENSITY;
  197. lineState.spTotal2 = 2 * lineState.spTotal;
  198. //
  199. // Compute starting style position (this is guaranteed not to overflow)
  200. // Note: "pLineAttrs->elStyleState" is a pair of 16-bit values supplied
  201. // by GDI whenever the driver calls PATHOBJ_bEnumClipLines. These two
  202. // values, packed into a LONG, specify where in the styling array
  203. // (at which pixel) to start the first subpath. This value must be
  204. // updated as part of the output routine if the line is not solid.
  205. // This member applies to cosmetic lines only.
  206. //
  207. lineState.spNext = HIWORD(pLineAttrs->elStyleState.l) * STYLE_DENSITY
  208. + LOWORD(pLineAttrs->elStyleState.l);
  209. fl |= FL_ARBITRARYSTYLED;
  210. lineState.cStyle = pLineAttrs->cstyle;
  211. lineState.aspRtoL = aspRtoL;
  212. lineState.aspLtoR = aspLtoR;
  213. if ( pLineAttrs->fl & LA_STARTGAP )
  214. {
  215. //
  216. // The first entry in the style array specifies the length of the
  217. // first gap. set "ulStartMask" to mark it as a GAP
  218. //
  219. lineState.ulStartMask = 0xffffffffL;
  220. }
  221. else
  222. {
  223. //
  224. // It must be LA_GEOMETRIC which specifies a geometric wide line. Mark
  225. // it as not a GAP
  226. //
  227. lineState.ulStartMask = 0L;
  228. }
  229. //
  230. // Let "pStyle" points to the 1st style array, "pspDown" ponits to the
  231. // "cStyle"th array in aspRtoL and "pspUp" points to the 1st array in
  232. // aspLtoR
  233. //
  234. pStyle = pLineAttrs->pstyle;
  235. pspDown = &lineState.aspRtoL[lineState.cStyle - 1];
  236. pspUp = &lineState.aspLtoR[0];
  237. //
  238. // Move backwards to assign all the style data
  239. //
  240. while ( pspDown >= &lineState.aspRtoL[0] )
  241. {
  242. //
  243. // Let the last style data in "pspDown" = the 1st in "pspUp", 2 to
  244. // last in "pspDown" = 2nd in "pspUp".....
  245. // pspDown [n][n-1]...[2][1]
  246. // pspUp [1][2]...[n-1][n]
  247. //
  248. *pspDown = pStyle->l * STYLE_DENSITY;
  249. *pspUp = *pspDown;
  250. pspUp++;
  251. pspDown--;
  252. pStyle++;
  253. }
  254. }// Non-solid line
  255. bRet = TRUE;
  256. apfn = &gapfnStrip[NUM_STRIP_DRAW_STYLES *
  257. ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  258. //
  259. // Set up to enumerate the path:
  260. //
  261. if ( pco->iDComplexity != DC_COMPLEX )
  262. {
  263. PATHDATA pd;
  264. RECTL* prclClip = (RECTL*)NULL;
  265. BOOL bMore;
  266. ULONG lPtFix;
  267. POINTFIX ptfxStartFigure;
  268. POINTFIX ptfxLast;
  269. POINTFIX* pptfxFirst;
  270. POINTFIX* pptfxBuf;
  271. if ( pco->iDComplexity == DC_RECT )
  272. {
  273. fl |= FL_SIMPLE_CLIP;
  274. //
  275. // This is the only clip region of importance to Permedia2
  276. //
  277. arclClip[0] = pco->rclBounds;
  278. //
  279. // FL_FLIP_D:
  280. //
  281. arclClip[1].top = pco->rclBounds.left;
  282. arclClip[1].left = pco->rclBounds.top;
  283. arclClip[1].bottom = pco->rclBounds.right;
  284. arclClip[1].right = pco->rclBounds.bottom;
  285. //
  286. // FL_FLIP_V:
  287. //
  288. arclClip[2].top = -pco->rclBounds.bottom + 1;
  289. arclClip[2].left = pco->rclBounds.left;
  290. arclClip[2].bottom = -pco->rclBounds.top + 1;
  291. arclClip[2].right = pco->rclBounds.right;
  292. //
  293. // FL_FLIP_V | FL_FLIP_D:
  294. //
  295. arclClip[3].top = pco->rclBounds.left;
  296. arclClip[3].left = -pco->rclBounds.bottom + 1;
  297. arclClip[3].bottom = pco->rclBounds.right;
  298. arclClip[3].right = -pco->rclBounds.top + 1;
  299. prclClip = arclClip;
  300. }// if ( pco->iDComplexity == DC_RECT )
  301. pd.flags = 0;
  302. //
  303. // Get the logic op and set up the flag to indicate reads from the frame
  304. // buffer will occur.
  305. //
  306. logicOp = ulRop3ToLogicop(gaMix[mix & 0xff]);
  307. DBG_GDI((7, "logicop is %d", logicOp));
  308. if ( LogicopReadDest[logicOp] )
  309. {
  310. fl |= FL_READ;
  311. }
  312. //
  313. // Need to set up Permedia2 modes and colors appropriately for the lines
  314. //
  315. bResetHW = bInitializeStrips(ppdev, pbo->iSolidColor,
  316. logicOp, prclClip);
  317. PATHOBJ_vEnumStart(ppo);
  318. do
  319. {
  320. bMore = PATHOBJ_bEnum(ppo, &pd);
  321. lPtFix = pd.count;
  322. if ( lPtFix == 0 )
  323. {
  324. //
  325. // If the pathdata contains no data, finish
  326. //
  327. break;
  328. }
  329. if ( pd.flags & PD_BEGINSUBPATH )
  330. {
  331. ptfxStartFigure = *pd.pptfx;
  332. pptfxFirst = pd.pptfx;
  333. pptfxBuf = pd.pptfx + 1;
  334. lPtFix--;
  335. }
  336. else
  337. {
  338. pptfxFirst = &ptfxLast;
  339. pptfxBuf = pd.pptfx;
  340. }
  341. if ( pd.flags & PD_RESETSTYLE )
  342. {
  343. lineState.spNext = 0;
  344. }
  345. if ( lPtFix > 0 )
  346. {
  347. if ( !bLines(ppdev,
  348. pptfxFirst,
  349. pptfxBuf,
  350. (RUN*)NULL,
  351. lPtFix,
  352. &lineState,
  353. prclClip,
  354. apfn,
  355. fl) )
  356. {
  357. bRet = FALSE;
  358. goto ResetReturn;
  359. }
  360. }
  361. ptfxLast = pd.pptfx[pd.count - 1];
  362. if ( pd.flags & PD_CLOSEFIGURE )
  363. {
  364. if ( !bLines(ppdev,
  365. &ptfxLast,
  366. &ptfxStartFigure,
  367. (RUN*)NULL,
  368. 1,
  369. &lineState,
  370. prclClip,
  371. apfn,
  372. fl) )
  373. {
  374. bRet = FALSE;
  375. goto ResetReturn;
  376. }
  377. }
  378. } while ( bMore );
  379. if ( fl & FL_STYLED )
  380. {
  381. //
  382. // Save the style state
  383. //
  384. ULONG ulHigh;
  385. ULONG ulLow;
  386. //
  387. // Masked styles don't normalize the style state. It's a good thing
  388. // to do, so let's do it now
  389. //
  390. if ( (ULONG)lineState.spNext >= (ULONG)lineState.spTotal2 )
  391. {
  392. lineState.spNext = (ULONG)lineState.spNext
  393. % (ULONG)lineState.spTotal2;
  394. }
  395. ulHigh = lineState.spNext / lineState.xyDensity;
  396. ulLow = lineState.spNext % lineState.xyDensity;
  397. pLineAttrs->elStyleState.l = MAKELONG(ulLow, ulHigh);
  398. }
  399. }
  400. else
  401. {
  402. //
  403. // Local state for path enumeration
  404. //
  405. BOOL bMore;
  406. union
  407. {
  408. BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
  409. CLIPLINE cl;
  410. } cl;
  411. fl |= FL_COMPLEX_CLIP;
  412. //
  413. // Need to set up hardware modes and colors appropriately for the lines.
  414. // NOTE, with a complex clip,we can not yet use permedia2 for fast lines
  415. //
  416. bResetHW = bInitializeStrips(ppdev, pbo->iSolidColor,
  417. ulRop3ToLogicop(gaMix[mix&0xff]),
  418. NULL);
  419. //
  420. // We use the clip object when non-simple clipping is involved:
  421. //
  422. PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pLineAttrs);
  423. do
  424. {
  425. bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
  426. if ( cl.cl.c != 0 )
  427. {
  428. if ( fl & FL_STYLED )
  429. {
  430. lineState.spComplex = HIWORD(cl.cl.lStyleState)
  431. * lineState.xyDensity
  432. + LOWORD(cl.cl.lStyleState);
  433. }
  434. if ( !bLines(ppdev,
  435. &cl.cl.ptfxA,
  436. &cl.cl.ptfxB,
  437. &cl.cl.arun[0],
  438. cl.cl.c,
  439. &lineState,
  440. (RECTL*) NULL,
  441. apfn,
  442. fl) )
  443. {
  444. bRet = FALSE;
  445. goto ResetReturn;
  446. }
  447. }
  448. } while ( bMore );
  449. }
  450. ResetReturn:
  451. if ( bResetHW )
  452. {
  453. vResetStrips(ppdev);
  454. }
  455. DBG_GDI((6, "DrvStrokePath done it"));
  456. InputBufferFlush(ppdev);
  457. //@@BEGIN_DDKSPLIT
  458. #if MULTITHREADED
  459. ppdev->ulLockCount--;
  460. EngReleaseSemaphore(ppdev->hsemLock);
  461. #endif
  462. //@@END_DDKSPLIT
  463. return (bRet);
  464. puntIt:
  465. //@@BEGIN_DDKSPLIT
  466. #if GDI_TEST
  467. ULONG flags = vPuntBefore(NULL, pso);
  468. #endif
  469. //@@END_DDKSPLIT
  470. bRet = EngStrokePath(pso, ppo, pco, pxo, pbo, pptlBrush,
  471. pLineAttrs, mix);
  472. //@@BEGIN_DDKSPLIT
  473. #if GDI_TEST
  474. vPuntAfter(flags, NULL, pso);
  475. vLogPunt();
  476. #endif
  477. //@@END_DDKSPLIT
  478. DBG_GDI((6, "DrvStrokePath punt it"));
  479. return bRet;
  480. }// DrvStrokePath()