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.

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