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.

545 lines
18 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: fastfill.c
  3. *
  4. * Draws fast unclipped, non-complex rectangles.
  5. *
  6. * Copyright (c) 1993-1995 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.h"
  9. #define RIGHT 0
  10. #define LEFT 1
  11. #define SWAP(a, b, tmp) { tmp = a; a = b; b = tmp; }
  12. typedef struct _EDGEDATA {
  13. LONG x; // Current x position
  14. LONG dx; // # pixels to advance x on each scan
  15. LONG lError; // Current DDA error
  16. LONG lErrorUp; // DDA error increment on each scan
  17. LONG lErrorDown; // DDA error adjustment
  18. POINTFIX* pptfx; // Points to start of current edge
  19. LONG dptfx; // Delta (in bytes) from pptfx to next point
  20. LONG cy; // Number of scans to go for this edge
  21. } EDGEDATA; /* ed, ped */
  22. /******************************Public*Routine******************************\
  23. * BOOL bFastFill
  24. *
  25. * Draws a non-complex, unclipped polygon. 'Non-complex' is defined as
  26. * having only two edges that are monotonic increasing in 'y'. That is,
  27. * the polygon cannot have more than one disconnected segment on any given
  28. * scan. Note that the edges of the polygon can self-intersect, so hourglass
  29. * shapes are permissible. This restriction permits this routine to run two
  30. * simultaneous DDAs, and no sorting of the edges is required.
  31. *
  32. * Note that NT's fill convention is different from that of Win 3.1 or 4.0.
  33. * With the additional complication of fractional end-points, our convention
  34. * is the same as in 'X-Windows'. But a DDA is a DDA is a DDA, so once you
  35. * figure out how we compute the DDA terms for NT, you're golden.
  36. *
  37. * Returns TRUE if the polygon was drawn; FALSE if the polygon was complex.
  38. *
  39. \**************************************************************************/
  40. BOOL bFastFill(
  41. PDEV* ppdev,
  42. LONG cEdges, // Includes close figure edge
  43. POINTFIX* pptfxFirst,
  44. ULONG ulHwMix,
  45. ULONG iSolidColor,
  46. RBRUSH* prb,
  47. POINTL* pptlBrush)
  48. {
  49. BYTE* pjBase;
  50. ULONG ulStat;
  51. LONG yTrapezoid; // Top scan for next trapezoid
  52. LONG cyTrapezoid; // Number of scans in current trapezoid
  53. LONG yStart; // y-position of start point in current edge
  54. LONG dM; // Edge delta in FIX units in x direction
  55. LONG dN; // Edge delta in FIX units in y direction
  56. LONG i;
  57. POINTFIX* pptfxLast; // Points to the last point in the polygon array
  58. POINTFIX* pptfxTop; // Points to the top-most point in the polygon
  59. POINTFIX* pptfxOld; // Start point in current edge
  60. POINTFIX* pptfxScan; // Current edge pointer for finding pptfxTop
  61. LONG cScanEdges; // Number of edges scanned to find pptfxTop
  62. // (doesn't include the closefigure edge)
  63. ULONG* pulPattern;
  64. ULONG ulPattern;
  65. LONG iEdge;
  66. LONG lQuotient;
  67. LONG lRemainder;
  68. EDGEDATA aed[2]; // DDA terms and stuff
  69. EDGEDATA* ped;
  70. // Most polygons will be convex, and so
  71. pjBase = ppdev->pjBase;
  72. if (iSolidColor == -1)
  73. {
  74. /////////////////////////////////////////////////////////////////
  75. // Setup for patterns
  76. // Make sure accelerator is not buy for all types.
  77. //
  78. CP_WAIT(ppdev, pjBase);
  79. if (P9000(ppdev))
  80. {
  81. CP_PATTERN_ORGX(ppdev, pjBase, ppdev->xOffset + pptlBrush->x);
  82. CP_PATTERN_ORGY(ppdev, pjBase, ppdev->yOffset + pptlBrush->y);
  83. CP_BACKGROUND(ppdev, pjBase, prb->ulColor[0]);
  84. CP_FOREGROUND(ppdev, pjBase, prb->ulColor[1]);
  85. pulPattern = &prb->aulPattern[0];
  86. for (i = 0; i < 4; i++)
  87. {
  88. ulPattern = *pulPattern++;
  89. CP_PATTERN(ppdev, pjBase, i, ulPattern);
  90. CP_PATTERN(ppdev, pjBase, i + 4, ulPattern);
  91. }
  92. if (((ulHwMix >> 8) & 0xff) == (ulHwMix & 0xff))
  93. {
  94. ulHwMix = gaulP9000OpaqueFromRop2[(ulHwMix & 0x3C) >> 2];
  95. CP_RASTER(ppdev, pjBase, ulHwMix | P9000_ENABLE_PATTERN);
  96. }
  97. else
  98. {
  99. ulHwMix = gaulP9000TransparentFromRop2[(ulHwMix & 0x3C) >> 2];
  100. CP_RASTER(ppdev, pjBase, ulHwMix | P9000_ENABLE_PATTERN);
  101. }
  102. }
  103. else
  104. {
  105. CP_PATTERN_ORGX(ppdev, pjBase, -(ppdev->xOffset + pptlBrush->x));
  106. CP_PATTERN_ORGY(ppdev, pjBase, -(ppdev->yOffset + pptlBrush->y));
  107. CP_COLOR0_FAST(ppdev, pjBase, prb->ulColor[0]);
  108. CP_COLOR1_FAST(ppdev, pjBase, prb->ulColor[1]);
  109. CP_PATTERN(ppdev, pjBase, 0, prb->aulPattern[0]);
  110. CP_PATTERN(ppdev, pjBase, 1, prb->aulPattern[1]);
  111. CP_PATTERN(ppdev, pjBase, 2, prb->aulPattern[2]);
  112. CP_PATTERN(ppdev, pjBase, 3, prb->aulPattern[3]);
  113. if (prb->fl & RBRUSH_2COLOR)
  114. {
  115. if (((ulHwMix >> 8) & 0xff) == (ulHwMix & 0xff))
  116. {
  117. CP_RASTER(ppdev, pjBase, (ulHwMix & 0xff)
  118. | P9100_ENABLE_PATTERN);
  119. }
  120. else
  121. {
  122. CP_RASTER(ppdev, pjBase, (ulHwMix & 0xff)
  123. | P9100_ENABLE_PATTERN | P9100_TRANSPARENT_PATTERN);
  124. }
  125. }
  126. else
  127. {
  128. CP_COLOR2_FAST(ppdev, pjBase, prb->ulColor[2]);
  129. CP_COLOR3_FAST(ppdev, pjBase, prb->ulColor[3]);
  130. CP_RASTER(ppdev, pjBase, (ulHwMix & 0xff)
  131. | P9100_ENABLE_PATTERN | P9100_FOUR_COLOR_PATTERN);
  132. }
  133. }
  134. }
  135. else
  136. {
  137. /////////////////////////////////////////////////////////////////
  138. // Setup the hardware for solid colours
  139. CP_WAIT(ppdev, pjBase);
  140. if (P9000(ppdev))
  141. {
  142. CP_BACKGROUND(ppdev, pjBase, iSolidColor);
  143. CP_RASTER(ppdev, pjBase, ulHwMix);
  144. }
  145. else
  146. {
  147. CP_COLOR0(ppdev, pjBase, iSolidColor);
  148. CP_RASTER(ppdev, pjBase, ulHwMix & 0xff);
  149. }
  150. }
  151. // We can do all integer triangles and convex quadrilaterals directly
  152. // with the hardware:
  153. if (cEdges <= 4)
  154. {
  155. ASSERTDD(cEdges >= 3, "What's with the degenerate polygon?");
  156. if ((((pptfxFirst)->x | (pptfxFirst)->y |
  157. (pptfxFirst+1)->x | (pptfxFirst+1)->y |
  158. (pptfxFirst+2)->x | (pptfxFirst+2)->y) & 0xF) == 0)
  159. {
  160. if (cEdges == 3)
  161. {
  162. CP_METATRI(ppdev, pjBase, (pptfxFirst)->x >> 4, (pptfxFirst)->y >> 4);
  163. CP_METATRI(ppdev, pjBase, (pptfxFirst+1)->x >> 4, (pptfxFirst+1)->y >> 4);
  164. CP_METATRI(ppdev, pjBase, (pptfxFirst+2)->x >> 4, (pptfxFirst+2)->y >> 4);
  165. CP_START_QUAD(ppdev, pjBase);
  166. return(TRUE);
  167. }
  168. else
  169. {
  170. if ((((pptfxFirst+3)->x | (pptfxFirst+3)->y) & 0xF) == 0)
  171. {
  172. CP_METAQUAD(ppdev, pjBase, (pptfxFirst)->x >> 4, (pptfxFirst)->y >> 4);
  173. CP_METAQUAD(ppdev, pjBase, (pptfxFirst+1)->x >> 4, (pptfxFirst+1)->y >> 4);
  174. CP_METAQUAD(ppdev, pjBase, (pptfxFirst+2)->x >> 4, (pptfxFirst+2)->y >> 4);
  175. CP_METAQUAD(ppdev, pjBase, (pptfxFirst+3)->x >> 4, (pptfxFirst+3)->y >> 4);
  176. CP_START_QUAD_STAT(ppdev, pjBase, ulStat);
  177. return(!(ulStat & QUADFAIL));
  178. }
  179. }
  180. }
  181. }
  182. /////////////////////////////////////////////////////////////////
  183. // See if the polygon is 'non-complex'
  184. pptfxScan = pptfxFirst;
  185. pptfxTop = pptfxFirst; // Assume for now that the first
  186. // point in path is the topmost
  187. pptfxLast = pptfxFirst + cEdges - 1;
  188. // 'pptfxScan' will always point to the first point in the current
  189. // edge, and 'cScanEdges' will the number of edges remaining, including
  190. // the current one:
  191. cScanEdges = cEdges - 1; // The number of edges, not counting close figure
  192. if ((pptfxScan + 1)->y > pptfxScan->y)
  193. {
  194. // Collect all downs:
  195. do {
  196. if (--cScanEdges == 0)
  197. goto SetUpForFilling;
  198. pptfxScan++;
  199. } while ((pptfxScan + 1)->y >= pptfxScan->y);
  200. // Collect all ups:
  201. do {
  202. if (--cScanEdges == 0)
  203. goto SetUpForFillingCheck;
  204. pptfxScan++;
  205. } while ((pptfxScan + 1)->y <= pptfxScan->y);
  206. // Collect all downs:
  207. pptfxTop = pptfxScan;
  208. do {
  209. if ((pptfxScan + 1)->y > pptfxFirst->y)
  210. break;
  211. if (--cScanEdges == 0)
  212. goto SetUpForFilling;
  213. pptfxScan++;
  214. } while ((pptfxScan + 1)->y >= pptfxScan->y);
  215. return(FALSE);
  216. }
  217. else
  218. {
  219. // Collect all ups:
  220. do {
  221. pptfxTop++; // We increment this now because we
  222. // want it to point to the very last
  223. // point if we early out in the next
  224. // statement...
  225. if (--cScanEdges == 0)
  226. goto SetUpForFilling;
  227. } while ((pptfxTop + 1)->y <= pptfxTop->y);
  228. // Collect all downs:
  229. pptfxScan = pptfxTop;
  230. do {
  231. if (--cScanEdges == 0)
  232. goto SetUpForFilling;
  233. pptfxScan++;
  234. } while ((pptfxScan + 1)->y >= pptfxScan->y);
  235. // Collect all ups:
  236. do {
  237. if ((pptfxScan + 1)->y < pptfxFirst->y)
  238. break;
  239. if (--cScanEdges == 0)
  240. goto SetUpForFilling;
  241. pptfxScan++;
  242. } while ((pptfxScan + 1)->y <= pptfxScan->y);
  243. return(FALSE);
  244. }
  245. SetUpForFillingCheck:
  246. // We check to see if the end of the current edge is higher
  247. // than the top edge we've found so far:
  248. if ((pptfxScan + 1)->y < pptfxTop->y)
  249. pptfxTop = pptfxScan + 1;
  250. SetUpForFilling:
  251. /////////////////////////////////////////////////////////////////
  252. // Some Initialization
  253. yTrapezoid = (pptfxTop->y + 15) >> 4;
  254. // Make sure we initialize the DDAs appropriately:
  255. aed[LEFT].cy = 0;
  256. aed[RIGHT].cy = 0;
  257. // For now, guess as to which is the left and which is the right edge:
  258. aed[LEFT].dptfx = -(LONG) sizeof(POINTFIX);
  259. aed[RIGHT].dptfx = sizeof(POINTFIX);
  260. aed[LEFT].pptfx = pptfxTop;
  261. aed[RIGHT].pptfx = pptfxTop;
  262. NewTrapezoid:
  263. /////////////////////////////////////////////////////////////////
  264. // DDA initialization
  265. for (iEdge = 1; iEdge >= 0; iEdge--)
  266. {
  267. ped = &aed[iEdge];
  268. if (ped->cy == 0)
  269. {
  270. // Need a new DDA:
  271. do {
  272. cEdges--;
  273. if (cEdges < 0)
  274. return(TRUE);
  275. // Find the next left edge, accounting for wrapping:
  276. pptfxOld = ped->pptfx;
  277. ped->pptfx = (POINTFIX*) ((BYTE*) ped->pptfx + ped->dptfx);
  278. if (ped->pptfx < pptfxFirst)
  279. ped->pptfx = pptfxLast;
  280. else if (ped->pptfx > pptfxLast)
  281. ped->pptfx = pptfxFirst;
  282. // Have to find the edge that spans yTrapezoid:
  283. ped->cy = ((ped->pptfx->y + 15) >> 4) - yTrapezoid;
  284. // With fractional coordinate end points, we may get edges
  285. // that don't cross any scans, in which case we try the
  286. // next one:
  287. } while (ped->cy <= 0);
  288. // 'pptfx' now points to the end point of the edge spanning
  289. // the scan 'yTrapezoid'.
  290. dN = ped->pptfx->y - pptfxOld->y;
  291. dM = ped->pptfx->x - pptfxOld->x;
  292. ASSERTDD(dN > 0, "Should be going down only");
  293. // Compute the DDA increment terms:
  294. if (dM < 0)
  295. {
  296. dM = -dM;
  297. if (dM < dN) // Can't be '<='
  298. {
  299. ped->dx = -1;
  300. ped->lErrorUp = dN - dM;
  301. }
  302. else
  303. {
  304. QUOTIENT_REMAINDER(dM, dN, lQuotient, lRemainder);
  305. ped->dx = -lQuotient; // - dM / dN
  306. ped->lErrorUp = lRemainder; // dM % dN
  307. if (ped->lErrorUp > 0)
  308. {
  309. ped->dx--;
  310. ped->lErrorUp = dN - ped->lErrorUp;
  311. }
  312. }
  313. }
  314. else
  315. {
  316. if (dM < dN) // Can't be '<='
  317. {
  318. ped->dx = 0;
  319. ped->lErrorUp = dM;
  320. }
  321. else
  322. {
  323. QUOTIENT_REMAINDER(dM, dN, lQuotient, lRemainder);
  324. ped->dx = lQuotient; // dM / dN
  325. ped->lErrorUp = lRemainder; // dM % dN
  326. }
  327. }
  328. ped->lErrorDown = dN; // DDA limit
  329. ped->lError = -1; // Error is initially zero (add dN - 1 for
  330. // the ceiling, but subtract off dN so that
  331. // we can check the sign instead of comparing
  332. // to dN)
  333. ped->x = pptfxOld->x;
  334. yStart = pptfxOld->y;
  335. if ((yStart & 15) != 0)
  336. {
  337. // Advance to the next integer y coordinate
  338. for (i = 16 - (yStart & 15); i != 0; i--)
  339. {
  340. ped->x += ped->dx;
  341. ped->lError += ped->lErrorUp;
  342. if (ped->lError >= 0)
  343. {
  344. ped->lError -= ped->lErrorDown;
  345. ped->x++;
  346. }
  347. }
  348. }
  349. if ((ped->x & 15) != 0)
  350. {
  351. ped->lError -= ped->lErrorDown * (16 - (ped->x & 15));
  352. ped->x += 15; // We'll want the ceiling in just a bit...
  353. }
  354. // Chop off those fractional bits:
  355. ped->x >>= 4;
  356. ped->lError >>= 4;
  357. }
  358. }
  359. cyTrapezoid = min(aed[LEFT].cy, aed[RIGHT].cy); // # of scans in this trap
  360. aed[LEFT].cy -= cyTrapezoid;
  361. aed[RIGHT].cy -= cyTrapezoid;
  362. // If the left and right edges are vertical, simply output as
  363. // a rectangle:
  364. if (((aed[LEFT].lErrorUp | aed[RIGHT].lErrorUp) == 0) &&
  365. ((aed[LEFT].dx | aed[RIGHT].dx) == 0))
  366. {
  367. /////////////////////////////////////////////////////////////////
  368. // Vertical-edge special case
  369. ContinueVertical:
  370. if (aed[LEFT].x < aed[RIGHT].x)
  371. {
  372. CP_METARECT(ppdev, pjBase, aed[LEFT].x, yTrapezoid);
  373. yTrapezoid += cyTrapezoid;
  374. CP_METARECT(ppdev, pjBase, aed[RIGHT].x, yTrapezoid);
  375. CP_START_QUAD_WAIT(ppdev, pjBase);
  376. }
  377. else if (aed[LEFT].x == aed[RIGHT].x)
  378. {
  379. // If the rectangle was too thin to light any pels, we still
  380. // have to advance the y current position:
  381. yTrapezoid += cyTrapezoid;
  382. }
  383. else
  384. {
  385. LONG lTmp;
  386. POINTFIX* pptfxTmp;
  387. SWAP(aed[LEFT].x, aed[RIGHT].x, lTmp);
  388. SWAP(aed[LEFT].cy, aed[RIGHT].cy, lTmp);
  389. SWAP(aed[LEFT].dptfx, aed[RIGHT].dptfx, lTmp);
  390. SWAP(aed[LEFT].pptfx, aed[RIGHT].pptfx, pptfxTmp);
  391. goto ContinueVertical;
  392. }
  393. goto NewTrapezoid;
  394. }
  395. while (TRUE)
  396. {
  397. /////////////////////////////////////////////////////////////////
  398. // Run the DDAs
  399. if (aed[LEFT].x < aed[RIGHT].x)
  400. {
  401. CP_METARECT(ppdev, pjBase, aed[LEFT].x, yTrapezoid);
  402. yTrapezoid++;
  403. CP_METARECT(ppdev, pjBase, aed[RIGHT].x, yTrapezoid);
  404. CP_START_QUAD_WAIT(ppdev, pjBase);
  405. ContinueAfterZero:
  406. // Advance the right wall:
  407. aed[RIGHT].x += aed[RIGHT].dx;
  408. aed[RIGHT].lError += aed[RIGHT].lErrorUp;
  409. if (aed[RIGHT].lError >= 0)
  410. {
  411. aed[RIGHT].lError -= aed[RIGHT].lErrorDown;
  412. aed[RIGHT].x++;
  413. }
  414. // Advance the left wall:
  415. aed[LEFT].x += aed[LEFT].dx;
  416. aed[LEFT].lError += aed[LEFT].lErrorUp;
  417. if (aed[LEFT].lError >= 0)
  418. {
  419. aed[LEFT].lError -= aed[LEFT].lErrorDown;
  420. aed[LEFT].x++;
  421. }
  422. cyTrapezoid--;
  423. if (cyTrapezoid == 0)
  424. goto NewTrapezoid;
  425. }
  426. else if (aed[LEFT].x == aed[RIGHT].x)
  427. {
  428. yTrapezoid++;
  429. goto ContinueAfterZero;
  430. }
  431. else
  432. {
  433. // We certainly don't want to optimize for this case because we
  434. // should rarely get self-intersecting polygons (if we're slow,
  435. // the app gets what it deserves):
  436. LONG lTmp;
  437. POINTFIX* pptfxTmp;
  438. SWAP(aed[LEFT].x, aed[RIGHT].x, lTmp);
  439. SWAP(aed[LEFT].dx, aed[RIGHT].dx, lTmp);
  440. SWAP(aed[LEFT].lError, aed[RIGHT].lError, lTmp);
  441. SWAP(aed[LEFT].lErrorUp, aed[RIGHT].lErrorUp, lTmp);
  442. SWAP(aed[LEFT].lErrorDown, aed[RIGHT].lErrorDown, lTmp);
  443. SWAP(aed[LEFT].cy, aed[RIGHT].cy, lTmp);
  444. SWAP(aed[LEFT].dptfx, aed[RIGHT].dptfx, lTmp);
  445. SWAP(aed[LEFT].pptfx, aed[RIGHT].pptfx, pptfxTmp);
  446. continue;
  447. }
  448. }
  449. }