Leaked source code of windows server 2003
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.

879 lines
29 KiB

  1. /******************************************************************************\
  2. *
  3. * $Workfile: LineTo.c $
  4. *
  5. * Contents:
  6. * This file contains the DrvLineTo function and simple line drawing code.
  7. *
  8. * Copyright (c) 1996 Cirrus Logic, Inc.
  9. *
  10. * $Log: V:/CirrusLogic/CL54xx/NT40/Archive/Display/LineTo.c_v $
  11. *
  12. * Rev 1.4 12 Aug 1996 16:53:50 frido
  13. * Added NT 3.5x/4.0 auto detection.
  14. *
  15. * Rev 1.3 29 Jul 1996 12:23:04 frido
  16. * Fixed bug in drawing horizontal lines from right to left.
  17. *
  18. * Rev 1.2 15 Jul 1996 15:56:12 frido
  19. * Changed DST_ADDR into DST_ADDR_ABS.
  20. *
  21. * Rev 1.1 12 Jul 1996 16:02:06 frido
  22. * Redefined some macros that caused irratic line drawing on device bitmaps.
  23. *
  24. * Rev 1.0 10 Jul 1996 17:53:40 frido
  25. * New code.
  26. *
  27. \******************************************************************************/
  28. #include "PreComp.h"
  29. #if LINETO
  30. #define LEFT 0x01
  31. #define TOP 0x02
  32. #define RIGHT 0x04
  33. #define BOTTOM 0x08
  34. bIoLineTo(
  35. PDEV* ppdev,
  36. LONG x1,
  37. LONG y1,
  38. LONG x2,
  39. LONG y2,
  40. ULONG ulSolidColor,
  41. MIX mix,
  42. ULONG ulDstAddr)
  43. {
  44. BYTE* pjPorts = ppdev->pjPorts;
  45. LONG lDelta = ppdev->lDelta;
  46. LONG dx, dy;
  47. LONG cx, cy;
  48. if (ulSolidColor != (ULONG) -1)
  49. {
  50. if (ppdev->cBpp == 1)
  51. {
  52. ulSolidColor |= ulSolidColor << 8;
  53. ulSolidColor |= ulSolidColor << 16;
  54. }
  55. else if (ppdev->cBpp == 2)
  56. {
  57. ulSolidColor |= ulSolidColor << 16;
  58. }
  59. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  60. CP_IO_ROP(ppdev, pjPorts, gajHwMixFromMix[mix & 0x0F]);
  61. CP_IO_SRC_ADDR(ppdev, pjPorts, ppdev->ulSolidColorOffset);
  62. CP_IO_BLT_MODE(ppdev, pjPorts, ENABLE_COLOR_EXPAND |
  63. ENABLE_8x8_PATTERN_COPY |
  64. ppdev->jModeColor);
  65. CP_IO_FG_COLOR(ppdev, pjPorts, ulSolidColor);
  66. }
  67. // Calculate deltas.
  68. dx = x2 - x1;
  69. dy = y2 - y1;
  70. // Horizontal lines.
  71. if (dy == 0)
  72. {
  73. if (dx < 0)
  74. {
  75. // From right to left.
  76. ulDstAddr += PELS_TO_BYTES(x2 - 1) + (y2 * lDelta);
  77. cx = PELS_TO_BYTES(-dx) - 1;
  78. }
  79. else if (dx > 0)
  80. {
  81. // From left to right.
  82. ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
  83. cx = PELS_TO_BYTES(dx) - 1;
  84. }
  85. else
  86. {
  87. // Nothing to do here!
  88. return(TRUE);
  89. }
  90. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  91. CP_IO_XCNT(ppdev, pjPorts, cx);
  92. CP_IO_YCNT(ppdev, pjPorts, 0);
  93. CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
  94. CP_IO_START_BLT(ppdev, pjPorts);
  95. return(TRUE);
  96. }
  97. // Vertical lines.
  98. else if (dx == 0)
  99. {
  100. if (dy < 0)
  101. {
  102. // From bottom to top.
  103. ulDstAddr += PELS_TO_BYTES(x2) + ((y2 + 1) * lDelta);
  104. cy = -dy - 1;
  105. }
  106. else
  107. {
  108. // From top to bottom.
  109. ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
  110. cy = dy - 1;
  111. }
  112. cx = PELS_TO_BYTES(1) - 1;
  113. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  114. CP_IO_XCNT(ppdev, pjPorts, cx);
  115. CP_IO_YCNT(ppdev, pjPorts, cy);
  116. CP_IO_DST_Y_OFFSET(ppdev, pjPorts, lDelta);
  117. CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
  118. CP_IO_START_BLT(ppdev, pjPorts);
  119. return(TRUE);
  120. }
  121. // Diagonal lines.
  122. else if ((dx == dy) || (dx == -dy))
  123. {
  124. if (dy < 0)
  125. {
  126. if (dx < 0)
  127. {
  128. // Diagonal line from bottom-right to upper-left.
  129. ulDstAddr += PELS_TO_BYTES(x2 + 1);
  130. }
  131. else
  132. {
  133. // Diagonal line from bottom-left to upper-right.
  134. ulDstAddr += PELS_TO_BYTES(x2 - 1);
  135. }
  136. ulDstAddr += (y2 + 1) * lDelta;
  137. cy = -dy - 1;
  138. }
  139. else
  140. {
  141. // Diagonal line from top to bottom, either from left to right or
  142. // right to left.
  143. ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
  144. cy = dy - 1;
  145. }
  146. if (dx == dy)
  147. {
  148. // Diagonal line from top-left to bottom-right or vice versa.
  149. lDelta += PELS_TO_BYTES(1);
  150. }
  151. else
  152. {
  153. // Diagonal line from top-right to bottom-left or vice versa.
  154. lDelta -= PELS_TO_BYTES(1);
  155. }
  156. cx = PELS_TO_BYTES(1) - 1;
  157. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  158. CP_IO_XCNT(ppdev, pjPorts, cx);
  159. CP_IO_YCNT(ppdev, pjPorts, cy);
  160. CP_IO_DST_Y_OFFSET(ppdev, pjPorts, lDelta);
  161. CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
  162. CP_IO_START_BLT(ppdev, pjPorts);
  163. return(TRUE);
  164. }
  165. // All other lines.
  166. if (dx < 0)
  167. {
  168. dx = -dx;
  169. }
  170. if (dy < 0)
  171. {
  172. dy = -dy;
  173. }
  174. ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
  175. // Horizontal major.
  176. if (dx > dy)
  177. {
  178. LONG run = dy;
  179. cy = (y1 > y2) ? -lDelta : lDelta;
  180. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  181. //
  182. // We would like to set the YCNT register once
  183. // here (outside the loops below). However, on
  184. // the CL5428, this register does not hold its value
  185. // after one iteration through the loop. So, I'll
  186. // have to set it inside the loop.
  187. //
  188. if (x1 < x2)
  189. {
  190. while (x1 < x2)
  191. {
  192. cx = 1 + (dx - run) / dy;
  193. if ((x1 + cx) < x2)
  194. {
  195. run += cx * dy - dx;
  196. }
  197. else
  198. {
  199. cx = x2 - x1;
  200. }
  201. x1 += cx;
  202. cx = PELS_TO_BYTES(cx);
  203. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  204. CP_IO_YCNT(ppdev, pjPorts, 0);
  205. CP_IO_XCNT(ppdev, pjPorts, cx - 1);
  206. CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
  207. CP_IO_START_BLT(ppdev, pjPorts);
  208. ulDstAddr += cx + cy;
  209. }
  210. }
  211. else
  212. {
  213. cy -= PELS_TO_BYTES(1);
  214. while (x1 > x2)
  215. {
  216. cx = 1 + (dx - run) / dy;
  217. if ((x1 - cx) > x2)
  218. {
  219. run += cx * dy - dx;
  220. }
  221. else
  222. {
  223. cx = x1 - x2;
  224. }
  225. ulDstAddr -= PELS_TO_BYTES(cx - 1);
  226. x1 -= cx;
  227. cx = PELS_TO_BYTES(cx);
  228. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  229. CP_IO_YCNT(ppdev, pjPorts, 0);
  230. CP_IO_XCNT(ppdev, pjPorts, cx - 1);
  231. CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
  232. CP_IO_START_BLT(ppdev, pjPorts);
  233. ulDstAddr += cy;
  234. }
  235. }
  236. }
  237. // Vertical major.
  238. else
  239. {
  240. LONG run = dx;
  241. cx = (x1 > x2) ? PELS_TO_BYTES(-1) : PELS_TO_BYTES(1);
  242. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  243. CP_IO_XCNT(ppdev, pjPorts, PELS_TO_BYTES(1) - 1);
  244. CP_IO_DST_Y_OFFSET(ppdev, pjPorts, lDelta);
  245. if (y1 < y2)
  246. {
  247. while (y1 < y2)
  248. {
  249. cy = 1 + (dy - run) / dx;
  250. if ((y1 + cy) < y2)
  251. {
  252. run += cy * dx - dy;
  253. }
  254. else
  255. {
  256. cy = y2 - y1;
  257. }
  258. y1 += cy;
  259. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  260. CP_IO_YCNT(ppdev, pjPorts, cy - 1);
  261. CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
  262. CP_IO_START_BLT(ppdev, pjPorts);
  263. ulDstAddr += cx + cy * lDelta;
  264. }
  265. }
  266. else
  267. {
  268. cx -= lDelta;
  269. while (y1 > y2)
  270. {
  271. cy = 1 + (dy - run) / dx;
  272. if ((y1 - cy) > y2)
  273. {
  274. run += cy * dx - dy;
  275. }
  276. else
  277. {
  278. cy = y1 - y2;
  279. }
  280. ulDstAddr -= (cy - 1) * lDelta;
  281. y1 -= cy;
  282. CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
  283. CP_IO_YCNT(ppdev, pjPorts, cy - 1);
  284. CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
  285. CP_IO_START_BLT(ppdev, pjPorts);
  286. ulDstAddr += cx;
  287. }
  288. }
  289. }
  290. return(TRUE);
  291. }
  292. bMmLineTo(
  293. PDEV* ppdev,
  294. LONG x1,
  295. LONG y1,
  296. LONG x2,
  297. LONG y2,
  298. ULONG ulSolidColor,
  299. MIX mix,
  300. ULONG ulDstAddr)
  301. {
  302. BYTE* pjBase = ppdev->pjBase;
  303. LONG lDelta = ppdev->lDelta;
  304. LONG dx, dy;
  305. LONG cx, cy;
  306. if (ulSolidColor != (ULONG) -1)
  307. {
  308. if (ppdev->cBpp == 1)
  309. {
  310. ulSolidColor |= ulSolidColor << 8;
  311. ulSolidColor |= ulSolidColor << 16;
  312. }
  313. else if (ppdev->cBpp == 2)
  314. {
  315. ulSolidColor |= ulSolidColor << 16;
  316. }
  317. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  318. CP_MM_ROP(ppdev, pjBase, gajHwMixFromMix[mix & 0x0F]);
  319. CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset);
  320. CP_MM_BLT_MODE(ppdev, pjBase, ENABLE_COLOR_EXPAND |
  321. ENABLE_8x8_PATTERN_COPY |
  322. ppdev->jModeColor);
  323. CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
  324. // if (ppdev->flCaps & CAPS_IS_5436)
  325. if (ppdev->flCaps & CAPS_AUTOSTART)
  326. {
  327. CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_SOLID_FILL);
  328. }
  329. }
  330. // Calculate deltas.
  331. dx = x2 - x1;
  332. dy = y2 - y1;
  333. // Horizontal lines.
  334. if (dy == 0)
  335. {
  336. if (dx < 0)
  337. {
  338. // From right to left.
  339. ulDstAddr += PELS_TO_BYTES(x2 + 1) + (y2 * lDelta);
  340. cx = PELS_TO_BYTES(-dx) - 1;
  341. }
  342. else if (dx > 0)
  343. {
  344. // From left to right.
  345. ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
  346. cx = PELS_TO_BYTES(dx) - 1;
  347. }
  348. else
  349. {
  350. // Nothing to do here!
  351. return(TRUE);
  352. }
  353. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  354. CP_MM_XCNT(ppdev, pjBase, cx);
  355. CP_MM_YCNT(ppdev, pjBase, 0);
  356. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
  357. CP_MM_START_BLT(ppdev, pjBase);
  358. return(TRUE);
  359. }
  360. // Vertical lines.
  361. else if (dx == 0)
  362. {
  363. if (dy < 0)
  364. {
  365. // From bottom to top.
  366. ulDstAddr += PELS_TO_BYTES(x2) + ((y2 + 1) * lDelta);
  367. cy = -dy - 1;
  368. }
  369. else
  370. {
  371. // From top to bottom.
  372. ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
  373. cy = dy - 1;
  374. }
  375. cx = PELS_TO_BYTES(1) - 1;
  376. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  377. CP_MM_XCNT(ppdev, pjBase, cx);
  378. CP_MM_YCNT(ppdev, pjBase, cy);
  379. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  380. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
  381. CP_MM_START_BLT(ppdev, pjBase);
  382. return(TRUE);
  383. }
  384. // Diagonal lines.
  385. else if ((dx == dy) || (dx == -dy))
  386. {
  387. if (dy < 0)
  388. {
  389. if (dx < 0)
  390. {
  391. // Diagonal line from bottom-right to upper-left.
  392. ulDstAddr += PELS_TO_BYTES(x2 + 1);
  393. }
  394. else
  395. {
  396. // Diagonal line from bottom-left to upper-right.
  397. ulDstAddr += PELS_TO_BYTES(x2 - 1);
  398. }
  399. ulDstAddr += (y2 + 1) * lDelta;
  400. cy = -dy - 1;
  401. }
  402. else
  403. {
  404. // Diagonal line from top to bottom, either from left to right or
  405. // right to left.
  406. ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
  407. cy = dy - 1;
  408. }
  409. if (dx == dy)
  410. {
  411. // Diagonal line from top-left to bottom-right or vice versa.
  412. lDelta += PELS_TO_BYTES(1);
  413. }
  414. else
  415. {
  416. // Diagonal line from top-right to bottom-left or vice versa.
  417. lDelta -= PELS_TO_BYTES(1);
  418. }
  419. cx = PELS_TO_BYTES(1) - 1;
  420. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  421. CP_MM_XCNT(ppdev, pjBase, cx);
  422. CP_MM_YCNT(ppdev, pjBase, cy);
  423. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  424. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
  425. CP_MM_START_BLT(ppdev, pjBase);
  426. return(TRUE);
  427. }
  428. // All other lines.
  429. if (dx < 0)
  430. {
  431. dx = -dx;
  432. }
  433. if (dy < 0)
  434. {
  435. dy = -dy;
  436. }
  437. ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
  438. // Horizontal major.
  439. if (dx > dy)
  440. {
  441. LONG run = dy;
  442. cy = (y1 > y2) ? -lDelta : lDelta;
  443. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  444. CP_MM_YCNT(ppdev, pjBase, 0);
  445. if (x1 < x2)
  446. {
  447. while (x1 < x2)
  448. {
  449. cx = 1 + (dx - run) / dy;
  450. if ((x1 + cx) < x2)
  451. {
  452. run += cx * dy - dx;
  453. }
  454. else
  455. {
  456. cx = x2 - x1;
  457. }
  458. x1 += cx;
  459. cx = PELS_TO_BYTES(cx);
  460. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  461. CP_MM_XCNT(ppdev, pjBase, cx - 1);
  462. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
  463. CP_MM_START_BLT(ppdev, pjBase);
  464. ulDstAddr += cx + cy;
  465. }
  466. }
  467. else
  468. {
  469. cy -= PELS_TO_BYTES(1);
  470. while (x1 > x2)
  471. {
  472. cx = 1 + (dx - run) / dy;
  473. if ((x1 - cx) > x2)
  474. {
  475. run += cx * dy - dx;
  476. }
  477. else
  478. {
  479. cx = x1 - x2;
  480. }
  481. ulDstAddr -= PELS_TO_BYTES(cx - 1);
  482. x1 -= cx;
  483. cx = PELS_TO_BYTES(cx);
  484. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  485. CP_MM_XCNT(ppdev, pjBase, cx - 1);
  486. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
  487. CP_MM_START_BLT(ppdev, pjBase);
  488. ulDstAddr += cy;
  489. }
  490. }
  491. }
  492. // Vertical major.
  493. else
  494. {
  495. LONG run = dx;
  496. cx = (x1 > x2) ? PELS_TO_BYTES(-1) : PELS_TO_BYTES(1);
  497. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  498. CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(1) - 1);
  499. CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
  500. if (y1 < y2)
  501. {
  502. while (y1 < y2)
  503. {
  504. cy = 1 + (dy - run) / dx;
  505. if ((y1 + cy) < y2)
  506. {
  507. run += cy * dx - dy;
  508. }
  509. else
  510. {
  511. cy = y2 - y1;
  512. }
  513. y1 += cy;
  514. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  515. CP_MM_YCNT(ppdev, pjBase, cy - 1);
  516. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
  517. CP_MM_START_BLT(ppdev, pjBase);
  518. ulDstAddr += cx + cy * lDelta;
  519. }
  520. }
  521. else
  522. {
  523. cx -= lDelta;
  524. while (y1 > y2)
  525. {
  526. cy = 1 + (dy - run) / dx;
  527. if ((y1 - cy) > y2)
  528. {
  529. run += cy * dx - dy;
  530. }
  531. else
  532. {
  533. cy = y1 - y2;
  534. }
  535. ulDstAddr -= (cy - 1) * lDelta;
  536. y1 -= cy;
  537. CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
  538. CP_MM_YCNT(ppdev, pjBase, cy - 1);
  539. CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
  540. CP_MM_START_BLT(ppdev, pjBase);
  541. ulDstAddr += cx;
  542. }
  543. }
  544. }
  545. return(TRUE);
  546. }
  547. BOOL bClipLine(LONG x1, LONG y1, LONG x2, LONG y2, RECTL* prcl)
  548. {
  549. ULONG ulCode1, ulCode2;
  550. RECTL rclClip1, rclClip2;
  551. LONG dx, dy;
  552. // Set clipping rectangles.
  553. rclClip1.left = prcl->left;
  554. rclClip1.top = prcl->top;
  555. rclClip1.right = prcl->right - 1;
  556. rclClip1.bottom = prcl->bottom - 1;
  557. rclClip2.left = prcl->left - 1;
  558. rclClip2.top = prcl->top - 1;
  559. rclClip2.right = prcl->right;
  560. rclClip2.bottom = prcl->bottom;
  561. // Set line deltas.
  562. dx = x2 - x1;
  563. dy = y2 - y1;
  564. // Set line flags.
  565. ulCode1 = 0;
  566. if (x1 < rclClip1.left) ulCode1 |= LEFT;
  567. if (y1 < rclClip1.top) ulCode1 |= TOP;
  568. if (x1 > rclClip1.right) ulCode1 |= RIGHT;
  569. if (y1 > rclClip1.bottom) ulCode1 |= BOTTOM;
  570. ulCode2 = 0;
  571. if (x2 < rclClip2.left) ulCode2 |= LEFT;
  572. if (y2 < rclClip2.top) ulCode2 |= TOP;
  573. if (x2 > rclClip2.right) ulCode2 |= RIGHT;
  574. if (y2 > rclClip2.bottom) ulCode2 |= BOTTOM;
  575. if ((ulCode1 & ulCode2) != 0)
  576. {
  577. // The line is completly clipped.
  578. return(FALSE);
  579. }
  580. // Vertical lines.
  581. if (dx == 0)
  582. {
  583. if (dy == 0)
  584. {
  585. return(FALSE);
  586. }
  587. if (ulCode1 & TOP)
  588. {
  589. y1 = rclClip1.top;
  590. }
  591. else if (ulCode1 & BOTTOM)
  592. {
  593. y1 = rclClip1.bottom;
  594. }
  595. if (ulCode2 & TOP)
  596. {
  597. y2 = rclClip2.top;
  598. }
  599. else if (ulCode2 & BOTTOM)
  600. {
  601. y2 = rclClip2.bottom;
  602. }
  603. goto ReturnTrue;
  604. }
  605. // Horizontal lines.
  606. if (dy == 0)
  607. {
  608. if (ulCode1 & LEFT)
  609. {
  610. x1 = rclClip1.left;
  611. }
  612. else if (ulCode1 & RIGHT)
  613. {
  614. x1 = rclClip1.right;
  615. }
  616. if (ulCode2 & LEFT)
  617. {
  618. x2 = rclClip2.left;
  619. }
  620. else if (ulCode2 & RIGHT)
  621. {
  622. x2 = rclClip2.right;
  623. }
  624. goto ReturnTrue;
  625. }
  626. // Clip start point.
  627. if (x1 < rclClip1.left)
  628. {
  629. y1 += dy * (rclClip1.left - x1) / dx;
  630. x1 = rclClip1.left;
  631. }
  632. else if (x1 > rclClip1.right)
  633. {
  634. y1 += dy * (rclClip1.right - x1) / dx;
  635. x1 = rclClip1.right;
  636. }
  637. if (y1 < rclClip1.top)
  638. {
  639. x1 += dx * (rclClip1.top - y1) / dy;
  640. y1 = rclClip1.top;
  641. }
  642. else if (y1 > rclClip1.bottom)
  643. {
  644. x1 += dx * (rclClip1.bottom - y1) / dy;
  645. y1 = rclClip1.bottom;
  646. }
  647. if ((x1 < rclClip1.left) || (y1 < rclClip1.top) || (x1 > rclClip1.right) ||
  648. (y1 > rclClip1.bottom))
  649. {
  650. // Start point fully clipped.
  651. return(FALSE);
  652. }
  653. // Clip end point.
  654. if (x2 < rclClip2.left)
  655. {
  656. y2 += dy * (rclClip2.left - x2) / dx;
  657. x2 = rclClip2.left;
  658. }
  659. else if (x2 > rclClip2.right)
  660. {
  661. y2 += dy * (rclClip2.right - x2) / dx;
  662. x2 = rclClip2.right;
  663. }
  664. if (y2 < rclClip2.top)
  665. {
  666. x2 += dx * (rclClip2.top - y2) / dy;
  667. y2 = rclClip2.top;
  668. }
  669. else if (y2 > rclClip2.bottom)
  670. {
  671. x2 += dx * (rclClip2.bottom - y2) / dy;
  672. y2 = rclClip2.bottom;
  673. }
  674. if ((x2 < rclClip2.left) || (y2 < rclClip2.top) || (x2 > rclClip2.right) ||
  675. (y2 > rclClip2.bottom))
  676. {
  677. // End point fully clipped.
  678. return(FALSE);
  679. }
  680. ReturnTrue:
  681. prcl->left = x1;
  682. prcl->top = y1;
  683. prcl->right = x2;
  684. prcl->bottom = y2;
  685. return(TRUE);
  686. }
  687. /******************************************************************************\
  688. *
  689. * Function: DrvLineTo
  690. *
  691. * This function draws a line between any two points. This function only draws
  692. * lines in solod color and that are just 1 pixel wide. The end-point is not
  693. * drawn.
  694. *
  695. * Parameters: pso Pointer to surface.
  696. * pco Pointer to CLIPOBJ.
  697. * pbo Pointer to BRUSHOBJ.
  698. * x1 Starting x-coordinate.
  699. * y1 Starting y-coordinate.
  700. * x2 Ending x-coordinate.
  701. * y2 Ending y-coordinate.
  702. * prclBounds Pointer to an unclipped bounding rectangle.
  703. * mix Mix to perform on the destination.
  704. *
  705. * Returns: TRUE if the line has been drawn, FALSE oftherwise.
  706. *
  707. \******************************************************************************/
  708. BOOL DrvLineTo(
  709. SURFOBJ* pso,
  710. CLIPOBJ* pco,
  711. BRUSHOBJ* pbo,
  712. LONG x1,
  713. LONG y1,
  714. LONG x2,
  715. LONG y2,
  716. RECTL* prclBounds,
  717. MIX mix)
  718. {
  719. PDEV* ppdev = (PPDEV)pso->dhpdev;
  720. DSURF* pdsurf = (DSURF *)pso->dhsurf;
  721. OH* poh;
  722. BOOL bMore;
  723. // If the device bitmap is a DIB, let GDI handle it.
  724. if (pdsurf->dt == DT_DIB)
  725. {
  726. return(EngLineTo(pdsurf->pso, pco, pbo, x1, y1, x2, y2, prclBounds,
  727. mix));
  728. }
  729. // Get the off-screen node.
  730. poh = pdsurf->poh;
  731. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  732. {
  733. // No clipping.
  734. return(ppdev->pfnLineTo(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix,
  735. poh->xy));
  736. }
  737. else if (pco->iDComplexity == DC_RECT)
  738. {
  739. // Clipped rectangle.
  740. RECTL rcl;
  741. rcl = pco->rclBounds;
  742. if (bClipLine(x1, y1, x2, y2, &rcl))
  743. {
  744. return(ppdev->pfnLineTo(ppdev, rcl.left, rcl.top, rcl.right,
  745. rcl.bottom, pbo->iSolidColor, mix,
  746. poh->xy));
  747. }
  748. return(TRUE);
  749. }
  750. // Complex clipping.
  751. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  752. do
  753. {
  754. CLIPENUM ce;
  755. RECTL* prcl;
  756. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), &ce.c);
  757. prcl = ce.arcl;
  758. while (ce.c--)
  759. {
  760. if (bClipLine(x1, y1, x2, y2, prcl))
  761. {
  762. if (!ppdev->pfnLineTo(ppdev, prcl->left, prcl->top, prcl->right,
  763. prcl->bottom, pbo->iSolidColor, mix,
  764. poh->xy))
  765. {
  766. return(FALSE);
  767. }
  768. }
  769. prcl++;
  770. }
  771. } while (bMore);
  772. return(TRUE);
  773. }
  774. #endif // LINETO