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.

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