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.

507 lines
14 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Stroke.c
  3. *
  4. * DrvStrokePath for the display driver
  5. *
  6. * Copyright (c) 1992-1995 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.h"
  9. // Note: the following table has 17 entries
  10. BYTE aMixToRop3[] = {
  11. 0xFF, /* 0 1 */
  12. 0x00, /* 1 0 */
  13. 0x05, /* 2 DPon */
  14. 0x0A, /* 3 DPna */
  15. 0x0F, /* 4 PN */
  16. 0x50, /* 5 PDna */
  17. 0x55, /* 6 Dn */
  18. 0x5a, /* 7 DPx */
  19. 0x5f, /* 8 DPan */
  20. 0xA0, /* 9 DPa */
  21. 0xA5, /* 10 DPxn */
  22. 0xAA, /* 11 D */
  23. 0xAF, /* 12 DPno */
  24. 0xF0, /* 13 P */
  25. 0xF5, /* 14 PDno */
  26. 0xFA, /* 15 DPo */
  27. 0xFF /* 16 1 */
  28. };
  29. VOID (*gapfnStripI[])(PDEV*, STRIP*, LINESTATE*) = {
  30. vrlSolidHorizontal,
  31. vrlSolidVertical,
  32. vrlSolidDiagonalHorizontal,
  33. vrlSolidDiagonalVertical,
  34. // Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
  35. vssSolidHorizontal,
  36. vssSolidVertical,
  37. vssSolidDiagonalHorizontal,
  38. vssSolidDiagonalVertical,
  39. // Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
  40. // solid lines, and the same number for non-solid lines:
  41. vStripStyledHorizontal,
  42. vStripStyledVertical,
  43. vStripStyledVertical, // Diagonal goes here
  44. vStripStyledVertical, // Diagonal goes here
  45. vStripStyledHorizontal,
  46. vStripStyledVertical,
  47. vStripStyledVertical, // Diagonal goes here
  48. vStripStyledVertical, // Diagonal goes here
  49. };
  50. VOID (*gapfnStripP[])(PDEV*, STRIP*, LINESTATE*) = {
  51. vrlSolidHorizontalP,
  52. vrlSolidVerticalP,
  53. vrlSolidDiagonalHorizontalP,
  54. vrlSolidDiagonalVerticalP,
  55. // Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
  56. vrlSolidHorizontalP,
  57. vrlSolidVerticalP,
  58. vrlSolidDiagonalHorizontalP,
  59. vrlSolidDiagonalVerticalP,
  60. // Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
  61. // solid lines, and the same number for non-solid lines:
  62. vStripStyledHorizontalP,
  63. vStripStyledVerticalP,
  64. vStripStyledVerticalP, // Diagonal goes here
  65. vStripStyledVerticalP, // Diagonal goes here
  66. vStripStyledHorizontalP,
  67. vStripStyledVerticalP,
  68. vStripStyledVerticalP, // Diagonal goes here
  69. vStripStyledVerticalP, // Diagonal goes here
  70. };
  71. // Style array for alternate style (alternates one pixel on, one pixel off):
  72. STYLEPOS gaspAlternateStyle[] = { 1 };
  73. /******************************Public*Routine******************************\
  74. * BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrush, pla, mix)
  75. *
  76. * Strokes the path.
  77. *
  78. \**************************************************************************/
  79. BOOL DrvStrokePath(
  80. SURFOBJ* pso,
  81. PATHOBJ* ppo,
  82. CLIPOBJ* pco,
  83. XFORMOBJ* pxo,
  84. BRUSHOBJ* pbo,
  85. POINTL* pptlBrush,
  86. LINEATTRS* pla,
  87. MIX mix)
  88. {
  89. PDEV *ppdev = (PDEV*) pso->dhpdev;
  90. DSURF *pdsurf;
  91. OH* poh;
  92. BYTE* pjBase;
  93. LONG cBpp;
  94. STYLEPOS aspLtoR[STYLE_MAX_COUNT];
  95. STYLEPOS aspRtoL[STYLE_MAX_COUNT];
  96. LINESTATE ls;
  97. PFNSTRIP* apfn;
  98. FLONG fl;
  99. RECTL arclClip[4]; // For rectangular clipping
  100. if ((mix & 0xf) != 0x0d) DISPDBG((3,"Line with mix(%x)", mix));
  101. // Pass the surface off to GDI if it's a device bitmap that we've
  102. // converted to a DIB:
  103. pdsurf = (DSURF*) pso->dhsurf;
  104. if (pdsurf->dt == DT_DIB)
  105. {
  106. return(EngStrokePath(pdsurf->pso, ppo, pco, pxo, pbo, pptlBrush,
  107. pla, mix));
  108. }
  109. // We'll be drawing to the screen or an off-screen DFB; copy the surface's
  110. // offset now so that we won't need to refer to the DSURF again:
  111. poh = pdsurf->poh;
  112. cBpp = ppdev->cBpp;
  113. ppdev->xOffset = poh->x;
  114. ppdev->yOffset = poh->y;
  115. ppdev->xyOffset = (poh->x * cBpp) +
  116. (poh->y * ppdev->lDelta);
  117. if (DRIVER_PUNT_ALL ||
  118. (pla->fl & LA_ALTERNATE) ||
  119. (pla->pstyle != (FLOAT_LONG*) NULL) ||
  120. ((cBpp == 3) && (ppdev->ulChipID != W32P) && (ppdev->ulChipID != ET6000)))
  121. {
  122. if (ppdev->bAutoBanking)
  123. {
  124. PVOID pvScan0;
  125. BOOL bRet;
  126. BYTE* pjBase = ppdev->pjBase;
  127. pvScan0 = ppdev->psoFrameBuffer->pvScan0;
  128. (BYTE*)ppdev->psoFrameBuffer->pvScan0 += ppdev->xyOffset;
  129. WAIT_FOR_IDLE_ACL(ppdev, pjBase);
  130. bRet = EngStrokePath(ppdev->psoFrameBuffer,ppo,pco,pxo,pbo,
  131. pptlBrush,pla,mix);
  132. ppdev->psoFrameBuffer->pvScan0 = pvScan0;
  133. return(bRet);
  134. }
  135. //
  136. // Bank and punt call to the engine (line was styled)
  137. //
  138. {
  139. BANK bnk;
  140. BOOL b;
  141. RECTL rclDraw;
  142. RECTL *prclDst = &pco->rclBounds;
  143. FLOAT_LONG elSavedStyleState = pla->elStyleState;
  144. {
  145. DISPDBG((110,"Simulating StrokePath\n"));
  146. // The bank manager requires that the 'draw' rectangle be
  147. // well-ordered:
  148. rclDraw = *prclDst;
  149. if (rclDraw.left > rclDraw.right)
  150. {
  151. rclDraw.left = prclDst->right;
  152. rclDraw.right = prclDst->left;
  153. }
  154. if (rclDraw.top > rclDraw.bottom)
  155. {
  156. rclDraw.top = prclDst->bottom;
  157. rclDraw.bottom = prclDst->top;
  158. }
  159. vBankStart(ppdev, &rclDraw, pco, &bnk);
  160. b = TRUE;
  161. do {
  162. pla->elStyleState = elSavedStyleState;
  163. b &= EngStrokePath(bnk.pso,
  164. ppo,
  165. bnk.pco,
  166. pxo,
  167. pbo,
  168. pptlBrush,
  169. pla,
  170. mix);
  171. } while (bBankEnum(&bnk));
  172. return(b);
  173. }
  174. }
  175. }
  176. // Get the device ready:
  177. pjBase = ppdev->pjBase;
  178. WAIT_FOR_EMPTY_ACL_QUEUE(ppdev, pjBase);
  179. CP_FG_ROP(ppdev, pjBase, (aMixToRop3[mix & 0xf]));
  180. CP_PAT_WRAP(ppdev, pjBase, (SOLID_COLOR_PATTERN_WRAP));
  181. CP_PAT_Y_OFFSET(ppdev, pjBase, (SOLID_COLOR_PATTERN_OFFSET - 1));
  182. CP_PAT_ADDR(ppdev, pjBase, (ppdev->ulSolidColorOffset));
  183. {
  184. ULONG ulSolidColor = pbo->iSolidColor;
  185. if (cBpp == 1)
  186. {
  187. ulSolidColor &= 0x000000FF; // We may get some extraneous data in the
  188. ulSolidColor |= ulSolidColor << 8;
  189. }
  190. if (cBpp <= 2)
  191. {
  192. ulSolidColor &= 0x0000FFFF;
  193. ulSolidColor |= ulSolidColor << 16;
  194. }
  195. WAIT_FOR_IDLE_ACL(ppdev, pjBase);
  196. // Set the color in offscreen memory
  197. if (ppdev->bAutoBanking)
  198. {
  199. *(PULONG)(ppdev->pjScreen + ppdev->ulSolidColorOffset) = ulSolidColor;
  200. }
  201. else
  202. {
  203. CP_MMU_BP0(ppdev, pjBase, ppdev->ulSolidColorOffset);
  204. CP_WRITE_MMU_DWORD(ppdev, 0, 0, ulSolidColor);
  205. }
  206. }
  207. fl = 0;
  208. // Look after styling initialization:
  209. if (pla->fl & LA_ALTERNATE)
  210. {
  211. ls.cStyle = 1;
  212. ls.spTotal = 1;
  213. ls.spTotal2 = 2;
  214. ls.spRemaining = 1;
  215. ls.aspRtoL = &gaspAlternateStyle[0];
  216. ls.aspLtoR = &gaspAlternateStyle[0];
  217. ls.spNext = HIWORD(pla->elStyleState.l);
  218. ls.xyDensity = 1;
  219. fl |= FL_STYLED;
  220. ls.ulStartMask = 0L;
  221. }
  222. else if (pla->pstyle != (FLOAT_LONG*) NULL)
  223. {
  224. PFLOAT_LONG pstyle;
  225. STYLEPOS* pspDown;
  226. STYLEPOS* pspUp;
  227. pstyle = &pla->pstyle[pla->cstyle];
  228. ls.xyDensity = STYLE_DENSITY;
  229. ls.spTotal = 0;
  230. while (pstyle-- > pla->pstyle)
  231. {
  232. ls.spTotal += pstyle->l;
  233. }
  234. ls.spTotal *= STYLE_DENSITY;
  235. ls.spTotal2 = 2 * ls.spTotal;
  236. // Compute starting style position (this is guaranteed not to overflow):
  237. ls.spNext = HIWORD(pla->elStyleState.l) * STYLE_DENSITY +
  238. LOWORD(pla->elStyleState.l);
  239. fl |= FL_STYLED;
  240. ls.cStyle = pla->cstyle;
  241. ls.aspRtoL = aspRtoL;
  242. ls.aspLtoR = aspLtoR;
  243. if (pla->fl & LA_STARTGAP)
  244. ls.ulStartMask = 0xffffffffL;
  245. else
  246. ls.ulStartMask = 0L;
  247. pstyle = pla->pstyle;
  248. pspDown = &ls.aspRtoL[ls.cStyle - 1];
  249. pspUp = &ls.aspLtoR[0];
  250. while (pspDown >= &ls.aspRtoL[0])
  251. {
  252. *pspDown = pstyle->l * STYLE_DENSITY;
  253. *pspUp = *pspDown;
  254. pspUp++;
  255. pspDown--;
  256. pstyle++;
  257. }
  258. }
  259. if ((ppdev->ulChipID == W32P) || (ppdev->ulChipID == ET6000))
  260. {
  261. apfn = &gapfnStripP[NUM_STRIP_DRAW_STYLES *
  262. ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  263. CP_PEL_DEPTH(ppdev, pjBase, ((cBpp - 1) << 4));
  264. }
  265. else
  266. {
  267. apfn = &gapfnStripI[NUM_STRIP_DRAW_STYLES *
  268. ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  269. }
  270. // Set up to enumerate the path:
  271. if (pco->iDComplexity != DC_COMPLEX)
  272. {
  273. PATHDATA pd;
  274. RECTL* prclClip = (RECTL*) NULL;
  275. BOOL bMore;
  276. ULONG cptfx;
  277. POINTFIX ptfxStartFigure;
  278. POINTFIX ptfxLast;
  279. POINTFIX* pptfxFirst;
  280. POINTFIX* pptfxBuf;
  281. if (pco->iDComplexity == DC_RECT)
  282. {
  283. fl |= FL_SIMPLE_CLIP;
  284. arclClip[0] = pco->rclBounds;
  285. // FL_FLIP_D:
  286. arclClip[1].top = pco->rclBounds.left;
  287. arclClip[1].left = pco->rclBounds.top;
  288. arclClip[1].bottom = pco->rclBounds.right;
  289. arclClip[1].right = pco->rclBounds.bottom;
  290. // FL_FLIP_V:
  291. arclClip[2].top = -pco->rclBounds.bottom + 1;
  292. arclClip[2].left = pco->rclBounds.left;
  293. arclClip[2].bottom = -pco->rclBounds.top + 1;
  294. arclClip[2].right = pco->rclBounds.right;
  295. // FL_FLIP_V | FL_FLIP_D:
  296. arclClip[3].top = pco->rclBounds.left;
  297. arclClip[3].left = -pco->rclBounds.bottom + 1;
  298. arclClip[3].bottom = pco->rclBounds.right;
  299. arclClip[3].right = -pco->rclBounds.top + 1;
  300. prclClip = arclClip;
  301. }
  302. pd.flags = 0;
  303. do {
  304. bMore = PATHOBJ_bEnum(ppo, &pd);
  305. cptfx = pd.count;
  306. if (cptfx == 0)
  307. {
  308. break;
  309. }
  310. if (pd.flags & PD_BEGINSUBPATH)
  311. {
  312. ptfxStartFigure = *pd.pptfx;
  313. pptfxFirst = pd.pptfx;
  314. pptfxBuf = pd.pptfx + 1;
  315. cptfx--;
  316. }
  317. else
  318. {
  319. pptfxFirst = &ptfxLast;
  320. pptfxBuf = pd.pptfx;
  321. }
  322. if (pd.flags & PD_RESETSTYLE)
  323. ls.spNext = 0;
  324. if (cptfx > 0)
  325. {
  326. if (!bLines(ppdev,
  327. pptfxFirst,
  328. pptfxBuf,
  329. (RUN*) NULL,
  330. cptfx,
  331. &ls,
  332. prclClip,
  333. apfn,
  334. fl))
  335. goto ReturnFalse;
  336. }
  337. ptfxLast = pd.pptfx[pd.count - 1];
  338. if (pd.flags & PD_CLOSEFIGURE)
  339. {
  340. if (!bLines(ppdev,
  341. &ptfxLast,
  342. &ptfxStartFigure,
  343. (RUN*) NULL,
  344. 1,
  345. &ls,
  346. prclClip,
  347. apfn,
  348. fl))
  349. goto ReturnFalse;
  350. }
  351. } while (bMore);
  352. if (fl & FL_STYLED)
  353. {
  354. // Save the style state:
  355. ULONG ulHigh;
  356. ULONG ulLow;
  357. // Masked styles don't normalize the style state. It's a good
  358. // thing to do, so let's do it now:
  359. if ((ULONG) ls.spNext >= (ULONG) ls.spTotal2)
  360. ls.spNext = (ULONG) ls.spNext % (ULONG) ls.spTotal2;
  361. ulHigh = ls.spNext / ls.xyDensity;
  362. ulLow = ls.spNext % ls.xyDensity;
  363. pla->elStyleState.l = MAKELONG(ulLow, ulHigh);
  364. }
  365. }
  366. else
  367. {
  368. // Local state for path enumeration:
  369. BOOL bMore;
  370. union {
  371. BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
  372. CLIPLINE cl;
  373. } cl;
  374. fl |= FL_COMPLEX_CLIP;
  375. // We use the clip object when non-simple clipping is involved:
  376. PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
  377. do {
  378. bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
  379. if (cl.cl.c != 0)
  380. {
  381. if (fl & FL_STYLED)
  382. {
  383. ls.spComplex = HIWORD(cl.cl.lStyleState) * ls.xyDensity
  384. + LOWORD(cl.cl.lStyleState);
  385. }
  386. if (!bLines(ppdev,
  387. &cl.cl.ptfxA,
  388. &cl.cl.ptfxB,
  389. &cl.cl.arun[0],
  390. cl.cl.c,
  391. &ls,
  392. (RECTL*) NULL,
  393. apfn,
  394. fl))
  395. goto ReturnFalse;
  396. }
  397. } while (bMore);
  398. }
  399. CP_PEL_DEPTH(ppdev, pjBase, 0);
  400. return(TRUE);
  401. ReturnFalse:
  402. CP_PEL_DEPTH(ppdev, pjBase, 0);
  403. return(FALSE);
  404. }