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.

954 lines
23 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Strips.c
  3. *
  4. * All the line code in this driver amounts to a big bag of dirt. Someday,
  5. * I'm going to rewrite it all. Not today, though (sigh)...
  6. *
  7. * Copyright (c) 1992-1994 Microsoft Corporation
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. /******************************Public*Routine******************************\
  11. * VOID vssSolidHorizontal
  12. *
  13. * Draws left-to-right x-major near-horizontal lines using short-stroke
  14. * vectors. Is faster than using the radial-line routine, but only works
  15. * when every strip is 15 pels in length or less.
  16. *
  17. \**************************************************************************/
  18. VOID vssSolidHorizontal(
  19. PDEV* ppdev,
  20. STRIP* pStrip,
  21. LINESTATE* pLineState)
  22. {
  23. LONG i, cStrips;
  24. PLONG pStrips;
  25. LONG xPels, xSumPels, yDir;
  26. USHORT Cmd, ssCmd, dirDraw, dirSkip;
  27. Cmd = DRAW | WRITE | MULTIPLE_PIXELS |
  28. DIR_TYPE_RADIAL | LAST_PIXEL_OFF |
  29. BUS_SIZE_16 | BYTE_SWAP;
  30. cStrips = pStrip->cStrips;
  31. IO_FIFO_WAIT(ppdev, 3);
  32. IO_CUR_X(ppdev, pStrip->ptlStart.x);
  33. IO_CUR_Y(ppdev, pStrip->ptlStart.y);
  34. IO_CMD(ppdev, Cmd);
  35. // Setup the drawing direction and the skip direction.
  36. dirDraw = 0x10;
  37. if (!(pStrip->flFlips & FL_FLIP_V))
  38. {
  39. yDir = 1;
  40. dirSkip = 0xC100;
  41. }
  42. else
  43. {
  44. dirSkip = 0x4100;
  45. yDir = -1;
  46. }
  47. // Output the short stroke commands.
  48. xSumPels = 0;
  49. pStrips = pStrip->alStrips;
  50. for (i = 0; i < cStrips; i++)
  51. {
  52. xPels = *pStrips++;
  53. xSumPels += xPels;
  54. ssCmd = (USHORT) (dirSkip | dirDraw | xPels);
  55. IO_FIFO_WAIT(ppdev, 4);
  56. IO_SHORT_STROKE(ppdev, ssCmd);
  57. }
  58. pStrip->ptlStart.x += xSumPels;
  59. pStrip->ptlStart.y += cStrips * yDir;
  60. }
  61. /******************************Public*Routine******************************\
  62. * VOID vrlSolidHorizontal
  63. *
  64. * Draws left-to-right x-major near-horizontal lines using radial lines.
  65. *
  66. \**************************************************************************/
  67. VOID vrlSolidHorizontal(
  68. PDEV* ppdev,
  69. STRIP* pStrip,
  70. LINESTATE* pLineState)
  71. {
  72. LONG cStrips;
  73. USHORT Cmd;
  74. LONG i, yInc, x, y;
  75. PLONG pStrips;
  76. Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
  77. LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_0 |
  78. WRITE;
  79. cStrips = pStrip->cStrips;
  80. x = pStrip->ptlStart.x;
  81. y = pStrip->ptlStart.y;
  82. yInc = 1;
  83. if (pStrip->flFlips & FL_FLIP_V)
  84. yInc = -1;
  85. pStrips = pStrip->alStrips;
  86. for (i = 0; i < cStrips; i++)
  87. {
  88. IO_FIFO_WAIT(ppdev, 4);
  89. IO_CUR_X(ppdev, x);
  90. IO_CUR_Y(ppdev, y);
  91. IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
  92. IO_CMD(ppdev, Cmd);
  93. x += *pStrips++;
  94. y += yInc;
  95. }
  96. pStrip->ptlStart.x = x;
  97. pStrip->ptlStart.y = y;
  98. }
  99. /******************************Public*Routine******************************\
  100. * VOID vssSolidVertical
  101. *
  102. * Draws left-to-right y-major near-vertical lines using short-stroke
  103. * vectors. Is faster than using the radial-line routine, but only works
  104. * when every strip is 15 pels in length or less.
  105. *
  106. \**************************************************************************/
  107. VOID vssSolidVertical(
  108. PDEV* ppdev,
  109. STRIP* pStrip,
  110. LINESTATE* pLineState)
  111. {
  112. LONG i, cStrips;
  113. PLONG pStrips;
  114. LONG yPels, ySumPels, yDir;
  115. USHORT Cmd, ssCmd, dirDraw, dirSkip;
  116. Cmd = DRAW | WRITE | MULTIPLE_PIXELS |
  117. DIR_TYPE_RADIAL | LAST_PIXEL_OFF |
  118. BUS_SIZE_16 | BYTE_SWAP;
  119. cStrips = pStrip->cStrips;
  120. IO_FIFO_WAIT(ppdev, 3);
  121. IO_CUR_X(ppdev, pStrip->ptlStart.x);
  122. IO_CUR_Y(ppdev, pStrip->ptlStart.y);
  123. IO_CMD(ppdev, Cmd);
  124. // Setup the drawing direction and the skip direction.
  125. if (!(pStrip->flFlips & FL_FLIP_V))
  126. {
  127. yDir = 1;
  128. dirDraw = 0xD0;
  129. }
  130. else
  131. {
  132. yDir = -1;
  133. dirDraw = 0x50;
  134. }
  135. dirSkip = 0x0100;
  136. // Output the short stroke commands.
  137. ySumPels = 0;
  138. pStrips = pStrip->alStrips;
  139. for (i = 0; i < cStrips; i++)
  140. {
  141. yPels = *pStrips++;
  142. ySumPels += yPels;
  143. ssCmd = (USHORT) (dirSkip | dirDraw | yPels);
  144. IO_FIFO_WAIT(ppdev, 4);
  145. IO_SHORT_STROKE(ppdev, ssCmd);
  146. }
  147. pStrip->ptlStart.x += cStrips;
  148. pStrip->ptlStart.y += ySumPels * yDir;
  149. }
  150. /******************************Public*Routine******************************\
  151. * VOID vrlSolidVertical
  152. *
  153. * Draws left-to-right y-major near-vertical lines using radial lines.
  154. *
  155. \**************************************************************************/
  156. VOID vrlSolidVertical(
  157. PDEV* ppdev,
  158. STRIP* pStrip,
  159. LINESTATE* pLineState)
  160. {
  161. LONG cStrips;
  162. USHORT Cmd;
  163. LONG i, x, y;
  164. PLONG pStrips;
  165. cStrips = pStrip->cStrips;
  166. pStrips = pStrip->alStrips;
  167. x = pStrip->ptlStart.x;
  168. y = pStrip->ptlStart.y;
  169. if (!(pStrip->flFlips & FL_FLIP_V))
  170. {
  171. Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
  172. LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_270 |
  173. WRITE;
  174. for (i = 0; i < cStrips; i++)
  175. {
  176. IO_FIFO_WAIT(ppdev, 4);
  177. IO_CUR_X(ppdev, x);
  178. IO_CUR_Y(ppdev, y);
  179. IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
  180. IO_CMD(ppdev, Cmd);
  181. y += *pStrips++;
  182. x++;
  183. }
  184. }
  185. else
  186. {
  187. Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
  188. LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_90 |
  189. WRITE;
  190. for (i = 0; i < cStrips; i++)
  191. {
  192. IO_FIFO_WAIT(ppdev, 4);
  193. IO_CUR_X(ppdev, x);
  194. IO_CUR_Y(ppdev, y);
  195. IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
  196. IO_CMD(ppdev, Cmd);
  197. y -= *pStrips++;
  198. x++;
  199. }
  200. }
  201. pStrip->ptlStart.x = x;
  202. pStrip->ptlStart.y = y;
  203. }
  204. /******************************Public*Routine******************************\
  205. * VOID vssSolidDiagonalHorizontal
  206. *
  207. * Draws left-to-right x-major near-diagonal lines using short-stroke
  208. * vectors. Is faster than using the radial-line routine, but only
  209. * works when every strip is 15 pels in length or less.
  210. *
  211. \**************************************************************************/
  212. VOID vssSolidDiagonalHorizontal(
  213. PDEV* ppdev,
  214. STRIP* pStrip,
  215. LINESTATE* pLineState)
  216. {
  217. LONG i, cStrips;
  218. PLONG pStrips;
  219. LONG Pels, SumPels, yDir;
  220. USHORT Cmd, ssCmd, dirDraw, dirSkip;
  221. Cmd = DRAW | WRITE | MULTIPLE_PIXELS |
  222. DIR_TYPE_RADIAL | LAST_PIXEL_OFF |
  223. BUS_SIZE_16 | BYTE_SWAP;
  224. cStrips = pStrip->cStrips;
  225. IO_FIFO_WAIT(ppdev, 3);
  226. IO_CUR_X(ppdev, pStrip->ptlStart.x);
  227. IO_CUR_Y(ppdev, pStrip->ptlStart.y);
  228. IO_CMD(ppdev, Cmd);
  229. // Setup the drawing direction and the skip direction.
  230. if (!(pStrip->flFlips & FL_FLIP_V))
  231. {
  232. yDir = 1;
  233. dirDraw = 0xF0;
  234. dirSkip = 0x4100;
  235. }
  236. else
  237. {
  238. yDir = -1;
  239. dirDraw = 0x30;
  240. dirSkip = 0xC100;
  241. }
  242. // Output the short stroke commands.
  243. SumPels = 0;
  244. pStrips = pStrip->alStrips;
  245. for (i = 0; i < cStrips; i++)
  246. {
  247. Pels = *pStrips++;
  248. SumPels += Pels;
  249. ssCmd = (USHORT)(dirSkip | dirDraw | Pels);
  250. IO_FIFO_WAIT(ppdev, 4);
  251. IO_SHORT_STROKE(ppdev, ssCmd);
  252. }
  253. pStrip->ptlStart.x += SumPels;
  254. pStrip->ptlStart.y += (SumPels - cStrips) * yDir;
  255. }
  256. /******************************Public*Routine******************************\
  257. * VOID vrlSolidDiagonalHorizontal
  258. *
  259. * Draws left-to-right x-major near-diagonal lines using radial lines.
  260. *
  261. \**************************************************************************/
  262. VOID vrlSolidDiagonalHorizontal(
  263. PDEV* ppdev,
  264. STRIP* pStrip,
  265. LINESTATE* pLineState)
  266. {
  267. LONG cStrips;
  268. USHORT Cmd;
  269. LONG i, x, y;
  270. PLONG pStrips;
  271. cStrips = pStrip->cStrips;
  272. pStrips = pStrip->alStrips;
  273. x = pStrip->ptlStart.x;
  274. y = pStrip->ptlStart.y;
  275. if (!(pStrip->flFlips & FL_FLIP_V))
  276. {
  277. Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
  278. LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_315 |
  279. WRITE;
  280. for (i = 0; i < cStrips; i++)
  281. {
  282. IO_FIFO_WAIT(ppdev, 4);
  283. IO_CUR_X(ppdev, x);
  284. IO_CUR_Y(ppdev, y);
  285. IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
  286. IO_CMD(ppdev, Cmd);
  287. y += *pStrips - 1;
  288. x += *pStrips++;
  289. }
  290. }
  291. else
  292. {
  293. Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
  294. LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_45 |
  295. WRITE;
  296. for (i = 0; i < cStrips; i++)
  297. {
  298. IO_FIFO_WAIT(ppdev, 4);
  299. IO_CUR_X(ppdev, x);
  300. IO_CUR_Y(ppdev, y);
  301. IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
  302. IO_CMD(ppdev, Cmd);
  303. y -= *pStrips - 1;
  304. x += *pStrips++;
  305. }
  306. }
  307. pStrip->ptlStart.x = x;
  308. pStrip->ptlStart.y = y;
  309. }
  310. /******************************Public*Routine******************************\
  311. * VOID vssSolidDiagonalVertical
  312. *
  313. * Draws left-to-right y-major near-diagonal lines using short-stroke
  314. * vectors. Is faster than using the radial-line routine, but only
  315. * works when every strip is 15 pels in length or less.
  316. *
  317. \**************************************************************************/
  318. VOID vssSolidDiagonalVertical(
  319. PDEV* ppdev,
  320. STRIP* pStrip,
  321. LINESTATE* pLineState)
  322. {
  323. LONG i, cStrips;
  324. PLONG pStrips;
  325. LONG Pels, SumPels, yDir;
  326. USHORT Cmd, ssCmd, dirDraw, dirSkip;
  327. Cmd = DRAW | WRITE | MULTIPLE_PIXELS |
  328. DIR_TYPE_RADIAL | LAST_PIXEL_OFF |
  329. BUS_SIZE_16 | BYTE_SWAP;
  330. cStrips = pStrip->cStrips;
  331. IO_FIFO_WAIT(ppdev, 3);
  332. IO_CUR_X(ppdev, pStrip->ptlStart.x);
  333. IO_CUR_Y(ppdev, pStrip->ptlStart.y);
  334. IO_CMD(ppdev, Cmd);
  335. // Setup the drawing direction and the skip direction.
  336. if (!(pStrip->flFlips & FL_FLIP_V))
  337. {
  338. yDir = 1;
  339. dirDraw = 0xF0;
  340. }
  341. else
  342. {
  343. yDir = -1;
  344. dirDraw = 0x30;
  345. }
  346. dirSkip = 0x8100;
  347. // Output the short stroke commands.
  348. SumPels = 0;
  349. pStrips = pStrip->alStrips;
  350. for (i = 0; i < cStrips; i++)
  351. {
  352. Pels = *pStrips++;
  353. SumPels += Pels;
  354. ssCmd = (USHORT)(dirSkip | dirDraw | Pels);
  355. IO_FIFO_WAIT(ppdev, 4);
  356. IO_SHORT_STROKE(ppdev, ssCmd);
  357. }
  358. pStrip->ptlStart.x += SumPels - cStrips;
  359. pStrip->ptlStart.y += SumPels * yDir;
  360. }
  361. /******************************Public*Routine******************************\
  362. * VOID vrlSolidDiagonalVertical
  363. *
  364. * Draws left-to-right y-major near-diagonal lines using radial lines.
  365. *
  366. \**************************************************************************/
  367. VOID vrlSolidDiagonalVertical(
  368. PDEV* ppdev,
  369. STRIP* pStrip,
  370. LINESTATE* pLineState)
  371. {
  372. LONG cStrips;
  373. USHORT Cmd;
  374. LONG i, x, y;
  375. PLONG pStrips;
  376. cStrips = pStrip->cStrips;
  377. pStrips = pStrip->alStrips;
  378. x = pStrip->ptlStart.x;
  379. y = pStrip->ptlStart.y;
  380. if (!(pStrip->flFlips & FL_FLIP_V))
  381. {
  382. Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
  383. LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_315 |
  384. WRITE;
  385. for (i = 0; i < cStrips; i++)
  386. {
  387. IO_FIFO_WAIT(ppdev, 4);
  388. IO_CUR_X(ppdev, x);
  389. IO_CUR_Y(ppdev, y);
  390. IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
  391. IO_CMD(ppdev, Cmd);
  392. y += *pStrips;
  393. x += *pStrips++ - 1;
  394. }
  395. }
  396. else
  397. {
  398. Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
  399. LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_45 |
  400. WRITE;
  401. for (i = 0; i < cStrips; i++)
  402. {
  403. IO_FIFO_WAIT(ppdev, 4);
  404. IO_CUR_X(ppdev, x);
  405. IO_CUR_Y(ppdev, y);
  406. IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
  407. IO_CMD(ppdev, Cmd);
  408. y -= *pStrips;
  409. x += *pStrips++ - 1;
  410. }
  411. }
  412. pStrip->ptlStart.x = x;
  413. pStrip->ptlStart.y = y;
  414. }
  415. /******************************Public*Routine******************************\
  416. * VOID vStripStyledHorizontal
  417. *
  418. * Takes the list of strips that define the pixels that would be lit for
  419. * a solid line, and breaks them into styling chunks according to the
  420. * styling information that is passed in.
  421. *
  422. * This particular routine handles x-major lines that run left-to-right,
  423. * and are comprised of horizontal strips. It draws the dashes using
  424. * short-stroke vectors.
  425. *
  426. * The performance of this routine could be improved significantly if
  427. * anyone cared enough about styled lines improve it.
  428. *
  429. \**************************************************************************/
  430. VOID vStripStyledHorizontal(
  431. PDEV* ppdev,
  432. STRIP* pstrip,
  433. LINESTATE* pls)
  434. {
  435. LONG x;
  436. LONG y;
  437. ULONG dirSkip;
  438. LONG dy;
  439. LONG* plStrip;
  440. LONG cStrips;
  441. LONG cStyle;
  442. LONG cStrip;
  443. LONG cThis;
  444. ULONG bIsGap;
  445. if (pstrip->flFlips & FL_FLIP_V)
  446. {
  447. // The minor direction of the line is 90 degrees, and the major
  448. // direction is 0 (it's a left-to-right x-major line going up):
  449. dirSkip = 0x4110;
  450. dy = -1;
  451. }
  452. else
  453. {
  454. // The minor direction of the line is 270 degrees, and the major
  455. // direction is 0 (it's a left-to-right x-major line going down):
  456. dirSkip = 0xc110;
  457. dy = 1;
  458. }
  459. cStrips = pstrip->cStrips; // Total number of strips we'll do
  460. plStrip = pstrip->alStrips; // Points to current strip
  461. x = pstrip->ptlStart.x; // x position of start of first strip
  462. y = pstrip->ptlStart.y; // y position of start of first strip
  463. // Warm up the hardware so that it will know we'll be outputing
  464. // short-stroke vectors, and so that it will have the current position
  465. // correctly set if we're starting in the middle of a 'dash':
  466. IO_FIFO_WAIT(ppdev, 3);
  467. IO_CUR_X(ppdev, x);
  468. IO_CUR_Y(ppdev, y);
  469. IO_CMD(ppdev, DRAW | WRITE | MULTIPLE_PIXELS |
  470. DIR_TYPE_RADIAL | LAST_PIXEL_OFF | BUS_SIZE_16 |
  471. BYTE_SWAP);
  472. cStrip = *plStrip; // Number of pels in first strip
  473. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  474. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  475. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  476. // and zero if we're in the middle of a 'dash':
  477. if (bIsGap)
  478. goto SkipAGap;
  479. else
  480. goto OutputADash;
  481. PrepareToSkipAGap:
  482. // Advance in the style-state array, so that we can find the next
  483. // 'dot' that we'll have to display:
  484. bIsGap = ~bIsGap;
  485. pls->psp++;
  486. if (pls->psp > pls->pspEnd)
  487. pls->psp = pls->pspStart;
  488. cStyle = *pls->psp;
  489. // If 'cStrip' is zero, we also need a new strip:
  490. if (cStrip != 0)
  491. goto SkipAGap;
  492. // Here, we're in the middle of a 'gap' where we don't have to
  493. // display anything. We simply cycle through all the strips
  494. // we can, keeping track of the current position, until we run
  495. // out of 'gap':
  496. while (TRUE)
  497. {
  498. // Each time we loop, we move to a new scan and need a new strip:
  499. y += dy;
  500. plStrip++;
  501. cStrips--;
  502. if (cStrips == 0)
  503. goto AllDone;
  504. cStrip = *plStrip;
  505. SkipAGap:
  506. cThis = min(cStrip, cStyle);
  507. cStyle -= cThis;
  508. cStrip -= cThis;
  509. x += cThis;
  510. if (cStyle == 0)
  511. goto PrepareToOutputADash;
  512. }
  513. PrepareToOutputADash:
  514. // Advance in the style-state array, so that we can find the next
  515. // 'dot' that we'll have to display:
  516. bIsGap = ~bIsGap;
  517. pls->psp++;
  518. if (pls->psp > pls->pspEnd)
  519. pls->psp = pls->pspStart;
  520. cStyle = *pls->psp;
  521. // We're gonna need the current position to be correct when we
  522. // start outputing short-stroke vectors:
  523. IO_FIFO_WAIT(ppdev, 2);
  524. IO_CUR_X(ppdev, x);
  525. // If 'cStrip' is zero, we also need a new strip.
  526. if (cStrip != 0)
  527. {
  528. // There's more to be done in the current strip, so set 'y'
  529. // to be the current scan:
  530. IO_CUR_Y(ppdev, y);
  531. goto OutputADash;
  532. }
  533. // Set 'y' to be the scan we're about to move to, because we've
  534. // finished with the current strip:
  535. IO_CUR_Y(ppdev, y + dy);
  536. while (TRUE)
  537. {
  538. // Each time we loop, we move to a new scan and need a new strip:
  539. y += dy;
  540. plStrip++;
  541. cStrips--;
  542. if (cStrips == 0)
  543. goto AllDone;
  544. cStrip = *plStrip;
  545. OutputADash:
  546. cThis = min(cStrip, cStyle);
  547. cStyle -= cThis;
  548. cStrip -= cThis;
  549. x += cThis;
  550. // Short stroke vectors can handle lines that are a maximum of
  551. // 15 pels long. When we have to draw a longer consecutive
  552. // segment than that, we simply break it into 16 pel portions:
  553. while (cThis > 15)
  554. {
  555. // Draw two horizontal strokes together to make up one 16 pel
  556. // segment:
  557. IO_FIFO_WAIT(ppdev, 1);
  558. IO_SHORT_STROKE(ppdev, 0x1f11);
  559. cThis -= 16;
  560. }
  561. // Draw the remaining lit part of the strip:
  562. IO_FIFO_WAIT(ppdev, 1);
  563. IO_SHORT_STROKE(ppdev, dirSkip | cThis);
  564. if (cStyle == 0)
  565. goto PrepareToSkipAGap;
  566. }
  567. AllDone:
  568. // Update our state variables so that the next line can continue
  569. // where we left off:
  570. pls->spRemaining = cStyle;
  571. pls->ulStyleMask = bIsGap;
  572. pstrip->ptlStart.x = x;
  573. pstrip->ptlStart.y = y;
  574. }
  575. /******************************Public*Routine******************************\
  576. * VOID vStripStyledVertical
  577. *
  578. * Takes the list of strips that define the pixels that would be lit for
  579. * a solid line, and breaks them into styling chunks according to the
  580. * styling information that is passed in.
  581. *
  582. * This particular routine handles y-major lines that run left-to-right,
  583. * and are comprised of vertical strips. It draws the dashes using
  584. * short-stroke vectors.
  585. *
  586. * The performance of this routine could be improved significantly if
  587. * anyone cared enough about styled lines improve it.
  588. *
  589. \**************************************************************************/
  590. VOID vStripStyledVertical(
  591. PDEV* ppdev,
  592. STRIP* pstrip,
  593. LINESTATE* pls)
  594. {
  595. LONG x;
  596. LONG y;
  597. ULONG dirSkip;
  598. ULONG dirSkip16;
  599. LONG dy;
  600. LONG* plStrip;
  601. LONG cStrips;
  602. LONG cStyle;
  603. LONG cStrip;
  604. LONG cThis;
  605. ULONG bIsGap;
  606. if (pstrip->flFlips & FL_FLIP_V)
  607. {
  608. // The minor direction of the line is 0 degrees, and the major
  609. // direction is 90 (it's a left-to-right y-major line going up):
  610. dirSkip = 0x0150;
  611. dirSkip16 = 0x5f51; // For drawing 16 pels straight up
  612. dy = -1;
  613. }
  614. else
  615. {
  616. // The minor direction of the line is 0 degrees, and the major
  617. // direction is 270 (it's a left-to-right y-major line going down):
  618. dirSkip = 0x01d0;
  619. dirSkip16 = 0xdfd1; // For drawing 16 pels straight down
  620. dy = 1;
  621. }
  622. cStrips = pstrip->cStrips; // Total number of strips we'll do
  623. plStrip = pstrip->alStrips; // Points to current strip
  624. x = pstrip->ptlStart.x; // x position of start of first strip
  625. y = pstrip->ptlStart.y; // y position of start of first strip
  626. // Warm up the hardware so that it will know we'll be outputing
  627. // short-stroke vectors, and so that it will have the current position
  628. // correctly set if we're starting in the middle of a 'dash':
  629. IO_FIFO_WAIT(ppdev, 3);
  630. IO_CUR_X(ppdev, x);
  631. IO_CUR_Y(ppdev, y);
  632. IO_CMD(ppdev, DRAW | WRITE | MULTIPLE_PIXELS |
  633. DIR_TYPE_RADIAL | LAST_PIXEL_OFF | BUS_SIZE_16 |
  634. BYTE_SWAP);
  635. cStrip = *plStrip; // Number of pels in first strip
  636. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  637. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  638. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  639. // and zero if we're in the middle of a 'dash':
  640. if (bIsGap)
  641. goto SkipAGap;
  642. else
  643. goto OutputADash;
  644. PrepareToSkipAGap:
  645. // Advance in the style-state array, so that we can find the next
  646. // 'dot' that we'll have to display:
  647. bIsGap = ~bIsGap;
  648. pls->psp++;
  649. if (pls->psp > pls->pspEnd)
  650. pls->psp = pls->pspStart;
  651. cStyle = *pls->psp;
  652. // If 'cStrip' is zero, we also need a new strip:
  653. if (cStrip != 0)
  654. goto SkipAGap;
  655. // Here, we're in the middle of a 'gap' where we don't have to
  656. // display anything. We simply cycle through all the strips
  657. // we can, keeping track of the current position, until we run
  658. // out of 'gap':
  659. while (TRUE)
  660. {
  661. // Each time we loop, we move to a new column and need a new strip:
  662. x++;
  663. plStrip++;
  664. cStrips--;
  665. if (cStrips == 0)
  666. goto AllDone;
  667. cStrip = *plStrip;
  668. SkipAGap:
  669. cThis = min(cStrip, cStyle);
  670. cStyle -= cThis;
  671. cStrip -= cThis;
  672. y += (dy > 0) ? cThis : -cThis;
  673. if (cStyle == 0)
  674. goto PrepareToOutputADash;
  675. }
  676. PrepareToOutputADash:
  677. // Advance in the style-state array, so that we can find the next
  678. // 'dot' that we'll have to display:
  679. bIsGap = ~bIsGap;
  680. pls->psp++;
  681. if (pls->psp > pls->pspEnd)
  682. pls->psp = pls->pspStart;
  683. cStyle = *pls->psp;
  684. // We're gonna need the current position to be correct when we
  685. // start outputing short-stroke vectors:
  686. IO_FIFO_WAIT(ppdev, 2);
  687. IO_CUR_Y(ppdev, y);
  688. // If 'cStrip' is zero, we also need a new strip.
  689. if (cStrip != 0)
  690. {
  691. // There's more to be done in the current strip, so set 'x'
  692. // to be the current column:
  693. IO_CUR_X(ppdev, x);
  694. goto OutputADash;
  695. }
  696. // Set 'x' to be the column we're about to move to, because we've
  697. // finished with the current strip:
  698. IO_CUR_X(ppdev, x + 1);
  699. while (TRUE)
  700. {
  701. // Each time we loop, we move to a new column and need a new strip:
  702. x++;
  703. plStrip++;
  704. cStrips--;
  705. if (cStrips == 0)
  706. goto AllDone;
  707. cStrip = *plStrip;
  708. OutputADash:
  709. cThis = min(cStrip, cStyle);
  710. cStyle -= cThis;
  711. cStrip -= cThis;
  712. y += (dy > 0) ? cThis : -cThis;
  713. // Short stroke vectors can handle lines that are a maximum of
  714. // 15 pels long. When we have to draw a longer consecutive
  715. // segment than that, we simply break it into 16 pel portions:
  716. while (cThis > 15)
  717. {
  718. // Draw two vertical strokes together to make up one 16 pel
  719. // segment:
  720. IO_FIFO_WAIT(ppdev, 1);
  721. IO_SHORT_STROKE(ppdev, dirSkip16);
  722. cThis -= 16;
  723. }
  724. // Draw the remaining lit part of the strip:
  725. IO_FIFO_WAIT(ppdev, 1);
  726. IO_SHORT_STROKE(ppdev, dirSkip | cThis);
  727. if (cStyle == 0)
  728. goto PrepareToSkipAGap;
  729. }
  730. AllDone:
  731. // Update our state variables so that the next line can continue
  732. // where we left off:
  733. pls->spRemaining = cStyle;
  734. pls->ulStyleMask = bIsGap;
  735. pstrip->ptlStart.x = x;
  736. pstrip->ptlStart.y = y;
  737. }