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.

545 lines
14 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. * We take advantage of the MGA's point-to-point vector drawing capability
  9. * to draw the strips. The MGA can automatically exclude the last pixel,
  10. * which makes our routines a little simpler.
  11. *
  12. * Copyright (c) 1992-1996 Microsoft Corporation
  13. * Copyright (c) 1993-1996 Matrox Electronic Systems, Ltd.
  14. \**************************************************************************/
  15. #include "precomp.h"
  16. /******************************Public*Routine******************************\
  17. * VOID vStripSolidHorizontal
  18. *
  19. * Draws left-to-right x-major near-horizontal lines using radial lines.
  20. *
  21. \**************************************************************************/
  22. VOID vStripSolidHorizontal(
  23. PDEV* ppdev,
  24. STRIP* pStrip,
  25. LINESTATE* pLineState)
  26. {
  27. BYTE* pjBase;
  28. LONG x;
  29. LONG y;
  30. LONG yDir;
  31. LONG* pStrips;
  32. LONG cStrips;
  33. LONG i;
  34. pjBase = ppdev->pjBase;
  35. x = pStrip->ptlStart.x + ppdev->xOffset;
  36. y = pStrip->ptlStart.y + ppdev->yOffset;
  37. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  38. pStrips = pStrip->alStrips;
  39. cStrips = pStrip->cStrips;
  40. for (i = cStrips; i != 0; i--)
  41. {
  42. CHECK_FIFO_SPACE(pjBase, 2);
  43. CP_WRITE(pjBase, DWG_XYSTRT, PACKXY(x, y));
  44. x += *pStrips++;
  45. CP_START(pjBase, DWG_XYEND, PACKXY(x, y));
  46. y += yDir;
  47. }
  48. pStrip->ptlStart.x = x - ppdev->xOffset;
  49. pStrip->ptlStart.y = y - ppdev->yOffset;
  50. }
  51. /******************************Public*Routine******************************\
  52. * VOID vStripSolidVertical
  53. *
  54. * Draws left-to-right y-major near-vertical lines using radial lines.
  55. *
  56. \**************************************************************************/
  57. VOID vStripSolidVertical(
  58. PDEV* ppdev,
  59. STRIP* pStrip,
  60. LINESTATE* pLineState)
  61. {
  62. BYTE* pjBase;
  63. LONG x;
  64. LONG y;
  65. LONG yDir;
  66. LONG* pStrips;
  67. LONG cStrips;
  68. LONG i;
  69. pjBase = ppdev->pjBase;
  70. x = pStrip->ptlStart.x + ppdev->xOffset;
  71. y = pStrip->ptlStart.y + ppdev->yOffset;
  72. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  73. pStrips = pStrip->alStrips;
  74. cStrips = pStrip->cStrips;
  75. for (i = cStrips; i != 0; i--)
  76. {
  77. CHECK_FIFO_SPACE(pjBase, 2);
  78. CP_WRITE(pjBase, DWG_XYSTRT, PACKXY(x, y));
  79. y += (yDir > 0) ? *pStrips : -*pStrips;
  80. pStrips++;
  81. CP_START(pjBase, DWG_XYEND, PACKXY(x, y));
  82. x++;
  83. }
  84. pStrip->ptlStart.x = x - ppdev->xOffset;
  85. pStrip->ptlStart.y = y - ppdev->yOffset;
  86. }
  87. /******************************Public*Routine******************************\
  88. * VOID vStripSolidDiagonalHorizontal
  89. *
  90. * Draws left-to-right x-major near-diagonal lines using radial lines.
  91. *
  92. \**************************************************************************/
  93. VOID vStripSolidDiagonalHorizontal(
  94. PDEV* ppdev,
  95. STRIP* pStrip,
  96. LINESTATE* pLineState)
  97. {
  98. BYTE* pjBase;
  99. LONG x;
  100. LONG y;
  101. LONG yDir;
  102. LONG* pStrips;
  103. LONG cStrips;
  104. LONG i;
  105. pjBase = ppdev->pjBase;
  106. x = pStrip->ptlStart.x + ppdev->xOffset;
  107. y = pStrip->ptlStart.y + ppdev->yOffset;
  108. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  109. pStrips = pStrip->alStrips;
  110. cStrips = pStrip->cStrips;
  111. for (i = cStrips; i != 0; i--)
  112. {
  113. CHECK_FIFO_SPACE(pjBase, 2);
  114. CP_WRITE(pjBase, DWG_XYSTRT, PACKXY(x, y));
  115. x += *pStrips;
  116. y += (yDir > 0) ? *pStrips : -*pStrips;
  117. pStrips++;
  118. CP_START(pjBase, DWG_XYEND, PACKXY(x, y));
  119. y -= yDir;
  120. }
  121. pStrip->ptlStart.x = x - ppdev->xOffset;
  122. pStrip->ptlStart.y = y - ppdev->yOffset;
  123. }
  124. /******************************Public*Routine******************************\
  125. * VOID vStripSolidDiagonalVertical
  126. *
  127. * Draws left-to-right y-major near-diagonal lines using radial lines.
  128. *
  129. \**************************************************************************/
  130. VOID vStripSolidDiagonalVertical(
  131. PDEV* ppdev,
  132. STRIP* pStrip,
  133. LINESTATE* pLineState)
  134. {
  135. BYTE* pjBase;
  136. LONG x;
  137. LONG y;
  138. LONG yDir;
  139. LONG* pStrips;
  140. LONG cStrips;
  141. LONG i;
  142. pjBase = ppdev->pjBase;
  143. x = pStrip->ptlStart.x + ppdev->xOffset;
  144. y = pStrip->ptlStart.y + ppdev->yOffset;
  145. yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
  146. pStrips = pStrip->alStrips;
  147. cStrips = pStrip->cStrips;
  148. for (i = cStrips; i != 0; i--)
  149. {
  150. CHECK_FIFO_SPACE(pjBase, 2);
  151. CP_WRITE(pjBase, DWG_XYSTRT, PACKXY(x, y));
  152. x += *pStrips;
  153. y += (yDir > 0) ? *pStrips : -*pStrips;
  154. pStrips++;
  155. CP_START(pjBase, DWG_XYEND, PACKXY(x, y));
  156. x--;
  157. }
  158. pStrip->ptlStart.x = x - ppdev->xOffset;
  159. pStrip->ptlStart.y = y - ppdev->yOffset;
  160. }
  161. /******************************Public*Routine******************************\
  162. * VOID vStripStyledHorizontal
  163. *
  164. * Takes the list of strips that define the pixels that would be lit for
  165. * a solid line, and breaks them into styling chunks according to the
  166. * styling information that is passed in.
  167. *
  168. * This particular routine handles x-major lines that run left-to-right,
  169. * and are comprised of horizontal strips. It draws the dashes using
  170. * short-stroke vectors.
  171. *
  172. * The performance of this routine could be improved significantly if
  173. * anyone cared enough about styled lines improve it.
  174. *
  175. \**************************************************************************/
  176. VOID vStripStyledHorizontal(
  177. PDEV* ppdev,
  178. STRIP* pstrip,
  179. LINESTATE* pls)
  180. {
  181. BYTE* pjBase;
  182. LONG x;
  183. LONG y;
  184. LONG dy;
  185. LONG* plStrip;
  186. LONG cStrips;
  187. LONG cStyle;
  188. LONG cStrip;
  189. LONG cThis;
  190. ULONG bIsGap;
  191. pjBase = ppdev->pjBase;
  192. if (pstrip->flFlips & FL_FLIP_V)
  193. {
  194. // The minor direction of the line is 90 degrees, and the major
  195. // direction is 0 (it's a left-to-right x-major line going up):
  196. dy = -1;
  197. }
  198. else
  199. {
  200. // The minor direction of the line is 270 degrees, and the major
  201. // direction is 0 (it's a left-to-right x-major line going down):
  202. dy = 1;
  203. }
  204. cStrips = pstrip->cStrips; // Total number of strips we'll do
  205. plStrip = pstrip->alStrips; // Points to current strip
  206. x = pstrip->ptlStart.x + ppdev->xOffset;
  207. // x position of start of first strip
  208. y = pstrip->ptlStart.y + ppdev->yOffset;
  209. // y position of start of first strip
  210. cStrip = *plStrip; // Number of pels in first strip
  211. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  212. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  213. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  214. // and zero if we're in the middle of a 'dash':
  215. if (bIsGap)
  216. goto SkipAGap;
  217. else
  218. goto OutputADash;
  219. PrepareToSkipAGap:
  220. // Advance in the style-state array, so that we can find the next
  221. // 'dot' that we'll have to display:
  222. bIsGap = ~bIsGap;
  223. pls->psp++;
  224. if (pls->psp > pls->pspEnd)
  225. pls->psp = pls->pspStart;
  226. cStyle = *pls->psp;
  227. // If 'cStrip' is zero, we also need a new strip:
  228. if (cStrip != 0)
  229. goto SkipAGap;
  230. // Here, we're in the middle of a 'gap' where we don't have to
  231. // display anything. We simply cycle through all the strips
  232. // we can, keeping track of the current position, until we run
  233. // out of 'gap':
  234. while (TRUE)
  235. {
  236. // Each time we loop, we move to a new scan and need a new strip:
  237. y += dy;
  238. plStrip++;
  239. cStrips--;
  240. if (cStrips == 0)
  241. goto AllDone;
  242. cStrip = *plStrip;
  243. SkipAGap:
  244. cThis = min(cStrip, cStyle);
  245. cStyle -= cThis;
  246. cStrip -= cThis;
  247. x += cThis;
  248. if (cStyle == 0)
  249. goto PrepareToOutputADash;
  250. }
  251. PrepareToOutputADash:
  252. // Advance in the style-state array, so that we can find the next
  253. // 'dot' that we'll have to display:
  254. bIsGap = ~bIsGap;
  255. pls->psp++;
  256. if (pls->psp > pls->pspEnd)
  257. pls->psp = pls->pspStart;
  258. cStyle = *pls->psp;
  259. // If 'cStrip' is zero, we also need a new strip.
  260. if (cStrip != 0)
  261. {
  262. // There's more to be done in the current strip:
  263. goto OutputADash;
  264. }
  265. // We've finished with the current strip:
  266. while (TRUE)
  267. {
  268. // Each time we loop, we move to a new scan and need a new strip:
  269. y += dy;
  270. plStrip++;
  271. cStrips--;
  272. if (cStrips == 0)
  273. goto AllDone;
  274. cStrip = *plStrip;
  275. OutputADash:
  276. cThis = min(cStrip, cStyle);
  277. cStyle -= cThis;
  278. cStrip -= cThis;
  279. CHECK_FIFO_SPACE(pjBase, 2);
  280. CP_WRITE(pjBase, DWG_XYSTRT, PACKXY(x, y));
  281. x += cThis;
  282. CP_START(pjBase, DWG_XYEND, PACKXY(x, y));
  283. if (cStyle == 0)
  284. goto PrepareToSkipAGap;
  285. }
  286. AllDone:
  287. // Update our state variables so that the next line can continue
  288. // where we left off:
  289. pls->spRemaining = cStyle;
  290. pls->ulStyleMask = bIsGap;
  291. pstrip->ptlStart.x = x - ppdev->xOffset;
  292. pstrip->ptlStart.y = y - ppdev->yOffset;
  293. }
  294. /******************************Public*Routine******************************\
  295. * VOID vStripStyledVertical
  296. *
  297. * Takes the list of strips that define the pixels that would be lit for
  298. * a solid line, and breaks them into styling chunks according to the
  299. * styling information that is passed in.
  300. *
  301. * This particular routine handles y-major lines that run left-to-right,
  302. * and are comprised of vertical strips. It draws the dashes using
  303. * short-stroke vectors.
  304. *
  305. * The performance of this routine could be improved significantly if
  306. * anyone cared enough about styled lines improve it.
  307. *
  308. \**************************************************************************/
  309. VOID vStripStyledVertical(
  310. PDEV* ppdev,
  311. STRIP* pstrip,
  312. LINESTATE* pls)
  313. {
  314. BYTE* pjBase;
  315. LONG x;
  316. LONG y;
  317. LONG dy;
  318. LONG* plStrip;
  319. LONG cStrips;
  320. LONG cStyle;
  321. LONG cStrip;
  322. LONG cThis;
  323. ULONG bIsGap;
  324. pjBase = ppdev->pjBase;
  325. if (pstrip->flFlips & FL_FLIP_V)
  326. {
  327. // The minor direction of the line is 0 degrees, and the major
  328. // direction is 90 (it's a left-to-right y-major line going up):
  329. dy = -1;
  330. }
  331. else
  332. {
  333. // The minor direction of the line is 0 degrees, and the major
  334. // direction is 270 (it's a left-to-right y-major line going down):
  335. dy = 1;
  336. }
  337. cStrips = pstrip->cStrips; // Total number of strips we'll do
  338. plStrip = pstrip->alStrips; // Points to current strip
  339. x = pstrip->ptlStart.x + ppdev->xOffset;
  340. // x position of start of first strip
  341. y = pstrip->ptlStart.y + ppdev->yOffset;
  342. // y position of start of first strip
  343. cStrip = *plStrip; // Number of pels in first strip
  344. cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
  345. bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
  346. // ulStyleMask is non-zero if we're in the middle of a 'gap',
  347. // and zero if we're in the middle of a 'dash':
  348. if (bIsGap)
  349. goto SkipAGap;
  350. else
  351. goto OutputADash;
  352. PrepareToSkipAGap:
  353. // Advance in the style-state array, so that we can find the next
  354. // 'dot' that we'll have to display:
  355. bIsGap = ~bIsGap;
  356. pls->psp++;
  357. if (pls->psp > pls->pspEnd)
  358. pls->psp = pls->pspStart;
  359. cStyle = *pls->psp;
  360. // If 'cStrip' is zero, we also need a new strip:
  361. if (cStrip != 0)
  362. goto SkipAGap;
  363. // Here, we're in the middle of a 'gap' where we don't have to
  364. // display anything. We simply cycle through all the strips
  365. // we can, keeping track of the current position, until we run
  366. // out of 'gap':
  367. while (TRUE)
  368. {
  369. // Each time we loop, we move to a new column and need a new strip:
  370. x++;
  371. plStrip++;
  372. cStrips--;
  373. if (cStrips == 0)
  374. goto AllDone;
  375. cStrip = *plStrip;
  376. SkipAGap:
  377. cThis = min(cStrip, cStyle);
  378. cStyle -= cThis;
  379. cStrip -= cThis;
  380. y += (dy > 0) ? cThis : -cThis;
  381. if (cStyle == 0)
  382. goto PrepareToOutputADash;
  383. }
  384. PrepareToOutputADash:
  385. // Advance in the style-state array, so that we can find the next
  386. // 'dot' that we'll have to display:
  387. bIsGap = ~bIsGap;
  388. pls->psp++;
  389. if (pls->psp > pls->pspEnd)
  390. pls->psp = pls->pspStart;
  391. cStyle = *pls->psp;
  392. // If 'cStrip' is zero, we also need a new strip.
  393. if (cStrip != 0)
  394. {
  395. // There's more to be done in the current strip:
  396. goto OutputADash;
  397. }
  398. // We've finished with the current strip:
  399. while (TRUE)
  400. {
  401. // Each time we loop, we move to a new column and need a new strip:
  402. x++;
  403. plStrip++;
  404. cStrips--;
  405. if (cStrips == 0)
  406. goto AllDone;
  407. cStrip = *plStrip;
  408. OutputADash:
  409. cThis = min(cStrip, cStyle);
  410. cStyle -= cThis;
  411. cStrip -= cThis;
  412. CHECK_FIFO_SPACE(pjBase, 2);
  413. CP_WRITE(pjBase, DWG_XYSTRT, PACKXY(x, y));
  414. y += (dy > 0) ? cThis : -cThis;
  415. CP_START(pjBase, DWG_XYEND, PACKXY(x, y));
  416. if (cStyle == 0)
  417. goto PrepareToSkipAGap;
  418. }
  419. AllDone:
  420. // Update our state variables so that the next line can continue
  421. // where we left off:
  422. pls->spRemaining = cStyle;
  423. pls->ulStyleMask = bIsGap;
  424. pstrip->ptlStart.x = x - ppdev->xOffset;
  425. pstrip->ptlStart.y = y - ppdev->yOffset;
  426. }