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.

442 lines
13 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Stroke.c
  3. *
  4. * DrvStrokePath for S3 driver
  5. *
  6. * Copyright (c) 1992-1994 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.h"
  9. VOID (*gapfnStrip[])(PDEV*, STRIP*, LINESTATE*) = {
  10. vrlSolidHorizontal,
  11. vrlSolidVertical,
  12. vrlSolidDiagonalHorizontal,
  13. vrlSolidDiagonalVertical,
  14. // Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
  15. vssSolidHorizontal,
  16. vssSolidVertical,
  17. vssSolidDiagonalHorizontal,
  18. vssSolidDiagonalVertical,
  19. // Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
  20. // solid lines, and the same number for non-solid lines:
  21. vStripStyledHorizontal,
  22. vStripStyledVertical,
  23. vStripStyledVertical, // Diagonal goes here
  24. vStripStyledVertical, // Diagonal goes here
  25. vStripStyledHorizontal,
  26. vStripStyledVertical,
  27. vStripStyledVertical, // Diagonal goes here
  28. vStripStyledVertical, // Diagonal goes here
  29. };
  30. // Style array for alternate style (alternates one pixel on, one pixel off):
  31. STYLEPOS gaspAlternateStyle[] = { 1 };
  32. /******************************Public*Routine******************************\
  33. * BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrush, pla, mix)
  34. *
  35. * Strokes the path.
  36. *
  37. \**************************************************************************/
  38. BOOL DrvStrokePath(
  39. SURFOBJ* pso,
  40. PATHOBJ* ppo,
  41. CLIPOBJ* pco,
  42. XFORMOBJ* pxo,
  43. BRUSHOBJ* pbo,
  44. POINTL* pptlBrush,
  45. LINEATTRS* pla,
  46. MIX mix)
  47. {
  48. STYLEPOS aspLtoR[STYLE_MAX_COUNT];
  49. STYLEPOS aspRtoL[STYLE_MAX_COUNT];
  50. LINESTATE ls;
  51. PFNSTRIP* apfn;
  52. FLONG fl;
  53. PDEV* ppdev;
  54. DSURF* pdsurf;
  55. OH* poh;
  56. ULONG ulHwMix;
  57. RECTL arclClip[4]; // For rectangular clipping
  58. RECTL rclBounds;
  59. RECTFX rcfxBounds;
  60. // Pass the surface off to GDI if it's a device bitmap that we've
  61. // converted to a DIB:
  62. pdsurf = (DSURF*) pso->dhsurf;
  63. if (pdsurf->dt == DT_DIB)
  64. {
  65. return(EngStrokePath(pdsurf->pso, ppo, pco, pxo, pbo, pptlBrush,
  66. pla, mix));
  67. }
  68. // We'll be drawing to the screen or an off-screen DFB; copy the surface's
  69. // offset now so that we won't need to refer to the DSURF again:
  70. poh = pdsurf->poh;
  71. ppdev = (PDEV*) pso->dhpdev;
  72. ppdev->xOffset = poh->x;
  73. ppdev->yOffset = poh->y;
  74. ulHwMix = gajHwMixFromMix[mix & 0xf];
  75. // x86 has special case ASM code for accelerating solid lines:
  76. #if defined(i386)
  77. if ((pla->pstyle == NULL) && !(pla->fl & LA_ALTERNATE))
  78. {
  79. // We can accelerate solid lines:
  80. if (pco->iDComplexity == DC_TRIVIAL)
  81. {
  82. ppdev->pfnFastLine(ppdev, ppo, NULL, &gapfnStrip[0], 0,
  83. pbo->iSolidColor, ulHwMix);
  84. return(TRUE);
  85. }
  86. else if (pco->iDComplexity == DC_RECT)
  87. {
  88. // We have to be sure that we don't overflow the hardware registers
  89. // for current position, line length, or DDA terms. We check
  90. // here to make sure that the current position and line length
  91. // values won't overflow (for integer lines, this check is
  92. // sufficient to ensure that the DDA terms won't overflow; for GIQ
  93. // lines, we specifically check on every line in pfnFastLine that we
  94. // don't overflow).
  95. PATHOBJ_vGetBounds(ppo, &rcfxBounds);
  96. if (rcfxBounds.xLeft + (ppdev->xOffset * F)
  97. >= (MIN_INTEGER_BOUND * F) &&
  98. rcfxBounds.xRight + (ppdev->xOffset * F)
  99. <= (MAX_INTEGER_BOUND * F) &&
  100. rcfxBounds.yTop + (ppdev->yOffset * F)
  101. >= (MIN_INTEGER_BOUND * F) &&
  102. rcfxBounds.yBottom + (ppdev->yOffset * F)
  103. <= (MAX_INTEGER_BOUND * F))
  104. {
  105. // Since we're going to be using the scissors registers to
  106. // do hardware clipping, we'll also have to make sure we don't
  107. // exceed its bounds. ATI chips have a maximum limit of 1023,
  108. // which we could exceed if we're running at 1280x1024, or for
  109. // off-screen device bitmaps.
  110. if ((pco->rclBounds.right + ppdev->xOffset < 1024) &&
  111. (pco->rclBounds.bottom + ppdev->yOffset < 1024))
  112. {
  113. arclClip[0] = pco->rclBounds;
  114. // FL_FLIP_D:
  115. arclClip[1].top = pco->rclBounds.left;
  116. arclClip[1].left = pco->rclBounds.top;
  117. arclClip[1].bottom = pco->rclBounds.right;
  118. arclClip[1].right = pco->rclBounds.bottom;
  119. // FL_FLIP_V:
  120. arclClip[2].top = -pco->rclBounds.bottom + 1;
  121. arclClip[2].left = pco->rclBounds.left;
  122. arclClip[2].bottom = -pco->rclBounds.top + 1;
  123. arclClip[2].right = pco->rclBounds.right;
  124. // FL_FLIP_V | FL_FLIP_D:
  125. arclClip[3].top = pco->rclBounds.left;
  126. arclClip[3].left = -pco->rclBounds.bottom + 1;
  127. arclClip[3].bottom = pco->rclBounds.right;
  128. arclClip[3].right = -pco->rclBounds.top + 1;
  129. rclBounds.left = pco->rclBounds.left;
  130. rclBounds.top = pco->rclBounds.top;
  131. rclBounds.right = pco->rclBounds.right;
  132. rclBounds.bottom = pco->rclBounds.bottom;
  133. vSetClipping(ppdev, &rclBounds);
  134. ppdev->pfnFastLine(ppdev, ppo, &arclClip[0], &gapfnStrip[0],
  135. FL_SIMPLE_CLIP, pbo->iSolidColor, ulHwMix);
  136. vResetClipping(ppdev);
  137. return(TRUE);
  138. }
  139. }
  140. }
  141. }
  142. #endif // i386
  143. // Get the device ready:
  144. if (DEPTH32(ppdev))
  145. {
  146. IO_FIFO_WAIT(ppdev, 4);
  147. MM_FRGD_COLOR32(ppdev, ppdev->pjMmBase, pbo->iSolidColor);
  148. }
  149. else
  150. {
  151. IO_FIFO_WAIT(ppdev, 3);
  152. IO_FRGD_COLOR(ppdev, pbo->iSolidColor);
  153. }
  154. IO_FRGD_MIX(ppdev, FOREGROUND_COLOR | ulHwMix);
  155. IO_PIX_CNTL(ppdev, ALL_ONES);
  156. fl = 0;
  157. // Look after styling initialization:
  158. if (pla->fl & LA_ALTERNATE)
  159. {
  160. ls.cStyle = 1;
  161. ls.spTotal = 1;
  162. ls.spTotal2 = 2;
  163. ls.spRemaining = 1;
  164. ls.aspRtoL = &gaspAlternateStyle[0];
  165. ls.aspLtoR = &gaspAlternateStyle[0];
  166. ls.spNext = HIWORD(pla->elStyleState.l);
  167. ls.xyDensity = 1;
  168. fl |= FL_ARBITRARYSTYLED;
  169. ls.ulStartMask = 0L;
  170. }
  171. else if (pla->pstyle != (FLOAT_LONG*) NULL)
  172. {
  173. PFLOAT_LONG pstyle;
  174. STYLEPOS* pspDown;
  175. STYLEPOS* pspUp;
  176. pstyle = &pla->pstyle[pla->cstyle];
  177. ls.xyDensity = STYLE_DENSITY;
  178. ls.spTotal = 0;
  179. while (pstyle-- > pla->pstyle)
  180. {
  181. ls.spTotal += pstyle->l;
  182. }
  183. ls.spTotal *= STYLE_DENSITY;
  184. ls.spTotal2 = 2 * ls.spTotal;
  185. // Compute starting style position (this is guaranteed not to overflow):
  186. ls.spNext = HIWORD(pla->elStyleState.l) * STYLE_DENSITY +
  187. LOWORD(pla->elStyleState.l);
  188. fl |= FL_ARBITRARYSTYLED;
  189. ls.cStyle = pla->cstyle;
  190. ls.aspRtoL = aspRtoL;
  191. ls.aspLtoR = aspLtoR;
  192. if (pla->fl & LA_STARTGAP)
  193. ls.ulStartMask = 0xffffffffL;
  194. else
  195. ls.ulStartMask = 0L;
  196. pstyle = pla->pstyle;
  197. pspDown = &ls.aspRtoL[ls.cStyle - 1];
  198. pspUp = &ls.aspLtoR[0];
  199. while (pspDown >= &ls.aspRtoL[0])
  200. {
  201. *pspDown = pstyle->l * STYLE_DENSITY;
  202. *pspUp = *pspDown;
  203. pspUp++;
  204. pspDown--;
  205. pstyle++;
  206. }
  207. }
  208. apfn = &gapfnStrip[NUM_STRIP_DRAW_STYLES *
  209. ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  210. // Set up to enumerate the path:
  211. #if defined(i386)
  212. // x86 ASM bLines supports DC_RECT clipping:
  213. if (pco->iDComplexity != DC_COMPLEX)
  214. #else
  215. // Non-x86 ASM bLines don't support DC_RECT clipping:
  216. if (pco->iDComplexity == DC_TRIVIAL)
  217. #endif
  218. {
  219. PATHDATA pd;
  220. RECTL* prclClip = (RECTL*) NULL;
  221. BOOL bMore;
  222. ULONG cptfx;
  223. POINTFIX ptfxStartFigure;
  224. POINTFIX ptfxLast;
  225. POINTFIX* pptfxFirst;
  226. POINTFIX* pptfxBuf;
  227. #if defined(i386)
  228. if (pco->iDComplexity == DC_RECT)
  229. {
  230. fl |= FL_SIMPLE_CLIP;
  231. arclClip[0] = pco->rclBounds;
  232. // FL_FLIP_D:
  233. arclClip[1].top = pco->rclBounds.left;
  234. arclClip[1].left = pco->rclBounds.top;
  235. arclClip[1].bottom = pco->rclBounds.right;
  236. arclClip[1].right = pco->rclBounds.bottom;
  237. // FL_FLIP_V:
  238. arclClip[2].top = -pco->rclBounds.bottom + 1;
  239. arclClip[2].left = pco->rclBounds.left;
  240. arclClip[2].bottom = -pco->rclBounds.top + 1;
  241. arclClip[2].right = pco->rclBounds.right;
  242. // FL_FLIP_V | FL_FLIP_D:
  243. arclClip[3].top = pco->rclBounds.left;
  244. arclClip[3].left = -pco->rclBounds.bottom + 1;
  245. arclClip[3].bottom = pco->rclBounds.right;
  246. arclClip[3].right = -pco->rclBounds.top + 1;
  247. prclClip = arclClip;
  248. }
  249. #endif // i386
  250. pd.flags = 0;
  251. do {
  252. bMore = PATHOBJ_bEnum(ppo, &pd);
  253. cptfx = pd.count;
  254. if (cptfx == 0)
  255. {
  256. break;
  257. }
  258. if (pd.flags & PD_BEGINSUBPATH)
  259. {
  260. ptfxStartFigure = *pd.pptfx;
  261. pptfxFirst = pd.pptfx;
  262. pptfxBuf = pd.pptfx + 1;
  263. cptfx--;
  264. }
  265. else
  266. {
  267. pptfxFirst = &ptfxLast;
  268. pptfxBuf = pd.pptfx;
  269. }
  270. if (pd.flags & PD_RESETSTYLE)
  271. ls.spNext = 0;
  272. if (cptfx > 0)
  273. {
  274. if (!bLines(ppdev,
  275. pptfxFirst,
  276. pptfxBuf,
  277. (RUN*) NULL,
  278. cptfx,
  279. &ls,
  280. prclClip,
  281. apfn,
  282. fl))
  283. return(FALSE);
  284. }
  285. ptfxLast = pd.pptfx[pd.count - 1];
  286. if (pd.flags & PD_CLOSEFIGURE)
  287. {
  288. if (!bLines(ppdev,
  289. &ptfxLast,
  290. &ptfxStartFigure,
  291. (RUN*) NULL,
  292. 1,
  293. &ls,
  294. prclClip,
  295. apfn,
  296. fl))
  297. return(FALSE);
  298. }
  299. } while (bMore);
  300. if (fl & FL_STYLED)
  301. {
  302. // Save the style state:
  303. ULONG ulHigh;
  304. ULONG ulLow;
  305. // Masked styles don't normalize the style state. It's a good
  306. // thing to do, so let's do it now:
  307. if ((ULONG) ls.spNext >= (ULONG) ls.spTotal2)
  308. ls.spNext = (ULONG) ls.spNext % (ULONG) ls.spTotal2;
  309. ulHigh = ls.spNext / ls.xyDensity;
  310. ulLow = ls.spNext % ls.xyDensity;
  311. pla->elStyleState.l = MAKELONG(ulLow, ulHigh);
  312. }
  313. }
  314. else
  315. {
  316. // Local state for path enumeration:
  317. BOOL bMore;
  318. union {
  319. BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
  320. CLIPLINE cl;
  321. } cl;
  322. fl |= FL_COMPLEX_CLIP;
  323. // We use the clip object when non-simple clipping is involved:
  324. PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
  325. do {
  326. bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
  327. if (cl.cl.c != 0)
  328. {
  329. if (fl & FL_STYLED)
  330. {
  331. ls.spComplex = HIWORD(cl.cl.lStyleState) * ls.xyDensity
  332. + LOWORD(cl.cl.lStyleState);
  333. }
  334. if (!bLines(ppdev,
  335. &cl.cl.ptfxA,
  336. &cl.cl.ptfxB,
  337. &cl.cl.arun[0],
  338. cl.cl.c,
  339. &ls,
  340. (RECTL*) NULL,
  341. apfn,
  342. fl))
  343. return(FALSE);
  344. }
  345. } while (bMore);
  346. }
  347. return(TRUE);
  348. }