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.

2337 lines
79 KiB

  1. /*************************************************************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: Lines.c
  8. *
  9. * Contains most of the required GDI line support. Supports drawing
  10. * lines in short 'strips' when clipping is complex or coordinates
  11. * are too large to be drawn by the line hardware.
  12. *
  13. * Copyright (c) 1990-1998 Microsoft Corporation
  14. \**************************************************************************/
  15. #include "precomp.h"
  16. /******************************Public*Routine******************************\
  17. * VOID vLinesSimple
  18. *
  19. * Historically, NT has used funky 'GIQ' coordinates that have 4 bits of
  20. * fraction, and is very picky about which pixels are lit even for lines
  21. * whose coordinates are all integers. But as of NT 4.0 Service-Pack 1,
  22. * NT now informs us when all the coordinates in a path are integers (via
  23. * the PO_ALL_INTEGERS flag), and what's more it allows us to request that
  24. * the path coordinates before returned as integers instead of the funky
  25. * 28.4 (by setting the PO_ENUM_AS_INTEGERS flag).
  26. *
  27. * But the best part is that GDI now allows us to choose which pixel we'll
  28. * light for tie-breaker cases, when the error term is exactly 0.5 (the
  29. * lines must still be last-pixel exclusive, of course).
  30. *
  31. * So we can now use the hardware's auto-Bresenham-setup (point-to-point
  32. * lines) capability! And that's exactly what we do here...
  33. *
  34. * Unfortunately, this code is complicated by the funky format for the MGA's
  35. * auto-line mechanism -- we have to send down batches composed of a 1 dword
  36. * flag, followed by 32 vertices. The dword flag indicates which of the
  37. * following vertices should be considered the disjoint from the rest (i.e.,
  38. * indicates PD_BEGINSUBPATH to the hardware).
  39. *
  40. \**************************************************************************/
  41. VOID vLinesSimple(
  42. PDEV* ppdev,
  43. PATHOBJ* ppo,
  44. LONG cFifo) // Number of S3 FIFO slots we know are free
  45. {
  46. BYTE* pjMmBase;
  47. LONG xOffset;
  48. LONG yOffset;
  49. BOOL bMore;
  50. PATHDATA pd;
  51. LONG cLines;
  52. POINTFIX* pptfx;
  53. POINTFIX ptfxStartFigure;
  54. // Notify GDI that we want the path enumerated as integers instead of
  55. // fixed coordinates. Note that we can only do this when GDI has set
  56. // the PO_ALL_INTEGERS flag:
  57. ppo->fl |= PO_ENUM_AS_INTEGERS;
  58. pjMmBase = ppdev->pjMmBase;
  59. xOffset = ppdev->xOffset;
  60. yOffset = ppdev->yOffset;
  61. do {
  62. bMore = PATHOBJ_bEnum(ppo, &pd);
  63. cLines = pd.count;
  64. pptfx = pd.pptfx;
  65. if (pd.flags & PD_BEGINSUBPATH)
  66. {
  67. cLines--;
  68. ptfxStartFigure.x = pptfx->x;
  69. ptfxStartFigure.y = pptfx->y;
  70. cFifo--;
  71. if (cFifo < 0)
  72. {
  73. IO_ALL_EMPTY(ppdev);
  74. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 1;
  75. }
  76. NW_ABS_CURXY(ppdev, pjMmBase, pptfx->x + xOffset, pptfx->y + yOffset);
  77. pptfx++;
  78. cFifo--;
  79. }
  80. PolylineSegments:
  81. while (cLines-- > 0)
  82. {
  83. cFifo -= 2;
  84. if (cFifo < 0)
  85. {
  86. IO_ALL_EMPTY(ppdev);
  87. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 2;
  88. }
  89. NW_ABS_STEPXY(ppdev, pjMmBase, pptfx->x + xOffset, pptfx->y + yOffset);
  90. NW_ALT_CMD(ppdev, pjMmBase, POLYLINE | WRITE | DRAW);
  91. pptfx++;
  92. }
  93. if (pd.flags & PD_CLOSEFIGURE)
  94. {
  95. pd.flags &= ~PD_CLOSEFIGURE;
  96. pptfx = &ptfxStartFigure;
  97. goto PolylineSegments;
  98. }
  99. } while (bMore);
  100. }
  101. ///////////////////////////////////////////////////////////////////////
  102. // We have to be careful of arithmetic overflow in a number of places.
  103. // Fortunately, the compiler is guaranteed to natively support 64-bit
  104. // signed LONGLONGs and 64-bit unsigned DWORDLONGs.
  105. //
  106. // UUInt32x32To64(a, b) is a macro defined in 'winnt.h' that multiplies
  107. // two 32-bit ULONGs to produce a 64-bit DWORDLONG result.
  108. //
  109. // UInt64By32To32 is our own macro to divide a 64-bit DWORDLONG by
  110. // a 32-bit ULONG to produce a 32-bit ULONG result.
  111. //
  112. // UInt64Mod32To32 is our own macro to modulus a 64-bit DWORDLONG by
  113. // a 32-bit ULONG to produce a 32-bit ULONG result.
  114. //
  115. // 64 bit divides are usually very expensive. Since it's very rare
  116. // that we'll get lines where the upper 32 bits of the 64 bit result
  117. // are used, we can almost always use 32-bit ULONG divides. We still
  118. // must correctly handle the larger cases:
  119. #define UInt64Div32To32(a, b) \
  120. ((((DWORDLONG)(a)) > ULONG_MAX) ? \
  121. (ULONG)((DWORDLONG)(a) / (ULONG)(b)) : \
  122. (ULONG)((ULONG)(a) / (ULONG)(b)))
  123. #define UInt64Mod32To32(a, b) \
  124. ((((DWORDLONG)(a)) > ULONG_MAX) ? \
  125. (ULONG)((DWORDLONG)(a) % (ULONG)(b)) : \
  126. (ULONG)((ULONG)(a) % (ULONG)(b)))
  127. #define SWAPL(x,y,t) {t = x; x = y; y = t;}
  128. FLONG gaflRound[] = {
  129. FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // no flips
  130. FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // FL_FLIP_D
  131. FL_H_ROUND_DOWN, // FL_FLIP_V
  132. FL_V_ROUND_DOWN, // FL_FLIP_V | FL_FLIP_D
  133. FL_V_ROUND_DOWN, // FL_FLIP_SLOPE_ONE
  134. 0xbaadf00d, // FL_FLIP_SLOPE_ONE | FL_FLIP_D
  135. FL_H_ROUND_DOWN, // FL_FLIP_SLOPE_ONE | FL_FLIP_V
  136. 0xbaadf00d // FL_FLIP_SLOPE_ONE | FL_FLIP_V | FL_FLIP_D
  137. };
  138. BOOL bHardwareLine(PDEV*, POINTFIX*, POINTFIX*);
  139. /******************************Public*Routine******************************\
  140. * BOOL bLines(ppdev, pptfxFirst, pptfxBuf, cptfx, pls,
  141. * prclClip, apfn[], flStart)
  142. *
  143. * Computes the DDA for the line and gets ready to draw it. Puts the
  144. * pixel data into an array of strips, and calls a strip routine to
  145. * do the actual drawing.
  146. *
  147. * Doing NT Lines Right
  148. * --------------------
  149. *
  150. * In NT, all lines are given to the device driver in fractional
  151. * coordinates, in a 28.4 fixed point format. The lower 4 bits are
  152. * fractional for sub-pixel positioning.
  153. *
  154. * Note that you CANNOT! just round the coordinates to integers
  155. * and pass the results to your favorite integer Bresenham routine!!
  156. * (Unless, of course, you have such a high resolution device that
  157. * nobody will notice -- not likely for a display device.) The
  158. * fractions give a more accurate rendering of the line -- this is
  159. * important for things like our Bezier curves, which would have 'kinks'
  160. * if the points in its polyline approximation were rounded to integers.
  161. *
  162. * Unfortunately, for fractional lines there is more setup work to do
  163. * a DDA than for integer lines. However, the main loop is exactly
  164. * the same (and can be done entirely with 32 bit math).
  165. *
  166. * If You've Got Hardware That Does Bresenham
  167. * ------------------------------------------
  168. *
  169. * A lot of hardware limits DDA error terms to 'n' bits. With fractional
  170. * coordinates, 4 bits are given to the fractional part, letting
  171. * you draw in hardware only those lines that lie entirely in a 2^(n-4)
  172. * by 2^(n-4) pixel space.
  173. *
  174. * And you still have to correctly draw those lines with coordinates
  175. * outside that space! Remember that the screen is only a viewport
  176. * onto a 28.4 by 28.4 space -- if any part of the line is visible
  177. * you MUST render it precisely, regardless of where the end points lie.
  178. * So even if you do it in software, somewhere you'll have to have a
  179. * 32 bit DDA routine.
  180. *
  181. * Our Implementation
  182. * ------------------
  183. *
  184. * We employ a run length slice algorithm: our DDA calculates the
  185. * number of pixels that are in each row (or 'strip') of pixels.
  186. *
  187. * We've separated the running of the DDA and the drawing of pixels:
  188. * we run the DDA for several iterations and store the results in
  189. * a 'strip' buffer (which are the lengths of consecutive pixel rows of
  190. * the line), then we crank up a 'strip drawer' that will draw all the
  191. * strips in the buffer.
  192. *
  193. * We also employ a 'half-flip' to reduce the number of strip
  194. * iterations we need to do in the DDA and strip drawing loops: when a
  195. * (normalized) line's slope is more than 1/2, we do a final flip
  196. * about the line y = (1/2)x. So now, instead of each strip being
  197. * consecutive horizontal or vertical pixel rows, each strip is composed
  198. * of those pixels aligned in 45 degree rows. So a line like (0, 0) to
  199. * (128, 128) would generate only one strip.
  200. *
  201. * We also always draw only left-to-right.
  202. *
  203. * Styled lines may have arbitrary style patterns. We specially
  204. * optimize the default patterns (and call them 'masked' styles).
  205. *
  206. * The DDA Derivation
  207. * ------------------
  208. *
  209. * Here is how I like to think of the DDA calculation.
  210. *
  211. * We employ Knuth's "diamond rule": rendering a one-pixel-wide line
  212. * can be thought of as dragging a one-pixel-wide by one-pixel-high
  213. * diamond along the true line. Pixel centers lie on the integer
  214. * coordinates, and so we light any pixel whose center gets covered
  215. * by the "drag" region (John D. Hobby, Journal of the Association
  216. * for Computing Machinery, Vol. 36, No. 2, April 1989, pp. 209-229).
  217. *
  218. * We must define which pixel gets lit when the true line falls
  219. * exactly half-way between two pixels. In this case, we follow
  220. * the rule: when two pels are equidistant, the upper or left pel
  221. * is illuminated, unless the slope is exactly one, in which case
  222. * the upper or right pel is illuminated. (So we make the edges
  223. * of the diamond exclusive, except for the top and left vertices,
  224. * which are inclusive, unless we have slope one.)
  225. *
  226. * This metric decides what pixels should be on any line BEFORE it is
  227. * flipped around for our calculation. Having a consistent metric
  228. * this way will let our lines blend nicely with our curves. The
  229. * metric also dictates that we will never have one pixel turned on
  230. * directly above another that's turned on. We will also never have
  231. * a gap; i.e., there will be exactly one pixel turned on for each
  232. * column between the start and end points. All that remains to be
  233. * done is to decide how many pixels should be turned on for each row.
  234. *
  235. * So lines we draw will consist of varying numbers of pixels on
  236. * successive rows, for example:
  237. *
  238. * ******
  239. * *****
  240. * ******
  241. * *****
  242. *
  243. * We'll call each set of pixels on a row a "strip".
  244. *
  245. * (Please remember that our coordinate space has the origin as the
  246. * upper left pixel on the screen; postive y is down and positive x
  247. * is right.)
  248. *
  249. * Device coordinates are specified as fixed point 28.4 numbers,
  250. * where the first 28 bits are the integer coordinate, and the last
  251. * 4 bits are the fraction. So coordinates may be thought of as
  252. * having the form (x, y) = (M/F, N/F) where F is the constant scaling
  253. * factor F = 2^4 = 16, and M and N are 32 bit integers.
  254. *
  255. * Consider the line from (M0/F, N0/F) to (M1/F, N1/F) which runs
  256. * left-to-right and whose slope is in the first octant, and let
  257. * dM = M1 - M0 and dN = N1 - N0. Then dM >= 0, dN >= 0 and dM >= dN.
  258. *
  259. * Since the slope of the line is less than 1, the edges of the
  260. * drag region are created by the top and bottom vertices of the
  261. * diamond. At any given pixel row y of the line, we light those
  262. * pixels whose centers are between the left and right edges.
  263. *
  264. * Let mL(n) denote the line representing the left edge of the drag
  265. * region. On pixel row j, the column of the first pixel to be
  266. * lit is
  267. *
  268. * iL(j) = ceiling( mL(j * F) / F)
  269. *
  270. * Since the line's slope is less than one:
  271. *
  272. * iL(j) = ceiling( mL([j + 1/2] F) / F )
  273. *
  274. * Recall the formula for our line:
  275. *
  276. * n(m) = (dN / dM) (m - M0) + N0
  277. *
  278. * m(n) = (dM / dN) (n - N0) + M0
  279. *
  280. * Since the line's slope is less than one, the line representing
  281. * the left edge of the drag region is the original line offset
  282. * by 1/2 pixel in the y direction:
  283. *
  284. * mL(n) = (dM / dN) (n - F/2 - N0) + M0
  285. *
  286. * From this we can figure out the column of the first pixel that
  287. * will be lit on row j, being careful of rounding (if the left
  288. * edge lands exactly on an integer point, the pixel at that
  289. * point is not lit because of our rounding convention):
  290. *
  291. * iL(j) = floor( mL(j F) / F ) + 1
  292. *
  293. * = floor( ((dM / dN) (j F - F/2 - N0) + M0) / F ) + 1
  294. *
  295. * = floor( F dM j - F/2 dM - N0 dM + dN M0) / F dN ) + 1
  296. *
  297. * F dM j - [ dM (N0 + F/2) - dN M0 ]
  298. * = floor( ---------------------------------- ) + 1
  299. * F dN
  300. *
  301. * dM j - [ dM (N0 + F/2) - dN M0 ] / F
  302. * = floor( ------------------------------------ ) + 1 (1)
  303. * dN
  304. *
  305. * = floor( (dM j + alpha) / dN ) + 1
  306. *
  307. * where
  308. *
  309. * alpha = - [ dM (N0 + F/2) - dN M0 ] / F
  310. *
  311. * We use equation (1) to calculate the DDA: there are iL(j+1) - iL(j)
  312. * pixels in row j. Because we are always calculating iL(j) for
  313. * integer quantities of j, we note that the only fractional term
  314. * is constant, and so we can 'throw away' the fractional bits of
  315. * alpha:
  316. *
  317. * beta = floor( - [ dM (N0 + F/2) - dN M0 ] / F ) (2)
  318. *
  319. * so
  320. *
  321. * iL(j) = floor( (dM j + beta) / dN ) + 1 (3)
  322. *
  323. * for integers j.
  324. *
  325. * Note if iR(j) is the line's rightmost pixel on row j, that
  326. * iR(j) = iL(j + 1) - 1.
  327. *
  328. * Similarly, rewriting equation (1) as a function of column i,
  329. * we can determine, given column i, on which pixel row j is the line
  330. * lit:
  331. *
  332. * dN i + [ dM (N0 + F/2) - dN M0 ] / F
  333. * j(i) = ceiling( ------------------------------------ ) - 1
  334. * dM
  335. *
  336. * Floors are easier to compute, so we can rewrite this:
  337. *
  338. * dN i + [ dM (N0 + F/2) - dN M0 ] / F + dM - 1/F
  339. * j(i) = floor( ----------------------------------------------- ) - 1
  340. * dM
  341. *
  342. * dN i + [ dM (N0 + F/2) - dN M0 ] / F + dM - 1/F - dM
  343. * = floor( ---------------------------------------------------- )
  344. * dM
  345. *
  346. * dN i + [ dM (N0 + F/2) - dN M0 - 1 ] / F
  347. * = floor( ---------------------------------------- )
  348. * dM
  349. *
  350. * We can once again wave our hands and throw away the fractional bits
  351. * of the remainder term:
  352. *
  353. * j(i) = floor( (dN i + gamma) / dM ) (4)
  354. *
  355. * where
  356. *
  357. * gamma = floor( [ dM (N0 + F/2) - dN M0 - 1 ] / F ) (5)
  358. *
  359. * We now note that
  360. *
  361. * beta = -gamma - 1 = ~gamma (6)
  362. *
  363. * To draw the pixels of the line, we could evaluate (3) on every scan
  364. * line to determine where the strip starts. Of course, we don't want
  365. * to do that because that would involve a multiply and divide for every
  366. * scan. So we do everything incrementally.
  367. *
  368. * We would like to easily compute c , the number of pixels on scan j:
  369. * j
  370. *
  371. * c = iL(j + 1) - iL(j)
  372. * j
  373. *
  374. * = floor((dM (j + 1) + beta) / dN) - floor((dM j + beta) / dN) (7)
  375. *
  376. * This may be rewritten as
  377. *
  378. * c = floor(i + r / dN) - floor(i + r / dN) (8)
  379. * j j+1 j+1 j j
  380. *
  381. * where i , i are integers and r < dN, r < dN.
  382. * j j+1 j j+1
  383. *
  384. * Rewriting (7) again:
  385. *
  386. * c = floor(i + r / dN + dM / dN) - floor(i + r / dN)
  387. * j j j j j
  388. *
  389. *
  390. * = floor((r + dM) / dN) - floor(r / dN)
  391. * j j
  392. *
  393. * This may be rewritten as
  394. *
  395. * c = dI + floor((r + dR) / dN) - floor(r / dN)
  396. * j j j
  397. *
  398. * where dI + dR / dN = dM / dN, dI is an integer and dR < dN.
  399. *
  400. * r is the remainder (or "error") term in the DDA loop: r / dN
  401. * j j
  402. * is the exact fraction of a pixel at which the strip ends. To go
  403. * on to the next scan and compute c we need to know r .
  404. * j+1 j+1
  405. *
  406. * So in the main loop of the DDA:
  407. *
  408. * c = dI + floor((r + dR) / dN) and r = (r + dR) % dN
  409. * j j j+1 j
  410. *
  411. * and we know r < dN, r < dN, and dR < dN.
  412. * j j+1
  413. *
  414. * We have derived the DDA only for lines in the first octant; to
  415. * handle other octants we do the common trick of flipping the line
  416. * to the first octant by first making the line left-to-right by
  417. * exchanging the end-points, then flipping about the lines y = 0 and
  418. * y = x, as necessary. We must record the transformation so we can
  419. * undo them later.
  420. *
  421. * We must also be careful of how the flips affect our rounding. If
  422. * to get the line to the first octant we flipped about x = 0, we now
  423. * have to be careful to round a y value of 1/2 up instead of down as
  424. * we would for a line originally in the first octant (recall that
  425. * "In the case where two pels are equidistant, the upper or left
  426. * pel is illuminated...").
  427. *
  428. * To account for this rounding when running the DDA, we shift the line
  429. * (or not) in the y direction by the smallest amount possible. That
  430. * takes care of rounding for the DDA, but we still have to be careful
  431. * about the rounding when determining the first and last pixels to be
  432. * lit in the line.
  433. *
  434. * Determining The First And Last Pixels In The Line
  435. * -------------------------------------------------
  436. *
  437. * Fractional coordinates also make it harder to determine which pixels
  438. * will be the first and last ones in the line. We've already taken
  439. * the fractional coordinates into account in calculating the DDA, but
  440. * the DDA cannot tell us which are the end pixels because it is quite
  441. * happy to calculate pixels on the line from minus infinity to positive
  442. * infinity.
  443. *
  444. * The diamond rule determines the start and end pixels. (Recall that
  445. * the sides are exclusive except for the left and top vertices.)
  446. * This convention can be thought of in another way: there are diamonds
  447. * around the pixels, and wherever the true line crosses a diamond,
  448. * that pel is illuminated.
  449. *
  450. * Consider a line where we've done the flips to the first octant, and the
  451. * floor of the start coordinates is the origin:
  452. *
  453. * +-----------------------> +x
  454. * |
  455. * | 0 1
  456. * | 0123456789abcdef
  457. * |
  458. * | 0 00000000?1111111
  459. * | 1 00000000 1111111
  460. * | 2 0000000 111111
  461. * | 3 000000 11111
  462. * | 4 00000 ** 1111
  463. * | 5 0000 ****1
  464. * | 6 000 1***
  465. * | 7 00 1 ****
  466. * | 8 ? ***
  467. * | 9 22 3 ****
  468. * | a 222 33 ***
  469. * | b 2222 333 ****
  470. * | c 22222 3333 **
  471. * | d 222222 33333
  472. * | e 2222222 333333
  473. * | f 22222222 3333333
  474. * |
  475. * | 2 3
  476. * v
  477. * +y
  478. *
  479. * If the start of the line lands on the diamond around pixel 0 (shown by
  480. * the '0' region here), pixel 0 is the first pel in the line. The same
  481. * is true for the other pels.
  482. *
  483. * A little more work has to be done if the line starts in the
  484. * 'nether-land' between the diamonds (as illustrated by the '*' line):
  485. * the first pel lit is the first diamond crossed by the line (pixel 1 in
  486. * our example). This calculation is determined by the DDA or slope of
  487. * the line.
  488. *
  489. * If the line starts exactly half way between two adjacent pixels
  490. * (denoted here by the '?' spots), the first pixel is determined by our
  491. * round-down convention (and is dependent on the flips done to
  492. * normalize the line).
  493. *
  494. * Last Pel Exclusive
  495. * ------------------
  496. *
  497. * To eliminate repeatedly lit pels between continuous connected lines,
  498. * we employ a last-pel exclusive convention: if the line ends exactly on
  499. * the diamond around a pel, that pel is not lit. (This eliminates the
  500. * checks we had in the old code to see if we were re-lighting pels.)
  501. *
  502. * The Half Flip
  503. * -------------
  504. *
  505. * To make our run length algorithm more efficient, we employ a "half
  506. * flip". If after normalizing to the first octant, the slope is more
  507. * than 1/2, we subtract the y coordinate from the x coordinate. This
  508. * has the effect of reflecting the coordinates through the line of slope
  509. * 1/2. Note that the diagonal gets mapped into the x-axis after a half
  510. * flip.
  511. *
  512. * How Many Bits Do We Need, Anyway?
  513. * ---------------------------------
  514. *
  515. * Note that if the line is visible on your screen, you must light up
  516. * exactly the correct pixels, no matter where in the 28.4 x 28.4 device
  517. * space the end points of the line lie (meaning you must handle 32 bit
  518. * DDAs, you can certainly have optimized cases for lesser DDAs).
  519. *
  520. * We move the origin to (floor(M0 / F), floor(N0 / F)), so when we
  521. * calculate gamma from (5), we know that 0 <= M0, N0 < F. And we
  522. * are in the first octant, so dM >= dN. Then we know that gamma can
  523. * be in the range [(-1/2)dM, (3/2)dM]. The DDI guarantees us that
  524. * valid lines will have dM and dN values at most 31 bits (unsigned)
  525. * of significance. So gamma requires 33 bits of significance (we store
  526. * this as a 64 bit number for convenience).
  527. *
  528. * When running through the DDA loop, r + dR can have a value in the
  529. * j
  530. * range 0 <= r < 2 dN; thus the result must be a 32 bit unsigned value.
  531. * j
  532. *
  533. * Testing Lines
  534. * -------------
  535. *
  536. * To be NT compliant, a display driver must exactly adhere to GIQ,
  537. * which means that for any given line, the driver must light exactly
  538. * the same pels as does GDI. This can be tested using the Guiman tool
  539. * provided elsewhere in the DDK, and 'ZTest', which draws random lines
  540. * on the screen and to a bitmap, and compares the results.
  541. *
  542. * If You've Got Line Hardware
  543. * ---------------------------
  544. *
  545. * If your hardware already adheres to GIQ, you're all set. Otherwise
  546. * you'll want to look at the sample code and read the following:
  547. *
  548. * 1) You'll want to special case integer-only lines, since they require
  549. * less processing time and are more common (CAD programs will probably
  550. * only ever give integer lines). GDI does not provide a flag saying
  551. * that all lines in a path are integer lines; consequently, you will
  552. * have to explicitly check every line.
  553. *
  554. * 2) You are required to correctly draw any line in the 28.4 device
  555. * space that intersects the viewport. If you have less than 32 bits
  556. * of significance in the hardware for the Bresenham terms, extremely
  557. * long lines would overflow the hardware. For such (rare) cases, you
  558. * can fall back to strip-drawing code (or if your display is a frame
  559. * buffer, fall back to the engine).
  560. *
  561. * 3) If you can explicitly set the Bresenham terms in your hardware, you
  562. * can draw non-integer lines using the hardware. If your hardware has
  563. * 'n' bits of precision, you can draw GIQ lines that are up to 2^(n-5)
  564. * pels long (4 bits are required for the fractional part, and one bit is
  565. * used as a sign bit). Note that integer lines don't require the 4
  566. * fractional bits, so if you special case them as in 1), you can do
  567. * integer lines that are up to 2^(n - 1) pels long. See the
  568. * 'bHardwareLine' routine for an example.
  569. *
  570. \**************************************************************************/
  571. BOOL bLines(
  572. PDEV* ppdev,
  573. POINTFIX* pptfxFirst, // Start of first line
  574. POINTFIX* pptfxBuf, // Pointer to buffer of all remaining lines
  575. RUN* prun, // Pointer to runs if doing complex clipping
  576. ULONG cptfx, // Number of points in pptfxBuf or number of runs
  577. // in prun
  578. LINESTATE* pls, // Colour and style info
  579. RECTL* prclClip, // Pointer to clip rectangle if doing simple clipping
  580. PFNSTRIP apfn[], // Array of strip functions
  581. FLONG flStart) // Flags for each line, which is a combination of:
  582. // FL_SIMPLE_CLIP
  583. // FL_COMPLEX_CLIP
  584. // FL_STYLED
  585. // FL_LAST_PEL_INCLUSIVE
  586. // - Should be set only for all integer lines,
  587. // and can't be used with FL_COMPLEX_CLIP
  588. {
  589. ULONG M0;
  590. ULONG dM;
  591. ULONG N0;
  592. ULONG dN;
  593. ULONG dN_Original;
  594. FLONG fl;
  595. LONG x;
  596. LONG y;
  597. LONGLONG llBeta;
  598. LONGLONG llGamma;
  599. LONGLONG dl;
  600. LONGLONG ll;
  601. ULONG ulDelta;
  602. ULONG x0;
  603. ULONG y0;
  604. ULONG x1;
  605. ULONG cStylePels; // Major length of line in pixels for styling
  606. ULONG xStart;
  607. POINTL ptlStart;
  608. STRIP strip;
  609. PFNSTRIP pfn;
  610. LONG cPels;
  611. LONG* plStrip;
  612. LONG* plStripEnd;
  613. LONG cStripsInNextRun;
  614. POINTFIX* pptfxBufEnd = pptfxBuf + cptfx; // Last point in path record
  615. STYLEPOS spThis; // Style pos for this line
  616. do {
  617. /***********************************************************************\
  618. * Start the DDA calculations. *
  619. \***********************************************************************/
  620. M0 = (LONG) pptfxFirst->x;
  621. dM = (LONG) pptfxBuf->x;
  622. N0 = (LONG) pptfxFirst->y;
  623. dN = (LONG) pptfxBuf->y;
  624. fl = flStart;
  625. // Check for non-clipped, non-styled integer endpoint lines:
  626. if ((fl & (FL_CLIP | FL_STYLED)) == 0)
  627. {
  628. // Special-case integer end-point lines:
  629. if (((M0 | dM | N0 | dN) & (F - 1)) == 0)
  630. {
  631. // -1 for 'iSolidColor' denotes that the currently set
  632. // colour and mix should be kept:
  633. ppdev->pfnLineToTrivial(ppdev,
  634. (M0 >> 4) + ppdev->xOffset,
  635. (N0 >> 4) + ppdev->yOffset,
  636. (dM >> 4) + ppdev->xOffset,
  637. (dN >> 4) + ppdev->yOffset,
  638. (ULONG) -1,
  639. 0);
  640. goto Next_Line;
  641. }
  642. // Check for fractional endpoint lines that are small enough
  643. // to use the hardware DDA:
  644. if (bHardwareLine(ppdev, pptfxFirst, pptfxBuf))
  645. goto Next_Line;
  646. }
  647. if ((LONG) M0 > (LONG) dM)
  648. {
  649. // Ensure that we run left-to-right:
  650. register ULONG ulTmp;
  651. SWAPL(M0, dM, ulTmp);
  652. SWAPL(N0, dN, ulTmp);
  653. fl |= FL_FLIP_H;
  654. }
  655. // Compute the delta dx. The DDI says we can never have a valid delta
  656. // with a magnitued more than 2^31 - 1, but GDI never actually checks
  657. // its transforms. So we have to check for this case to avoid overflow:
  658. dM -= M0;
  659. if ((LONG) dM < 0)
  660. {
  661. goto Next_Line;
  662. }
  663. if ((LONG) dN < (LONG) N0)
  664. {
  665. // Line runs from bottom to top, so flip across y = 0:
  666. N0 = -(LONG) N0;
  667. dN = -(LONG) dN;
  668. fl |= FL_FLIP_V;
  669. }
  670. dN -= N0;
  671. if ((LONG) dN < 0)
  672. {
  673. goto Next_Line;
  674. }
  675. // We now have a line running left-to-right, top-to-bottom from (M0, N0)
  676. // to (M0 + dM, N0 + dN):
  677. if (dN >= dM)
  678. {
  679. if (dN == dM)
  680. {
  681. // Have to special case slopes of one:
  682. fl |= FL_FLIP_SLOPE_ONE;
  683. }
  684. else
  685. {
  686. // Since line has slope greater than 1, flip across x = y:
  687. register ULONG ulTmp;
  688. SWAPL(dM, dN, ulTmp);
  689. SWAPL(M0, N0, ulTmp);
  690. fl |= FL_FLIP_D;
  691. }
  692. }
  693. fl |= gaflRound[(fl & FL_ROUND_MASK) >> FL_ROUND_SHIFT];
  694. x = LFLOOR((LONG) M0);
  695. y = LFLOOR((LONG) N0);
  696. M0 = FXFRAC(M0);
  697. N0 = FXFRAC(N0);
  698. // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]:
  699. llGamma = UInt32x32To64(dM, N0 + F/2) - UInt32x32To64(M0, dN);
  700. if (fl & FL_V_ROUND_DOWN) // Adjust so y = 1/2 rounds down
  701. {
  702. llGamma--;
  703. }
  704. llGamma >>= FLOG2;
  705. llBeta = ~llGamma;
  706. /***********************************************************************\
  707. * Figure out which pixels are at the ends of the line. *
  708. \***********************************************************************/
  709. // The toughest part of GIQ is determining the start and end pels.
  710. //
  711. // Our approach here is to calculate x0 and x1 (the inclusive start
  712. // and end columns of the line respectively, relative to our normalized
  713. // origin). Then x1 - x0 + 1 is the number of pels in the line. The
  714. // start point is easily calculated by plugging x0 into our line equation
  715. // (which takes care of whether y = 1/2 rounds up or down in value)
  716. // getting y0, and then undoing the normalizing flips to get back
  717. // into device space.
  718. //
  719. // We look at the fractional parts of the coordinates of the start and
  720. // end points, and call them (M0, N0) and (M1, N1) respectively, where
  721. // 0 <= M0, N0, M1, N1 < 16. We plot (M0, N0) on the following grid
  722. // to determine x0:
  723. //
  724. // +-----------------------> +x
  725. // |
  726. // | 0 1
  727. // | 0123456789abcdef
  728. // |
  729. // | 0 ........?xxxxxxx
  730. // | 1 ..........xxxxxx
  731. // | 2 ...........xxxxx
  732. // | 3 ............xxxx
  733. // | 4 .............xxx
  734. // | 5 ..............xx
  735. // | 6 ...............x
  736. // | 7 ................
  737. // | 8 ................
  738. // | 9 ......**........
  739. // | a ........****...x
  740. // | b ............****
  741. // | c .............xxx****
  742. // | d ............xxxx ****
  743. // | e ...........xxxxx ****
  744. // | f ..........xxxxxx
  745. // |
  746. // | 2 3
  747. // v
  748. //
  749. // +y
  750. //
  751. // This grid accounts for the appropriate rounding of GIQ and last-pel
  752. // exclusion. If (M0, N0) lands on an 'x', x0 = 2. If (M0, N0) lands
  753. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  754. // depending on what flips have been done to normalize the line.
  755. //
  756. // For the end point, if (M1, N1) lands on an 'x', x1 =
  757. // floor((M0 + dM) / 16) + 1. If (M1, N1) lands on a '.', x1 =
  758. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  759. // depending on what flips have been done to normalize the line.
  760. //
  761. // Lines of exactly slope one require a special case for both the start
  762. // and end. For example, if the line ends such that (M1, N1) is (9, 1),
  763. // the line has gone exactly through (8, 0) -- which may be considered
  764. // to be part of 'x' because of rounding! So slopes of exactly slope
  765. // one going through (8, 0) must also be considered as belonging in 'x'.
  766. //
  767. // For lines that go left-to-right, we have the following grid:
  768. //
  769. // +-----------------------> +x
  770. // |
  771. // | 0 1
  772. // | 0123456789abcdef
  773. // |
  774. // | 0 xxxxxxxx?.......
  775. // | 1 xxxxxxx.........
  776. // | 2 xxxxxx..........
  777. // | 3 xxxxx...........
  778. // | 4 xxxx............
  779. // | 5 xxx.............
  780. // | 6 xx..............
  781. // | 7 x...............
  782. // | 8 x...............
  783. // | 9 x.....**........
  784. // | a xx......****....
  785. // | b xxx.........****
  786. // | c xxxx............****
  787. // | d xxxxx........... ****
  788. // | e xxxxxx.......... ****
  789. // | f xxxxxxx.........
  790. // |
  791. // | 2 3
  792. // v
  793. //
  794. // +y
  795. //
  796. // This grid accounts for the appropriate rounding of GIQ and last-pel
  797. // exclusion. If (M0, N0) lands on an 'x', x0 = 0. If (M0, N0) lands
  798. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  799. // depending on what flips have been done to normalize the line.
  800. //
  801. // For the end point, if (M1, N1) lands on an 'x', x1 =
  802. // floor((M0 + dM) / 16) - 1. If (M1, N1) lands on a '.', x1 =
  803. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  804. // depending on what flips have been done to normalize the line.
  805. //
  806. // Lines of exactly slope one must be handled similarly to the right-to-
  807. // left case.
  808. {
  809. // Calculate x0, x1
  810. ULONG N1 = FXFRAC(N0 + dN);
  811. ULONG M1 = FXFRAC(M0 + dM);
  812. x1 = LFLOOR(M0 + dM);
  813. if (fl & FL_LAST_PEL_INCLUSIVE)
  814. {
  815. // It sure is easy to compute the first pel when lines have only
  816. // integer coordinates and are last-pel inclusive:
  817. x0 = 0;
  818. y0 = 0;
  819. // Last-pel inclusive lines that are exactly one pixel long
  820. // have a 'delta-x' and 'delta-y' equal to zero. The problem is
  821. // that our clip code assumes that 'delta-x' is always non-zero
  822. // (since it never happens with last-pel exclusive lines). As
  823. // an inelegant solution, we simply modify 'delta-x' in this
  824. // case -- because the line is exactly one pixel long, changing
  825. // the slope will obviously have no effect on rasterization.
  826. if (x1 == 0)
  827. {
  828. dM = 1;
  829. llGamma = 0;
  830. llBeta = ~llGamma;
  831. }
  832. }
  833. else
  834. {
  835. if (fl & FL_FLIP_H)
  836. {
  837. // ---------------------------------------------------------------
  838. // Line runs right-to-left: <----
  839. // Compute x1:
  840. if (N1 == 0)
  841. {
  842. if (LROUND(M1, fl & FL_H_ROUND_DOWN))
  843. {
  844. x1++;
  845. }
  846. }
  847. else if (abs((LONG) (N1 - F/2)) + M1 > F)
  848. {
  849. x1++;
  850. }
  851. if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  852. == (FL_FLIP_SLOPE_ONE))
  853. {
  854. // Have to special-case diagonal lines going through our
  855. // the point exactly equidistant between two horizontal
  856. // pixels, if we're supposed to round x=1/2 down:
  857. if ((N1 > 0) && (M1 == N1 + 8))
  858. x1++;
  859. // Don't you love special cases? Is this a rhetorical question?
  860. if ((N0 > 0) && (M0 == N0 + 8))
  861. {
  862. x0 = 2;
  863. ulDelta = dN;
  864. goto right_to_left_compute_y0;
  865. }
  866. }
  867. // Compute x0:
  868. x0 = 1;
  869. ulDelta = 0;
  870. if (N0 == 0)
  871. {
  872. if (LROUND(M0, fl & FL_H_ROUND_DOWN))
  873. {
  874. x0 = 2;
  875. ulDelta = dN;
  876. }
  877. }
  878. else if (abs((LONG) (N0 - F/2)) + M0 > F)
  879. {
  880. x0 = 2;
  881. ulDelta = dN;
  882. }
  883. // Compute y0:
  884. right_to_left_compute_y0:
  885. y0 = 0;
  886. ll = llGamma + (LONGLONG) ulDelta;
  887. if (ll >= (LONGLONG) (2 * dM - dN))
  888. y0 = 2;
  889. else if (ll >= (LONGLONG) (dM - dN))
  890. y0 = 1;
  891. }
  892. else
  893. {
  894. // ---------------------------------------------------------------
  895. // Line runs left-to-right: ---->
  896. // Compute x1:
  897. if (!(fl & FL_LAST_PEL_INCLUSIVE))
  898. x1--;
  899. if (M1 > 0)
  900. {
  901. if (N1 == 0)
  902. {
  903. if (LROUND(M1, fl & FL_H_ROUND_DOWN))
  904. x1++;
  905. }
  906. else if (abs((LONG) (N1 - F/2)) <= (LONG) M1)
  907. {
  908. x1++;
  909. }
  910. }
  911. if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  912. == (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  913. {
  914. // Have to special-case diagonal lines going through our
  915. // the point exactly equidistant between two horizontal
  916. // pixels, if we're supposed to round x=1/2 down:
  917. if ((M1 > 0) && (N1 == M1 + 8))
  918. x1--;
  919. if ((M0 > 0) && (N0 == M0 + 8))
  920. {
  921. x0 = 0;
  922. goto left_to_right_compute_y0;
  923. }
  924. }
  925. // Compute x0:
  926. x0 = 0;
  927. if (M0 > 0)
  928. {
  929. if (N0 == 0)
  930. {
  931. if (LROUND(M0, fl & FL_H_ROUND_DOWN))
  932. x0 = 1;
  933. }
  934. else if (abs((LONG) (N0 - F/2)) <= (LONG) M0)
  935. {
  936. x0 = 1;
  937. }
  938. }
  939. // Compute y0:
  940. left_to_right_compute_y0:
  941. y0 = 0;
  942. if (llGamma >= (LONGLONG) (dM - (dN & (-(LONG) x0))))
  943. {
  944. y0 = 1;
  945. }
  946. }
  947. }
  948. }
  949. cStylePels = x1 - x0 + 1;
  950. if ((LONG) cStylePels <= 0)
  951. goto Next_Line;
  952. xStart = x0;
  953. /***********************************************************************\
  954. * Complex clipping. *
  955. \***********************************************************************/
  956. if (fl & FL_COMPLEX_CLIP)
  957. {
  958. dN_Original = dN;
  959. Continue_Complex_Clipping:
  960. if (fl & FL_FLIP_H)
  961. {
  962. // Line runs right-to-left <-----
  963. x0 = xStart + cStylePels - prun->iStop - 1;
  964. x1 = xStart + cStylePels - prun->iStart - 1;
  965. }
  966. else
  967. {
  968. // Line runs left-to-right ----->
  969. x0 = xStart + prun->iStart;
  970. x1 = xStart + prun->iStop;
  971. }
  972. prun++;
  973. // Reset some variables we'll nuke a little later:
  974. dN = dN_Original;
  975. pls->spNext = pls->spComplex;
  976. // No overflow since large integer math is used. Both values
  977. // will be positive:
  978. dl = UInt32x32To64(x0, dN) + llGamma;
  979. // y0 = dl / dM:
  980. y0 = UInt64Div32To32(dl, dM);
  981. ASSERTDD((LONG) y0 >= 0, "y0 weird: Goofed up end pel calc?");
  982. }
  983. /***********************************************************************\
  984. * Simple rectangular clipping. *
  985. \***********************************************************************/
  986. if (fl & FL_SIMPLE_CLIP)
  987. {
  988. ULONG y1;
  989. LONG xRight;
  990. LONG xLeft;
  991. LONG yBottom;
  992. LONG yTop;
  993. // Note that y0 and y1 are actually the lower and upper bounds,
  994. // respectively, of the y coordinates of the line (the line may
  995. // have actually shrunk due to first/last pel clipping).
  996. //
  997. // Also note that x0, y0 are not necessarily zero.
  998. RECTL* prcl = &prclClip[(fl & FL_RECTLCLIP_MASK) >>
  999. FL_RECTLCLIP_SHIFT];
  1000. // Normalize to the same point we've normalized for the DDA
  1001. // calculations:
  1002. xRight = prcl->right - x;
  1003. xLeft = prcl->left - x;
  1004. yBottom = prcl->bottom - y;
  1005. yTop = prcl->top - y;
  1006. if (yBottom <= (LONG) y0 ||
  1007. xRight <= (LONG) x0 ||
  1008. xLeft > (LONG) x1)
  1009. {
  1010. Totally_Clipped:
  1011. if (fl & FL_STYLED)
  1012. {
  1013. pls->spNext += cStylePels;
  1014. if (pls->spNext >= pls->spTotal2)
  1015. pls->spNext %= pls->spTotal2;
  1016. }
  1017. goto Next_Line;
  1018. }
  1019. if ((LONG) x1 >= xRight)
  1020. x1 = xRight - 1;
  1021. // We have to know the correct y1, which we haven't bothered to
  1022. // calculate up until now. This multiply and divide is quite
  1023. // expensive; we could replace it with code similar to that which
  1024. // we used for computing y0.
  1025. //
  1026. // The reason why we need the actual value, and not an upper
  1027. // bounds guess like y1 = LFLOOR(dM) + 2 is that we have to be
  1028. // careful when calculating x(y) that y0 <= y <= y1, otherwise
  1029. // we can overflow on the divide (which, needless to say, is very
  1030. // bad).
  1031. dl = UInt32x32To64(x1, dN) + llGamma;
  1032. // y1 = dl / dM:
  1033. y1 = UInt64Div32To32(dl, dM);
  1034. if (yTop > (LONG) y1)
  1035. goto Totally_Clipped;
  1036. if (yBottom <= (LONG) y1)
  1037. {
  1038. y1 = yBottom;
  1039. dl = UInt32x32To64(y1, dM) + llBeta;
  1040. // x1 = dl / dN:
  1041. x1 = UInt64Div32To32(dl, dN);
  1042. }
  1043. // At this point, we've taken care of calculating the intercepts
  1044. // with the right and bottom edges. Now we work on the left and
  1045. // top edges:
  1046. if (xLeft > (LONG) x0)
  1047. {
  1048. x0 = xLeft;
  1049. dl = UInt32x32To64(x0, dN) + llGamma;
  1050. // y0 = dl / dM;
  1051. y0 = UInt64Div32To32(dl, dM);
  1052. if (yBottom <= (LONG) y0)
  1053. goto Totally_Clipped;
  1054. }
  1055. if (yTop > (LONG) y0)
  1056. {
  1057. y0 = yTop;
  1058. dl = UInt32x32To64(y0, dM) + llBeta;
  1059. // x0 = dl / dN + 1;
  1060. x0 = UInt64Div32To32(dl, dN) + 1;
  1061. if (xRight <= (LONG) x0)
  1062. goto Totally_Clipped;
  1063. }
  1064. ASSERTDD(x0 <= x1, "Improper rectangle clip");
  1065. }
  1066. /***********************************************************************\
  1067. * Done clipping. Unflip if necessary. *
  1068. \***********************************************************************/
  1069. ptlStart.x = x + x0;
  1070. ptlStart.y = y + y0;
  1071. if (fl & FL_FLIP_D)
  1072. {
  1073. register LONG lTmp;
  1074. SWAPL(ptlStart.x, ptlStart.y, lTmp);
  1075. }
  1076. if (fl & FL_FLIP_V)
  1077. {
  1078. ptlStart.y = -ptlStart.y;
  1079. }
  1080. cPels = x1 - x0 + 1;
  1081. /***********************************************************************\
  1082. * Style calculations. *
  1083. \***********************************************************************/
  1084. if (fl & FL_STYLED)
  1085. {
  1086. STYLEPOS sp;
  1087. spThis = pls->spNext;
  1088. pls->spNext += cStylePels;
  1089. {
  1090. if (pls->spNext >= pls->spTotal2)
  1091. pls->spNext %= pls->spTotal2;
  1092. if (fl & FL_FLIP_H)
  1093. sp = pls->spNext - x0 + xStart;
  1094. else
  1095. sp = spThis + x0 - xStart;
  1096. ASSERTDD(fl & FL_STYLED, "Oops");
  1097. // Normalize our target style position:
  1098. if ((sp < 0) || (sp >= pls->spTotal2))
  1099. {
  1100. sp %= pls->spTotal2;
  1101. // The modulus of a negative number is not well-defined
  1102. // in C -- if it's negative we'll adjust it so that it's
  1103. // back in the range [0, spTotal2):
  1104. if (sp < 0)
  1105. sp += pls->spTotal2;
  1106. }
  1107. // Since we always draw the line left-to-right, but styling is
  1108. // always done in the direction of the original line, we have
  1109. // to figure out where we are in the style array for the left
  1110. // edge of this line.
  1111. if (fl & FL_FLIP_H)
  1112. {
  1113. // Line originally ran right-to-left:
  1114. sp = -sp;
  1115. if (sp < 0)
  1116. sp += pls->spTotal2;
  1117. pls->ulStyleMask = ~pls->ulStartMask;
  1118. pls->pspStart = &pls->aspRtoL[0];
  1119. pls->pspEnd = &pls->aspRtoL[pls->cStyle - 1];
  1120. }
  1121. else
  1122. {
  1123. // Line originally ran left-to-right:
  1124. pls->ulStyleMask = pls->ulStartMask;
  1125. pls->pspStart = &pls->aspLtoR[0];
  1126. pls->pspEnd = &pls->aspLtoR[pls->cStyle - 1];
  1127. }
  1128. if (sp >= pls->spTotal)
  1129. {
  1130. sp -= pls->spTotal;
  1131. if (pls->cStyle & 1)
  1132. pls->ulStyleMask = ~pls->ulStyleMask;
  1133. }
  1134. pls->psp = pls->pspStart;
  1135. while (sp >= *pls->psp)
  1136. sp -= *pls->psp++;
  1137. ASSERTDD(pls->psp <= pls->pspEnd,
  1138. "Flew off into NeverNeverLand");
  1139. pls->spRemaining = *pls->psp - sp;
  1140. if ((pls->psp - pls->pspStart) & 1)
  1141. pls->ulStyleMask = ~pls->ulStyleMask;
  1142. }
  1143. }
  1144. plStrip = &strip.alStrips[0];
  1145. plStripEnd = &strip.alStrips[STRIP_MAX]; // Is exclusive
  1146. cStripsInNextRun = 0x7fffffff;
  1147. strip.ptlStart = ptlStart;
  1148. if (2 * dN > dM &&
  1149. !(fl & FL_STYLED))
  1150. {
  1151. // Do a half flip! Remember that we may doing this on the
  1152. // same line multiple times for complex clipping (meaning the
  1153. // affected variables should be reset for every clip run):
  1154. fl |= FL_FLIP_HALF;
  1155. llBeta = llGamma - (LONGLONG) ((LONG) dM);
  1156. dN = dM - dN;
  1157. y0 = x0 - y0; // Note this may overflow, but that's okay
  1158. }
  1159. // Now, run the DDA starting at (ptlStart.x, ptlStart.y)!
  1160. strip.flFlips = fl;
  1161. pfn = apfn[(fl & FL_STRIP_MASK) >> FL_STRIP_SHIFT];
  1162. // Now calculate the DDA variables needed to figure out how many pixels
  1163. // go in the very first strip:
  1164. {
  1165. register LONG i;
  1166. register ULONG dI;
  1167. register ULONG dR;
  1168. ULONG r;
  1169. if (dN == 0)
  1170. i = 0x7fffffff;
  1171. else
  1172. {
  1173. dl = UInt32x32To64(y0 + 1, dM) + llBeta;
  1174. ASSERTDD(dl >= 0, "Oops!");
  1175. // i = (dl / dN) - x0 + 1;
  1176. // r = (dl % dN);
  1177. i = UInt64Div32To32(dl, dN);
  1178. r = UInt64Mod32To32(dl, dN);
  1179. i = i - x0 + 1;
  1180. dI = dM / dN;
  1181. dR = dM % dN; // 0 <= dR < dN
  1182. ASSERTDD(dI > 0, "Weird dI");
  1183. }
  1184. ASSERTDD(i > 0 && i <= 0x7fffffff, "Weird initial strip length");
  1185. ASSERTDD(cPels > 0, "Zero pel line");
  1186. /***********************************************************************\
  1187. * Run the DDA! *
  1188. \***********************************************************************/
  1189. while(TRUE)
  1190. {
  1191. cPels -= i;
  1192. if (cPels <= 0)
  1193. break;
  1194. *plStrip++ = i;
  1195. if (plStrip == plStripEnd)
  1196. {
  1197. strip.cStrips = (LONG)(plStrip - &strip.alStrips[0]);
  1198. (*pfn)(ppdev, &strip, pls);
  1199. plStrip = &strip.alStrips[0];
  1200. }
  1201. i = dI;
  1202. r += dR;
  1203. if (r >= dN)
  1204. {
  1205. r -= dN;
  1206. i++;
  1207. }
  1208. }
  1209. *plStrip++ = cPels + i;
  1210. strip.cStrips = (LONG)(plStrip - &strip.alStrips[0]);
  1211. (*pfn)(ppdev, &strip, pls);
  1212. }
  1213. Next_Line:
  1214. if (fl & FL_COMPLEX_CLIP)
  1215. {
  1216. cptfx--;
  1217. if (cptfx != 0)
  1218. goto Continue_Complex_Clipping;
  1219. break;
  1220. }
  1221. else
  1222. {
  1223. pptfxFirst = pptfxBuf;
  1224. pptfxBuf++;
  1225. }
  1226. } while (pptfxBuf < pptfxBufEnd);
  1227. return(TRUE);
  1228. }
  1229. //////////////////////////////////////////////////////////////////////////
  1230. // General defines for bHardwareLine
  1231. #define HW_FLIP_D 0x0001L // Diagonal flip
  1232. #define HW_FLIP_V 0x0002L // Vertical flip
  1233. #define HW_FLIP_H 0x0004L // Horizontal flip
  1234. #define HW_FLIP_SLOPE_ONE 0x0008L // Normalized line has exactly slope one
  1235. #define HW_FLIP_MASK (HW_FLIP_D | HW_FLIP_V | HW_FLIP_H)
  1236. #define HW_X_ROUND_DOWN 0x0100L // x = 1/2 rounds down in value
  1237. #define HW_Y_ROUND_DOWN 0x0200L // y = 1/2 rounds down in value
  1238. LONG gaiDir[] = { 0, 1, 7, 6, 3, 2, 4, 5 };
  1239. FLONG gaflHardwareRound[] = {
  1240. HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN, // | | |
  1241. HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN, // | | | FLIP_D
  1242. HW_X_ROUND_DOWN, // | | FLIP_V |
  1243. HW_Y_ROUND_DOWN, // | | FLIP_V | FLIP_D
  1244. HW_Y_ROUND_DOWN, // | FLIP_H | |
  1245. HW_X_ROUND_DOWN, // | FLIP_H | | FLIP_D
  1246. 0, // | FLIP_H | FLIP_V |
  1247. 0, // | FLIP_H | FLIP_V | FLIP_D
  1248. HW_Y_ROUND_DOWN, // SLOPE_ONE | | |
  1249. 0xffffffff, // SLOPE_ONE | | | FLIP_D
  1250. HW_X_ROUND_DOWN, // SLOPE_ONE | | FLIP_V |
  1251. 0xffffffff, // SLOPE_ONE | | FLIP_V | FLIP_D
  1252. HW_Y_ROUND_DOWN, // SLOPE_ONE | FLIP_H | |
  1253. 0xffffffff, // SLOPE_ONE | FLIP_H | | FLIP_D
  1254. HW_X_ROUND_DOWN, // SLOPE_ONE | FLIP_H | FLIP_V |
  1255. 0xffffffff // SLOPE_ONE | FLIP_H | FLIP_V | FLIP_D
  1256. };
  1257. //////////////////////////////////////////////////////////////////////////
  1258. // S3 specific defines
  1259. #define DEFAULT_DRAW_CMD (DRAW_LINE | DRAW | DIR_TYPE_XY | MULTIPLE_PIXELS | \
  1260. WRITE | LAST_PIXEL_OFF)
  1261. LONG gaiDrawCmd[] = {
  1262. DEFAULT_DRAW_CMD | PLUS_X | PLUS_Y | 0, // Octant 0
  1263. DEFAULT_DRAW_CMD | PLUS_X | PLUS_Y | MAJOR_Y, // Octant 1
  1264. DEFAULT_DRAW_CMD | PLUS_X | 0 | 0, // Octant 7
  1265. DEFAULT_DRAW_CMD | PLUS_X | 0 | MAJOR_Y, // Octant 6
  1266. DEFAULT_DRAW_CMD | 0 | PLUS_Y | 0, // Octant 3
  1267. DEFAULT_DRAW_CMD | 0 | PLUS_Y | MAJOR_Y, // Octant 2
  1268. DEFAULT_DRAW_CMD | 0 | 0 | 0, // Octant 4
  1269. DEFAULT_DRAW_CMD | 0 | 0 | MAJOR_Y, // Octant 5
  1270. };
  1271. // The S3's hardware can have 13 bits of significance for the error and
  1272. // step terms:
  1273. #define NUM_DDA_BITS 13
  1274. /******************************Public*Routine******************************\
  1275. * BOOL bHardwareLine(ppdev, pptfxStart, pptfxEnd)
  1276. *
  1277. * This routine is useful for folks who have line drawing hardware where
  1278. * they can explicitly set the Bresenham terms -- they can use this routine
  1279. * to draw fractional coordinate GIQ lines with the hardware.
  1280. *
  1281. * Fractional coordinate lines require an extra 4 bits of precision in the
  1282. * Bresenham terms. For example, if your hardware has 13 bits of precision
  1283. * for the terms, you can only draw GIQ lines up to 255 pels long using this
  1284. * routine.
  1285. *
  1286. * Input:
  1287. * pptfxStart - Points to GIQ coordinate of start of line
  1288. * pptfxEnd - Points to GIQ coordinate of end of line
  1289. * NUM_DDA_BITS- The number of bits of precision your hardware can support.
  1290. *
  1291. * Output:
  1292. * returns - TRUE if the line was drawn.
  1293. * FALSE if the line is too long, and the strips code must be
  1294. * used.
  1295. *
  1296. * DDALINE:
  1297. * iDir - Direction of the line, as an octant numbered as follows:
  1298. *
  1299. * \ 5 | 6 /
  1300. * \ | /
  1301. * 4 \ | / 7
  1302. * \ /
  1303. * -----+-----
  1304. * /|\
  1305. * 3 / | \ 0
  1306. * / | \
  1307. * / 2 | 1 \
  1308. *
  1309. * ptlStart - Start pixel of line.
  1310. * cPels - # of pels in line. *NOTE* You must check if this is <= 0!
  1311. * dMajor - Major axis delta.
  1312. * dMinor - Minor axis delta.
  1313. * lErrorTerm - Error term.
  1314. *
  1315. * What you do with the last 3 terms may be a little tricky. They are
  1316. * actually the terms for the formula of the normalized line
  1317. *
  1318. * dMinor * x + (lErrorTerm + dMajor)
  1319. * y(x) = floor( ---------------------------------- )
  1320. * dMajor
  1321. *
  1322. * where y(x) is the y coordinate of the pixel to be lit as a function of
  1323. * the x-coordinate.
  1324. *
  1325. * Every time the line advances one in the major direction 'x', dMinor
  1326. * gets added to the current error term. If the resulting value is >= 0,
  1327. * we know we have to move one pixel in the minor direction 'y', and
  1328. * dMajor must be subtracted from the current error term.
  1329. *
  1330. * If you're trying to figure out what this means for your hardware, you can
  1331. * think of the DDALINE terms as having been computed equivalently as
  1332. * follows:
  1333. *
  1334. * dMinor = 2 * (minor axis delta)
  1335. * dMajor = 2 * (major axis delta)
  1336. * lErrorTerm = - (major axis delta) - fixup
  1337. *
  1338. * That is, if your documentation tells you that for integer lines, a
  1339. * register is supposed to be initialized with the value
  1340. * '2 * (minor axis delta)', you'll actually use dMinor.
  1341. *
  1342. * Example: Setting up the 8514
  1343. *
  1344. * AXSTPSIGN is supposed to be the axial step constant register, defined
  1345. * as 2 * (minor axis delta). You set:
  1346. *
  1347. * AXSTPSIGN = dMinor
  1348. *
  1349. * DGSTPSIGN is supposed to be the diagonal step constant register,
  1350. * defined as 2 * (minor axis delta) - 2 * (major axis delta). You set:
  1351. *
  1352. * DGSTPSIGN = dMinor - dMajor
  1353. *
  1354. * ERR_TERM is supposed to be the adjusted error term, defined as
  1355. * 2 * (minor axis delta) - (major axis delta) - fixup. You set:
  1356. *
  1357. * ERR_TERM = lErrorTerm + dMinor
  1358. *
  1359. * Implementation:
  1360. *
  1361. * You'll want to special case integer lines before calling this routine
  1362. * (since they're very common, take less time to the computation of line
  1363. * terms, and can handle longer lines than this routine because 4 bits
  1364. * aren't being given to the fraction).
  1365. *
  1366. * If a GIQ line is too long to be handled by this routine, you can just
  1367. * use the slower strip routines for that line. Note that you cannot
  1368. * just fail the call -- you must be able to accurately draw any line
  1369. * in the 28.4 device space when it intersects the viewport.
  1370. *
  1371. * Testing:
  1372. *
  1373. * Use Guiman, or some other test that draws random fractional coordinate
  1374. * lines and compares them to what GDI itself draws to a bitmap.
  1375. *
  1376. \**************************************************************************/
  1377. BOOL bHardwareLine(
  1378. PDEV* ppdev,
  1379. POINTFIX* pptfxStart, // Start of line
  1380. POINTFIX* pptfxEnd) // End of line
  1381. {
  1382. FLONG fl; // Various flags
  1383. ULONG M0; // Normalized fractional unit x start coordinate (0 <= M0 < F)
  1384. ULONG N0; // Normalized fractional unit y start coordinate (0 <= N0 < F)
  1385. ULONG M1; // Normalized fractional unit x end coordinate (0 <= M1 < F)
  1386. ULONG N1; // Normalized fractional unit x end coordinate (0 <= N1 < F)
  1387. ULONG dM; // Normalized fractional unit x-delta (0 <= dM)
  1388. ULONG dN; // Normalized fractional unit y-delta (0 <= dN <= dM)
  1389. LONG x; // Normalized x coordinate of origin
  1390. LONG y; // Normalized y coordinate of origin
  1391. LONG x0; // Normalized x offset from origin to start pixel (inclusive)
  1392. LONG y0; // Normalized y offset from origin to start pixel (inclusive)
  1393. LONG x1; // Normalized x offset from origin to end pixel (inclusive)
  1394. LONG lGamma;// Bresenham error term at origin
  1395. LONG cPels; // Number of pixels in line
  1396. /***********************************************************************\
  1397. * Normalize line to the first octant.
  1398. \***********************************************************************/
  1399. fl = 0;
  1400. M0 = pptfxStart->x;
  1401. dM = pptfxEnd->x;
  1402. if ((LONG) dM < (LONG) M0)
  1403. {
  1404. // Line runs from right to left, so flip across x = 0:
  1405. M0 = -(LONG) M0;
  1406. dM = -(LONG) dM;
  1407. fl |= HW_FLIP_H;
  1408. }
  1409. // Compute the delta. The DDI says we can never have a valid delta
  1410. // with a magnitude more than 2^31 - 1, but the engine never actually
  1411. // checks its transforms. So we check for that case and simply refuse
  1412. // to draw the line:
  1413. dM -= M0;
  1414. if ((LONG) dM < 0)
  1415. return(FALSE);
  1416. N0 = pptfxStart->y;
  1417. dN = pptfxEnd->y;
  1418. if ((LONG) dN < (LONG) N0)
  1419. {
  1420. // Line runs from bottom to top, so flip across y = 0:
  1421. N0 = -(LONG) N0;
  1422. dN = -(LONG) dN;
  1423. fl |= HW_FLIP_V;
  1424. }
  1425. // Compute another delta:
  1426. dN -= N0;
  1427. if ((LONG) dN < 0)
  1428. return(FALSE);
  1429. if (dN >= dM)
  1430. {
  1431. if (dN == dM)
  1432. {
  1433. // Have to special case slopes of one:
  1434. fl |= HW_FLIP_SLOPE_ONE;
  1435. }
  1436. else
  1437. {
  1438. // Since line has slope greater than 1, flip across x = y:
  1439. register ULONG ulTmp;
  1440. ulTmp = dM; dM = dN; dN = ulTmp;
  1441. ulTmp = M0; M0 = N0; N0 = ulTmp;
  1442. fl |= HW_FLIP_D;
  1443. }
  1444. }
  1445. // Figure out if we can do the line in hardware, given that we have a
  1446. // limited number of bits of precision for the Bresenham terms.
  1447. //
  1448. // Remember that one bit has to be kept as a sign bit:
  1449. if ((LONG) dM >= (1L << (NUM_DDA_BITS - 1)))
  1450. return(FALSE);
  1451. fl |= gaflHardwareRound[fl];
  1452. /***********************************************************************\
  1453. * Calculate the error term at pixel 0.
  1454. \***********************************************************************/
  1455. x = LFLOOR((LONG) M0);
  1456. y = LFLOOR((LONG) N0);
  1457. M0 = FXFRAC(M0);
  1458. N0 = FXFRAC(N0);
  1459. // NOTE NOTE NOTE: If this routine were to handle any line in the 28.4
  1460. // space, it will overflow its math (the following part requires 36 bits
  1461. // of precision)! But we get here for lines that the hardware can handle
  1462. // (see the expression (dM >= (1L << (NUM_DDA_BITS - 1))) above?), so if
  1463. // cBits is less than 28, we're safe.
  1464. //
  1465. // If you're going to use this routine to handle all lines in the 28.4
  1466. // device space, you will HAVE to make sure the math doesn't overflow,
  1467. // otherwise you won't be NT compliant! (See 'bHardwareLine' for an example
  1468. // how to do that. You don't have to worry about this if you simply
  1469. // default to the strips code for long lines, because those routines
  1470. // already do the math correctly.)
  1471. // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]. Note
  1472. // that M0 and N0 have at most 4 bits of significance (and if the
  1473. // arguments are properly ordered, on a 486 each multiply would be no
  1474. // more than 13 cycles):
  1475. lGamma = (N0 + F/2) * dM - M0 * dN;
  1476. if (fl & HW_Y_ROUND_DOWN)
  1477. lGamma--;
  1478. lGamma >>= FLOG2;
  1479. /***********************************************************************\
  1480. * Figure out which pixels are at the ends of the line.
  1481. \***********************************************************************/
  1482. // The toughest part of GIQ is determining the start and end pels.
  1483. //
  1484. // Our approach here is to calculate x0 and x1 (the inclusive start
  1485. // and end columns of the line respectively, relative to our normalized
  1486. // origin). Then x1 - x0 + 1 is the number of pels in the line. The
  1487. // start point is easily calculated by plugging x0 into our line equation
  1488. // (which takes care of whether y = 1/2 rounds up or down in value)
  1489. // getting y0, and then undoing the normalizing flips to get back
  1490. // into device space.
  1491. //
  1492. // We look at the fractional parts of the coordinates of the start and
  1493. // end points, and call them (M0, N0) and (M1, N1) respectively, where
  1494. // 0 <= M0, N0, M1, N1 < 16. We plot (M0, N0) on the following grid
  1495. // to determine x0:
  1496. //
  1497. // +-----------------------> +x
  1498. // |
  1499. // | 0 1
  1500. // | 0123456789abcdef
  1501. // |
  1502. // | 0 ........?xxxxxxx
  1503. // | 1 ..........xxxxxx
  1504. // | 2 ...........xxxxx
  1505. // | 3 ............xxxx
  1506. // | 4 .............xxx
  1507. // | 5 ..............xx
  1508. // | 6 ...............x
  1509. // | 7 ................
  1510. // | 8 ................
  1511. // | 9 ......**........
  1512. // | a ........****...x
  1513. // | b ............****
  1514. // | c .............xxx****
  1515. // | d ............xxxx ****
  1516. // | e ...........xxxxx ****
  1517. // | f ..........xxxxxx
  1518. // |
  1519. // | 2 3
  1520. // v
  1521. //
  1522. // +y
  1523. //
  1524. // This grid accounts for the appropriate rounding of GIQ and last-pel
  1525. // exclusion. If (M0, N0) lands on an 'x', x0 = 2. If (M0, N0) lands
  1526. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  1527. // depending on what flips have been done to normalize the line.
  1528. //
  1529. // For the end point, if (M1, N1) lands on an 'x', x1 =
  1530. // floor((M0 + dM) / 16) + 1. If (M1, N1) lands on a '.', x1 =
  1531. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  1532. // depending on what flips have been done to normalize the line.
  1533. //
  1534. // Lines of exactly slope one require a special case for both the start
  1535. // and end. For example, if the line ends such that (M1, N1) is (9, 1),
  1536. // the line has gone exactly through (8, 0) -- which may be considered
  1537. // to be part of 'x' because of rounding! So slopes of exactly slope
  1538. // one going through (8, 0) must also be considered as belonging in 'x'
  1539. // when an x value of 1/2 is supposed to round up in value.
  1540. // Calculate x0, x1:
  1541. N1 = FXFRAC(N0 + dN);
  1542. M1 = FXFRAC(M0 + dM);
  1543. x1 = LFLOOR(M0 + dM);
  1544. // Line runs left-to-right:
  1545. // Compute x1:
  1546. x1--;
  1547. if (M1 > 0)
  1548. {
  1549. if (N1 == 0)
  1550. {
  1551. if (LROUND(M1, fl & HW_X_ROUND_DOWN))
  1552. x1++;
  1553. }
  1554. else if (abs((LONG) (N1 - F/2)) <= (LONG) M1)
  1555. {
  1556. x1++;
  1557. }
  1558. }
  1559. if ((fl & (HW_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
  1560. == (HW_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
  1561. {
  1562. // Have to special-case diagonal lines going through our
  1563. // the point exactly equidistant between two horizontal
  1564. // pixels, if we're supposed to round x=1/2 down:
  1565. if ((M1 > 0) && (N1 == M1 + 8))
  1566. x1--;
  1567. if ((M0 > 0) && (N0 == M0 + 8))
  1568. {
  1569. x0 = 0;
  1570. goto left_to_right_compute_y0;
  1571. }
  1572. }
  1573. // Compute x0:
  1574. x0 = 0;
  1575. if (M0 > 0)
  1576. {
  1577. if (N0 == 0)
  1578. {
  1579. if (LROUND(M0, fl & HW_X_ROUND_DOWN))
  1580. x0 = 1;
  1581. }
  1582. else if (abs((LONG) (N0 - F/2)) <= (LONG) M0)
  1583. {
  1584. x0 = 1;
  1585. }
  1586. }
  1587. left_to_right_compute_y0:
  1588. /***********************************************************************\
  1589. * Calculate the start pixel.
  1590. \***********************************************************************/
  1591. // We now compute y0 and adjust the error term. We know x0, and we know
  1592. // the current formula for the pixels to be lit on the line:
  1593. //
  1594. // dN * x + lGamma
  1595. // y(x) = floor( --------------- )
  1596. // dM
  1597. //
  1598. // The remainder of this expression is the new error term at (x0, y0).
  1599. // Since x0 is going to be either 0 or 1, we don't actually have to do a
  1600. // multiply or divide to compute y0. Finally, we subtract dM from the
  1601. // new error term so that it is in the range [-dM, 0).
  1602. y0 = 0;
  1603. lGamma += (dN & (-x0));
  1604. lGamma -= dM;
  1605. if (lGamma >= 0)
  1606. {
  1607. y0 = 1;
  1608. lGamma -= dM;
  1609. }
  1610. // Undo our flips to get the start coordinate:
  1611. x += x0;
  1612. y += y0;
  1613. if (fl & HW_FLIP_D)
  1614. {
  1615. register LONG lTmp;
  1616. lTmp = x; x = y; y = lTmp;
  1617. }
  1618. if (fl & HW_FLIP_V)
  1619. {
  1620. y = -y;
  1621. }
  1622. if (fl & HW_FLIP_H)
  1623. {
  1624. x = -x;
  1625. }
  1626. /***********************************************************************\
  1627. * Return the Bresenham terms:
  1628. \***********************************************************************/
  1629. // iDir = gaiDir[fl & HW_FLIP_MASK];
  1630. // ptlStart.x = x;
  1631. // ptlStart.y = y;
  1632. // cPels = x1 - x0 + 1; // NOTE: You'll have to check if cPels <= 0!
  1633. // dMajor = dM;
  1634. // dMinor = dN;
  1635. // lErrorTerm = lGamma;
  1636. /***********************************************************************\
  1637. * Draw the line. S3 specific code follows:
  1638. \***********************************************************************/
  1639. cPels = x1 - x0 + 1;
  1640. if (cPels > 0)
  1641. {
  1642. IO_FIFO_WAIT(ppdev, 7);
  1643. IO_CUR_X(ppdev, x);
  1644. IO_CUR_Y(ppdev, y);
  1645. IO_MAJ_AXIS_PCNT(ppdev, cPels);
  1646. IO_AXSTP(ppdev, dN);
  1647. IO_DIASTP(ppdev, dN - dM);
  1648. IO_ERR_TERM(ppdev, dN + lGamma);
  1649. IO_CMD(ppdev, gaiDrawCmd[fl & HW_FLIP_MASK]);
  1650. }
  1651. return(TRUE);
  1652. }
  1653. /*******************************Public*Table*******************************\
  1654. * gapfnStrip
  1655. *
  1656. * Look-up table for DrvStrokePath to find which strip routines to call.
  1657. *
  1658. \**************************************************************************/
  1659. VOID (*gapfnStrip[])(PDEV*, STRIP*, LINESTATE*) = {
  1660. vrlSolidHorizontal,
  1661. vrlSolidVertical,
  1662. vrlSolidDiagonalHorizontal,
  1663. vrlSolidDiagonalVertical,
  1664. // Should be NUM_STRIP_DRAW_DIRECTIONS = 4 strip drawers in every group
  1665. vssSolidHorizontal,
  1666. vssSolidVertical,
  1667. vssSolidDiagonalHorizontal,
  1668. vssSolidDiagonalVertical,
  1669. // Should be NUM_STRIP_DRAW_STYLES = 8 strip drawers in total for doing
  1670. // solid lines, and the same number for non-solid lines:
  1671. vStripStyledHorizontal,
  1672. vStripStyledVertical,
  1673. vStripStyledVertical, // Diagonal goes here
  1674. vStripStyledVertical, // Diagonal goes here
  1675. vStripStyledHorizontal,
  1676. vStripStyledVertical,
  1677. vStripStyledVertical, // Diagonal goes here
  1678. vStripStyledVertical, // Diagonal goes here
  1679. };
  1680. // Style array for alternate style (alternates one pixel on, one pixel off):
  1681. STYLEPOS gaspAlternateStyle[] = { 1 };
  1682. /******************************Public*Routine******************************\
  1683. * BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrush, pla, mix)
  1684. *
  1685. * Strokes the path.
  1686. *
  1687. \**************************************************************************/
  1688. BOOL DrvStrokePath(
  1689. SURFOBJ* pso,
  1690. PATHOBJ* ppo,
  1691. CLIPOBJ* pco,
  1692. XFORMOBJ* pxo,
  1693. BRUSHOBJ* pbo,
  1694. POINTL* pptlBrush,
  1695. LINEATTRS* pla,
  1696. MIX mix)
  1697. {
  1698. STYLEPOS aspLtoR[STYLE_MAX_COUNT];
  1699. STYLEPOS aspRtoL[STYLE_MAX_COUNT];
  1700. LINESTATE ls;
  1701. PFNSTRIP* apfn;
  1702. FLONG fl;
  1703. PDEV* ppdev;
  1704. DSURF* pdsurf;
  1705. RECTL arclClip[4]; // For rectangular clipping
  1706. BYTE* pjMmBase;
  1707. RECTL* prclClip;
  1708. ULONG ulHwMix;
  1709. RECTFX rcfxBounds;
  1710. BOOL bMore;
  1711. CLIPENUM ce;
  1712. LONG i;
  1713. ULONG iSolidColor;
  1714. LONG cFifo;
  1715. ASSERTDD(((mix >> 8) & 0xff) == (mix & 0xff),
  1716. "GDI gave us an improper mix");
  1717. pdsurf = (DSURF*) pso->dhsurf;
  1718. ASSERTDD(!(pdsurf->dt & DT_DIB), "Didn't expect DT_DIB");
  1719. // We'll be drawing to the screen or an off-screen DFB; copy the surface's
  1720. // offset now so that we won't need to refer to the DSURF again:
  1721. ppdev = (PDEV*) pso->dhpdev;
  1722. ppdev->xOffset = pdsurf->x;
  1723. ppdev->yOffset = pdsurf->y;
  1724. pjMmBase = ppdev->pjMmBase;
  1725. //////////////////////////////////////////////////////////////////////
  1726. // Special case solid integer lines:
  1727. if ((ppdev->flCaps & CAPS_POLYGON) && // S3 must be capable of polylines
  1728. (ppo->fl & PO_ALL_INTEGERS) && // Points must be integer
  1729. !(pla->fl & LA_STYLED)) // Solid lines, no styles
  1730. {
  1731. // As of NT 4.0 SP2, the rasterization convention has been loosened
  1732. // for paths that have the PO_ALL_INTEGERS flag set. For those paths,
  1733. // you may do the 'tie-breaker' pixels anyway you like, which usually
  1734. // means that you can use the point-to-point line drawing capabilities
  1735. // of the hardware.
  1736. //
  1737. // HOWEVER: Your implementation must be invariant, regardless of clipping!
  1738. // This means that if you choose to deviate from the standard NT
  1739. // line convention, you MUST draw the same thing for DC_TRIVIAL,
  1740. // DC_RECT, *and* DC_COMPLEX clipping.
  1741. // First, do the common setup:
  1742. IO_ALL_EMPTY(ppdev);
  1743. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 3;
  1744. NW_FRGD_COLOR(ppdev, pjMmBase, pbo->iSolidColor);
  1745. NW_PIX_CNTL(ppdev, pjMmBase, ALL_ONES);
  1746. NW_ALT_MIX(ppdev, pjMmBase, FOREGROUND_COLOR | gajHwMixFromMix[mix & 0xf], 0);
  1747. // Now, do the drawing:
  1748. if (pco->iDComplexity == DC_TRIVIAL)
  1749. {
  1750. vLinesSimple(ppdev, ppo, cFifo);
  1751. return(TRUE);
  1752. }
  1753. else
  1754. {
  1755. // We have to make sure that the path coordinates would not
  1756. // overflow our hardware precision! Note that the path's
  1757. // bounds are still expressed as 28.4 coordinates even if
  1758. // PO_ALL_INTEGERS or PO_ENUM_AS_INTEGERS is set:
  1759. PATHOBJ_vGetBounds(ppo, &rcfxBounds);
  1760. if ((rcfxBounds.xLeft >= 16 * MIN_INTEGER_BOUND) &&
  1761. (rcfxBounds.yTop >= 16 * MIN_INTEGER_BOUND) &&
  1762. (rcfxBounds.xRight <= 16 * MAX_INTEGER_BOUND) &&
  1763. (rcfxBounds.yBottom <= 16 * MAX_INTEGER_BOUND))
  1764. {
  1765. // NOTE that if you deviate from the standard NT line
  1766. // convention for PO_ALL_INTEGERS flags, you must support
  1767. // all clipping types!
  1768. if (pco->iDComplexity == DC_RECT)
  1769. {
  1770. vSetClipping(ppdev, &pco->rclBounds);
  1771. vLinesSimple(ppdev, ppo, 0);
  1772. }
  1773. else
  1774. {
  1775. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_RIGHTDOWN,
  1776. 0);
  1777. do {
  1778. // Get a batch of region rectangles:
  1779. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (VOID*) &ce);
  1780. for (i = 0; i < ce.c; i++)
  1781. {
  1782. vSetClipping(ppdev, &ce.arcl[i]);
  1783. vLinesSimple(ppdev, ppo, 0);
  1784. }
  1785. } while (bMore);
  1786. }
  1787. vResetClipping(ppdev);
  1788. return(TRUE);
  1789. }
  1790. }
  1791. }
  1792. prclClip = NULL;
  1793. fl = 0;
  1794. // Look after styling initialization:
  1795. if (pla->fl & LA_ALTERNATE)
  1796. {
  1797. ls.cStyle = 1;
  1798. ls.spTotal = 1;
  1799. ls.spTotal2 = 2;
  1800. ls.spRemaining = 1;
  1801. ls.aspRtoL = &gaspAlternateStyle[0];
  1802. ls.aspLtoR = &gaspAlternateStyle[0];
  1803. ls.spNext = HIWORD(pla->elStyleState.l);
  1804. ls.xyDensity = 1;
  1805. fl |= FL_STYLED;
  1806. ls.ulStartMask = 0L;
  1807. }
  1808. else if (pla->pstyle != (FLOAT_LONG*) NULL)
  1809. {
  1810. PFLOAT_LONG pstyle;
  1811. STYLEPOS* pspDown;
  1812. STYLEPOS* pspUp;
  1813. pstyle = &pla->pstyle[pla->cstyle];
  1814. ls.xyDensity = STYLE_DENSITY;
  1815. ls.spTotal = 0;
  1816. while (pstyle-- > pla->pstyle)
  1817. {
  1818. ls.spTotal += pstyle->l;
  1819. }
  1820. ls.spTotal *= STYLE_DENSITY;
  1821. ls.spTotal2 = 2 * ls.spTotal;
  1822. // Compute starting style position (this is guaranteed not to overflow):
  1823. ls.spNext = HIWORD(pla->elStyleState.l) * STYLE_DENSITY +
  1824. LOWORD(pla->elStyleState.l);
  1825. fl |= FL_STYLED;
  1826. ls.cStyle = pla->cstyle;
  1827. ls.aspRtoL = aspRtoL;
  1828. ls.aspLtoR = aspLtoR;
  1829. if (pla->fl & LA_STARTGAP)
  1830. ls.ulStartMask = 0xffffffffL;
  1831. else
  1832. ls.ulStartMask = 0L;
  1833. pstyle = pla->pstyle;
  1834. pspDown = &ls.aspRtoL[ls.cStyle - 1];
  1835. pspUp = &ls.aspLtoR[0];
  1836. while (pspDown >= &ls.aspRtoL[0])
  1837. {
  1838. *pspDown = pstyle->l * STYLE_DENSITY;
  1839. *pspUp = *pspDown;
  1840. pspUp++;
  1841. pspDown--;
  1842. pstyle++;
  1843. }
  1844. }
  1845. if (pco->iDComplexity == DC_RECT)
  1846. {
  1847. fl |= FL_SIMPLE_CLIP;
  1848. arclClip[0] = pco->rclBounds;
  1849. // FL_FLIP_D:
  1850. arclClip[1].top = pco->rclBounds.left;
  1851. arclClip[1].left = pco->rclBounds.top;
  1852. arclClip[1].bottom = pco->rclBounds.right;
  1853. arclClip[1].right = pco->rclBounds.bottom;
  1854. // FL_FLIP_V:
  1855. arclClip[2].top = -pco->rclBounds.bottom + 1;
  1856. arclClip[2].left = pco->rclBounds.left;
  1857. arclClip[2].bottom = -pco->rclBounds.top + 1;
  1858. arclClip[2].right = pco->rclBounds.right;
  1859. // FL_FLIP_V | FL_FLIP_D:
  1860. arclClip[3].top = pco->rclBounds.left;
  1861. arclClip[3].left = -pco->rclBounds.bottom + 1;
  1862. arclClip[3].bottom = pco->rclBounds.right;
  1863. arclClip[3].right = -pco->rclBounds.top + 1;
  1864. prclClip = arclClip;
  1865. }
  1866. apfn = &gapfnStrip[NUM_STRIP_DRAW_STYLES *
  1867. ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  1868. //////////////////////////////////////////////////////////////////////
  1869. // S3 specific initialization:
  1870. ulHwMix = gajHwMixFromMix[mix & 0xf];
  1871. // Get the device ready:
  1872. if (ppdev->flCaps & CAPS_MM_IO)
  1873. {
  1874. IO_FIFO_WAIT(ppdev, 3);
  1875. MM_FRGD_MIX(ppdev, pjMmBase, FOREGROUND_COLOR | ulHwMix);
  1876. MM_PIX_CNTL(ppdev, pjMmBase, ALL_ONES);
  1877. MM_FRGD_COLOR(ppdev, pjMmBase, pbo->iSolidColor);
  1878. }
  1879. else
  1880. {
  1881. IO_FIFO_WAIT(ppdev, 4);
  1882. IO_FRGD_MIX(ppdev, FOREGROUND_COLOR | ulHwMix);
  1883. IO_PIX_CNTL(ppdev, ALL_ONES);
  1884. if (DEPTH32(ppdev))
  1885. {
  1886. IO_FRGD_COLOR32(ppdev, pbo->iSolidColor);
  1887. }
  1888. else
  1889. {
  1890. IO_FRGD_COLOR(ppdev, pbo->iSolidColor);
  1891. }
  1892. }
  1893. //////////////////////////////////////////////////////////////////////
  1894. // Set up to enumerate the path:
  1895. if (pco->iDComplexity != DC_COMPLEX)
  1896. {
  1897. PATHDATA pd;
  1898. BOOL bMoreSetup;
  1899. ULONG cptfx;
  1900. POINTFIX ptfxStartFigure;
  1901. POINTFIX ptfxLast;
  1902. POINTFIX* pptfxFirst;
  1903. POINTFIX* pptfxBuf;
  1904. pd.flags = 0;
  1905. PATHOBJ_vEnumStart(ppo);
  1906. do {
  1907. bMoreSetup = PATHOBJ_bEnum(ppo, &pd);
  1908. cptfx = pd.count;
  1909. if (cptfx == 0)
  1910. break;
  1911. if (pd.flags & PD_BEGINSUBPATH)
  1912. {
  1913. ptfxStartFigure = *pd.pptfx;
  1914. pptfxFirst = pd.pptfx;
  1915. pptfxBuf = pd.pptfx + 1;
  1916. cptfx--;
  1917. }
  1918. else
  1919. {
  1920. pptfxFirst = &ptfxLast;
  1921. pptfxBuf = pd.pptfx;
  1922. }
  1923. if (pd.flags & PD_RESETSTYLE)
  1924. ls.spNext = 0;
  1925. if (cptfx > 0)
  1926. {
  1927. if (!bLines(ppdev,
  1928. pptfxFirst,
  1929. pptfxBuf,
  1930. (RUN*) NULL,
  1931. cptfx,
  1932. &ls,
  1933. prclClip,
  1934. apfn,
  1935. fl))
  1936. return(FALSE);
  1937. }
  1938. ptfxLast = pd.pptfx[pd.count - 1];
  1939. if (pd.flags & PD_CLOSEFIGURE)
  1940. {
  1941. if (!bLines(ppdev,
  1942. &ptfxLast,
  1943. &ptfxStartFigure,
  1944. (RUN*) NULL,
  1945. 1,
  1946. &ls,
  1947. prclClip,
  1948. apfn,
  1949. fl))
  1950. return(FALSE);
  1951. }
  1952. } while (bMoreSetup);
  1953. if (fl & FL_STYLED)
  1954. {
  1955. // Save the style state:
  1956. ULONG ulHigh;
  1957. ULONG ulLow;
  1958. // Masked styles don't normalize the style state. It's a good
  1959. // thing to do, so let's do it now:
  1960. if ((ULONG) ls.spNext >= (ULONG) ls.spTotal2)
  1961. ls.spNext = (ULONG) ls.spNext % (ULONG) ls.spTotal2;
  1962. ulHigh = ls.spNext / ls.xyDensity;
  1963. ulLow = ls.spNext % ls.xyDensity;
  1964. pla->elStyleState.l = MAKELONG(ulLow, ulHigh);
  1965. }
  1966. }
  1967. else
  1968. {
  1969. // Local state for path enumeration:
  1970. BOOL bMoreClips;
  1971. union {
  1972. BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
  1973. CLIPLINE cl;
  1974. } cl;
  1975. fl |= FL_COMPLEX_CLIP;
  1976. // We use the clip object when non-simple clipping is involved:
  1977. PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
  1978. do {
  1979. bMoreClips = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
  1980. if (cl.cl.c != 0)
  1981. {
  1982. if (fl & FL_STYLED)
  1983. {
  1984. ls.spComplex = HIWORD(cl.cl.lStyleState) * ls.xyDensity
  1985. + LOWORD(cl.cl.lStyleState);
  1986. }
  1987. if (!bLines(ppdev,
  1988. &cl.cl.ptfxA,
  1989. &cl.cl.ptfxB,
  1990. &cl.cl.arun[0],
  1991. cl.cl.c,
  1992. &ls,
  1993. (RECTL*) NULL,
  1994. apfn,
  1995. fl))
  1996. return(FALSE);
  1997. }
  1998. } while (bMoreClips);
  1999. }
  2000. return(TRUE);
  2001. }