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.

956 lines
23 KiB

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