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.

1087 lines
27 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Strips.c
  3. *
  4. * These are the line rendering routines of last resort, and are called
  5. * by 'bLines' when a line is clipped or otherwise cannot be drawn
  6. * directly by the hardware.
  7. *
  8. * Note that we don't take advantage in the strip routines of the QVision's
  9. * capability for automatically starting when the Y1 register is written,
  10. * because that requires different state from what is required for the
  11. * integer line special case in 'bLines' -- and we want that integer line
  12. * special case to be as fast as possible, at cost to these strip routines.
  13. *
  14. * Copyright (c) 1992-1995 Microsoft Corporation
  15. \**************************************************************************/
  16. #include "precomp.h"
  17. /******************************Public*Routine******************************\
  18. * VOID vIoStripSolidHorizontal
  19. *
  20. * Draws left-to-right x-major near-horizontal lines using radial lines.
  21. *
  22. \**************************************************************************/
  23. VOID vIoStripSolidHorizontal(
  24. PDEV* ppdev,
  25. STRIP* pStrip,
  26. LINESTATE* pLineState)
  27. {
  28. BYTE* pjIoBase;
  29. LONG x;
  30. LONG y;
  31. LONG yDir;
  32. LONG* pStrips;
  33. LONG cStrips;
  34. LONG i;
  35. pjIoBase = ppdev->pjIoBase;
  36. x = pStrip->ptlStart.x;
  37. y = pStrip->ptlStart.y;
  38. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  39. pStrips = pStrip->alStrips;
  40. cStrips = pStrip->cStrips;
  41. for (i = cStrips; i != 0; i--)
  42. {
  43. IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
  44. IO_X0_Y0(ppdev, pjIoBase, x, y);
  45. x += *pStrips++;
  46. IO_X1_Y1(ppdev, pjIoBase, x - 1, y);
  47. y += yDir;
  48. IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
  49. }
  50. pStrip->ptlStart.x = x;
  51. pStrip->ptlStart.y = y;
  52. }
  53. /******************************Public*Routine******************************\
  54. * VOID vIoStripSolidVertical
  55. *
  56. * Draws left-to-right y-major near-vertical lines using radial lines.
  57. *
  58. \**************************************************************************/
  59. VOID vIoStripSolidVertical(
  60. PDEV* ppdev,
  61. STRIP* pStrip,
  62. LINESTATE* pLineState)
  63. {
  64. BYTE* pjIoBase;
  65. LONG x;
  66. LONG y;
  67. LONG yDir;
  68. LONG* pStrips;
  69. LONG cStrips;
  70. LONG i;
  71. pjIoBase = ppdev->pjIoBase;
  72. x = pStrip->ptlStart.x;
  73. y = pStrip->ptlStart.y;
  74. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  75. pStrips = pStrip->alStrips;
  76. cStrips = pStrip->cStrips;
  77. for (i = cStrips; i != 0; i--)
  78. {
  79. IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
  80. IO_X0_Y0(ppdev, pjIoBase, x, y);
  81. y += (yDir > 0) ? *pStrips : -*pStrips;
  82. pStrips++;
  83. IO_X1_Y1(ppdev, pjIoBase, x, y - yDir);
  84. x++;
  85. IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
  86. }
  87. pStrip->ptlStart.x = x;
  88. pStrip->ptlStart.y = y;
  89. }
  90. /******************************Public*Routine******************************\
  91. * VOID vIoStripSolidDiagonalHorizontal
  92. *
  93. * Draws left-to-right x-major near-diagonal lines using radial lines.
  94. *
  95. \**************************************************************************/
  96. VOID vIoStripSolidDiagonalHorizontal(
  97. PDEV* ppdev,
  98. STRIP* pStrip,
  99. LINESTATE* pLineState)
  100. {
  101. BYTE* pjIoBase;
  102. LONG x;
  103. LONG y;
  104. LONG yDir;
  105. LONG* pStrips;
  106. LONG cStrips;
  107. LONG i;
  108. pjIoBase = ppdev->pjIoBase;
  109. x = pStrip->ptlStart.x;
  110. y = pStrip->ptlStart.y;
  111. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  112. pStrips = pStrip->alStrips;
  113. cStrips = pStrip->cStrips;
  114. for (i = cStrips; i != 0; i--)
  115. {
  116. IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
  117. IO_X0_Y0(ppdev, pjIoBase, x, y);
  118. x += *pStrips;
  119. y += (yDir > 0) ? *pStrips : -*pStrips;
  120. pStrips++;
  121. IO_X1_Y1(ppdev, pjIoBase, x - 1, y - yDir);
  122. y -= yDir;
  123. IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
  124. }
  125. pStrip->ptlStart.x = x;
  126. pStrip->ptlStart.y = y;
  127. }
  128. /******************************Public*Routine******************************\
  129. * VOID vIoStripSolidDiagonalVertical
  130. *
  131. * Draws left-to-right y-major near-diagonal lines using radial lines.
  132. *
  133. \**************************************************************************/
  134. VOID vIoStripSolidDiagonalVertical(
  135. PDEV* ppdev,
  136. STRIP* pStrip,
  137. LINESTATE* pLineState)
  138. {
  139. BYTE* pjIoBase;
  140. LONG x;
  141. LONG y;
  142. LONG yDir;
  143. LONG* pStrips;
  144. LONG cStrips;
  145. LONG i;
  146. pjIoBase = ppdev->pjIoBase;
  147. x = pStrip->ptlStart.x;
  148. y = pStrip->ptlStart.y;
  149. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  150. pStrips = pStrip->alStrips;
  151. cStrips = pStrip->cStrips;
  152. for (i = cStrips; i != 0; i--)
  153. {
  154. IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
  155. IO_X0_Y0(ppdev, pjIoBase, x, y);
  156. x += *pStrips;
  157. y += (yDir > 0) ? *pStrips : -*pStrips;
  158. pStrips++;
  159. IO_X1_Y1(ppdev, pjIoBase, x - 1, y - yDir);
  160. x--;
  161. IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
  162. }
  163. pStrip->ptlStart.x = x;
  164. pStrip->ptlStart.y = y;
  165. }
  166. /******************************Public*Routine******************************\
  167. * VOID vIoStripStyledHorizontal
  168. *
  169. * Takes the list of strips that define the pixels that would be lit for
  170. * a solid line, and breaks them into styling chunks according to the
  171. * styling information that is passed in.
  172. *
  173. * This particular routine handles x-major lines that run left-to-right,
  174. * and are comprised of horizontal strips. It draws the dashes using
  175. * short-stroke vectors.
  176. *
  177. * The performance of this routine could be improved significantly if
  178. * anyone cared enough about styled lines improve it.
  179. *
  180. \**************************************************************************/
  181. VOID vIoStripStyledHorizontal(
  182. PDEV* ppdev,
  183. STRIP* pstrip,
  184. LINESTATE* pls)
  185. {
  186. BYTE* pjIoBase;
  187. LONG x;
  188. LONG y;
  189. LONG dy;
  190. LONG* plStrip;
  191. LONG cStrips;
  192. LONG cStyle;
  193. LONG cStrip;
  194. LONG cThis;
  195. ULONG bIsGap;
  196. pjIoBase = ppdev->pjIoBase;
  197. if (pstrip->flFlips & FL_FLIP_V)
  198. {
  199. // The minor direction of the line is 90 degrees, and the major
  200. // direction is 0 (it's a left-to-right x-major line going up):
  201. dy = -1;
  202. }
  203. else
  204. {
  205. // The minor direction of the line is 270 degrees, and the major
  206. // direction is 0 (it's a left-to-right x-major line going down):
  207. dy = 1;
  208. }
  209. cStrips = pstrip->cStrips; // Total number of strips we'll do
  210. plStrip = pstrip->alStrips; // Points to current strip
  211. x = pstrip->ptlStart.x; // x position of start of first strip
  212. y = pstrip->ptlStart.y; // y position of start of first strip
  213. cStrip = *plStrip; // Number of pels in first strip
  214. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  215. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  216. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  217. // and zero if we're in the middle of a 'dash':
  218. if (bIsGap)
  219. goto SkipAGap;
  220. else
  221. goto OutputADash;
  222. PrepareToSkipAGap:
  223. // Advance in the style-state array, so that we can find the next
  224. // 'dot' that we'll have to display:
  225. bIsGap = ~bIsGap;
  226. pls->psp++;
  227. if (pls->psp > pls->pspEnd)
  228. pls->psp = pls->pspStart;
  229. cStyle = *pls->psp;
  230. // If 'cStrip' is zero, we also need a new strip:
  231. if (cStrip != 0)
  232. goto SkipAGap;
  233. // Here, we're in the middle of a 'gap' where we don't have to
  234. // display anything. We simply cycle through all the strips
  235. // we can, keeping track of the current position, until we run
  236. // out of 'gap':
  237. while (TRUE)
  238. {
  239. // Each time we loop, we move to a new scan and need a new strip:
  240. y += dy;
  241. plStrip++;
  242. cStrips--;
  243. if (cStrips == 0)
  244. goto AllDone;
  245. cStrip = *plStrip;
  246. SkipAGap:
  247. cThis = min(cStrip, cStyle);
  248. cStyle -= cThis;
  249. cStrip -= cThis;
  250. x += cThis;
  251. if (cStyle == 0)
  252. goto PrepareToOutputADash;
  253. }
  254. PrepareToOutputADash:
  255. // Advance in the style-state array, so that we can find the next
  256. // 'dot' that we'll have to display:
  257. bIsGap = ~bIsGap;
  258. pls->psp++;
  259. if (pls->psp > pls->pspEnd)
  260. pls->psp = pls->pspStart;
  261. cStyle = *pls->psp;
  262. // If 'cStrip' is zero, we also need a new strip.
  263. if (cStrip != 0)
  264. {
  265. // There's more to be done in the current strip:
  266. goto OutputADash;
  267. }
  268. // We've finished with the current strip:
  269. while (TRUE)
  270. {
  271. // Each time we loop, we move to a new scan and need a new strip:
  272. y += dy;
  273. plStrip++;
  274. cStrips--;
  275. if (cStrips == 0)
  276. goto AllDone;
  277. cStrip = *plStrip;
  278. OutputADash:
  279. cThis = min(cStrip, cStyle);
  280. cStyle -= cThis;
  281. cStrip -= cThis;
  282. // Short stroke vectors can handle lines that are a maximum of
  283. // 15 pels long. When we have to draw a longer consecutive
  284. // segment than that, we simply break it into 16 pel portions:
  285. IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
  286. IO_X0_Y0(ppdev, pjIoBase, x, y);
  287. x += cThis;
  288. IO_X1_Y1(ppdev, pjIoBase, x - 1, y);
  289. IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
  290. if (cStyle == 0)
  291. goto PrepareToSkipAGap;
  292. }
  293. AllDone:
  294. // Update our state variables so that the next line can continue
  295. // where we left off:
  296. pls->spRemaining = cStyle;
  297. pls->ulStyleMask = bIsGap;
  298. pstrip->ptlStart.x = x;
  299. pstrip->ptlStart.y = y;
  300. }
  301. /******************************Public*Routine******************************\
  302. * VOID vIoStripStyledVertical
  303. *
  304. * Takes the list of strips that define the pixels that would be lit for
  305. * a solid line, and breaks them into styling chunks according to the
  306. * styling information that is passed in.
  307. *
  308. * This particular routine handles y-major lines that run left-to-right,
  309. * and are comprised of vertical strips. It draws the dashes using
  310. * short-stroke vectors.
  311. *
  312. * The performance of this routine could be improved significantly if
  313. * anyone cared enough about styled lines improve it.
  314. *
  315. \**************************************************************************/
  316. VOID vIoStripStyledVertical(
  317. PDEV* ppdev,
  318. STRIP* pstrip,
  319. LINESTATE* pls)
  320. {
  321. BYTE* pjIoBase;
  322. LONG x;
  323. LONG y;
  324. LONG dy;
  325. LONG* plStrip;
  326. LONG cStrips;
  327. LONG cStyle;
  328. LONG cStrip;
  329. LONG cThis;
  330. ULONG bIsGap;
  331. pjIoBase = ppdev->pjIoBase;
  332. if (pstrip->flFlips & FL_FLIP_V)
  333. {
  334. // The minor direction of the line is 0 degrees, and the major
  335. // direction is 90 (it's a left-to-right y-major line going up):
  336. dy = -1;
  337. }
  338. else
  339. {
  340. // The minor direction of the line is 0 degrees, and the major
  341. // direction is 270 (it's a left-to-right y-major line going down):
  342. dy = 1;
  343. }
  344. cStrips = pstrip->cStrips; // Total number of strips we'll do
  345. plStrip = pstrip->alStrips; // Points to current strip
  346. x = pstrip->ptlStart.x; // x position of start of first strip
  347. y = pstrip->ptlStart.y; // y position of start of first strip
  348. cStrip = *plStrip; // Number of pels in first strip
  349. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  350. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  351. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  352. // and zero if we're in the middle of a 'dash':
  353. if (bIsGap)
  354. goto SkipAGap;
  355. else
  356. goto OutputADash;
  357. PrepareToSkipAGap:
  358. // Advance in the style-state array, so that we can find the next
  359. // 'dot' that we'll have to display:
  360. bIsGap = ~bIsGap;
  361. pls->psp++;
  362. if (pls->psp > pls->pspEnd)
  363. pls->psp = pls->pspStart;
  364. cStyle = *pls->psp;
  365. // If 'cStrip' is zero, we also need a new strip:
  366. if (cStrip != 0)
  367. goto SkipAGap;
  368. // Here, we're in the middle of a 'gap' where we don't have to
  369. // display anything. We simply cycle through all the strips
  370. // we can, keeping track of the current position, until we run
  371. // out of 'gap':
  372. while (TRUE)
  373. {
  374. // Each time we loop, we move to a new column and need a new strip:
  375. x++;
  376. plStrip++;
  377. cStrips--;
  378. if (cStrips == 0)
  379. goto AllDone;
  380. cStrip = *plStrip;
  381. SkipAGap:
  382. cThis = min(cStrip, cStyle);
  383. cStyle -= cThis;
  384. cStrip -= cThis;
  385. y += (dy > 0) ? cThis : -cThis;
  386. if (cStyle == 0)
  387. goto PrepareToOutputADash;
  388. }
  389. PrepareToOutputADash:
  390. // Advance in the style-state array, so that we can find the next
  391. // 'dot' that we'll have to display:
  392. bIsGap = ~bIsGap;
  393. pls->psp++;
  394. if (pls->psp > pls->pspEnd)
  395. pls->psp = pls->pspStart;
  396. cStyle = *pls->psp;
  397. // If 'cStrip' is zero, we also need a new strip.
  398. if (cStrip != 0)
  399. {
  400. // There's more to be done in the current strip:
  401. goto OutputADash;
  402. }
  403. // We've finished with the current strip:
  404. while (TRUE)
  405. {
  406. // Each time we loop, we move to a new column and need a new strip:
  407. x++;
  408. plStrip++;
  409. cStrips--;
  410. if (cStrips == 0)
  411. goto AllDone;
  412. cStrip = *plStrip;
  413. OutputADash:
  414. cThis = min(cStrip, cStyle);
  415. cStyle -= cThis;
  416. cStrip -= cThis;
  417. IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
  418. IO_X0_Y0(ppdev, pjIoBase, x, y);
  419. y += (dy > 0) ? cThis : -cThis;
  420. IO_X1_Y1(ppdev, pjIoBase, x, y - dy);
  421. IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
  422. if (cStyle == 0)
  423. goto PrepareToSkipAGap;
  424. }
  425. AllDone:
  426. // Update our state variables so that the next line can continue
  427. // where we left off:
  428. pls->spRemaining = cStyle;
  429. pls->ulStyleMask = bIsGap;
  430. pstrip->ptlStart.x = x;
  431. pstrip->ptlStart.y = y;
  432. }
  433. /******************************Public*Routine******************************\
  434. * VOID vMmStripSolidHorizontal
  435. *
  436. * Draws left-to-right x-major near-horizontal lines using radial lines.
  437. *
  438. \**************************************************************************/
  439. VOID vMmStripSolidHorizontal(
  440. PDEV* ppdev,
  441. STRIP* pStrip,
  442. LINESTATE* pLineState)
  443. {
  444. BYTE* pjMmBase;
  445. LONG x;
  446. LONG y;
  447. LONG yDir;
  448. LONG* pStrips;
  449. LONG cStrips;
  450. LONG i;
  451. pjMmBase = ppdev->pjMmBase;
  452. x = pStrip->ptlStart.x;
  453. y = pStrip->ptlStart.y;
  454. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  455. pStrips = pStrip->alStrips;
  456. cStrips = pStrip->cStrips;
  457. for (i = cStrips; i != 0; i--)
  458. {
  459. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  460. MM_X0_Y0(ppdev, pjMmBase, x, y);
  461. x += *pStrips++;
  462. MM_X1_Y1(ppdev, pjMmBase, x - 1, y);
  463. y += yDir;
  464. MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
  465. }
  466. pStrip->ptlStart.x = x;
  467. pStrip->ptlStart.y = y;
  468. }
  469. /******************************Public*Routine******************************\
  470. * VOID vMmStripSolidVertical
  471. *
  472. * Draws left-to-right y-major near-vertical lines using radial lines.
  473. *
  474. \**************************************************************************/
  475. VOID vMmStripSolidVertical(
  476. PDEV* ppdev,
  477. STRIP* pStrip,
  478. LINESTATE* pLineState)
  479. {
  480. BYTE* pjMmBase;
  481. LONG x;
  482. LONG y;
  483. LONG yDir;
  484. LONG* pStrips;
  485. LONG cStrips;
  486. LONG i;
  487. pjMmBase = ppdev->pjMmBase;
  488. x = pStrip->ptlStart.x;
  489. y = pStrip->ptlStart.y;
  490. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  491. pStrips = pStrip->alStrips;
  492. cStrips = pStrip->cStrips;
  493. for (i = cStrips; i != 0; i--)
  494. {
  495. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  496. MM_X0_Y0(ppdev, pjMmBase, x, y);
  497. y += (yDir > 0) ? *pStrips : -*pStrips;
  498. pStrips++;
  499. MM_X1_Y1(ppdev, pjMmBase, x, y - yDir);
  500. x++;
  501. MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
  502. }
  503. pStrip->ptlStart.x = x;
  504. pStrip->ptlStart.y = y;
  505. }
  506. /******************************Public*Routine******************************\
  507. * VOID vMmStripSolidDiagonalHorizontal
  508. *
  509. * Draws left-to-right x-major near-diagonal lines using radial lines.
  510. *
  511. \**************************************************************************/
  512. VOID vMmStripSolidDiagonalHorizontal(
  513. PDEV* ppdev,
  514. STRIP* pStrip,
  515. LINESTATE* pLineState)
  516. {
  517. BYTE* pjMmBase;
  518. LONG x;
  519. LONG y;
  520. LONG yDir;
  521. LONG* pStrips;
  522. LONG cStrips;
  523. LONG i;
  524. pjMmBase = ppdev->pjMmBase;
  525. x = pStrip->ptlStart.x;
  526. y = pStrip->ptlStart.y;
  527. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  528. pStrips = pStrip->alStrips;
  529. cStrips = pStrip->cStrips;
  530. for (i = cStrips; i != 0; i--)
  531. {
  532. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  533. MM_X0_Y0(ppdev, pjMmBase, x, y);
  534. x += *pStrips;
  535. y += (yDir > 0) ? *pStrips : -*pStrips;
  536. pStrips++;
  537. MM_X1_Y1(ppdev, pjMmBase, x - 1, y - yDir);
  538. y -= yDir;
  539. MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
  540. }
  541. pStrip->ptlStart.x = x;
  542. pStrip->ptlStart.y = y;
  543. }
  544. /******************************Public*Routine******************************\
  545. * VOID vMmStripSolidDiagonalVertical
  546. *
  547. * Draws left-to-right y-major near-diagonal lines using radial lines.
  548. *
  549. \**************************************************************************/
  550. VOID vMmStripSolidDiagonalVertical(
  551. PDEV* ppdev,
  552. STRIP* pStrip,
  553. LINESTATE* pLineState)
  554. {
  555. BYTE* pjMmBase;
  556. LONG x;
  557. LONG y;
  558. LONG yDir;
  559. LONG* pStrips;
  560. LONG cStrips;
  561. LONG i;
  562. pjMmBase = ppdev->pjMmBase;
  563. x = pStrip->ptlStart.x;
  564. y = pStrip->ptlStart.y;
  565. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  566. pStrips = pStrip->alStrips;
  567. cStrips = pStrip->cStrips;
  568. for (i = cStrips; i != 0; i--)
  569. {
  570. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  571. MM_X0_Y0(ppdev, pjMmBase, x, y);
  572. x += *pStrips;
  573. y += (yDir > 0) ? *pStrips : -*pStrips;
  574. pStrips++;
  575. MM_X1_Y1(ppdev, pjMmBase, x - 1, y - yDir);
  576. x--;
  577. MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
  578. }
  579. pStrip->ptlStart.x = x;
  580. pStrip->ptlStart.y = y;
  581. }
  582. /******************************Public*Routine******************************\
  583. * VOID vMmStripStyledHorizontal
  584. *
  585. * Takes the list of strips that define the pixels that would be lit for
  586. * a solid line, and breaks them into styling chunks according to the
  587. * styling information that is passed in.
  588. *
  589. * This particular routine handles x-major lines that run left-to-right,
  590. * and are comprised of horizontal strips. It draws the dashes using
  591. * short-stroke vectors.
  592. *
  593. * The performance of this routine could be improved significantly if
  594. * anyone cared enough about styled lines improve it.
  595. *
  596. \**************************************************************************/
  597. VOID vMmStripStyledHorizontal(
  598. PDEV* ppdev,
  599. STRIP* pstrip,
  600. LINESTATE* pls)
  601. {
  602. BYTE* pjMmBase;
  603. LONG x;
  604. LONG y;
  605. LONG dy;
  606. LONG* plStrip;
  607. LONG cStrips;
  608. LONG cStyle;
  609. LONG cStrip;
  610. LONG cThis;
  611. ULONG bIsGap;
  612. pjMmBase = ppdev->pjMmBase;
  613. if (pstrip->flFlips & FL_FLIP_V)
  614. {
  615. // The minor direction of the line is 90 degrees, and the major
  616. // direction is 0 (it's a left-to-right x-major line going up):
  617. dy = -1;
  618. }
  619. else
  620. {
  621. // The minor direction of the line is 270 degrees, and the major
  622. // direction is 0 (it's a left-to-right x-major line going down):
  623. dy = 1;
  624. }
  625. cStrips = pstrip->cStrips; // Total number of strips we'll do
  626. plStrip = pstrip->alStrips; // Points to current strip
  627. x = pstrip->ptlStart.x; // x position of start of first strip
  628. y = pstrip->ptlStart.y; // y position of start of first strip
  629. cStrip = *plStrip; // Number of pels in first strip
  630. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  631. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  632. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  633. // and zero if we're in the middle of a 'dash':
  634. if (bIsGap)
  635. goto SkipAGap;
  636. else
  637. goto OutputADash;
  638. PrepareToSkipAGap:
  639. // Advance in the style-state array, so that we can find the next
  640. // 'dot' that we'll have to display:
  641. bIsGap = ~bIsGap;
  642. pls->psp++;
  643. if (pls->psp > pls->pspEnd)
  644. pls->psp = pls->pspStart;
  645. cStyle = *pls->psp;
  646. // If 'cStrip' is zero, we also need a new strip:
  647. if (cStrip != 0)
  648. goto SkipAGap;
  649. // Here, we're in the middle of a 'gap' where we don't have to
  650. // display anything. We simply cycle through all the strips
  651. // we can, keeping track of the current position, until we run
  652. // out of 'gap':
  653. while (TRUE)
  654. {
  655. // Each time we loop, we move to a new scan and need a new strip:
  656. y += dy;
  657. plStrip++;
  658. cStrips--;
  659. if (cStrips == 0)
  660. goto AllDone;
  661. cStrip = *plStrip;
  662. SkipAGap:
  663. cThis = min(cStrip, cStyle);
  664. cStyle -= cThis;
  665. cStrip -= cThis;
  666. x += cThis;
  667. if (cStyle == 0)
  668. goto PrepareToOutputADash;
  669. }
  670. PrepareToOutputADash:
  671. // Advance in the style-state array, so that we can find the next
  672. // 'dot' that we'll have to display:
  673. bIsGap = ~bIsGap;
  674. pls->psp++;
  675. if (pls->psp > pls->pspEnd)
  676. pls->psp = pls->pspStart;
  677. cStyle = *pls->psp;
  678. // If 'cStrip' is zero, we also need a new strip.
  679. if (cStrip != 0)
  680. {
  681. // There's more to be done in the current strip:
  682. goto OutputADash;
  683. }
  684. // We've finished with the current strip:
  685. while (TRUE)
  686. {
  687. // Each time we loop, we move to a new scan and need a new strip:
  688. y += dy;
  689. plStrip++;
  690. cStrips--;
  691. if (cStrips == 0)
  692. goto AllDone;
  693. cStrip = *plStrip;
  694. OutputADash:
  695. cThis = min(cStrip, cStyle);
  696. cStyle -= cThis;
  697. cStrip -= cThis;
  698. // Short stroke vectors can handle lines that are a maximum of
  699. // 15 pels long. When we have to draw a longer consecutive
  700. // segment than that, we simply break it into 16 pel portions:
  701. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  702. MM_X0_Y0(ppdev, pjMmBase, x, y);
  703. x += cThis;
  704. MM_X1_Y1(ppdev, pjMmBase, x - 1, y);
  705. MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
  706. if (cStyle == 0)
  707. goto PrepareToSkipAGap;
  708. }
  709. AllDone:
  710. // Update our state variables so that the next line can continue
  711. // where we left off:
  712. pls->spRemaining = cStyle;
  713. pls->ulStyleMask = bIsGap;
  714. pstrip->ptlStart.x = x;
  715. pstrip->ptlStart.y = y;
  716. }
  717. /******************************Public*Routine******************************\
  718. * VOID vMmStripStyledVertical
  719. *
  720. * Takes the list of strips that define the pixels that would be lit for
  721. * a solid line, and breaks them into styling chunks according to the
  722. * styling information that is passed in.
  723. *
  724. * This particular routine handles y-major lines that run left-to-right,
  725. * and are comprised of vertical strips. It draws the dashes using
  726. * short-stroke vectors.
  727. *
  728. * The performance of this routine could be improved significantly if
  729. * anyone cared enough about styled lines improve it.
  730. *
  731. \**************************************************************************/
  732. VOID vMmStripStyledVertical(
  733. PDEV* ppdev,
  734. STRIP* pstrip,
  735. LINESTATE* pls)
  736. {
  737. BYTE* pjMmBase;
  738. LONG x;
  739. LONG y;
  740. LONG dy;
  741. LONG* plStrip;
  742. LONG cStrips;
  743. LONG cStyle;
  744. LONG cStrip;
  745. LONG cThis;
  746. ULONG bIsGap;
  747. pjMmBase = ppdev->pjMmBase;
  748. if (pstrip->flFlips & FL_FLIP_V)
  749. {
  750. // The minor direction of the line is 0 degrees, and the major
  751. // direction is 90 (it's a left-to-right y-major line going up):
  752. dy = -1;
  753. }
  754. else
  755. {
  756. // The minor direction of the line is 0 degrees, and the major
  757. // direction is 270 (it's a left-to-right y-major line going down):
  758. dy = 1;
  759. }
  760. cStrips = pstrip->cStrips; // Total number of strips we'll do
  761. plStrip = pstrip->alStrips; // Points to current strip
  762. x = pstrip->ptlStart.x; // x position of start of first strip
  763. y = pstrip->ptlStart.y; // y position of start of first strip
  764. cStrip = *plStrip; // Number of pels in first strip
  765. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  766. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  767. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  768. // and zero if we're in the middle of a 'dash':
  769. if (bIsGap)
  770. goto SkipAGap;
  771. else
  772. goto OutputADash;
  773. PrepareToSkipAGap:
  774. // Advance in the style-state array, so that we can find the next
  775. // 'dot' that we'll have to display:
  776. bIsGap = ~bIsGap;
  777. pls->psp++;
  778. if (pls->psp > pls->pspEnd)
  779. pls->psp = pls->pspStart;
  780. cStyle = *pls->psp;
  781. // If 'cStrip' is zero, we also need a new strip:
  782. if (cStrip != 0)
  783. goto SkipAGap;
  784. // Here, we're in the middle of a 'gap' where we don't have to
  785. // display anything. We simply cycle through all the strips
  786. // we can, keeping track of the current position, until we run
  787. // out of 'gap':
  788. while (TRUE)
  789. {
  790. // Each time we loop, we move to a new column and need a new strip:
  791. x++;
  792. plStrip++;
  793. cStrips--;
  794. if (cStrips == 0)
  795. goto AllDone;
  796. cStrip = *plStrip;
  797. SkipAGap:
  798. cThis = min(cStrip, cStyle);
  799. cStyle -= cThis;
  800. cStrip -= cThis;
  801. y += (dy > 0) ? cThis : -cThis;
  802. if (cStyle == 0)
  803. goto PrepareToOutputADash;
  804. }
  805. PrepareToOutputADash:
  806. // Advance in the style-state array, so that we can find the next
  807. // 'dot' that we'll have to display:
  808. bIsGap = ~bIsGap;
  809. pls->psp++;
  810. if (pls->psp > pls->pspEnd)
  811. pls->psp = pls->pspStart;
  812. cStyle = *pls->psp;
  813. // If 'cStrip' is zero, we also need a new strip.
  814. if (cStrip != 0)
  815. {
  816. // There's more to be done in the current strip:
  817. goto OutputADash;
  818. }
  819. // We've finished with the current strip:
  820. while (TRUE)
  821. {
  822. // Each time we loop, we move to a new column and need a new strip:
  823. x++;
  824. plStrip++;
  825. cStrips--;
  826. if (cStrips == 0)
  827. goto AllDone;
  828. cStrip = *plStrip;
  829. OutputADash:
  830. cThis = min(cStrip, cStyle);
  831. cStyle -= cThis;
  832. cStrip -= cThis;
  833. MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
  834. MM_X0_Y0(ppdev, pjMmBase, x, y);
  835. y += (dy > 0) ? cThis : -cThis;
  836. MM_X1_Y1(ppdev, pjMmBase, x, y - dy);
  837. MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
  838. if (cStyle == 0)
  839. goto PrepareToSkipAGap;
  840. }
  841. AllDone:
  842. // Update our state variables so that the next line can continue
  843. // where we left off:
  844. pls->spRemaining = cStyle;
  845. pls->ulStyleMask = bIsGap;
  846. pstrip->ptlStart.x = x;
  847. pstrip->ptlStart.y = y;
  848. }