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.

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