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.

2270 lines
76 KiB

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