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.

1765 lines
58 KiB

  1. /*************************************************************************\
  2. * Module Name: Lines.c
  3. *
  4. * C template for the ASM version of the line DDA calculator.
  5. *
  6. * Copyright (c) 1990-1994 Microsoft Corporation
  7. * Copyright (c) 1992 Digital Equipment Corporation
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. #define DIVREM(u64,u32,pul) \
  11. RtlEnlargedUnsignedDivide(*(ULARGE_INTEGER*) &(u64), (u32), (pul))
  12. #define SWAPL(x,y,t) {t = x; x = y; y = t;} // from wingdip.h
  13. #define ROR_BYTE(x) ((((x) >> 1) & 0x7f) | (((x) & 0x01) << 7))
  14. #define ROL_BYTE(x) ((((x) << 1) & 0xfe) | (((x) & 0x80) >> 7))
  15. #define MIN(a, b) ((a) < (b) ? (a) : (b))
  16. #define ABS(a) ((a) < 0 ? -(a) : (a))
  17. FLONG gaflRound[] = {
  18. FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // no flips
  19. FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // FL_FLIP_D
  20. FL_H_ROUND_DOWN, // FL_FLIP_V
  21. FL_V_ROUND_DOWN, // FL_FLIP_V | FL_FLIP_D
  22. FL_V_ROUND_DOWN, // FL_FLIP_SLOPE_ONE
  23. 0xbaadf00d, // FL_FLIP_SLOPE_ONE | FL_FLIP_D
  24. FL_H_ROUND_DOWN, // FL_FLIP_SLOPE_ONE | FL_FLIP_V
  25. 0xbaadf00d // FL_FLIP_SLOPE_ONE | FL_FLIP_V
  26. | FL_FLIP_D
  27. };
  28. BOOL bIntegerLine(PDEV*, ULONG, ULONG, ULONG, ULONG);
  29. /******************************Public*Routine******************************\
  30. * BOOL bLines(ppdev, pptfxFirst, pptfxBuf, cptfx, pls,
  31. * prclClip, apfn[], flStart)
  32. *
  33. * Computes the DDA for the line and gets ready to draw it. Puts the
  34. * pixel data into an array of strips, and calls a strip routine to
  35. * do the actual drawing.
  36. *
  37. * Doing Lines Right
  38. * -----------------
  39. *
  40. * In NT, all lines are given to the device driver in fractional
  41. * coordinates, in a 28.4 fixed point format. The lower 4 bits are
  42. * fractional for sub-pixel positioning.
  43. *
  44. * Note that you CANNOT! just round the coordinates to integers
  45. * and pass the results to your favorite integer Bresenham routine!!
  46. * (Unless, of course, you have such a high resolution device that
  47. * nobody will notice -- not likely for a display device.) The
  48. * fractions give a more accurate rendering of the line -- this is
  49. * important for things like our Bezier curves, which would have 'kinks'
  50. * if the points in its polyline approximation were rounded to integers.
  51. *
  52. * Unfortunately, for fractional lines there is more setup work to do
  53. * a DDA than for integer lines. However, the main loop is exactly
  54. * the same (and can be done entirely with 32 bit math).
  55. *
  56. * If You've Got Hardware That Does Bresenham
  57. * ------------------------------------------
  58. *
  59. * A lot of hardware limits DDA error terms to 'n' bits. With fractional
  60. * coordinates, 4 bits are given to the fractional part, letting
  61. * you draw in hardware only those lines that lie entirely in a 2^(n-4)
  62. * by 2^(n-4) pixel space.
  63. *
  64. * And you still have to correctly draw those lines with coordinates
  65. * outside that space! Remember that the screen is only a viewport
  66. * onto a 28.4 by 28.4 space -- if any part of the line is visible
  67. * you MUST render it precisely, regardless of where the end points lie.
  68. * So even if you do it in software, somewhere you'll have to have a
  69. * 32 bit DDA routine.
  70. *
  71. * Our Implementation
  72. * ------------------
  73. *
  74. * We employ a run length slice algorithm: our DDA calculates the
  75. * number of pixels that are in each row (or 'strip') of pixels.
  76. *
  77. * We've separated the running of the DDA and the drawing of pixels:
  78. * we run the DDA for several iterations and store the results in
  79. * a 'strip' buffer (which are the lengths of consecutive pixel rows of
  80. * the line), then we crank up a 'strip drawer' that will draw all the
  81. * strips in the buffer.
  82. *
  83. * We also employ a 'half-flip' to reduce the number of strip
  84. * iterations we need to do in the DDA and strip drawing loops: when a
  85. * (normalized) line's slope is more than 1/2, we do a final flip
  86. * about the line y = (1/2)x. So now, instead of each strip being
  87. * consecutive horizontal or vertical pixel rows, each strip is composed
  88. * of those pixels aligned in 45 degree rows. So a line like (0, 0) to
  89. * (128, 128) would generate only one strip.
  90. *
  91. * We also always draw only left-to-right.
  92. *
  93. * Style lines may have arbitrary style patterns. We specially
  94. * optimize the default patterns (and call them 'masked' styles).
  95. *
  96. * The DDA Derivation
  97. * ------------------
  98. *
  99. * Here is how I like to think of the DDA calculation.
  100. *
  101. * We employ Knuth's "diamond rule": rendering a one-pixel-wide line
  102. * can be thought of as dragging a one-pixel-wide by one-pixel-high
  103. * diamond along the true line. Pixel centers lie on the integer
  104. * coordinates, and so we light any pixel whose center gets covered
  105. * by the "drag" region (John D. Hobby, Journal of the Association
  106. * for Computing Machinery, Vol. 36, No. 2, April 1989, pp. 209-229).
  107. *
  108. * We must define which pixel gets lit when the true line falls
  109. * exactly half-way between two pixels. In this case, we follow
  110. * the rule: when two pels are equidistant, the upper or left pel
  111. * is illuminated, unless the slope is exactly one, in which case
  112. * the upper or right pel is illuminated. (So we make the edges
  113. * of the diamond exclusive, except for the top and left vertices,
  114. * which are inclusive, unless we have slope one.)
  115. *
  116. * This metric decides what pixels should be on any line BEFORE it is
  117. * flipped around for our calculation. Having a consistent metric
  118. * this way will let our lines blend nicely with our curves. The
  119. * metric also dictates that we will never have one pixel turned on
  120. * directly above another that's turned on. We will also never have
  121. * a gap; i.e., there will be exactly one pixel turned on for each
  122. * column between the start and end points. All that remains to be
  123. * done is to decide how many pixels should be turned on for each row.
  124. *
  125. * So lines we draw will consist of varying numbers of pixels on
  126. * successive rows, for example:
  127. *
  128. * ******
  129. * *****
  130. * ******
  131. * *****
  132. *
  133. * We'll call each set of pixels on a row a "strip".
  134. *
  135. * (Please remember that our coordinate space has the origin as the
  136. * upper left pixel on the screen; postive y is down and positive x
  137. * is right.)
  138. *
  139. * Device coordinates are specified as fixed point 28.4 numbers,
  140. * where the first 28 bits are the integer coordinate, and the last
  141. * 4 bits are the fraction. So coordinates may be thought of as
  142. * having the form (x, y) = (M/F, N/F) where F is the constant scaling
  143. * factor F = 2^4 = 16, and M and N are 32 bit integers.
  144. *
  145. * Consider the line from (M0/F, N0/F) to (M1/F, N1/F) which runs
  146. * left-to-right and whose slope is in the first octant, and let
  147. * dM = M1 - M0 and dN = N1 - N0. Then dM >= 0, dN >= 0 and dM >= dN.
  148. *
  149. * Since the slope of the line is less than 1, the edges of the
  150. * drag region are created by the top and bottom vertices of the
  151. * diamond. At any given pixel row y of the line, we light those
  152. * pixels whose centers are between the left and right edges.
  153. *
  154. * Let mL(n) denote the line representing the left edge of the drag
  155. * region. On pixel row j, the column of the first pixel to be
  156. * lit is
  157. *
  158. * iL(j) = ceiling( mL(j * F) / F)
  159. *
  160. * Since the line's slope is less than one:
  161. *
  162. * iL(j) = ceiling( mL([j + 1/2] F) / F )
  163. *
  164. * Recall the formula for our line:
  165. *
  166. * n(m) = (dN / dM) (m - M0) + N0
  167. *
  168. * m(n) = (dM / dN) (n - N0) + M0
  169. *
  170. * Since the line's slope is less than one, the line representing
  171. * the left edge of the drag region is the original line offset
  172. * by 1/2 pixel in the y direction:
  173. *
  174. * mL(n) = (dM / dN) (n - F/2 - N0) + M0
  175. *
  176. * From this we can figure out the column of the first pixel that
  177. * will be lit on row j, being careful of rounding (if the left
  178. * edge lands exactly on an integer point, the pixel at that
  179. * point is not lit because of our rounding convention):
  180. *
  181. * iL(j) = floor( mL(j F) / F ) + 1
  182. *
  183. * = floor( ((dM / dN) (j F - F/2 - N0) + M0) / F ) + 1
  184. *
  185. * = floor( F dM j - F/2 dM - N0 dM + dN M0) / F dN ) + 1
  186. *
  187. * F dM j - [ dM (N0 + F/2) - dN M0 ]
  188. * = floor( ---------------------------------- ) + 1
  189. * F dN
  190. *
  191. * dM j - [ dM (N0 + F/2) - dN M0 ] / F
  192. * = floor( ------------------------------------ ) + 1 (1)
  193. * dN
  194. *
  195. * = floor( (dM j + alpha) / dN ) + 1
  196. *
  197. * where
  198. *
  199. * alpha = - [ dM (N0 + F/2) - dN M0 ] / F
  200. *
  201. * We use equation (1) to calculate the DDA: there are iL(j+1) - iL(j)
  202. * pixels in row j. Because we are always calculating iL(j) for
  203. * integer quantities of j, we note that the only fractional term
  204. * is constant, and so we can 'throw away' the fractional bits of
  205. * alpha:
  206. *
  207. * beta = floor( - [ dM (N0 + F/2) - dN M0 ] / F ) (2)
  208. *
  209. * so
  210. *
  211. * iL(j) = floor( (dM j + beta) / dN ) + 1 (3)
  212. *
  213. * for integers j.
  214. *
  215. * Note if iR(j) is the line's rightmost pixel on row j, that
  216. * iR(j) = iL(j + 1) - 1.
  217. *
  218. * Similarly, rewriting equation (1) as a function of column i,
  219. * we can determine, given column i, on which pixel row j is the line
  220. * lit:
  221. *
  222. * dN i + [ dM (N0 + F/2) - dN M0 ] / F
  223. * j(i) = ceiling( ------------------------------------ ) - 1
  224. * dM
  225. *
  226. * Floors are easier to compute, so we can rewrite this:
  227. *
  228. * dN i + [ dM (N0 + F/2) - dN M0 ] / F + dM - 1/F
  229. * j(i) = floor( ----------------------------------------------- ) - 1
  230. * dM
  231. *
  232. * dN i + [ dM (N0 + F/2) - dN M0 ] / F + dM - 1/F - dM
  233. * = floor( ---------------------------------------------------- )
  234. * dM
  235. *
  236. * dN i + [ dM (N0 + F/2) - dN M0 - 1 ] / F
  237. * = floor( ---------------------------------------- )
  238. * dM
  239. *
  240. * We can once again wave our hands and throw away the fractional bits
  241. * of the remainder term:
  242. *
  243. * j(i) = floor( (dN i + gamma) / dM ) (4)
  244. *
  245. * where
  246. *
  247. * gamma = floor( [ dM (N0 + F/2) - dN M0 - 1 ] / F ) (5)
  248. *
  249. * We now note that
  250. *
  251. * beta = -gamma - 1 = ~gamma (6)
  252. *
  253. * To draw the pixels of the line, we could evaluate (3) on every scan
  254. * line to determine where the strip starts. Of course, we don't want
  255. * to do that because that would involve a multiply and divide for every
  256. * scan. So we do everything incrementally.
  257. *
  258. * We would like to easily compute c , the number of pixels on scan j:
  259. * j
  260. *
  261. * c = iL(j + 1) - iL(j)
  262. * j
  263. *
  264. * = floor((dM (j + 1) + beta) / dN) - floor((dM j + beta) / dN) (7)
  265. *
  266. * This may be rewritten as
  267. *
  268. * c = floor(i + r / dN) - floor(i + r / dN) (8)
  269. * j j+1 j+1 j j
  270. *
  271. * where i , i are integers and r < dN, r < dN.
  272. * j j+1 j j+1
  273. *
  274. * Rewriting (7) again:
  275. *
  276. * c = floor(i + r / dN + dM / dN) - floor(i + r / dN)
  277. * j j j j j
  278. *
  279. *
  280. * = floor((r + dM) / dN) - floor(r / dN)
  281. * j j
  282. *
  283. * This may be rewritten as
  284. *
  285. * c = dI + floor((r + dR) / dN) - floor(r / dN)
  286. * j j j
  287. *
  288. * where dI + dR / dN = dM / dN, dI is an integer and dR < dN.
  289. *
  290. * r is the remainder (or "error") term in the DDA loop: r / dN
  291. * j j
  292. * is the exact fraction of a pixel at which the strip ends. To go
  293. * on to the next scan and compute c we need to know r .
  294. * j+1 j+1
  295. *
  296. * So in the main loop of the DDA:
  297. *
  298. * c = dI + floor((r + dR) / dN) and r = (r + dR) % dN
  299. * j j j+1 j
  300. *
  301. * and we know r < dN, r < dN, and dR < dN.
  302. * j j+1
  303. *
  304. * We have derived the DDA only for lines in the first octant; to
  305. * handle other octants we do the common trick of flipping the line
  306. * to the first octant by first making the line left-to-right by
  307. * exchanging the end-points, then flipping about the lines y = 0 and
  308. * y = x, as necessary. We must record the transformation so we can
  309. * undo them later.
  310. *
  311. * We must also be careful of how the flips affect our rounding. If
  312. * to get the line to the first octant we flipped about x = 0, we now
  313. * have to be careful to round a y value of 1/2 up instead of down as
  314. * we would for a line originally in the first octant (recall that
  315. * "In the case where two pels are equidistant, the upper or left
  316. * pel is illuminated...").
  317. *
  318. * To account for this rounding when running the DDA, we shift the line
  319. * (or not) in the y direction by the smallest amount possible. That
  320. * takes care of rounding for the DDA, but we still have to be careful
  321. * about the rounding when determining the first and last pixels to be
  322. * lit in the line.
  323. *
  324. * Determining The First And Last Pixels In The Line
  325. * -------------------------------------------------
  326. *
  327. * Fractional coordinates also make it harder to determine which pixels
  328. * will be the first and last ones in the line. We've already taken
  329. * the fractional coordinates into account in calculating the DDA, but
  330. * the DDA cannot tell us which are the end pixels because it is quite
  331. * happy to calculate pixels on the line from minus infinity to positive
  332. * infinity.
  333. *
  334. * The diamond rule determines the start and end pixels. (Recall that
  335. * the sides are exclusive except for the left and top vertices.)
  336. * This convention can be thought of in another way: there are diamonds
  337. * around the pixels, and wherever the true line crosses a diamond,
  338. * that pel is illuminated.
  339. *
  340. * Consider a line where we've done the flips to the first octant, and the
  341. * floor of the start coordinates is the origin:
  342. *
  343. * +-----------------------> +x
  344. * |
  345. * | 0 1
  346. * | 0123456789abcdef
  347. * |
  348. * | 0 00000000?1111111
  349. * | 1 00000000 1111111
  350. * | 2 0000000 111111
  351. * | 3 000000 11111
  352. * | 4 00000 ** 1111
  353. * | 5 0000 ****1
  354. * | 6 000 1***
  355. * | 7 00 1 ****
  356. * | 8 ? ***
  357. * | 9 22 3 ****
  358. * | a 222 33 ***
  359. * | b 2222 333 ****
  360. * | c 22222 3333 **
  361. * | d 222222 33333
  362. * | e 2222222 333333
  363. * | f 22222222 3333333
  364. * |
  365. * | 2 3
  366. * v
  367. * +y
  368. *
  369. * If the start of the line lands on the diamond around pixel 0 (shown by
  370. * the '0' region here), pixel 0 is the first pel in the line. The same
  371. * is true for the other pels.
  372. *
  373. * A little more work has to be done if the line starts in the
  374. * 'nether-land' between the diamonds (as illustrated by the '*' line):
  375. * the first pel lit is the first diamond crossed by the line (pixel 1 in
  376. * our example). This calculation is determined by the DDA or slope of
  377. * the line.
  378. *
  379. * If the line starts exactly half way between two adjacent pixels
  380. * (denoted here by the '?' spots), the first pixel is determined by our
  381. * round-down convention (and is dependent on the flips done to
  382. * normalize the line).
  383. *
  384. * Last Pel Exclusive
  385. * ------------------
  386. *
  387. * To eliminate repeatedly lit pels between continuous connected lines,
  388. * we employ a last-pel exclusive convention: if the line ends exactly on
  389. * the diamond around a pel, that pel is not lit. (This eliminates the
  390. * checks we had in the old code to see if we were re-lighting pels.)
  391. *
  392. * The Half Flip
  393. * -------------
  394. *
  395. * To make our run length algorithm more efficient, we employ a "half
  396. * flip". If after normalizing to the first octant, the slope is more
  397. * than 1/2, we subtract the y coordinate from the x coordinate. This
  398. * has the effect of reflecting the coordinates through the line of slope
  399. * 1/2. Note that the diagonal gets mapped into the x-axis after a half
  400. * flip.
  401. *
  402. * How Many Bits Do We Need, Anyway?
  403. * ---------------------------------
  404. *
  405. * Note that if the line is visible on your screen, you must light up
  406. * exactly the correct pixels, no matter where in the 28.4 x 28.4 device
  407. * space the end points of the line lie (meaning you must handle 32 bit
  408. * DDAs, you can certainly have optimized cases for lesser DDAs).
  409. *
  410. * We move the origin to (floor(M0 / F), floor(N0 / F)), so when we
  411. * calculate gamma from (5), we know that 0 <= M0, N0 < F. And we
  412. * are in the first octant, so dM >= dN. Then we know that gamma can
  413. * be in the range [(-1/2)dM, (3/2)dM]. The DDI guarantees us that
  414. * valid lines will have dM and dN values at most 31 bits (unsigned)
  415. * of significance. So gamma requires 33 bits of significance (we store
  416. * this as a 64 bit number for convenience).
  417. *
  418. * When running through the DDA loop, r + dR can have a value in the
  419. * j
  420. * range 0 <= r < 2 dN; thus the result must be a 32 bit unsigned value.
  421. * j
  422. *
  423. * Testing Lines
  424. * -------------
  425. *
  426. * To be NT compliant, a display driver must exactly adhere to GIQ,
  427. * which means that for any given line, the driver must light exactly
  428. * the same pels as does GDI. This can be tested using the Guiman tool
  429. * provided elsewhere in the DDK, and 'ZTest', which draws random lines
  430. * on the screen and to a bitmap, and compares the results.
  431. *
  432. * If You've Got Line Hardware
  433. * ---------------------------
  434. *
  435. * If your hardware already adheres to GIQ, you're all set. Otherwise
  436. * you'll want to look at the S3 sample code and read the following:
  437. *
  438. * 1) You'll want to special case integer-only lines, since they require
  439. * less processing time and are more common (CAD programs will probably
  440. * only ever give integer lines). GDI does not provide a flag saying
  441. * that all lines in a path are integer lines; consequently, you will
  442. * have to explicitly check every line.
  443. *
  444. * 2) You are required to correctly draw any line in the 28.4 device
  445. * space that intersects the viewport. If you have less than 32 bits
  446. * of significance in the hardware for the Bresenham terms, extremely
  447. * long lines would overflow the hardware. For such (rare) cases, you
  448. * can fall back to strip-drawing code, of which there is a C version in
  449. * the S3's lines.cxx (or if your display is a frame buffer, fall back
  450. * to the engine).
  451. *
  452. * 3) If you can explicitly set the Bresenham terms in your hardware, you
  453. * can draw non-integer lines using the hardware. If your hardware has
  454. * 'n' bits of precision, you can draw GIQ lines that are up to 2^(n-5)
  455. * pels long (4 bits are required for the fractional part, and one bit is
  456. * used as a sign bit). Note that integer lines don't require the 4
  457. * fractional bits, so if you special case them as in 1), you can do
  458. * integer lines that are up to 2^(n - 1) pels long. See the S3's
  459. * fastline.asm for an example.
  460. *
  461. \**************************************************************************/
  462. BOOL bLines(
  463. PDEV* ppdev,
  464. POINTFIX* pptfxFirst, // Start of first line
  465. POINTFIX* pptfxBuf, // Pointer to buffer of all remaining lines
  466. RUN* prun, // Pointer to runs if doing complex clipping
  467. ULONG cptfx, // Number of points in pptfxBuf or number of runs
  468. // in prun
  469. LINESTATE* pls, // Colour and style info
  470. RECTL* prclClip, // Pointer to clip rectangle if doing simple clipping
  471. PFNSTRIP apfn[], // Array of strip functions
  472. FLONG flStart) // Flags for each line
  473. {
  474. ULONG M0;
  475. ULONG dM;
  476. ULONG N0;
  477. ULONG dN;
  478. ULONG dN_Original;
  479. FLONG fl;
  480. LONG x;
  481. LONG y;
  482. LONGLONG eqBeta;
  483. LONGLONG eqGamma;
  484. LONGLONG euq;
  485. LONGLONG eq;
  486. ULONG ulDelta;
  487. ULONG x0;
  488. ULONG y0;
  489. ULONG x1;
  490. ULONG cStylePels; // Major length of line in pixels for styling
  491. ULONG xStart;
  492. POINTL ptlStart;
  493. STRIP strip;
  494. PFNSTRIP pfn;
  495. LONG cPels;
  496. LONG* plStrip;
  497. LONG* plStripEnd;
  498. LONG cStripsInNextRun;
  499. POINTFIX* pptfxBufEnd = pptfxBuf + cptfx; // Last point in path record
  500. STYLEPOS spThis; // Style pos for this line
  501. do {
  502. /***********************************************************************\
  503. * Start the DDA calculations. *
  504. \***********************************************************************/
  505. M0 = (LONG) pptfxFirst->x;
  506. dM = (LONG) pptfxBuf->x;
  507. N0 = (LONG) pptfxFirst->y;
  508. dN = (LONG) pptfxBuf->y;
  509. fl = flStart;
  510. // Check for non-clipped, non-styled integer endpoint lines - ECR
  511. if ( ( (fl & (FL_CLIP | FL_STYLED)) == 0 ) &&
  512. ( ((M0 | dM | N0 | dN) & (F-1)) == 0 ) )
  513. {
  514. if (bIntegerLine(ppdev, M0, N0, dM, dN))
  515. {
  516. goto Next_Line;
  517. }
  518. }
  519. if ((LONG) M0 > (LONG) dM)
  520. {
  521. // Ensure that we run left-to-right:
  522. register ULONG ulTmp;
  523. SWAPL(M0, dM, ulTmp);
  524. SWAPL(N0, dN, ulTmp);
  525. fl |= FL_FLIP_H;
  526. }
  527. // Compute the deltas:
  528. dM -= M0;
  529. dN -= N0;
  530. // We now have a line running left-to-right from (M0, N0) to
  531. // (M0 + dM, N0 + dN):
  532. if ((LONG) dN < 0)
  533. {
  534. // Line runs from bottom to top, so flip across y = 0:
  535. N0 = -(LONG) N0;
  536. dN = -(LONG) dN;
  537. fl |= FL_FLIP_V;
  538. }
  539. if (dN >= dM)
  540. {
  541. if (dN == dM)
  542. {
  543. // Have to special case slopes of one:
  544. fl |= FL_FLIP_SLOPE_ONE;
  545. }
  546. else
  547. {
  548. // Since line has slope greater than 1, flip across x = y:
  549. register ULONG ulTmp;
  550. SWAPL(dM, dN, ulTmp);
  551. SWAPL(M0, N0, ulTmp);
  552. fl |= FL_FLIP_D;
  553. }
  554. }
  555. fl |= gaflRound[(fl & FL_ROUND_MASK) >> FL_ROUND_SHIFT];
  556. x = LFLOOR((LONG) M0);
  557. y = LFLOOR((LONG) N0);
  558. M0 = FXFRAC(M0);
  559. N0 = FXFRAC(N0);
  560. // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]:
  561. {
  562. // eqGamma = dM * (N0 + F/2);
  563. eqGamma = Int32x32To64(dM, N0 + F/2);
  564. // eq = M0 * dN;
  565. eq = Int32x32To64(M0, dN);
  566. eqGamma -= eq;
  567. if (fl & FL_V_ROUND_DOWN) // Adjust so y = 1/2 rounds down
  568. {
  569. eqGamma--;
  570. }
  571. eqGamma >>= FLOG2;
  572. eqBeta = ~eqGamma;
  573. }
  574. /***********************************************************************\
  575. * Figure out which pixels are at the ends of the line. *
  576. \***********************************************************************/
  577. // The toughest part of GIQ is determining the start and end pels.
  578. //
  579. // Our approach here is to calculate x0 and x1 (the inclusive start
  580. // and end columns of the line respectively, relative to our normalized
  581. // origin). Then x1 - x0 + 1 is the number of pels in the line. The
  582. // start point is easily calculated by plugging x0 into our line equation
  583. // (which takes care of whether y = 1/2 rounds up or down in value)
  584. // getting y0, and then undoing the normalizing flips to get back
  585. // into device space.
  586. //
  587. // We look at the fractional parts of the coordinates of the start and
  588. // end points, and call them (M0, N0) and (M1, N1) respectively, where
  589. // 0 <= M0, N0, M1, N1 < 16. We plot (M0, N0) on the following grid
  590. // to determine x0:
  591. //
  592. // +-----------------------> +x
  593. // |
  594. // | 0 1
  595. // | 0123456789abcdef
  596. // |
  597. // | 0 ........?xxxxxxx
  598. // | 1 ..........xxxxxx
  599. // | 2 ...........xxxxx
  600. // | 3 ............xxxx
  601. // | 4 .............xxx
  602. // | 5 ..............xx
  603. // | 6 ...............x
  604. // | 7 ................
  605. // | 8 ................
  606. // | 9 ......**........
  607. // | a ........****...x
  608. // | b ............****
  609. // | c .............xxx****
  610. // | d ............xxxx ****
  611. // | e ...........xxxxx ****
  612. // | f ..........xxxxxx
  613. // |
  614. // | 2 3
  615. // v
  616. //
  617. // +y
  618. //
  619. // This grid accounts for the appropriate rounding of GIQ and last-pel
  620. // exclusion. If (M0, N0) lands on an 'x', x0 = 2. If (M0, N0) lands
  621. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  622. // depending on what flips have been done to normalize the line.
  623. //
  624. // For the end point, if (M1, N1) lands on an 'x', x1 =
  625. // floor((M0 + dM) / 16) + 1. If (M1, N1) lands on a '.', x1 =
  626. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  627. // depending on what flips have been done to normalize the line.
  628. //
  629. // Lines of exactly slope one require a special case for both the start
  630. // and end. For example, if the line ends such that (M1, N1) is (9, 1),
  631. // the line has gone exactly through (8, 0) -- which may be considered
  632. // to be part of 'x' because of rounding! So slopes of exactly slope
  633. // one going through (8, 0) must also be considered as belonging in 'x'.
  634. //
  635. // For lines that go left-to-right, we have the following grid:
  636. //
  637. // +-----------------------> +x
  638. // |
  639. // | 0 1
  640. // | 0123456789abcdef
  641. // |
  642. // | 0 xxxxxxxx?.......
  643. // | 1 xxxxxxx.........
  644. // | 2 xxxxxx..........
  645. // | 3 xxxxx...........
  646. // | 4 xxxx............
  647. // | 5 xxx.............
  648. // | 6 xx..............
  649. // | 7 x...............
  650. // | 8 x...............
  651. // | 9 x.....**........
  652. // | a xx......****....
  653. // | b xxx.........****
  654. // | c xxxx............****
  655. // | d xxxxx........... ****
  656. // | e xxxxxx.......... ****
  657. // | f xxxxxxx.........
  658. // |
  659. // | 2 3
  660. // v
  661. //
  662. // +y
  663. //
  664. // This grid accounts for the appropriate rounding of GIQ and last-pel
  665. // exclusion. If (M0, N0) lands on an 'x', x0 = 0. If (M0, N0) lands
  666. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  667. // depending on what flips have been done to normalize the line.
  668. //
  669. // For the end point, if (M1, N1) lands on an 'x', x1 =
  670. // floor((M0 + dM) / 16) - 1. If (M1, N1) lands on a '.', x1 =
  671. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  672. // depending on what flips have been done to normalize the line.
  673. //
  674. // Lines of exactly slope one must be handled similarly to the right-to-
  675. // left case.
  676. {
  677. // Calculate x0, x1
  678. ULONG N1 = FXFRAC(N0 + dN);
  679. ULONG M1 = FXFRAC(M0 + dM);
  680. x1 = LFLOOR(M0 + dM);
  681. if (fl & FL_FLIP_H)
  682. {
  683. // ---------------------------------------------------------------
  684. // Line runs right-to-left: <----
  685. // Compute x1:
  686. if (N1 == 0)
  687. {
  688. if (LROUND(M1, fl & FL_H_ROUND_DOWN))
  689. {
  690. x1++;
  691. }
  692. }
  693. else if (ABS((LONG) (N1 - F/2)) + M1 > F)
  694. {
  695. x1++;
  696. }
  697. if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  698. == (FL_FLIP_SLOPE_ONE))
  699. {
  700. // Have to special-case diagonal lines going through our
  701. // the point exactly equidistant between two horizontal
  702. // pixels, if we're supposed to round x=1/2 down:
  703. if ((N1 > 0) && (M1 == N1 + 8))
  704. x1++;
  705. // Don't you love special cases? Is this a rhetorical question?
  706. if ((M0 > 0) && (N0 == M0 + 8))
  707. {
  708. x0 = 2;
  709. ulDelta = dN;
  710. goto right_to_left_compute_y0;
  711. }
  712. }
  713. // Compute x0:
  714. x0 = 1;
  715. ulDelta = 0;
  716. if (N0 == 0)
  717. {
  718. if (LROUND(M0, fl & FL_H_ROUND_DOWN))
  719. {
  720. x0 = 2;
  721. ulDelta = dN;
  722. }
  723. }
  724. else if (ABS((LONG) (N0 - F/2)) + M0 > F)
  725. {
  726. x0 = 2;
  727. ulDelta = dN;
  728. }
  729. // Compute y0:
  730. right_to_left_compute_y0:
  731. y0 = 0;
  732. eq = eqGamma + ulDelta;
  733. if ((eq>>32) >= 0)
  734. {
  735. if ((eq>>32) > 0 || (ULONG) eq >= 2 * dM - dN)
  736. y0 = 2;
  737. else if ((ULONG) eq >= dM - dN)
  738. y0 = 1;
  739. }
  740. }
  741. else
  742. {
  743. // ---------------------------------------------------------------
  744. // Line runs left-to-right: ---->
  745. // Compute x1:
  746. x1--;
  747. if (M1 > 0)
  748. {
  749. if (N1 == 0)
  750. {
  751. if (LROUND(M1, fl & FL_H_ROUND_DOWN))
  752. x1++;
  753. }
  754. else if (ABS((LONG) (N1 - F/2)) <= (LONG) M1)
  755. {
  756. x1++;
  757. }
  758. }
  759. if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  760. == (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  761. {
  762. // Have to special-case diagonal lines going through our
  763. // the point exactly equidistant between two horizontal
  764. // pixels, if we're supposed to round x=1/2 down:
  765. if ((N1 > 0) && (M1 == N1 + 8))
  766. x1--;
  767. if ((M0 > 0) && (N0 == M0 + 8))
  768. {
  769. x0 = 0;
  770. goto left_to_right_compute_y0;
  771. }
  772. }
  773. // Compute x0:
  774. x0 = 0;
  775. if (M0 > 0)
  776. {
  777. if (N0 == 0)
  778. {
  779. if (LROUND(M0, fl & FL_H_ROUND_DOWN))
  780. x0 = 1;
  781. }
  782. else if (ABS((LONG) (N0 - F/2)) <= (LONG) M0)
  783. {
  784. x0 = 1;
  785. }
  786. }
  787. // Compute y0:
  788. left_to_right_compute_y0:
  789. y0 = 0;
  790. if ((eqGamma>>32) >= 0 &&
  791. (ULONG) eqGamma >= dM - (dN & (-(LONG) x0)))
  792. {
  793. y0 = 1;
  794. }
  795. }
  796. }
  797. cStylePels = x1 - x0 + 1;
  798. if ((LONG) cStylePels <= 0)
  799. goto Next_Line;
  800. xStart = x0;
  801. /***********************************************************************\
  802. * Complex clipping. *
  803. \***********************************************************************/
  804. #ifdef SIMPLE_CLIP
  805. if (fl & FL_COMPLEX_CLIP)
  806. #else
  807. if (fl & FL_CLIP)
  808. #endif // SIMPLE_CLIP
  809. {
  810. dN_Original = dN;
  811. Continue_Complex_Clipping:
  812. if (fl & FL_FLIP_H)
  813. {
  814. // Line runs right-to-left <-----
  815. x0 = xStart + cStylePels - prun->iStop - 1;
  816. x1 = xStart + cStylePels - prun->iStart - 1;
  817. }
  818. else
  819. {
  820. // Line runs left-to-right ----->
  821. x0 = xStart + prun->iStart;
  822. x1 = xStart + prun->iStop;
  823. }
  824. prun++;
  825. // Reset some variables we'll nuke a little later:
  826. dN = dN_Original;
  827. pls->spNext = pls->spComplex;
  828. // No overflow since large integer math is used. Both values
  829. // will be positive:
  830. // euq = x0 * dN:
  831. euq = Int32x32To64(x0, dN);
  832. euq += eqGamma:
  833. // y0 = euq / dM:
  834. y0 = DIVREM(euq, dM, NULL);
  835. ASSERTDD((LONG) y0 >= 0, "y0 weird: Goofed up end pel calc?");
  836. }
  837. /////////////////////////////////////////////////////////////////////////
  838. // The following clip code works great -- we simply aren't using it yet.
  839. /////////////////////////////////////////////////////////////////////////
  840. #ifdef SIMPLE_CLIP
  841. /***********************************************************************\
  842. * Simple rectangular clipping. *
  843. \***********************************************************************/
  844. if (fl & FL_SIMPLE_CLIP)
  845. {
  846. ULONG y1;
  847. LONG xRight;
  848. LONG xLeft;
  849. LONG yBottom;
  850. LONG yTop;
  851. // Note that y0 and y1 are actually the lower and upper bounds,
  852. // respectively, of the y coordinates of the line (the line may
  853. // have actually shrunk due to first/last pel clipping).
  854. //
  855. // Also note that x0, y0 are not necessarily zero.
  856. RECTL* prcl = &prclClip[(fl & FL_RECTLCLIP_MASK) >>
  857. FL_RECTLCLIP_SHIFT];
  858. // Normalize to the same point we've normalized for the DDA
  859. // calculations:
  860. xRight = prcl->right - x;
  861. xLeft = prcl->left - x;
  862. yBottom = prcl->bottom - y;
  863. yTop = prcl->top - y;
  864. if (yBottom <= (LONG) y0 ||
  865. xRight <= (LONG) x0 ||
  866. xLeft > (LONG) x1)
  867. {
  868. Totally_Clipped:
  869. if (fl & FL_STYLED)
  870. {
  871. pls->spNext += cStylePels;
  872. if (pls->spNext >= pls->spTotal2)
  873. pls->spNext %= pls->spTotal2;
  874. }
  875. goto Next_Line;
  876. }
  877. if ((LONG) x1 >= xRight)
  878. x1 = xRight - 1;
  879. // We have to know the correct y1, which we haven't bothered to
  880. // calculate up until now. This multiply and divide is quite
  881. // expensive; we could replace it with code similar to that which
  882. // we used for computing y0.
  883. //
  884. // The reason why we need the actual value, and not an upper
  885. // bounds guess like y1 = LFLOOR(dM) + 2 is that we have to be
  886. // careful when calculating x(y) that y0 <= y <= y1, otherwise
  887. // we can overflow on the divide (which, needless to say, is very
  888. // bad).
  889. // euq = x1 * dN;
  890. euq = Int32x32To64(x1, dN);
  891. euq += eqGamma;
  892. // y1 = euq / dM:
  893. y1 = DIVREM(euq, dM, NULL);
  894. if (yTop > (LONG) y1)
  895. goto Totally_Clipped;
  896. if (yBottom <= (LONG) y1)
  897. {
  898. y1 = yBottom;
  899. // euq = y1 * dM;
  900. euq = Int32x32To64(y1, dM);
  901. euq += eqBeta;
  902. // x1 = euq / dN:
  903. x1 = DIVREM(euq, dN, NULL);
  904. }
  905. // At this point, we've taken care of calculating the intercepts
  906. // with the right and bottom edges. Now we work on the left and
  907. // top edges:
  908. if (xLeft > (LONG) x0)
  909. {
  910. x0 = xLeft;
  911. // euq = x0 * dN;
  912. euq = Int32x32To64(x0, dN);
  913. euq += eqGamma;
  914. // y0 = euq / dM;
  915. y0 = DIVREM(euq, dM, NULL);
  916. if (yBottom <= (LONG) y0)
  917. goto Totally_Clipped;
  918. }
  919. if (yTop > (LONG) y0)
  920. {
  921. y0 = yTop;
  922. // euq = y0 * dM;
  923. euq = Int32x32To64(y0, dM);
  924. euq += eqBeta;
  925. // x0 = euq / dN + 1;
  926. x0 = DIVREM(euq, dN) + 1;
  927. if (xRight <= (LONG) x0)
  928. goto Totally_Clipped;
  929. }
  930. ASSERTDD(x0 <= x1, "Improper rectangle clip");
  931. }
  932. #endif // SIMPLE_CLIP
  933. /***********************************************************************\
  934. * Done clipping. Unflip if necessary. *
  935. \***********************************************************************/
  936. ptlStart.x = x + x0;
  937. ptlStart.y = y + y0;
  938. if (fl & FL_FLIP_D)
  939. {
  940. register LONG lTmp;
  941. SWAPL(ptlStart.x, ptlStart.y, lTmp);
  942. }
  943. if (fl & FL_FLIP_V)
  944. {
  945. ptlStart.y = -ptlStart.y;
  946. }
  947. cPels = x1 - x0 + 1;
  948. /***********************************************************************\
  949. * Style calculations. *
  950. \***********************************************************************/
  951. if (fl & FL_STYLED)
  952. {
  953. STYLEPOS sp;
  954. spThis = pls->spNext;
  955. pls->spNext += cStylePels;
  956. {
  957. if (pls->spNext >= pls->spTotal2)
  958. pls->spNext %= pls->spTotal2;
  959. if (fl & FL_FLIP_H)
  960. sp = pls->spNext - x0 + xStart;
  961. else
  962. sp = spThis + x0 - xStart;
  963. ASSERTDD(fl & FL_ARBITRARYSTYLED, "Oops");
  964. // Normalize our target style position:
  965. if ((sp < 0) || (sp >= pls->spTotal2))
  966. {
  967. sp %= pls->spTotal2;
  968. // The modulus of a negative number is not well-defined
  969. // in C -- if it's negative we'll adjust it so that it's
  970. // back in the range [0, spTotal2):
  971. if (sp < 0)
  972. sp += pls->spTotal2;
  973. }
  974. // Since we always draw the line left-to-right, but styling is
  975. // always done in the direction of the original line, we have
  976. // to figure out where we are in the style array for the left
  977. // edge of this line.
  978. if (fl & FL_FLIP_H)
  979. {
  980. // Line originally ran right-to-left:
  981. sp = -sp;
  982. if (sp < 0)
  983. sp += pls->spTotal2;
  984. pls->ulStyleMask = ~pls->ulStartMask;
  985. pls->pspStart = &pls->aspRtoL[0];
  986. pls->pspEnd = &pls->aspRtoL[pls->cStyle - 1];
  987. }
  988. else
  989. {
  990. // Line originally ran left-to-right:
  991. pls->ulStyleMask = pls->ulStartMask;
  992. pls->pspStart = &pls->aspLtoR[0];
  993. pls->pspEnd = &pls->aspLtoR[pls->cStyle - 1];
  994. }
  995. if (sp >= pls->spTotal)
  996. {
  997. sp -= pls->spTotal;
  998. if (pls->cStyle & 1)
  999. pls->ulStyleMask = ~pls->ulStyleMask;
  1000. }
  1001. pls->psp = pls->pspStart;
  1002. while (sp >= *pls->psp)
  1003. sp -= *pls->psp++;
  1004. ASSERTDD(pls->psp <= pls->pspEnd,
  1005. "Flew off into NeverNeverLand");
  1006. pls->spRemaining = *pls->psp - sp;
  1007. if ((pls->psp - pls->pspStart) & 1)
  1008. pls->ulStyleMask = ~pls->ulStyleMask;
  1009. }
  1010. }
  1011. plStrip = &strip.alStrips[0];
  1012. plStripEnd = &strip.alStrips[STRIP_MAX]; // Is exclusive
  1013. cStripsInNextRun = 0x7fffffff;
  1014. strip.ptlStart = ptlStart;
  1015. if (2 * dN > dM &&
  1016. !(fl & FL_STYLED) &&
  1017. !(fl & FL_DONT_DO_HALF_FLIP))
  1018. {
  1019. // Do a half flip! Remember that we may doing this on the
  1020. // same line multiple times for complex clipping (meaning the
  1021. // affected variables should be reset for every clip run):
  1022. fl |= FL_FLIP_HALF;
  1023. eqBeta = eqGamma;
  1024. eqBeta -= dM;
  1025. dN = dM - dN;
  1026. y0 = x0 - y0; // Note this may overflow, but that's okay
  1027. }
  1028. // Now, run the DDA starting at (ptlStart.x, ptlStart.y)!
  1029. strip.flFlips = fl;
  1030. pfn = apfn[(fl & FL_STRIP_MASK) >> FL_STRIP_SHIFT];
  1031. // Now calculate the DDA variables needed to figure out how many pixels
  1032. // go in the very first strip:
  1033. {
  1034. register LONG i;
  1035. register ULONG dI;
  1036. register ULONG dR;
  1037. ULONG r;
  1038. if (dN == 0)
  1039. i = 0x7fffffff;
  1040. else
  1041. {
  1042. // euq = (y0 + 1) * dM;
  1043. euq = Int32x32To64((y0 + 1), dM);
  1044. // euq += eqBeta;
  1045. euq += eqBeta;
  1046. #if DBG
  1047. if (euq < 0)
  1048. {
  1049. RIP("Oops!");
  1050. }
  1051. #endif
  1052. // i = (euq / dN) - x0 + 1;
  1053. // r = (euq % dN);
  1054. i = DIVREM(euq, dN, &r);
  1055. i = i - x0 + 1;
  1056. dI = dM / dN;
  1057. dR = dM % dN; // 0 <= dR < dN
  1058. ASSERTDD(dI > 0, "Weird dI");
  1059. }
  1060. ASSERTDD(i > 0 && i <= 0x7fffffff, "Weird initial strip length");
  1061. ASSERTDD(cPels > 0, "Zero pel line");
  1062. /***********************************************************************\
  1063. * Run the DDA! *
  1064. \***********************************************************************/
  1065. while(TRUE)
  1066. {
  1067. cPels -= i;
  1068. if (cPels <= 0)
  1069. break;
  1070. *plStrip++ = i;
  1071. if (plStrip == plStripEnd)
  1072. {
  1073. strip.cStrips = plStrip - &strip.alStrips[0];
  1074. (*pfn)(ppdev, &strip, pls);
  1075. plStrip = &strip.alStrips[0];
  1076. }
  1077. i = dI;
  1078. r += dR;
  1079. if (r >= dN)
  1080. {
  1081. r -= dN;
  1082. i++;
  1083. }
  1084. }
  1085. *plStrip++ = cPels + i;
  1086. strip.cStrips = plStrip - &strip.alStrips[0];
  1087. (*pfn)(ppdev, &strip, pls);
  1088. }
  1089. Next_Line:
  1090. if (fl & FL_COMPLEX_CLIP)
  1091. {
  1092. cptfx--;
  1093. if (cptfx != 0)
  1094. goto Continue_Complex_Clipping;
  1095. break;
  1096. }
  1097. else
  1098. {
  1099. pptfxFirst = pptfxBuf;
  1100. pptfxBuf++;
  1101. }
  1102. } while (pptfxBuf < pptfxBufEnd);
  1103. return(TRUE);
  1104. }
  1105. #ifdef HARDWAREGIQ
  1106. /////////////////////////////////////////////////////////////////////////
  1107. // The following GIQ code works great -- we simply aren't using it yet.
  1108. /////////////////////////////////////////////////////////////////////////
  1109. typedef struct _DDALINE /* dl */
  1110. {
  1111. LONG iDir;
  1112. POINTL ptlStart;
  1113. LONG cPels;
  1114. LONG dMajor;
  1115. LONG dMinor;
  1116. LONG lErrorTerm;
  1117. } DDALINE;
  1118. #define HW_FLIP_D 0x0001L // Diagonal flip
  1119. #define HW_FLIP_V 0x0002L // Vertical flip
  1120. #define HW_FLIP_H 0x0004L // Horizontal flip
  1121. #define HW_FLIP_SLOPE_ONE 0x0008L // Normalized line has exactly slope one
  1122. #define HW_FLIP_MASK (HW_FLIP_D | HW_FLIP_V | HW_FLIP_H)
  1123. #define HW_X_ROUND_DOWN 0x0100L // x = 1/2 rounds down in value
  1124. #define HW_Y_ROUND_DOWN 0x0200L // y = 1/2 rounds down in value
  1125. LONG gaiDir[] = { 0, 1, 7, 6, 3, 2, 4, 5 };
  1126. FLONG gaflHardwareRound[] = {
  1127. HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN, // | | |
  1128. HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN, // | | | FLIP_D
  1129. HW_X_ROUND_DOWN, // | | FLIP_V |
  1130. HW_Y_ROUND_DOWN, // | | FLIP_V | FLIP_D
  1131. HW_Y_ROUND_DOWN, // | FLIP_H | |
  1132. HW_X_ROUND_DOWN, // | FLIP_H | | FLIP_D
  1133. 0, // | FLIP_H | FLIP_V |
  1134. 0, // | FLIP_H | FLIP_V | FLIP_D
  1135. HW_Y_ROUND_DOWN, // SLOPE_ONE | | |
  1136. 0xffffffff, // SLOPE_ONE | | | FLIP_D
  1137. HW_X_ROUND_DOWN, // SLOPE_ONE | | FLIP_V |
  1138. 0xffffffff, // SLOPE_ONE | | FLIP_V | FLIP_D
  1139. HW_Y_ROUND_DOWN, // SLOPE_ONE | FLIP_H | |
  1140. 0xffffffff, // SLOPE_ONE | FLIP_H | | FLIP_D
  1141. HW_X_ROUND_DOWN, // SLOPE_ONE | FLIP_H | FLIP_V |
  1142. 0xffffffff // SLOPE_ONE | FLIP_H | FLIP_V | FLIP_D
  1143. };
  1144. /******************************Public*Routine******************************\
  1145. * BOOL bHardwareLine(pptfxStart, pptfxEnd, cBits, pdl)
  1146. *
  1147. * This routine is useful for folks who have line drawing hardware where
  1148. * they can explicitly set the Bresenham terms -- they can use this routine
  1149. * to draw fractional coordinate GIQ lines with the hardware.
  1150. *
  1151. * Fractional coordinate lines require an extra 4 bits of precision in the
  1152. * Bresenham terms. For example, if your hardware has 13 bits of precision
  1153. * for the terms, you can only draw GIQ lines up to 255 pels long using this
  1154. * routine.
  1155. *
  1156. * Input:
  1157. * pptfxStart - Points to GIQ coordinate of start of line
  1158. * pptfxEnd - Points to GIQ coordinate of end of line
  1159. * cBits - The number of bits of precision your hardware can support.
  1160. *
  1161. * Output:
  1162. * returns - TRUE if the line can be drawn directly using the line
  1163. * hardware (in which case pdl contains the Bresenham terms
  1164. * for drawing the line).
  1165. * FALSE if the line is too long, and the strips code must be
  1166. * used.
  1167. * pdl - Returns the Bresenham line terms for drawing the line.
  1168. *
  1169. * DDALINE:
  1170. * iDir - Direction of the line, as an octant numbered as follows:
  1171. *
  1172. * \ 5 | 6 /
  1173. * \ | /
  1174. * 4 \ | / 7
  1175. * \ /
  1176. * -----+-----
  1177. * /|\
  1178. * 3 / | \ 0
  1179. * / | \
  1180. * / 2 | 1 \
  1181. *
  1182. * ptlStart - Start pixel of line.
  1183. * cPels - # of pels in line. *NOTE* You must check if this is <= 0!
  1184. * dMajor - Major axis delta.
  1185. * dMinor - Minor axis delta.
  1186. * lErrorTerm - Error term.
  1187. *
  1188. * What you do with the last 3 terms may be a little tricky. They are
  1189. * actually the terms for the formula of the normalized line
  1190. *
  1191. * dMinor * x + (lErrorTerm + dMajor)
  1192. * y(x) = floor( ---------------------------------- )
  1193. * dMajor
  1194. *
  1195. * where y(x) is the y coordinate of the pixel to be lit as a function of
  1196. * the x-coordinate.
  1197. *
  1198. * Every time the line advances one in the major direction 'x', dMinor
  1199. * gets added to the current error term. If the resulting value is >= 0,
  1200. * we know we have to move one pixel in the minor direction 'y', and
  1201. * dMajor must be subtracted from the current error term.
  1202. *
  1203. * If you're trying to figure out what this means for your hardware, you can
  1204. * think of the DDALINE terms as having been computed equivalently as
  1205. * follows:
  1206. *
  1207. * pdl->dMinor = 2 * (minor axis delta)
  1208. * pdl->dMajor = 2 * (major axis delta)
  1209. * pdl->lErrorTerm = - (major axis delta) - fixup
  1210. *
  1211. * That is, if your documentation tells you that for integer lines, a
  1212. * register is supposed to be initialized with the value
  1213. * '2 * (minor axis delta)', you'll actually use pdl->dMinor.
  1214. *
  1215. * Example: Setting up the 8514
  1216. *
  1217. * AXSTPSIGN is supposed to be the axial step constant register, defined
  1218. * as 2 * (minor axis delta). You set:
  1219. *
  1220. * AXSTPSIGN = pdl->dMinor
  1221. *
  1222. * DGSTPSIGN is supposed to be the diagonal step constant register,
  1223. * defined as 2 * (minor axis delta) - 2 * (major axis delta). You set:
  1224. *
  1225. * DGSTPSIGN = pdl->dMinor - pdl->dMajor
  1226. *
  1227. * ERR_TERM is supposed to be the adjusted error term, defined as
  1228. * 2 * (minor axis delta) - (major axis delta) - fixup. You set:
  1229. *
  1230. * ERR_TERM = pdl->lErrorTerm + pdl->dMinor
  1231. *
  1232. * Implementation:
  1233. *
  1234. * You'll want to special case integer lines before calling this routine
  1235. * (since they're very common, take less time to the computation of line
  1236. * terms, and can handle longer lines than this routine because 4 bits
  1237. * aren't being given to the fraction).
  1238. *
  1239. * If a GIQ line is too long to be handled by this routine, you can just
  1240. * use the slower strip routines for that line. Note that you cannot
  1241. * just fail the call -- you must be able to accurately draw any line
  1242. * in the 28.4 device space when it intersects the viewport.
  1243. *
  1244. * Testing:
  1245. *
  1246. * Use Guiman, or some other test that draws random fractional coordinate
  1247. * lines and compares them to what GDI itself draws to a bitmap.
  1248. *
  1249. \**************************************************************************/
  1250. BOOL bHardwareLine(
  1251. POINTFIX* pptfxStart, // Start of line
  1252. POINTFIX* pptfxEnd, // End of line
  1253. LONG cBits, // # bits precision in hardware Bresenham terms
  1254. DDALINE* pdl) // Returns Bresenham terms for doing line
  1255. {
  1256. FLONG fl; // Various flags
  1257. ULONG M0; // Normalized fractional unit x start coordinate (0 <= M0 < F)
  1258. ULONG N0; // Normalized fractional unit y start coordinate (0 <= N0 < F)
  1259. ULONG M1; // Normalized fractional unit x end coordinate (0 <= M1 < F)
  1260. ULONG N1; // Normalized fractional unit x end coordinate (0 <= N1 < F)
  1261. ULONG dM; // Normalized fractional unit x-delta (0 <= dM)
  1262. ULONG dN; // Normalized fractional unit y-delta (0 <= dN <= dM)
  1263. LONG x; // Normalized x coordinate of origin
  1264. LONG y; // Normalized y coordinate of origin
  1265. LONG x0; // Normalized x offset from origin to start pixel (inclusive)
  1266. LONG y0; // Normalized y offset from origin to start pixel (inclusive)
  1267. LONG x1; // Normalized x offset from origin to end pixel (inclusive)
  1268. LONG lGamma;// Bresenham error term at origin
  1269. /***********************************************************************\
  1270. * Normalize line to the first octant.
  1271. \***********************************************************************/
  1272. fl = 0;
  1273. M0 = pptfxStart->x;
  1274. dM = pptfxEnd->x;
  1275. if ((LONG) dM < (LONG) M0)
  1276. {
  1277. // Line runs from right to left, so flip across x = 0:
  1278. M0 = -(LONG) M0;
  1279. dM = -(LONG) dM;
  1280. fl |= HW_FLIP_H;
  1281. }
  1282. // Compute the delta. The DDI says we can never have a valid delta
  1283. // with a magnitude more than 2^31 - 1, but the engine never actually
  1284. // checks its transforms. To ensure that we'll never puke on our shoes,
  1285. // we check for that case and simply refuse to draw the line:
  1286. dM -= M0;
  1287. if ((LONG) dM < 0)
  1288. return(FALSE);
  1289. N0 = pptfxStart->y;
  1290. dN = pptfxEnd->y;
  1291. if ((LONG) dN < (LONG) N0)
  1292. {
  1293. // Line runs from bottom to top, so flip across y = 0:
  1294. N0 = -(LONG) N0;
  1295. dN = -(LONG) dN;
  1296. fl |= HW_FLIP_V;
  1297. }
  1298. // Compute another delta:
  1299. dN -= N0;
  1300. if ((LONG) dN < 0)
  1301. return(FALSE);
  1302. if (dN >= dM)
  1303. {
  1304. if (dN == dM)
  1305. {
  1306. // Have to special case slopes of one:
  1307. fl |= HW_FLIP_SLOPE_ONE;
  1308. }
  1309. else
  1310. {
  1311. // Since line has slope greater than 1, flip across x = y:
  1312. register ULONG ulTmp;
  1313. ulTmp = dM; dM = dN; dN = ulTmp;
  1314. ulTmp = M0; M0 = N0; N0 = ulTmp;
  1315. fl |= HW_FLIP_D;
  1316. }
  1317. }
  1318. // Figure out if we can do the line in hardware, given that we have a
  1319. // limited number of bits of precision for the Bresenham terms.
  1320. //
  1321. // Remember that one bit has to be kept as a sign bit:
  1322. if ((LONG) dM >= (1L << (cBits - 1)))
  1323. return(FALSE);
  1324. fl |= gaflHardwareRound[fl];
  1325. /***********************************************************************\
  1326. * Calculate the error term at pixel 0.
  1327. \***********************************************************************/
  1328. x = LFLOOR((LONG) M0);
  1329. y = LFLOOR((LONG) N0);
  1330. M0 = FXFRAC(M0);
  1331. N0 = FXFRAC(N0);
  1332. // NOTE NOTE NOTE: If this routine were to handle any line in the 28.4
  1333. // space, it will overflow its math (the following part requires 36 bits
  1334. // of precision)! But we get here for lines that the hardware can handle
  1335. // (see the expression (dM >= (1L << (cBits - 1))) above?), so if cBits
  1336. // is less than 28, we're safe.
  1337. //
  1338. // If you're going to use this routine to handle all lines in the 28.4
  1339. // device space, you will HAVE to make sure the math doesn't overflow,
  1340. // otherwise you won't be NT compliant! (See lines.cxx for an example
  1341. // how to do that. You don't have to worry about this if you simply
  1342. // default to the strips code for long lines, because those routines
  1343. // already do the math correctly.)
  1344. // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]. Note
  1345. // that M0 and N0 have at most 4 bits of significance (and if the
  1346. // arguments are properly ordered, on a 486 each multiply would be no
  1347. // more than 13 cycles):
  1348. lGamma = (N0 + F/2) * dM - M0 * dN;
  1349. if (fl & HW_Y_ROUND_DOWN)
  1350. lGamma--;
  1351. lGamma >>= FLOG2;
  1352. /***********************************************************************\
  1353. * Figure out which pixels are at the ends of the line.
  1354. \***********************************************************************/
  1355. // The toughest part of GIQ is determining the start and end pels.
  1356. //
  1357. // Our approach here is to calculate x0 and x1 (the inclusive start
  1358. // and end columns of the line respectively, relative to our normalized
  1359. // origin). Then x1 - x0 + 1 is the number of pels in the line. The
  1360. // start point is easily calculated by plugging x0 into our line equation
  1361. // (which takes care of whether y = 1/2 rounds up or down in value)
  1362. // getting y0, and then undoing the normalizing flips to get back
  1363. // into device space.
  1364. //
  1365. // We look at the fractional parts of the coordinates of the start and
  1366. // end points, and call them (M0, N0) and (M1, N1) respectively, where
  1367. // 0 <= M0, N0, M1, N1 < 16. We plot (M0, N0) on the following grid
  1368. // to determine x0:
  1369. //
  1370. // +-----------------------> +x
  1371. // |
  1372. // | 0 1
  1373. // | 0123456789abcdef
  1374. // |
  1375. // | 0 ........?xxxxxxx
  1376. // | 1 ..........xxxxxx
  1377. // | 2 ...........xxxxx
  1378. // | 3 ............xxxx
  1379. // | 4 .............xxx
  1380. // | 5 ..............xx
  1381. // | 6 ...............x
  1382. // | 7 ................
  1383. // | 8 ................
  1384. // | 9 ......**........
  1385. // | a ........****...x
  1386. // | b ............****
  1387. // | c .............xxx****
  1388. // | d ............xxxx ****
  1389. // | e ...........xxxxx ****
  1390. // | f ..........xxxxxx
  1391. // |
  1392. // | 2 3
  1393. // v
  1394. //
  1395. // +y
  1396. //
  1397. // This grid accounts for the appropriate rounding of GIQ and last-pel
  1398. // exclusion. If (M0, N0) lands on an 'x', x0 = 2. If (M0, N0) lands
  1399. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  1400. // depending on what flips have been done to normalize the line.
  1401. //
  1402. // For the end point, if (M1, N1) lands on an 'x', x1 =
  1403. // floor((M0 + dM) / 16) + 1. If (M1, N1) lands on a '.', x1 =
  1404. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  1405. // depending on what flips have been done to normalize the line.
  1406. //
  1407. // Lines of exactly slope one require a special case for both the start
  1408. // and end. For example, if the line ends such that (M1, N1) is (9, 1),
  1409. // the line has gone exactly through (8, 0) -- which may be considered
  1410. // to be part of 'x' because of rounding! So slopes of exactly slope
  1411. // one going through (8, 0) must also be considered as belonging in 'x'
  1412. // when an x value of 1/2 is supposed to round up in value.
  1413. // Calculate x0, x1:
  1414. N1 = FXFRAC(N0 + dN);
  1415. M1 = FXFRAC(M0 + dM);
  1416. x1 = LFLOOR(M0 + dM);
  1417. // Line runs left-to-right:
  1418. // Compute x1:
  1419. x1--;
  1420. if (M1 > 0)
  1421. {
  1422. if (N1 == 0)
  1423. {
  1424. if (LROUND(M1, fl & HW_X_ROUND_DOWN))
  1425. x1++;
  1426. }
  1427. else if (ABS((LONG) (N1 - F/2)) <= (LONG) M1)
  1428. {
  1429. x1++;
  1430. }
  1431. }
  1432. if ((fl & (HW_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
  1433. == (HW_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
  1434. {
  1435. // Have to special-case diagonal lines going through our
  1436. // the point exactly equidistant between two horizontal
  1437. // pixels, if we're supposed to round x=1/2 down:
  1438. if ((N1 > 0) && (M1 == N1 + 8))
  1439. x1--;
  1440. if ((M0 > 0) && (N0 == M0 + 8))
  1441. {
  1442. x0 = 0;
  1443. goto left_to_right_compute_y0;
  1444. }
  1445. }
  1446. // Compute x0:
  1447. x0 = 0;
  1448. if (M0 > 0)
  1449. {
  1450. if (N0 == 0)
  1451. {
  1452. if (LROUND(M0, fl & HW_X_ROUND_DOWN))
  1453. x0 = 1;
  1454. }
  1455. else if (ABS((LONG) (N0 - F/2)) <= (LONG) M0)
  1456. {
  1457. x0 = 1;
  1458. }
  1459. }
  1460. left_to_right_compute_y0:
  1461. /***********************************************************************\
  1462. * Calculate the start pixel.
  1463. \***********************************************************************/
  1464. // We now compute y0 and adjust the error term. We know x0, and we know
  1465. // the current formula for the pixels to be lit on the line:
  1466. //
  1467. // dN * x + lGamma
  1468. // y(x) = floor( --------------- )
  1469. // dM
  1470. //
  1471. // The remainder of this expression is the new error term at (x0, y0).
  1472. // Since x0 is going to be either 0 or 1, we don't actually have to do a
  1473. // multiply or divide to compute y0. Finally, we subtract dM from the
  1474. // new error term so that it is in the range [-dM, 0).
  1475. y0 = 0;
  1476. lGamma += (dN & (-x0));
  1477. lGamma -= dM;
  1478. if (lGamma >= 0)
  1479. {
  1480. y0 = 1;
  1481. lGamma -= dM;
  1482. }
  1483. // Undo our flips to get the start coordinate:
  1484. x += x0;
  1485. y += y0;
  1486. if (fl & HW_FLIP_D)
  1487. {
  1488. register LONG lTmp;
  1489. lTmp = x; x = y; y = lTmp;
  1490. }
  1491. if (fl & HW_FLIP_V)
  1492. {
  1493. y = -y;
  1494. }
  1495. if (fl & HW_FLIP_H)
  1496. {
  1497. x = -x;
  1498. }
  1499. /***********************************************************************\
  1500. * Return the Bresenham terms:
  1501. \***********************************************************************/
  1502. pdl->iDir = gaiDir[fl & HW_FLIP_MASK];
  1503. pdl->ptlStart.x = x;
  1504. pdl->ptlStart.y = y;
  1505. pdl->cPels = x1 - x0 + 1; // NOTE: You'll have to check if cPels <= 0!
  1506. pdl->dMajor = dM;
  1507. pdl->dMinor = dN;
  1508. pdl->lErrorTerm = lGamma;
  1509. return(TRUE);
  1510. }
  1511. #endif // HARDWAREGIQ