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.

395 lines
12 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Stroke.c
  3. *
  4. * DrvStrokePath for VGA driver
  5. *
  6. * Copyright (c) 1992 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "driver.h"
  9. #include "lines.h"
  10. // Style array for alternate style (alternates one pixel on, one pixel off):
  11. STYLEPOS gaspAlternateStyle[] = { 1 };
  12. // Array to compute ROP masks:
  13. LONG gaiLineMix[] = {
  14. AND_ZERO | XOR_ONE,
  15. AND_ZERO | XOR_ZERO,
  16. AND_NOTPEN | XOR_NOTPEN,
  17. AND_NOTPEN | XOR_ZERO,
  18. AND_ZERO | XOR_NOTPEN,
  19. AND_PEN | XOR_PEN,
  20. AND_ONE | XOR_ONE,
  21. AND_ONE | XOR_PEN,
  22. AND_PEN | XOR_ONE,
  23. AND_PEN | XOR_ZERO,
  24. AND_ONE | XOR_NOTPEN,
  25. AND_ONE | XOR_ZERO,
  26. AND_PEN | XOR_NOTPEN,
  27. AND_ZERO | XOR_PEN,
  28. AND_NOTPEN | XOR_ONE,
  29. AND_NOTPEN | XOR_PEN
  30. };
  31. // We have 4 basic strip drawers, one for every semi-octant. The near-
  32. // horizontal semi-octant is number 0, and the rest are numbered
  33. // consecutively.
  34. // Prototypes to go to the screen and handle any ROPs:
  35. VOID vStripSolid0(STRIP*, LINESTATE*, LONG*);
  36. VOID vStripSolid1(STRIP*, LINESTATE*, LONG*);
  37. VOID vStripSolid2(STRIP*, LINESTATE*, LONG*);
  38. VOID vStripSolid3(STRIP*, LINESTATE*, LONG*);
  39. VOID vStripStyled0(STRIP*, LINESTATE*, LONG*);
  40. VOID vStripStyled123(STRIP*, LINESTATE*, LONG*);
  41. // Prototypes to go to the screen and handle only set-style ROPs:
  42. VOID vStripSolidSet0(STRIP*, LINESTATE*, LONG*);
  43. VOID vStripSolidSet1(STRIP*, LINESTATE*, LONG*);
  44. VOID vStripSolidSet2(STRIP*, LINESTATE*, LONG*);
  45. VOID vStripSolidSet3(STRIP*, LINESTATE*, LONG*);
  46. VOID vStripStyledSet0(STRIP*, LINESTATE*, LONG*);
  47. VOID vStripStyledSet123(STRIP*, LINESTATE*, LONG*);
  48. PFNSTRIP gapfnStrip[] = {
  49. vStripSolid0,
  50. vStripSolid3,
  51. vStripSolid1,
  52. vStripSolid2,
  53. vStripStyled0,
  54. vStripStyled123,
  55. vStripStyled123,
  56. vStripStyled123,
  57. vStripSolidSet0,
  58. vStripSolidSet3,
  59. vStripSolidSet1,
  60. vStripSolidSet2,
  61. vStripStyledSet0,
  62. vStripStyledSet123,
  63. vStripStyledSet123,
  64. vStripStyledSet123,
  65. };
  66. /******************************Public*Routine******************************\
  67. * BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrushOrg, pla, mix)
  68. *
  69. * Strokes the path.
  70. \**************************************************************************/
  71. BOOL DrvStrokePath(
  72. SURFOBJ* pso,
  73. PATHOBJ* ppo,
  74. CLIPOBJ* pco,
  75. XFORMOBJ* pxo,
  76. BRUSHOBJ* pbo,
  77. POINTL* pptlBrushOrg,
  78. LINEATTRS* pla,
  79. MIX mix)
  80. {
  81. STYLEPOS aspLtoR[STYLE_MAX_COUNT];
  82. STYLEPOS aspRtoL[STYLE_MAX_COUNT];
  83. LINESTATE ls;
  84. PFNSTRIP* apfn;
  85. FLONG fl;
  86. PPDEV ppdev = (PPDEV) pso->dhsurf;
  87. UNREFERENCED_PARAMETER(pxo);
  88. UNREFERENCED_PARAMETER(pptlBrushOrg);
  89. // Fast lines can't handle trivial clipping, ROPs other than R2_COPYPEN, or
  90. // styles:
  91. mix &= 0xf;
  92. if ((mix == 0x0d) &&
  93. (pco->iDComplexity == DC_TRIVIAL) &&
  94. (pla->pstyle == NULL) && !(pla->fl & LA_ALTERNATE))
  95. {
  96. vFastLine(ppdev, ppo, ppdev->lNextScan,
  97. (pbo->iSolidColor << 8) | (pbo->iSolidColor & 0xff));
  98. return(TRUE);
  99. }
  100. fl = 0;
  101. // Look after styling initialization:
  102. if (pla->fl & LA_ALTERNATE)
  103. {
  104. ASSERTVGA(pla->pstyle == (FLOAT_LONG*) NULL && pla->cstyle == 0,
  105. "Non-empty style array for PS_ALTERNATE");
  106. ls.bStartIsGap = 0; // First pel is a dash
  107. ls.cStyle = 1; // Size of style array
  108. ls.spTotal = 1; // Sum of style array
  109. ls.spTotal2 = 2; // Twice the sum
  110. ls.aspRtoL = &gaspAlternateStyle[0]; // Right-to-left array
  111. ls.aspLtoR = &gaspAlternateStyle[0]; // Left-to-right array
  112. ls.spNext = HIWORD(pla->elStyleState.l) & 1;
  113. // Light first pixel if
  114. // a multiple of 2
  115. ls.xyDensity = 1; // Each 'dot' is one
  116. // pixel long
  117. fl |= FL_ARBITRARYSTYLED;
  118. }
  119. else if (pla->pstyle != (FLOAT_LONG*) NULL)
  120. {
  121. FLOAT_LONG* pstyle;
  122. STYLEPOS* pspDown;
  123. STYLEPOS* pspUp;
  124. ASSERTVGA(pla->cstyle <= STYLE_MAX_COUNT, "Style array too large");
  125. // Compute length of style array:
  126. pstyle = &pla->pstyle[pla->cstyle];
  127. ls.xyDensity = STYLE_DENSITY;
  128. ls.spTotal = 0;
  129. while (pstyle-- > pla->pstyle)
  130. {
  131. ls.spTotal += pstyle->l;
  132. }
  133. // The style array is given in 'style' units. Since we're going to
  134. // assign each unit to be STYLE_DENSITY (3) pixels long, multiply:
  135. ls.spTotal *= STYLE_DENSITY;
  136. ls.spTotal2 = 2 * ls.spTotal;
  137. // Compute starting style position (this is guaranteed not to overflow).
  138. // Note that since the array repeats infinitely, this number might
  139. // actually be more than ls.spTotal2, but we take care of that later
  140. // in our code:
  141. ls.spNext = HIWORD(pla->elStyleState.l) * STYLE_DENSITY +
  142. LOWORD(pla->elStyleState.l);
  143. fl |= FL_ARBITRARYSTYLED;
  144. ls.cStyle = pla->cstyle;
  145. ls.aspRtoL = aspRtoL; // Style array in right-to-left order
  146. ls.aspLtoR = aspLtoR; // Style array in left-to-right order
  147. // ulStartMask determines if the first entry in the style array is for
  148. // a dash or a gap:
  149. ls.bStartIsGap = (pla->fl & LA_STARTGAP) ? -1L : 0L;
  150. pstyle = pla->pstyle;
  151. pspDown = &ls.aspRtoL[ls.cStyle - 1];
  152. pspUp = &ls.aspLtoR[0];
  153. // We always draw strips left-to-right, but styles have to be laid
  154. // down in the direction of the original line. This means that in
  155. // the strip code we have to traverse the style array in the
  156. // opposite direction;
  157. while (pspDown >= &ls.aspRtoL[0])
  158. {
  159. ASSERTVGA(pstyle->l > 0 && pstyle->l <= STYLE_MAX_VALUE,
  160. "Illegal style array value");
  161. *pspDown = pstyle->l * STYLE_DENSITY;
  162. *pspUp = *pspDown;
  163. pspUp++;
  164. pspDown--;
  165. pstyle++;
  166. }
  167. }
  168. {
  169. // All ROPs are handled in a single pass:
  170. ULONG achColor[4];
  171. LONG iIndex;
  172. ULONG iColor = (pbo->iSolidColor & 0xff);
  173. achColor[AND_ZERO] = 0;
  174. achColor[AND_PEN] = pbo->iSolidColor;
  175. achColor[AND_NOTPEN] = ~pbo->iSolidColor;
  176. achColor[AND_ONE] = (ULONG) -1L;
  177. iIndex = gaiLineMix[mix];
  178. // We have special strip drawers for set-style ROPs (where we don't
  179. // have to read video memory):
  180. if ((iIndex & 0xff) == AND_ZERO)
  181. fl |= FL_SET;
  182. // Put the AND index in the low byte, and the XOR index in the next:
  183. *((BYTE*) &ls.chAndXor) = (BYTE) achColor[iIndex & 0xff];
  184. *((BYTE*) &ls.chAndXor + 1) = (BYTE) achColor[iIndex >> MIX_XOR_OFFSET];
  185. }
  186. apfn = &gapfnStrip[4 * ((fl & FL_STRIP_ARRAY_MASK) >> FL_STRIP_ARRAY_SHIFT)];
  187. // Set up to enumerate the path:
  188. if (pco->iDComplexity != DC_COMPLEX)
  189. {
  190. RECTL arclClip[4]; // For rectangular clipping
  191. PATHDATA pd;
  192. RECTL* prclClip = (RECTL*) NULL;
  193. BOOL bMore;
  194. ULONG cptfx;
  195. POINTFIX ptfxStartFigure;
  196. POINTFIX ptfxLast;
  197. POINTFIX* pptfxFirst;
  198. POINTFIX* pptfxBuf;
  199. if (pco->iDComplexity == DC_RECT)
  200. {
  201. fl |= FL_SIMPLE_CLIP;
  202. arclClip[0] = pco->rclBounds;
  203. // FL_FLIP_D:
  204. arclClip[1].top = pco->rclBounds.left;
  205. arclClip[1].left = pco->rclBounds.top;
  206. arclClip[1].bottom = pco->rclBounds.right;
  207. arclClip[1].right = pco->rclBounds.bottom;
  208. // FL_FLIP_V:
  209. arclClip[2].top = -pco->rclBounds.bottom + 1;
  210. arclClip[2].left = pco->rclBounds.left;
  211. arclClip[2].bottom = -pco->rclBounds.top + 1;
  212. arclClip[2].right = pco->rclBounds.right;
  213. // FL_FLIP_V | FL_FLIP_D:
  214. arclClip[3].top = pco->rclBounds.left;
  215. arclClip[3].left = -pco->rclBounds.bottom + 1;
  216. arclClip[3].bottom = pco->rclBounds.right;
  217. arclClip[3].right = -pco->rclBounds.top + 1;
  218. prclClip = arclClip;
  219. }
  220. do {
  221. bMore = PATHOBJ_bEnum(ppo, &pd);
  222. cptfx = pd.count;
  223. if (cptfx == 0)
  224. {
  225. ASSERTVGA(!bMore, "Empty path record in non-empty path");
  226. break;
  227. }
  228. if (pd.flags & PD_BEGINSUBPATH)
  229. {
  230. ptfxStartFigure = *pd.pptfx;
  231. pptfxFirst = pd.pptfx;
  232. pptfxBuf = pd.pptfx + 1;
  233. cptfx--;
  234. }
  235. else
  236. {
  237. pptfxFirst = &ptfxLast;
  238. pptfxBuf = pd.pptfx;
  239. }
  240. if (pd.flags & PD_RESETSTYLE)
  241. ls.spNext = 0;
  242. // We have to check for cptfx == 0 because the only point in the
  243. // subpath may have been the StartFigure point:
  244. if (cptfx > 0)
  245. {
  246. if (!bLines(ppdev,
  247. pptfxFirst,
  248. pptfxBuf,
  249. (RUN*) NULL,
  250. cptfx,
  251. &ls,
  252. prclClip,
  253. apfn,
  254. fl))
  255. return(FALSE);
  256. }
  257. ptfxLast = pd.pptfx[pd.count - 1];
  258. if (pd.flags & PD_CLOSEFIGURE)
  259. {
  260. if (!bLines(ppdev,
  261. &ptfxLast,
  262. &ptfxStartFigure,
  263. (RUN*) NULL,
  264. 1,
  265. &ls,
  266. prclClip,
  267. apfn,
  268. fl))
  269. return(FALSE);
  270. }
  271. } while (bMore);
  272. if (fl & FL_STYLED)
  273. {
  274. // Save the style state:
  275. ULONG ulHigh;
  276. ULONG ulLow;
  277. ulHigh = ls.spNext / ls.xyDensity;
  278. ulLow = ls.spNext % ls.xyDensity;
  279. pla->elStyleState.l = MAKELONG(ulLow, ulHigh);
  280. }
  281. }
  282. else
  283. {
  284. // Local state for path enumeration:
  285. BOOL bMore;
  286. union {
  287. BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
  288. CLIPLINE cl;
  289. } cl;
  290. fl |= FL_COMPLEX_CLIP;
  291. // We use the clip object when non-simple clipping is involved:
  292. PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
  293. do {
  294. bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
  295. if (cl.cl.c != 0)
  296. {
  297. if (fl & FL_STYLED)
  298. {
  299. ls.spComplex = HIWORD(cl.cl.lStyleState) * ls.xyDensity
  300. + LOWORD(cl.cl.lStyleState);
  301. }
  302. if (!bLines(ppdev,
  303. &cl.cl.ptfxA,
  304. &cl.cl.ptfxB,
  305. &cl.cl.arun[0],
  306. cl.cl.c,
  307. &ls,
  308. (RECTL*) NULL,
  309. apfn,
  310. fl))
  311. return(FALSE);
  312. }
  313. } while (bMore);
  314. }
  315. return(TRUE);
  316. }