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.

3451 lines
75 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name:
  3. *
  4. * solline.cxx
  5. *
  6. * Abstract
  7. *
  8. * This module draws solid color, single pixel wide, non-styled, trivial or
  9. * rectangularly clipped lines to a DIB.
  10. *
  11. * Author:
  12. *
  13. * Mark Enstrom (marke) 12-1-93
  14. *
  15. * Copyright (c) 1993-1999 Microsoft Corporation
  16. \**************************************************************************/
  17. #include "precomp.hxx"
  18. #include "solline.hxx"
  19. #define DBG_LINE 0
  20. #if DBG_LINE
  21. ULONG DbgLine = 0;
  22. #endif
  23. //
  24. // horizontal line accelerators
  25. //
  26. PFN_HORZ gapfnHorizontal[6] =
  27. {
  28. vHorizontalLine1,vHorizontalLine4,vHorizontalLine8,
  29. vHorizontalLine16,vHorizontalLine24,vHorizontalLine32
  30. };
  31. //
  32. // line DDA routines for each DIB format
  33. //
  34. PFN_OCTANT gapfnOctant[6][8] =
  35. {
  36. {
  37. vLine1Octant07,vLine1Octant16,vLine1Octant07,vLine1Octant16,
  38. vLine1Octant34,vLine1Octant25,vLine1Octant34,vLine1Octant25
  39. },
  40. {
  41. vLine4Octant07,vLine4Octant16,vLine4Octant07,vLine4Octant16,
  42. vLine4Octant34,vLine4Octant25,vLine4Octant34,vLine4Octant25
  43. },
  44. {
  45. vLine8Octant07,vLine8Octant16,vLine8Octant07,vLine8Octant16,
  46. vLine8Octant34,vLine8Octant25,vLine8Octant34,vLine8Octant25
  47. },
  48. {
  49. vLine16Octant07,vLine16Octant16,vLine16Octant07,vLine16Octant16,
  50. vLine16Octant34,vLine16Octant25,vLine16Octant34,vLine16Octant25
  51. },
  52. {
  53. vLine24Octant07,vLine24Octant16,vLine24Octant07,vLine24Octant16,
  54. vLine24Octant34,vLine24Octant25,vLine24Octant34,vLine24Octant25
  55. },
  56. {
  57. vLine32Octant07,vLine32Octant16,vLine32Octant07,vLine32Octant16,
  58. vLine32Octant34,vLine32Octant25,vLine32Octant34,vLine32Octant25
  59. }
  60. };
  61. //
  62. // mask for 4bpp pixels
  63. //
  64. UCHAR PixelLineMask4[2] = {0x0f,0xf0};
  65. /******************************Public*Routine******************************\
  66. *
  67. * Routine Name
  68. *
  69. * vSolidLine
  70. *
  71. * Routine Description:
  72. *
  73. * Extract line end points from path object and call lower lever drawing
  74. * routine
  75. *
  76. * Arguments:
  77. *
  78. * pso - destination surface object
  79. * ppo - path object
  80. * pptfx - line coordinates if 'ppo' is NULL
  81. * pco - clip object
  82. * iSolidColor - solid color to draw
  83. *
  84. * Return Value:
  85. *
  86. * none
  87. *
  88. \**************************************************************************/
  89. VOID
  90. vSolidLine (
  91. SURFACE *pSurf,
  92. PATHOBJ *ppo,
  93. POINTFIX*pptfx,
  94. CLIPOBJ *pco,
  95. ULONG iSolidColor
  96. )
  97. {
  98. PATHDATA pd;
  99. BOOL bMore;
  100. ULONG cptfx;
  101. POINTFIX ptfxStartFigure;
  102. POINTFIX ptfxLast;
  103. POINTFIX* pptfxFirst;
  104. POINTFIX* pptfxBuf;
  105. ULONG ulFormat;
  106. LONG lDelta;
  107. PBYTE pjDst;
  108. RECTL arclClip[4];
  109. PRECTL prclClip = (PRECTL) NULL;
  110. //
  111. // check out params
  112. //
  113. ASSERTGDI((pco == NULL) || (pco->iDComplexity != DC_COMPLEX),
  114. "Routine does not handle complex clipping");
  115. ulFormat = pSurf->iFormat();
  116. lDelta = pSurf->lDelta();
  117. pjDst = (PUCHAR)(pSurf->pvScan0());
  118. //
  119. // determine format and routines
  120. //
  121. switch (ulFormat)
  122. {
  123. case BMF_1BPP:
  124. iSolidColor = iSolidColor ? 0xffffffff : 0x00000000;
  125. break;
  126. //
  127. // rest fall through
  128. //
  129. case BMF_4BPP:
  130. iSolidColor |= (iSolidColor << 4);
  131. case BMF_8BPP:
  132. iSolidColor |= (iSolidColor << 8);
  133. case BMF_16BPP:
  134. iSolidColor |= (iSolidColor << 16);
  135. case BMF_24BPP:
  136. case BMF_32BPP:
  137. break;
  138. default:
  139. RIP("Invalid bitmap format");
  140. }
  141. //
  142. // get clipping rectangle if needed, copy the rectangle into several
  143. // formats for use by the GIQ clipping routine
  144. //
  145. if ((pco != NULL) && (pco->iDComplexity == DC_RECT))
  146. {
  147. //
  148. // assign temp rectangles to clipping bounds
  149. //
  150. arclClip[0] = pco->rclBounds;
  151. #if DBG_LINE
  152. if (DbgLine >= 2) {
  153. DbgPrint("Clipping rect = %li,%li to %li,%li\n",
  154. arclClip[0].left,
  155. arclClip[0].top,
  156. arclClip[0].right,
  157. arclClip[0].bottom);
  158. }
  159. #endif
  160. //
  161. // generate clipping rect variants for use in
  162. // GIQ line routines
  163. //
  164. arclClip[1].top = pco->rclBounds.left;
  165. arclClip[2].left = pco->rclBounds.left;
  166. arclClip[3].top = pco->rclBounds.left;
  167. arclClip[1].left = pco->rclBounds.top;
  168. arclClip[2].bottom = -pco->rclBounds.top + 1;
  169. arclClip[3].right = arclClip[2].bottom;
  170. arclClip[1].bottom = pco->rclBounds.right;
  171. arclClip[2].right = pco->rclBounds.right;
  172. arclClip[3].bottom = pco->rclBounds.right;
  173. arclClip[1].right = pco->rclBounds.bottom;
  174. arclClip[2].top = -pco->rclBounds.bottom + 1;
  175. arclClip[3].left = arclClip[2].top;
  176. prclClip = arclClip;
  177. }
  178. //
  179. // subtract 1 from ulFormat to use as array index
  180. //
  181. ulFormat --;
  182. //
  183. // if the path pointer 'ppo' is NULL, then we must use the vertice
  184. // pointer 'pptfx':
  185. //
  186. if (ppo == NULL)
  187. {
  188. vDrawLine(pptfx,pptfx + 1,pjDst,lDelta,iSolidColor,prclClip,ulFormat);
  189. }
  190. else
  191. {
  192. //
  193. // Enumerate the paths and send line segments to
  194. // vDrawLine
  195. //
  196. //
  197. // start enumeration of lines
  198. //
  199. pd.flags = 0;
  200. ((EPATHOBJ*) ppo)->vEnumStart();
  201. //
  202. // enumerate each set
  203. //
  204. do
  205. {
  206. bMore = ((EPATHOBJ*) ppo)->bEnum(&pd);
  207. cptfx = pd.count;
  208. //
  209. // Should not get to here with empty path
  210. //
  211. if (cptfx == 0)
  212. {
  213. ASSERTGDI(!bMore, "Empty path record in non-empty path");
  214. break;
  215. }
  216. //
  217. // if BEGINSUBPATH, save the starting point for the
  218. // figure
  219. //
  220. if (pd.flags & PD_BEGINSUBPATH)
  221. {
  222. ptfxStartFigure = *pd.pptfx;
  223. pptfxFirst = pd.pptfx;
  224. pptfxBuf = pd.pptfx + 1;
  225. cptfx--;
  226. } else {
  227. pptfxFirst = &ptfxLast;
  228. pptfxBuf = pd.pptfx;
  229. }
  230. //
  231. // draw line segments
  232. //
  233. if (cptfx > 0)
  234. {
  235. //
  236. // draw line segment
  237. //
  238. while (cptfx --) {
  239. vDrawLine(pptfxFirst,pptfxBuf,pjDst,lDelta,iSolidColor,prclClip,ulFormat);
  240. pptfxFirst = pptfxBuf;
  241. pptfxBuf++;
  242. }
  243. }
  244. ptfxLast = pd.pptfx[pd.count - 1];
  245. if (pd.flags & PD_CLOSEFIGURE)
  246. {
  247. //
  248. // draw closure line segment
  249. //
  250. vDrawLine(&ptfxLast,&ptfxStartFigure,pjDst,lDelta,iSolidColor,prclClip,ulFormat);
  251. }
  252. } while (bMore);
  253. }
  254. }
  255. /******************************Public*Routine******************************\
  256. *
  257. * Routine Name
  258. *
  259. * vDrawLine
  260. *
  261. * Routine Description:
  262. *
  263. * This routine is passed end points of a line segment, either integer or
  264. * GIQ. The DDA equation for the line is determined then specific routines
  265. * are called to run the line DDA and draw the pixels for each bitmap format
  266. *
  267. *
  268. * Arguments:
  269. *
  270. * pptfx0 - end point 0
  271. * pptfx1 - end point 1
  272. * pjDst - pointer to dst
  273. * lDelta - byte scan line increment for dst
  274. * iSolidColor - draw color expnaded to 32 bits
  275. * prclClip - clip rectangles
  276. * FormatIndex - look up for dst bitmap format
  277. *
  278. * Return Value:
  279. *
  280. * none
  281. *
  282. \**************************************************************************/
  283. VOID
  284. vDrawLine (
  285. POINTFIX *pptfx0,
  286. POINTFIX *pptfx1,
  287. PUCHAR pjDst,
  288. LONG lDelta,
  289. ULONG iSolidColor,
  290. PRECTL prclClip,
  291. ULONG FormatIndex
  292. )
  293. {
  294. LONG x0;
  295. LONG y0;
  296. LONG x1;
  297. LONG y1;
  298. LONG dx;
  299. LONG dy;
  300. ULONG ulTmp;
  301. PFN_OCTANT pfnOctant;
  302. LONG DeltaDst = lDelta;
  303. DDALINE DDALine;
  304. LONG Reduce;
  305. DDALine.ulFlags = 0;
  306. //
  307. // check for GIQ lines
  308. //
  309. ulTmp = ( (ULONG)pptfx0->x |
  310. (ULONG)pptfx0->y |
  311. (ULONG)pptfx1->x |
  312. (ULONG)pptfx1->y
  313. ) & 0x0F;
  314. //
  315. // check for integer lines
  316. //
  317. if (ulTmp == 0)
  318. {
  319. //
  320. // check for no clipping rectangle or trivial
  321. // accept/reject of each line with the clipping
  322. // rectangle
  323. //
  324. x0 = pptfx0->x >> 4;
  325. y0 = pptfx0->y >> 4;
  326. x1 = pptfx1->x >> 4;
  327. y1 = pptfx1->y >> 4;
  328. DDALine.ptlStart.x = x0;
  329. DDALine.ptlStart.y = y0;
  330. //
  331. // order x0,x1 and y0,y1 for clip check and slope calculation
  332. //
  333. if (x1 < x0) {
  334. ULONG Tmp = x1;
  335. x1 = x0;
  336. x0 = Tmp;
  337. DDALine.ulFlags |= FL_SOL_FLIP_H;
  338. }
  339. if (y1 < y0) {
  340. ULONG Tmp = y1;
  341. y1 = y0;
  342. y0 = Tmp;
  343. DDALine.ulFlags |= FL_SOL_FLIP_V;
  344. }
  345. if (prclClip != (PRECTL) NULL)
  346. {
  347. //
  348. // check for a line totally outside clip rect
  349. //
  350. if (
  351. (x1 < prclClip->left) ||
  352. (x0 >= prclClip->right) ||
  353. (y1 < prclClip->top) ||
  354. (y0 >= prclClip->bottom)
  355. )
  356. {
  357. //
  358. // line is totally clipped out
  359. //
  360. #if DBG_LINE
  361. if (DbgLine >= 1) {
  362. DbgPrint("Trivial reject line %li,%li to %li,%li\n",x0,y0,x1,y1);
  363. DbgPrint("Clipping rect: %li,%li to %li,%li\n",
  364. prclClip->left,
  365. prclClip->top,
  366. prclClip->right,
  367. prclClip->bottom);
  368. }
  369. #endif
  370. return;
  371. }
  372. //
  373. // check for line that is not totally inside clip rect,
  374. // if not then call GIQ routine which has rectangular
  375. // clipping.
  376. //
  377. if
  378. (
  379. (x0 < prclClip->left) ||
  380. (x1 >= prclClip->right) ||
  381. (y0 < prclClip->top) ||
  382. (y1 >= prclClip->bottom)
  383. )
  384. {
  385. goto calc_GIQ_line;
  386. }
  387. }
  388. //
  389. // transform line to the first octant and calculate
  390. // terms and flags
  391. //
  392. //
  393. // find out if line is x major or y major
  394. //
  395. dx = x1 - x0;
  396. dy = y1 - y0;
  397. //
  398. // check for x-major or y-major lines
  399. //
  400. if (dx >= dy) {
  401. //
  402. // check for horizontal line
  403. //
  404. if (dy == 0)
  405. {
  406. PFN_HORZ pfnHorz = gapfnHorizontal[FormatIndex];
  407. pjDst = pjDst + (DDALine.ptlStart.y * lDelta);
  408. //
  409. // must check to see if end points have been
  410. // swapped due to exclusive line drawing
  411. //
  412. if (DDALine.ulFlags & FL_SOL_FLIP_H)
  413. {
  414. x0++;
  415. x1++;
  416. }
  417. (*pfnHorz)(pjDst,x0,x1,iSolidColor);
  418. return;
  419. }
  420. //
  421. // check for zero length
  422. //
  423. if (dx == 0) {
  424. return;
  425. }
  426. Reduce = -1;
  427. //
  428. // x major line
  429. //
  430. DDALine.dMajor = dx;
  431. DDALine.dMinor = dy;
  432. //
  433. // see if y has been flipped
  434. //
  435. if (DDALine.ulFlags & FL_SOL_FLIP_V)
  436. {
  437. DeltaDst = -DeltaDst;
  438. Reduce = 0;
  439. }
  440. //
  441. // Bresenham term except lErrorTerm is normally dy - dx/2 or
  442. // 2x which is 2*dy - dx. In this case the 2*2y is not added to
  443. // the error term until the start of the inner loop routine so that
  444. // the x86 can immediately use the flag register to determine the sign
  445. // of the error term after the addition of 2*dy.
  446. //
  447. DDALine.cPels = DDALine.dMajor;
  448. DDALine.lErrorTerm = -DDALine.dMajor;
  449. DDALine.dMajor = 2 * DDALine.dMajor;
  450. DDALine.dMinor = 2 * DDALine.dMinor;
  451. //
  452. // if FL_SOL_FLIP_V then lError term must be reduced by one to
  453. // compensate for the rounding convention
  454. //
  455. DDALine.lErrorTerm += Reduce;
  456. } else {
  457. //
  458. // check for 0 length
  459. //
  460. if (dy == 0) {
  461. return;
  462. }
  463. Reduce = -1;
  464. //
  465. // y major line, swap the meaning of dMajor and dMinor
  466. //
  467. DDALine.dMajor = dy;
  468. DDALine.dMinor = dx;
  469. DDALine.ulFlags |= FL_SOL_FLIP_D;
  470. DDALine.xInc = 1;
  471. //
  472. // check for flipped x
  473. //
  474. if (DDALine.ulFlags & FL_SOL_FLIP_H) {
  475. //
  476. // compensate for negative x in y major line
  477. //
  478. Reduce = 0;
  479. }
  480. //
  481. // + or - y
  482. //
  483. if (DDALine.ulFlags & FL_SOL_FLIP_V) {
  484. DeltaDst = -DeltaDst;
  485. }
  486. //
  487. // Bresenham term except lErrorTerm is normally dy - dx/2 or
  488. // 2x which is 2*dy - dx. In this case the 2*2y is not added to
  489. // the error term until the start of the inner loop routine so that
  490. // the x86 can immediately use the flag register to determine the sign
  491. // of the error term after the addition of 2*dy.
  492. //
  493. DDALine.cPels = DDALine.dMajor;
  494. DDALine.lErrorTerm = -DDALine.dMajor;
  495. DDALine.dMajor = 2 * DDALine.dMajor;
  496. DDALine.dMinor = 2 * DDALine.dMinor;
  497. //
  498. // if FL_SOL_FLIP_H then lError term must be reduced by one to
  499. // compensate for the rounding convention
  500. //
  501. DDALine.lErrorTerm += Reduce;
  502. }
  503. #if DBG_LINE
  504. if (DbgLine >= 2) {
  505. DbgPrint("Integer line:\n");
  506. DbgPrint("x0 = %li, y0 = %li\n",x0,y0);
  507. DbgPrint("Error term = %li\n",DDALine.lErrorTerm);
  508. DbgPrint("dMajor = %li\n",DDALine.dMajor);
  509. DbgPrint("dMinor = %li\n",DDALine.dMinor);
  510. DbgPrint("Pixel Count = %li\n",DDALine.cPels);
  511. DbgPrint("ulFlags = 0x%08lx\n\n",DDALine.ulFlags);
  512. }
  513. #endif
  514. } else {
  515. calc_GIQ_line:
  516. //
  517. // caclulate GIQ parameters
  518. //
  519. if (!bGIQtoIntegerLine(pptfx0,pptfx1,prclClip,&DDALine)) {
  520. return;
  521. }
  522. //
  523. // check for 0 length
  524. //
  525. if (DDALine.cPels <= 0) {
  526. return;
  527. }
  528. if (DDALine.ulFlags & FL_SOL_FLIP_V)
  529. {
  530. DeltaDst = -DeltaDst;
  531. }
  532. #if DBG_LINE
  533. if (DbgLine >= 2) {
  534. DbgPrint("GIQ line:\n");
  535. DbgPrint("x0 = %li\n",DDALine.ptlStart.x);
  536. DbgPrint("y0 = %li\n",DDALine.ptlStart.y);
  537. DbgPrint("Error term = %li\n",DDALine.lErrorTerm);
  538. DbgPrint("dMajor = %li\n",DDALine.dMajor);
  539. DbgPrint("dMinor = %li\n",DDALine.dMinor);
  540. DbgPrint("Pixel Count = %li\n",DDALine.cPels);
  541. DbgPrint("DeltaDst = %li\n",DeltaDst);
  542. DbgPrint("xInc = %li\n",DDALine.xInc);
  543. DbgPrint("ulFlags = 0x%08lx\n\n",DDALine.ulFlags);
  544. }
  545. #endif
  546. }
  547. //
  548. // select drawing routine based on format and octant
  549. //
  550. pfnOctant = gapfnOctant[FormatIndex][DDALine.ulFlags & 0x07];
  551. pjDst = pjDst + (DDALine.ptlStart.y * lDelta);
  552. (*pfnOctant)(&DDALine,pjDst,DeltaDst,iSolidColor);
  553. }
  554. /******************************Public*Routine******************************\
  555. *
  556. * Routine Name
  557. *
  558. * Inner loop DDA line drawing routines for 8bpp
  559. *
  560. * Routine Description:
  561. *
  562. * 4 dda routines for line drawing in each octant for each resolution
  563. *
  564. *
  565. * Arguments:
  566. *
  567. * pDDALine - dda parameters
  568. * pjDst - Destination line address
  569. * lDeltaDst - Destination address scan line increment (bytes)
  570. * iSolidColor - Solid color for line
  571. *
  572. * Return Value:
  573. *
  574. * VOID
  575. *
  576. \**************************************************************************/
  577. #if !defined(_X86_)
  578. VOID
  579. vLine8Octant07(
  580. PDDALINE pDDALine,
  581. PUCHAR pjDst,
  582. LONG lDeltaDst,
  583. ULONG iSolidColor
  584. )
  585. {
  586. LONG ErrorTerm = pDDALine->lErrorTerm;
  587. LONG dM = pDDALine->dMajor;
  588. LONG dN = pDDALine->dMinor;
  589. LONG PixelCount = pDDALine->cPels;
  590. //
  591. // octant 0
  592. //
  593. // x major
  594. //
  595. // x - positive
  596. // y - positive/negative
  597. //
  598. pjDst += pDDALine->ptlStart.x;
  599. while (TRUE) {
  600. *pjDst = (UCHAR)iSolidColor;
  601. if (--PixelCount == 0) {
  602. return;
  603. }
  604. pjDst++;
  605. ErrorTerm += dN;
  606. if (ErrorTerm >= 0){
  607. ErrorTerm -= dM;
  608. pjDst += lDeltaDst;
  609. }
  610. }
  611. }
  612. VOID
  613. vLine8Octant34(
  614. PDDALINE pDDALine,
  615. PUCHAR pjDst,
  616. LONG lDeltaDst,
  617. ULONG iSolidColor
  618. )
  619. {
  620. LONG ErrorTerm = pDDALine->lErrorTerm;
  621. LONG dM = pDDALine->dMajor;
  622. LONG dN = pDDALine->dMinor;
  623. LONG PixelCount = pDDALine->cPels;
  624. //
  625. // octant 3
  626. //
  627. // x major
  628. //
  629. // x - negative
  630. // y - positive/negative
  631. //
  632. pjDst += pDDALine->ptlStart.x;
  633. //
  634. // integer line
  635. //
  636. while (TRUE) {
  637. *pjDst = (UCHAR)iSolidColor;
  638. if (--PixelCount == 0) {
  639. return;
  640. }
  641. pjDst--;
  642. ErrorTerm += dN;
  643. if (ErrorTerm >= 0){
  644. ErrorTerm -= dM;
  645. pjDst += lDeltaDst;
  646. }
  647. }
  648. }
  649. VOID
  650. vLine8Octant16(
  651. PDDALINE pDDALine,
  652. PUCHAR pjDst,
  653. LONG lDeltaDst,
  654. ULONG iSolidColor
  655. )
  656. {
  657. LONG ErrorTerm = pDDALine->lErrorTerm;
  658. LONG dM = pDDALine->dMajor;
  659. LONG dN = pDDALine->dMinor;
  660. LONG PixelCount = pDDALine->cPels;
  661. //
  662. // octant 1
  663. //
  664. // y major
  665. //
  666. // x - positive/negative
  667. // y - positive
  668. //
  669. pjDst += pDDALine->ptlStart.x;
  670. while (TRUE) {
  671. *pjDst = (UCHAR)iSolidColor;
  672. //
  673. // integer line
  674. //
  675. if (--PixelCount == 0) {
  676. return;
  677. }
  678. pjDst += lDeltaDst;
  679. ErrorTerm += dN;
  680. if (ErrorTerm >= 0){
  681. ErrorTerm -= dM;
  682. pjDst ++;
  683. }
  684. }
  685. }
  686. VOID
  687. vLine8Octant25(
  688. PDDALINE pDDALine,
  689. PUCHAR pjDst,
  690. LONG lDeltaDst,
  691. ULONG iSolidColor
  692. )
  693. {
  694. LONG ErrorTerm = pDDALine->lErrorTerm;
  695. LONG dM = pDDALine->dMajor;
  696. LONG dN = pDDALine->dMinor;
  697. LONG PixelCount = pDDALine->cPels;
  698. LONG xInc = pDDALine->xInc;
  699. //
  700. // octant 5,6
  701. //
  702. // y major
  703. //
  704. // x - positive/negative
  705. // y - negative
  706. //
  707. pjDst += pDDALine->ptlStart.x;
  708. while (TRUE) {
  709. *pjDst = (UCHAR)iSolidColor;
  710. //
  711. // integer line
  712. //
  713. if (--PixelCount == 0) {
  714. return;
  715. }
  716. pjDst += lDeltaDst;
  717. ErrorTerm += dN;
  718. if (ErrorTerm >= 0){
  719. ErrorTerm -= dM;
  720. pjDst --;
  721. }
  722. }
  723. }
  724. #endif
  725. /******************************Public*Routine******************************\
  726. *
  727. * Routine Name
  728. *
  729. * Inner loop DDA line drawing routines for 16 bpp
  730. *
  731. * Routine Description:
  732. *
  733. * 4 dda routines for line drawing in each octant for each resolution
  734. *
  735. *
  736. * Arguments:
  737. *
  738. * pDDALine - dda parameters
  739. * pjDst - Destination line address
  740. * lDeltaDst - Destination address scan line increment (bytes)
  741. * iSolidColor - Solid color for line
  742. *
  743. * Return Value:
  744. *
  745. * VOID
  746. *
  747. \**************************************************************************/
  748. VOID
  749. vLine16Octant07(
  750. PDDALINE pDDALine,
  751. PUCHAR pjDst,
  752. LONG lDeltaDst,
  753. ULONG iSolidColor
  754. )
  755. {
  756. LONG ErrorTerm = pDDALine->lErrorTerm;
  757. LONG dM = pDDALine->dMajor;
  758. LONG dN = pDDALine->dMinor;
  759. LONG PixelCount = pDDALine->cPels;
  760. PUSHORT pusDst = (PUSHORT)pjDst;
  761. //
  762. // octant 0
  763. //
  764. // x major
  765. //
  766. // x - positive
  767. // y - positive/negative
  768. //
  769. pusDst += pDDALine->ptlStart.x;
  770. while (TRUE) {
  771. *pusDst = (USHORT)iSolidColor;
  772. //
  773. // integer line
  774. //
  775. if (--PixelCount == 0) {
  776. return;
  777. }
  778. pusDst++;
  779. ErrorTerm += dN;
  780. if (ErrorTerm >= 0){
  781. ErrorTerm -= dM;
  782. pusDst = (PUSHORT)((PUCHAR)pusDst + lDeltaDst);
  783. }
  784. }
  785. }
  786. VOID
  787. vLine16Octant34(
  788. PDDALINE pDDALine,
  789. PUCHAR pjDst,
  790. LONG lDeltaDst,
  791. ULONG iSolidColor
  792. )
  793. {
  794. LONG ErrorTerm = pDDALine->lErrorTerm;
  795. LONG dM = pDDALine->dMajor;
  796. LONG dN = pDDALine->dMinor;
  797. LONG PixelCount = pDDALine->cPels;
  798. PUSHORT pusDst = (PUSHORT)pjDst;
  799. //
  800. // octant 3
  801. //
  802. // x major
  803. //
  804. // x - negative
  805. // y - positive/negative
  806. //
  807. pusDst += pDDALine->ptlStart.x;
  808. while (TRUE) {
  809. *pusDst = (USHORT)iSolidColor;
  810. //
  811. // integer line
  812. //
  813. if (--PixelCount == 0) {
  814. return;
  815. }
  816. pusDst--;
  817. ErrorTerm += dN;
  818. if (ErrorTerm >= 0){
  819. ErrorTerm -= dM;
  820. pusDst = (PUSHORT)((PUCHAR)pusDst + lDeltaDst);
  821. }
  822. }
  823. }
  824. VOID
  825. vLine16Octant16(
  826. PDDALINE pDDALine,
  827. PUCHAR pjDst,
  828. LONG lDeltaDst,
  829. ULONG iSolidColor
  830. )
  831. {
  832. LONG ErrorTerm = pDDALine->lErrorTerm;
  833. LONG dM = pDDALine->dMajor;
  834. LONG dN = pDDALine->dMinor;
  835. LONG PixelCount = pDDALine->cPels;
  836. LONG xInc = pDDALine->xInc;
  837. PUSHORT pusDst = (PUSHORT)pjDst;
  838. //
  839. // octant 1
  840. //
  841. // y major
  842. //
  843. // x - positive
  844. // y - positive/negative
  845. //
  846. pusDst += pDDALine->ptlStart.x;
  847. while (TRUE) {
  848. *pusDst = (USHORT)iSolidColor;
  849. //
  850. // integer line
  851. //
  852. if (--PixelCount == 0) {
  853. return;
  854. }
  855. pusDst = (PUSHORT)((PUCHAR)pusDst + lDeltaDst);
  856. ErrorTerm += dN;
  857. if (ErrorTerm >= 0){
  858. ErrorTerm -= dM;
  859. pusDst ++;
  860. }
  861. }
  862. }
  863. VOID
  864. vLine16Octant25(
  865. PDDALINE pDDALine,
  866. PUCHAR pjDst,
  867. LONG lDeltaDst,
  868. ULONG iSolidColor
  869. )
  870. {
  871. LONG ErrorTerm = pDDALine->lErrorTerm;
  872. LONG dM = pDDALine->dMajor;
  873. LONG dN = pDDALine->dMinor;
  874. LONG PixelCount = pDDALine->cPels;
  875. LONG xInc = pDDALine->xInc;
  876. PUSHORT pusDst = (PUSHORT)pjDst;
  877. //
  878. // octant 5,6
  879. //
  880. // y major
  881. //
  882. // x - negative
  883. // y - positive/ negative
  884. //
  885. pusDst += pDDALine->ptlStart.x;
  886. while (TRUE) {
  887. *pusDst = (USHORT)iSolidColor;
  888. //
  889. // integer line
  890. //
  891. if (--PixelCount == 0) {
  892. return;
  893. }
  894. pusDst = (PUSHORT)((PUCHAR)pusDst + lDeltaDst);
  895. ErrorTerm += dN;
  896. if (ErrorTerm >= 0){
  897. ErrorTerm -= dM;
  898. pusDst --;
  899. }
  900. }
  901. }
  902. /******************************Public*Routine******************************\
  903. *
  904. * Routine Name
  905. *
  906. * Inner loop DDA line drawing routines for 24bpp
  907. *
  908. * Routine Description:
  909. *
  910. * 4 dda routines for line drawing in each octant for each resolution
  911. *
  912. *
  913. * Arguments:
  914. *
  915. * pDDALine - dda parameters
  916. * pjDst - Destination line address
  917. * lDeltaDst - Destination address scan line increment (bytes)
  918. * iSolidColor - Solid color for line
  919. *
  920. * Return Value:
  921. *
  922. * VOID
  923. *
  924. \**************************************************************************/
  925. VOID
  926. vLine24Octant07(
  927. PDDALINE pDDALine,
  928. PUCHAR pjDst,
  929. LONG lDeltaDst,
  930. ULONG iSolidColor
  931. )
  932. {
  933. LONG ErrorTerm = pDDALine->lErrorTerm;
  934. LONG dM = pDDALine->dMajor;
  935. LONG dN = pDDALine->dMinor;
  936. LONG PixelCount = pDDALine->cPels;
  937. UCHAR Red = (UCHAR)iSolidColor;
  938. UCHAR Green = (UCHAR)(iSolidColor >> 8);
  939. UCHAR Blue = (UCHAR)(iSolidColor >> 16);
  940. //
  941. // octant 0
  942. //
  943. // x major
  944. //
  945. // x - positive
  946. // y - positive/negative
  947. //
  948. pjDst += (3 * pDDALine->ptlStart.x);
  949. while (TRUE) {
  950. *pjDst = Red;
  951. *(pjDst+1) = Green;
  952. *(pjDst+2) = Blue;
  953. //
  954. // integer line
  955. //
  956. if (--PixelCount == 0) {
  957. return;
  958. }
  959. pjDst += 3;
  960. ErrorTerm += dN;
  961. if (ErrorTerm >= 0){
  962. ErrorTerm -= dM;
  963. pjDst += lDeltaDst;
  964. }
  965. *pjDst = Red;
  966. *(pjDst+1) = Green;
  967. *(pjDst+2) = Blue;
  968. }
  969. }
  970. VOID
  971. vLine24Octant34(
  972. PDDALINE pDDALine,
  973. PUCHAR pjDst,
  974. LONG lDeltaDst,
  975. ULONG iSolidColor
  976. )
  977. {
  978. LONG ErrorTerm = pDDALine->lErrorTerm;
  979. LONG dM = pDDALine->dMajor;
  980. LONG dN = pDDALine->dMinor;
  981. LONG PixelCount = pDDALine->cPels;
  982. UCHAR Red = (UCHAR)iSolidColor;
  983. UCHAR Green = (UCHAR)(iSolidColor >> 8);
  984. UCHAR Blue = (UCHAR)(iSolidColor >> 16);
  985. //
  986. // octant 3
  987. //
  988. // x major
  989. //
  990. // x - negative
  991. // y - positive/negative
  992. //
  993. pjDst += (3 * pDDALine->ptlStart.x);
  994. while (TRUE) {
  995. *pjDst = Red;
  996. *(pjDst+1) = Green;
  997. *(pjDst+2) = Blue;
  998. //
  999. // integer line
  1000. //
  1001. if (--PixelCount == 0) {
  1002. return;
  1003. }
  1004. pjDst -= 3;
  1005. ErrorTerm += dN;
  1006. if (ErrorTerm >= 0){
  1007. ErrorTerm -= dM;
  1008. pjDst += lDeltaDst;
  1009. }
  1010. *pjDst = Red;
  1011. *(pjDst+1) = Green;
  1012. *(pjDst+2) = Blue;
  1013. }
  1014. }
  1015. VOID
  1016. vLine24Octant16(
  1017. PDDALINE pDDALine,
  1018. PUCHAR pjDst,
  1019. LONG lDeltaDst,
  1020. ULONG iSolidColor
  1021. )
  1022. {
  1023. LONG ErrorTerm = pDDALine->lErrorTerm;
  1024. LONG dM = pDDALine->dMajor;
  1025. LONG dN = pDDALine->dMinor;
  1026. LONG PixelCount = pDDALine->cPels;
  1027. UCHAR Red = (UCHAR)iSolidColor;
  1028. UCHAR Green = (UCHAR)(iSolidColor >> 8);
  1029. UCHAR Blue = (UCHAR)(iSolidColor >> 16);
  1030. //
  1031. // octant 1,2
  1032. //
  1033. // y major
  1034. //
  1035. // x - positive
  1036. // y - positive/negative
  1037. //
  1038. pjDst += (3*pDDALine->ptlStart.x);
  1039. while (TRUE) {
  1040. *pjDst = Red;
  1041. *(pjDst+1) = Green;
  1042. *(pjDst+2) = Blue;
  1043. //
  1044. // integer line
  1045. //
  1046. if (--PixelCount == 0) {
  1047. return;
  1048. }
  1049. pjDst += lDeltaDst;
  1050. ErrorTerm += dN;
  1051. if (ErrorTerm >= 0){
  1052. ErrorTerm -= dM;
  1053. pjDst+=3;
  1054. }
  1055. }
  1056. }
  1057. VOID
  1058. vLine24Octant25(
  1059. PDDALINE pDDALine,
  1060. PUCHAR pjDst,
  1061. LONG lDeltaDst,
  1062. ULONG iSolidColor
  1063. )
  1064. {
  1065. LONG ErrorTerm = pDDALine->lErrorTerm;
  1066. LONG dM = pDDALine->dMajor;
  1067. LONG dN = pDDALine->dMinor;
  1068. LONG PixelCount = pDDALine->cPels;
  1069. UCHAR Red = (UCHAR)iSolidColor;
  1070. UCHAR Green = (UCHAR)(iSolidColor >> 8);
  1071. UCHAR Blue = (UCHAR)(iSolidColor >> 16);
  1072. //
  1073. // octant 5,6
  1074. //
  1075. // y major
  1076. //
  1077. // x - negative
  1078. // y - positive/negative
  1079. //
  1080. pjDst += (3*pDDALine->ptlStart.x);
  1081. while (TRUE) {
  1082. *pjDst = Red;
  1083. *(pjDst+1) = Green;
  1084. *(pjDst+2) = Blue;
  1085. //
  1086. // integer line
  1087. //
  1088. if (--PixelCount == 0) {
  1089. return;
  1090. }
  1091. pjDst += lDeltaDst;
  1092. ErrorTerm += dN;
  1093. if (ErrorTerm >= 0){
  1094. ErrorTerm -= dM;
  1095. pjDst-=3;
  1096. }
  1097. }
  1098. }
  1099. /******************************Public*Routine******************************\
  1100. *
  1101. * Routine Name
  1102. *
  1103. * Inner loop DDA line drawing routines for 32 bpp
  1104. *
  1105. * Routine Description:
  1106. *
  1107. * 4 dda routines for line drawing in each octant for each resolution
  1108. *
  1109. *
  1110. * Arguments:
  1111. *
  1112. * pDDALine - dda parameters
  1113. * pjDst - Destination line address
  1114. * lDeltaDst - Destination address scan line increment (bytes)
  1115. * iSolidColor - Solid color for line
  1116. *
  1117. * Return Value:
  1118. *
  1119. * VOID
  1120. *
  1121. \**************************************************************************/
  1122. VOID
  1123. vLine32Octant07(
  1124. PDDALINE pDDALine,
  1125. PUCHAR pjDst,
  1126. LONG lDeltaDst,
  1127. ULONG iSolidColor
  1128. )
  1129. {
  1130. LONG ErrorTerm = pDDALine->lErrorTerm;
  1131. LONG dM = pDDALine->dMajor;
  1132. LONG dN = pDDALine->dMinor;
  1133. LONG PixelCount = pDDALine->cPels;
  1134. PULONG pulDst = (PULONG)pjDst;
  1135. //
  1136. // octant 0
  1137. //
  1138. // x major
  1139. //
  1140. // x - positive
  1141. // y - positive/negative
  1142. //
  1143. pulDst += pDDALine->ptlStart.x;
  1144. while (TRUE) {
  1145. *pulDst = iSolidColor;
  1146. //
  1147. // integer line
  1148. //
  1149. if (--PixelCount == 0) {
  1150. return;
  1151. }
  1152. pulDst++;
  1153. ErrorTerm += dN;
  1154. if (ErrorTerm >= 0){
  1155. ErrorTerm -= dM;
  1156. pulDst = (PULONG)((PUCHAR)pulDst + lDeltaDst);
  1157. }
  1158. }
  1159. }
  1160. VOID
  1161. vLine32Octant34(
  1162. PDDALINE pDDALine,
  1163. PUCHAR pjDst,
  1164. LONG lDeltaDst,
  1165. ULONG iSolidColor
  1166. )
  1167. {
  1168. LONG ErrorTerm = pDDALine->lErrorTerm;
  1169. LONG dM = pDDALine->dMajor;
  1170. LONG dN = pDDALine->dMinor;
  1171. LONG PixelCount = pDDALine->cPels;
  1172. PULONG pulDst = (PULONG)pjDst;
  1173. //
  1174. // octant 3
  1175. //
  1176. // x major
  1177. //
  1178. // x - negative
  1179. // y - positive/negative
  1180. //
  1181. pulDst += pDDALine->ptlStart.x;
  1182. while (TRUE) {
  1183. *pulDst = iSolidColor;
  1184. //
  1185. // integer line
  1186. //
  1187. if (--PixelCount == 0) {
  1188. return;
  1189. }
  1190. pulDst--;
  1191. ErrorTerm += dN;
  1192. if (ErrorTerm >= 0){
  1193. ErrorTerm -= dM;
  1194. pulDst = (PULONG)((PUCHAR)pulDst + lDeltaDst);
  1195. }
  1196. }
  1197. }
  1198. VOID
  1199. vLine32Octant16(
  1200. PDDALINE pDDALine,
  1201. PUCHAR pjDst,
  1202. LONG lDeltaDst,
  1203. ULONG iSolidColor
  1204. )
  1205. {
  1206. LONG ErrorTerm = pDDALine->lErrorTerm;
  1207. LONG dM = pDDALine->dMajor;
  1208. LONG dN = pDDALine->dMinor;
  1209. LONG PixelCount = pDDALine->cPels;
  1210. LONG xInc = pDDALine->xInc;
  1211. PULONG pulDst = (PULONG)pjDst;
  1212. //
  1213. // octant 1
  1214. //
  1215. // y major
  1216. //
  1217. // x - positive/negative
  1218. // y - positive
  1219. //
  1220. pulDst += pDDALine->ptlStart.x;
  1221. while (TRUE) {
  1222. *pulDst = iSolidColor;
  1223. //
  1224. // integer line
  1225. //
  1226. if (--PixelCount == 0) {
  1227. return;
  1228. }
  1229. pulDst = (PULONG)((PUCHAR)pulDst + lDeltaDst);
  1230. ErrorTerm += dN;
  1231. if (ErrorTerm >= 0){
  1232. ErrorTerm -= dM;
  1233. pulDst++;
  1234. }
  1235. *pulDst = iSolidColor;
  1236. }
  1237. }
  1238. VOID
  1239. vLine32Octant25(
  1240. PDDALINE pDDALine,
  1241. PUCHAR pjDst,
  1242. LONG lDeltaDst,
  1243. ULONG iSolidColor
  1244. )
  1245. {
  1246. LONG ErrorTerm = pDDALine->lErrorTerm;
  1247. LONG dM = pDDALine->dMajor;
  1248. LONG dN = pDDALine->dMinor;
  1249. LONG PixelCount = pDDALine->cPels;
  1250. LONG xInc = pDDALine->xInc;
  1251. PULONG pulDst = (PULONG)pjDst;
  1252. //
  1253. // octant 5,6
  1254. //
  1255. // y major
  1256. //
  1257. // x - positive/negative
  1258. // y - negative
  1259. //
  1260. pulDst += pDDALine->ptlStart.x;
  1261. while (TRUE) {
  1262. *pulDst = iSolidColor;
  1263. //
  1264. // integer line
  1265. //
  1266. if (--PixelCount == 0) {
  1267. return;
  1268. }
  1269. pulDst = (PULONG)((PUCHAR)pulDst + lDeltaDst);
  1270. ErrorTerm += dN;
  1271. if (ErrorTerm >= 0){
  1272. ErrorTerm -= dM;
  1273. pulDst--;
  1274. }
  1275. *pulDst = iSolidColor;
  1276. }
  1277. }
  1278. /******************************Public*Routine******************************\
  1279. *
  1280. * Routine Name
  1281. *
  1282. * Inner loop DDA line drawing routines for 1bpp
  1283. *
  1284. * Routine Description:
  1285. *
  1286. * 4 dda routines for line drawing in each octant for each resolution
  1287. *
  1288. *
  1289. * Arguments:
  1290. *
  1291. * pDDALine - dda parameters
  1292. * pjDst - Destination line address
  1293. * lDeltaDst - Destination address scan line increment (bytes)
  1294. * iSolidColor - Solid color for line
  1295. *
  1296. * Return Value:
  1297. *
  1298. * VOID
  1299. *
  1300. \**************************************************************************/
  1301. VOID
  1302. vLine1Octant07(
  1303. PDDALINE pDDALine,
  1304. PUCHAR pjDst,
  1305. LONG lDeltaDst,
  1306. ULONG iSolidColor
  1307. )
  1308. {
  1309. LONG ErrorTerm = pDDALine->lErrorTerm;
  1310. LONG dM = pDDALine->dMajor;
  1311. LONG dN = pDDALine->dMinor;
  1312. LONG PixelCount = pDDALine->cPels;
  1313. ULONG Pixel;
  1314. //
  1315. // octant 0
  1316. //
  1317. // x major
  1318. //
  1319. // x - positive
  1320. // y - positive/negative
  1321. //
  1322. Pixel = pDDALine->ptlStart.x;
  1323. UCHAR Mask = (UCHAR)(0x80 >> (Pixel & 0x07));
  1324. pjDst = pjDst + (Pixel >> 3);
  1325. //
  1326. // integer line
  1327. //
  1328. if (iSolidColor) {
  1329. //
  1330. // loop for storing '1' pixels
  1331. //
  1332. while (TRUE) {
  1333. *pjDst |= Mask;
  1334. if (--PixelCount == 0) {
  1335. return;
  1336. }
  1337. Mask = (UCHAR)(Mask >> 1);
  1338. if (!(Mask)) {
  1339. Mask = 0x80;
  1340. pjDst++;
  1341. }
  1342. ErrorTerm += dN;
  1343. if (ErrorTerm >= 0){
  1344. ErrorTerm -= dM;
  1345. pjDst += lDeltaDst;
  1346. }
  1347. }
  1348. } else {
  1349. //
  1350. // loop for storing '0' pixels
  1351. //
  1352. while (TRUE) {
  1353. *pjDst &= (~Mask);
  1354. if (--PixelCount == 0) {
  1355. return;
  1356. }
  1357. Mask = (UCHAR)(Mask >> 1);
  1358. if (!(Mask)) {
  1359. Mask = 0x80;
  1360. pjDst++;
  1361. }
  1362. ErrorTerm += dN;
  1363. if (ErrorTerm >= 0){
  1364. ErrorTerm -= dM;
  1365. pjDst += lDeltaDst;
  1366. }
  1367. }
  1368. }
  1369. }
  1370. VOID
  1371. vLine1Octant34(
  1372. PDDALINE pDDALine,
  1373. PUCHAR pjDst,
  1374. LONG lDeltaDst,
  1375. ULONG iSolidColor
  1376. )
  1377. {
  1378. LONG ErrorTerm = pDDALine->lErrorTerm;
  1379. LONG dM = pDDALine->dMajor;
  1380. LONG dN = pDDALine->dMinor;
  1381. LONG PixelCount = pDDALine->cPels;
  1382. ULONG Pixel;
  1383. //
  1384. // octant 3,4
  1385. //
  1386. // x major
  1387. //
  1388. // x - negative
  1389. // y - positive/negative
  1390. //
  1391. Pixel = pDDALine->ptlStart.x;
  1392. UCHAR Mask = (UCHAR)(0x80 >> (Pixel & 0x07));
  1393. pjDst = pjDst + (Pixel >> 3);
  1394. //
  1395. // integer line
  1396. //
  1397. if (iSolidColor) {
  1398. //
  1399. // loop for storing '1' pixels
  1400. //
  1401. while (TRUE) {
  1402. *pjDst |= Mask;
  1403. if (--PixelCount == 0) {
  1404. return;
  1405. }
  1406. Mask = (UCHAR)(Mask << 1);
  1407. if (!(Mask)) {
  1408. Mask = 0x01;
  1409. pjDst--;
  1410. }
  1411. ErrorTerm += dN;
  1412. if (ErrorTerm >= 0){
  1413. ErrorTerm -= dM;
  1414. pjDst += lDeltaDst;
  1415. }
  1416. }
  1417. } else {
  1418. while (TRUE) {
  1419. *pjDst &= (~Mask);
  1420. if (--PixelCount == 0) {
  1421. return;
  1422. }
  1423. Mask = (UCHAR)(Mask << 1);
  1424. if (!(Mask)) {
  1425. Mask = 0x01;
  1426. pjDst--;
  1427. }
  1428. ErrorTerm += dN;
  1429. if (ErrorTerm >= 0){
  1430. ErrorTerm -= dM;
  1431. pjDst += lDeltaDst;
  1432. }
  1433. }
  1434. }
  1435. }
  1436. VOID
  1437. vLine1Octant16(
  1438. PDDALINE pDDALine,
  1439. PUCHAR pjDst,
  1440. LONG lDeltaDst,
  1441. ULONG iSolidColor
  1442. )
  1443. {
  1444. LONG ErrorTerm = pDDALine->lErrorTerm;
  1445. LONG dM = pDDALine->dMajor;
  1446. LONG dN = pDDALine->dMinor;
  1447. LONG PixelCount = pDDALine->cPels;
  1448. ULONG Pixel;
  1449. //
  1450. // octant 1,6
  1451. //
  1452. // y major
  1453. //
  1454. // x - positive
  1455. // y - positive/negative
  1456. //
  1457. Pixel = pDDALine->ptlStart.x;
  1458. UCHAR Mask = (UCHAR)(0x80 >> (Pixel & 0x07));
  1459. pjDst = pjDst + (Pixel >> 3);
  1460. //
  1461. // integer line
  1462. //
  1463. if (iSolidColor) {
  1464. //
  1465. // loop for storing '1' pixels
  1466. //
  1467. while (TRUE) {
  1468. *pjDst |= Mask;
  1469. if (--PixelCount == 0) {
  1470. return;
  1471. }
  1472. pjDst += lDeltaDst;
  1473. ErrorTerm += dN;
  1474. if (ErrorTerm >= 0){
  1475. ErrorTerm -= dM;
  1476. Mask = (UCHAR)(Mask >> 1);
  1477. if (!(Mask)) {
  1478. Mask = 0x80;
  1479. pjDst++;
  1480. }
  1481. }
  1482. }
  1483. } else {
  1484. while (TRUE) {
  1485. *pjDst &= (~Mask);
  1486. if (--PixelCount == 0) {
  1487. return;
  1488. }
  1489. pjDst += lDeltaDst;
  1490. ErrorTerm += dN;
  1491. if (ErrorTerm >= 0){
  1492. ErrorTerm -= dM;
  1493. Mask = (UCHAR)(Mask >> 1);
  1494. if (!(Mask)) {
  1495. Mask = 0x80;
  1496. pjDst++;
  1497. }
  1498. }
  1499. }
  1500. }
  1501. }
  1502. VOID
  1503. vLine1Octant25(
  1504. PDDALINE pDDALine,
  1505. PUCHAR pjDst,
  1506. LONG lDeltaDst,
  1507. ULONG iSolidColor
  1508. )
  1509. {
  1510. LONG ErrorTerm = pDDALine->lErrorTerm;
  1511. LONG dM = pDDALine->dMajor;
  1512. LONG dN = pDDALine->dMinor;
  1513. LONG PixelCount = pDDALine->cPels;
  1514. LONG xInc = pDDALine->xInc;
  1515. ULONG Pixel;
  1516. //
  1517. // octant 2,5
  1518. //
  1519. // y major
  1520. //
  1521. // x - negative
  1522. // y - negative/positive
  1523. //
  1524. Pixel = pDDALine->ptlStart.x;
  1525. UCHAR Mask = (UCHAR)(0x80 >> (Pixel & 0x07));
  1526. pjDst = pjDst + (Pixel >> 3);
  1527. //
  1528. // integer line
  1529. //
  1530. if (iSolidColor) {
  1531. //
  1532. // loop for storing '1' pixels
  1533. //
  1534. while (TRUE) {
  1535. *pjDst |= Mask;
  1536. if (--PixelCount == 0) {
  1537. return;
  1538. }
  1539. pjDst += lDeltaDst;
  1540. ErrorTerm += dN;
  1541. if (ErrorTerm >= 0){
  1542. ErrorTerm -= dM;
  1543. Mask = (UCHAR)(Mask << 1);
  1544. if (!(Mask)) {
  1545. Mask = 0x01;
  1546. pjDst--;
  1547. }
  1548. }
  1549. }
  1550. } else {
  1551. while (TRUE) {
  1552. *pjDst &= (~Mask);
  1553. if (--PixelCount == 0) {
  1554. return;
  1555. }
  1556. pjDst += lDeltaDst;
  1557. ErrorTerm += dN;
  1558. if (ErrorTerm >= 0){
  1559. ErrorTerm -= dM;
  1560. Mask = (UCHAR)(Mask << 1);
  1561. if (!(Mask)) {
  1562. Mask = 0x01;
  1563. pjDst--;
  1564. }
  1565. }
  1566. }
  1567. }
  1568. }
  1569. /******************************Public*Routine******************************\
  1570. *
  1571. * Routine Name
  1572. *
  1573. * Inner loop DDA line drawing routines for 4bpp
  1574. *
  1575. * Routine Description:
  1576. *
  1577. * 4 dda routines for line drawing in each octant for each resolution
  1578. *
  1579. *
  1580. * Arguments:
  1581. *
  1582. * pDDALine - dda parameters
  1583. * pjDst - Destination line address
  1584. * lDeltaDst - Destination address scan line increment (bytes)
  1585. * iSolidColor - Solid color for line
  1586. *
  1587. * Return Value:
  1588. *
  1589. * VOID
  1590. *
  1591. \**************************************************************************/
  1592. VOID
  1593. vLine4Octant07(
  1594. PDDALINE pDDALine,
  1595. PUCHAR pjDst,
  1596. LONG lDeltaDst,
  1597. ULONG iSolidColor
  1598. )
  1599. {
  1600. LONG ErrorTerm = pDDALine->lErrorTerm;
  1601. LONG dM = pDDALine->dMajor;
  1602. LONG dN = pDDALine->dMinor;
  1603. LONG PixelCount = pDDALine->cPels;
  1604. ULONG Pixel;
  1605. PUCHAR PixelAddr;
  1606. iSolidColor &= 0x0f;
  1607. iSolidColor |= iSolidColor << 4;
  1608. //
  1609. // octant 0
  1610. //
  1611. // x major
  1612. //
  1613. // x - positive
  1614. // y - positive/negative
  1615. //
  1616. Pixel = pDDALine->ptlStart.x;
  1617. while (TRUE) {
  1618. PixelAddr = pjDst + (Pixel >> 1);
  1619. *PixelAddr = (UCHAR)((*PixelAddr & PixelLineMask4[Pixel & 1]) |
  1620. (iSolidColor & ~PixelLineMask4[Pixel & 1]));
  1621. //
  1622. // integer line
  1623. //
  1624. if (--PixelCount == 0) {
  1625. return;
  1626. }
  1627. Pixel++;
  1628. ErrorTerm += dN;
  1629. if (ErrorTerm >= 0){
  1630. ErrorTerm -= dM;
  1631. pjDst += lDeltaDst;
  1632. }
  1633. }
  1634. }
  1635. VOID
  1636. vLine4Octant34(
  1637. PDDALINE pDDALine,
  1638. PUCHAR pjDst,
  1639. LONG lDeltaDst,
  1640. ULONG iSolidColor
  1641. )
  1642. {
  1643. LONG ErrorTerm = pDDALine->lErrorTerm;
  1644. LONG dM = pDDALine->dMajor;
  1645. LONG dN = pDDALine->dMinor;
  1646. LONG PixelCount = pDDALine->cPels;
  1647. ULONG Pixel;
  1648. PUCHAR PixelAddr;
  1649. iSolidColor &= 0x0f;
  1650. iSolidColor |= iSolidColor << 4;
  1651. //
  1652. // octant 3
  1653. //
  1654. // x major
  1655. //
  1656. // x - negative
  1657. // y - positive/negative
  1658. //
  1659. Pixel = pDDALine->ptlStart.x;
  1660. while (TRUE) {
  1661. PixelAddr = pjDst + (Pixel >> 1);
  1662. *PixelAddr = (UCHAR)((*PixelAddr & PixelLineMask4[Pixel & 1]) |
  1663. (iSolidColor & ~PixelLineMask4[Pixel & 1]));
  1664. //
  1665. // integer line
  1666. //
  1667. if (--PixelCount == 0) {
  1668. return;
  1669. }
  1670. Pixel--;
  1671. ErrorTerm += dN;
  1672. if (ErrorTerm >= 0){
  1673. ErrorTerm -= dM;
  1674. pjDst += lDeltaDst;
  1675. }
  1676. }
  1677. }
  1678. VOID
  1679. vLine4Octant16(
  1680. PDDALINE pDDALine,
  1681. PUCHAR pjDst,
  1682. LONG lDeltaDst,
  1683. ULONG iSolidColor
  1684. )
  1685. {
  1686. LONG ErrorTerm = pDDALine->lErrorTerm;
  1687. LONG dM = pDDALine->dMajor;
  1688. LONG dN = pDDALine->dMinor;
  1689. LONG PixelCount = pDDALine->cPels;
  1690. LONG xInc = pDDALine->xInc;
  1691. ULONG Pixel;
  1692. PUCHAR PixelAddr;
  1693. iSolidColor &= 0x0f;
  1694. iSolidColor |= iSolidColor << 4;
  1695. //
  1696. // octant 1,6
  1697. //
  1698. // y major
  1699. //
  1700. // x - positive
  1701. // y - positive/negative
  1702. //
  1703. Pixel = pDDALine->ptlStart.x;
  1704. while (TRUE) {
  1705. PixelAddr = pjDst + (Pixel >> 1);
  1706. *PixelAddr = (UCHAR)((*PixelAddr & PixelLineMask4[Pixel & 1]) |
  1707. (iSolidColor & ~PixelLineMask4[Pixel & 1]));
  1708. //
  1709. // integer line
  1710. //
  1711. if (--PixelCount == 0) {
  1712. return;
  1713. }
  1714. pjDst += lDeltaDst;
  1715. ErrorTerm += dN;
  1716. if (ErrorTerm >= 0){
  1717. ErrorTerm -= dM;
  1718. Pixel ++;
  1719. }
  1720. }
  1721. }
  1722. VOID
  1723. vLine4Octant25(
  1724. PDDALINE pDDALine,
  1725. PUCHAR pjDst,
  1726. LONG lDeltaDst,
  1727. ULONG iSolidColor
  1728. )
  1729. {
  1730. LONG ErrorTerm = pDDALine->lErrorTerm;
  1731. LONG dM = pDDALine->dMajor;
  1732. LONG dN = pDDALine->dMinor;
  1733. LONG PixelCount = pDDALine->cPels;
  1734. LONG xInc = pDDALine->xInc;
  1735. ULONG Pixel;
  1736. PUCHAR PixelAddr;
  1737. iSolidColor &= 0x0f;
  1738. iSolidColor |= iSolidColor << 4;
  1739. //
  1740. // octant 2,5
  1741. //
  1742. // y major
  1743. //
  1744. // x - negative
  1745. // y - psoitive\negative
  1746. //
  1747. Pixel = pDDALine->ptlStart.x;
  1748. while (TRUE) {
  1749. PixelAddr = pjDst + (Pixel >> 1);
  1750. *PixelAddr = (UCHAR)((*PixelAddr & PixelLineMask4[Pixel & 1]) |
  1751. (iSolidColor & ~PixelLineMask4[Pixel & 1]));
  1752. //
  1753. // integer line
  1754. //
  1755. if (--PixelCount == 0) {
  1756. return;
  1757. }
  1758. pjDst += lDeltaDst;
  1759. ErrorTerm += dN;
  1760. if (ErrorTerm >= 0){
  1761. ErrorTerm -= dM;
  1762. Pixel --;
  1763. }
  1764. }
  1765. }
  1766. /******************************Public*Routine******************************\
  1767. *
  1768. * Routine Name
  1769. *
  1770. * vHorizontalLineN
  1771. *
  1772. * Routine Description:
  1773. *
  1774. * Accelerator for horizontal lines
  1775. *
  1776. * Arguments:
  1777. *
  1778. * pjDst - Scan line dst address
  1779. * x0 - Starting pixel location
  1780. * x1 - Ending pixel location (exclusive)
  1781. * iSolidColor - Solid Color replicated to 32 bits if needed
  1782. *
  1783. * Return Value:
  1784. *
  1785. * VOID
  1786. *
  1787. \**************************************************************************/
  1788. VOID
  1789. vHorizontalLine1(
  1790. PUCHAR pjDst,
  1791. LONG x0,
  1792. LONG x1,
  1793. ULONG iSolidColor)
  1794. {
  1795. ULONG Count;
  1796. ULONG Alignment;
  1797. //
  1798. // count = number of pixels to write, make sure it is not 0
  1799. //
  1800. Count = x1 - x0;
  1801. if (Count) {
  1802. pjDst += (x0 >> 3);
  1803. Alignment = x0 & 0x07;
  1804. //
  1805. // alignment Start bits
  1806. //
  1807. if ((Alignment) && ((ULONG)Count >= (8 - Alignment)))
  1808. {
  1809. //
  1810. // partial byte
  1811. //
  1812. *pjDst = (UCHAR)((*pjDst & (~(0xFF >> Alignment))) |
  1813. (iSolidColor & (0xFF >> Alignment)));
  1814. pjDst ++;
  1815. Count -= ( 8 - Alignment);
  1816. Alignment = 0;
  1817. }
  1818. //
  1819. // byte loop
  1820. //
  1821. if (Alignment == 0) {
  1822. //
  1823. // full byte stores
  1824. //
  1825. ULONG NumBytes = Count >> 3;
  1826. if (NumBytes > 0) {
  1827. RtlFillMemory((PVOID)pjDst,NumBytes,(UCHAR)iSolidColor);
  1828. pjDst += NumBytes;
  1829. Count = (Count & 0x07);
  1830. }
  1831. //
  1832. // last store
  1833. //
  1834. if (Count > 0) {
  1835. *pjDst = (UCHAR)((*pjDst & (0xFF >> Count)) |
  1836. (iSolidColor & (~(0xFF >> Count))));
  1837. }
  1838. return;
  1839. }
  1840. //
  1841. // do whats left, partial of 1 byte with
  1842. // start bit = alignment, number of bits = Count
  1843. //
  1844. //
  1845. // bit
  1846. // ���������������Ŀ
  1847. // �7�6�5�4�3�2�1�0�
  1848. // �����������������
  1849. //
  1850. // pixel
  1851. // ���������������Ŀ
  1852. // �0�1�2�3�4�5�6�7�
  1853. // �����������������
  1854. {
  1855. UCHAR DstMask = (UCHAR)(0xff >> Alignment);
  1856. UCHAR AndMask = (UCHAR)(0xff << (8 - (Count + Alignment)));
  1857. DstMask &= AndMask;
  1858. *pjDst = (UCHAR)((*pjDst & (~DstMask)) | (iSolidColor & DstMask));
  1859. }
  1860. }
  1861. }
  1862. VOID
  1863. vHorizontalLine4(
  1864. PUCHAR pjDst,
  1865. LONG x0,
  1866. LONG x1,
  1867. ULONG iSolidColor)
  1868. {
  1869. ULONG Count;
  1870. ULONG Alignment;
  1871. ULONG NumBytes;
  1872. Count = x1 - x0;
  1873. if (Count) {
  1874. pjDst += (x0 >> 1);
  1875. //
  1876. // alignment Start nibble
  1877. //
  1878. Alignment = x0 & 0x01;
  1879. if (Alignment)
  1880. {
  1881. *pjDst = (UCHAR)((*pjDst & 0xf0) |
  1882. (iSolidColor & 0x0f));
  1883. Count--;
  1884. pjDst++;
  1885. }
  1886. //
  1887. // aligned to byte boundary
  1888. //
  1889. NumBytes = Count >> 1;
  1890. if (NumBytes) {
  1891. RtlFillMemory((PVOID)pjDst,NumBytes,(BYTE)iSolidColor);
  1892. pjDst += NumBytes;
  1893. Count = Count & 0x01;
  1894. }
  1895. //
  1896. // end alignment if needed
  1897. //
  1898. if (Count) {
  1899. *pjDst = (UCHAR)((*pjDst & 0x0f) |
  1900. (iSolidColor & 0xf0));
  1901. }
  1902. }
  1903. }
  1904. VOID
  1905. vHorizontalLine8(
  1906. PUCHAR pjDst,
  1907. LONG x0,
  1908. LONG x1,
  1909. ULONG iSolidColor)
  1910. {
  1911. ULONG Count;
  1912. UCHAR Align;
  1913. //
  1914. // increment pjDst to x0 address
  1915. //
  1916. pjDst += x0;
  1917. //
  1918. // if byte count is less then 7, then just quickly do
  1919. // the bytes
  1920. //
  1921. Count = x1 - x0;
  1922. if (Count <= 6) {
  1923. while (Count--) {
  1924. *pjDst++ = (UCHAR)iSolidColor;
  1925. }
  1926. return;
  1927. }
  1928. //
  1929. // large scan line that at least covers 1 full DWORD,
  1930. // first do partial bytes if needed
  1931. //
  1932. //
  1933. // do partial bytes, count is gaurenteed to be
  1934. // greater than max of 3 alignment bytes
  1935. //
  1936. Align = (UCHAR)(x0 & 0x03);
  1937. switch (Align) {
  1938. case 1:
  1939. *pjDst++ = (UCHAR)iSolidColor;
  1940. Count--;
  1941. case 2:
  1942. *(PUSHORT)pjDst = (USHORT)iSolidColor;
  1943. pjDst += 2;
  1944. Count -= 2;
  1945. break;
  1946. case 3:
  1947. *pjDst++ = (UCHAR)iSolidColor;
  1948. Count--;
  1949. }
  1950. ULONG NumBytes = Count & (~0x03);
  1951. //
  1952. // fill Dwords
  1953. //
  1954. RtlFillMemoryUlong((PVOID)pjDst,NumBytes,iSolidColor);
  1955. pjDst += NumBytes;
  1956. //
  1957. // fill last partial bytes
  1958. //
  1959. switch (Count & 0x03) {
  1960. case 1:
  1961. *pjDst = (UCHAR)iSolidColor;
  1962. break;
  1963. case 2:
  1964. *(PUSHORT)pjDst = (USHORT)iSolidColor;
  1965. break;
  1966. case 3:
  1967. *(PUSHORT)pjDst = (USHORT)iSolidColor;
  1968. *(pjDst+2) = (UCHAR)iSolidColor;
  1969. }
  1970. }
  1971. VOID
  1972. vHorizontalLine16(
  1973. PUCHAR pjDst,
  1974. LONG x0,
  1975. LONG x1,
  1976. ULONG iSolidColor)
  1977. {
  1978. PUSHORT pusDst = (PUSHORT)pjDst + x0;
  1979. ULONG Count = x1 - x0;
  1980. if (Count) {
  1981. //
  1982. // do starting alignment
  1983. //
  1984. if (x0 & 0x01) {
  1985. *pusDst++ = (USHORT)iSolidColor;
  1986. Count--;
  1987. }
  1988. //
  1989. // fill dwords
  1990. //
  1991. ULONG NumDwords = Count >> 1;
  1992. if (NumDwords) {
  1993. RtlFillMemoryUlong((PVOID)pusDst,NumDwords << 2,iSolidColor);
  1994. }
  1995. //
  1996. // fill last 16 if needed
  1997. //
  1998. if (Count & 0x01) {
  1999. //
  2000. // add Number of USHORTS stored in RtlFillMemoryUlong to pusDst
  2001. // then store final USHORT
  2002. //
  2003. pusDst += NumDwords << 1;
  2004. *pusDst = (USHORT)iSolidColor;
  2005. }
  2006. }
  2007. }
  2008. VOID
  2009. vHorizontalLine24(
  2010. PUCHAR pjDst,
  2011. LONG x0,
  2012. LONG x1,
  2013. ULONG iSolidColor)
  2014. {
  2015. UCHAR Red = (UCHAR)iSolidColor;
  2016. UCHAR Green = (UCHAR)(iSolidColor >> 8);
  2017. UCHAR Blue = (UCHAR)(iSolidColor >> 16);
  2018. PUCHAR pjEnd = pjDst + 3*x1;
  2019. pjDst += 3*x0;
  2020. while (pjDst < pjEnd) {
  2021. *pjDst = Red;
  2022. *(pjDst+1) = Green;
  2023. *(pjDst+2) = Blue;
  2024. pjDst += 3;
  2025. }
  2026. }
  2027. VOID
  2028. vHorizontalLine32(
  2029. PUCHAR pjDst,
  2030. LONG x0,
  2031. LONG x1,
  2032. ULONG iSolidColor)
  2033. {
  2034. //
  2035. // incremnet pjDst x0 DWORDs
  2036. //
  2037. pjDst += (x0 << 2);
  2038. //
  2039. // fill
  2040. //
  2041. if (x1 != x0) {
  2042. RtlFillMemoryUlong((PVOID)pjDst,(x1 - x0) << 2,iSolidColor);
  2043. }
  2044. }
  2045. /******************************Public*Routine******************************\
  2046. *
  2047. * Routine Name
  2048. *
  2049. * bGIQtoIntegerLine
  2050. *
  2051. * Routine Description:
  2052. *
  2053. * This routine takes GIQ endpoints and calculates the correct integer
  2054. * endpoints, error term and flags.
  2055. *
  2056. * Arguments:
  2057. *
  2058. * pptfxStart - GIQ point 0
  2059. * pptfxEnd - GIQ point 1
  2060. * prclClip - clip rectangles
  2061. * pDDALine - Interger line params
  2062. *
  2063. * Return Value:
  2064. *
  2065. * True if this line can be drawn with 32 bit arithmatic and
  2066. * all params are calculated, otherwise false
  2067. *
  2068. \**************************************************************************/
  2069. #define HW_X_ROUND_DOWN 0x0100L // x = 1/2 rounds down in value
  2070. #define HW_Y_ROUND_DOWN 0x0200L // y = 1/2 rounds down in value
  2071. FLONG gaflHardwareRound[] = {
  2072. HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN, // | | |
  2073. HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN, // | | | FLIP_D
  2074. HW_X_ROUND_DOWN, // | | FLIP_V |
  2075. HW_Y_ROUND_DOWN, // | | FLIP_V | FLIP_D
  2076. HW_Y_ROUND_DOWN, // | FLIP_H | |
  2077. HW_X_ROUND_DOWN, // | FLIP_H | | FLIP_D
  2078. 0, // | FLIP_H | FLIP_V |
  2079. 0, // | FLIP_H | FLIP_V | FLIP_D
  2080. HW_Y_ROUND_DOWN, // SLOPE_ONE | | |
  2081. 0xffffffff, // SLOPE_ONE | | | FLIP_D
  2082. HW_X_ROUND_DOWN, // SLOPE_ONE | | FLIP_V |
  2083. 0xffffffff, // SLOPE_ONE | | FLIP_V | FLIP_D
  2084. HW_Y_ROUND_DOWN, // SLOPE_ONE | FLIP_H | |
  2085. 0xffffffff, // SLOPE_ONE | FLIP_H | | FLIP_D
  2086. HW_X_ROUND_DOWN, // SLOPE_ONE | FLIP_H | FLIP_V |
  2087. 0xffffffff // SLOPE_ONE | FLIP_H | FLIP_V | FLIP_D
  2088. };
  2089. BOOL bGIQtoIntegerLine(
  2090. POINTFIX* pptfxStart,
  2091. POINTFIX* pptfxEnd,
  2092. PRECTL prclClip,
  2093. DDALINE* pDDALine)
  2094. {
  2095. FLONG fl; // Various flags
  2096. ULONG M0; // Normalized fractional unit x start coordinate (0 <= M0 < F)
  2097. ULONG N0; // Normalized fractional unit y start coordinate (0 <= N0 < F)
  2098. ULONG M1; // Normalized fractional unit x end coordinate (0 <= M1 < F)
  2099. ULONG N1; // Normalized fractional unit x end coordinate (0 <= N1 < F)
  2100. ULONG dM; // Normalized fractional unit x-delta (0 <= dM)
  2101. ULONG dN; // Normalized fractional unit y-delta (0 <= dN <= dM)
  2102. LONG x; // Normalized x coordinate of origin
  2103. LONG y; // Normalized y coordinate of origin
  2104. LONG x0; // Normalized x offset from origin to start Pixel (inclusive)
  2105. LONG y0; // Normalized y offset from origin to start Pixel (inclusive)
  2106. LONG x1; // Normalized x offset from origin to end Pixel (inclusive)
  2107. LONG lGamma; // Possibly overflowing Bresenham error term at origin
  2108. LONGLONG eqGamma;// Non-overflowing Bresenham error term at origin
  2109. BOOL bReturn = FALSE;
  2110. /***********************************************************************\
  2111. * Normalize line to the first octant.
  2112. \***********************************************************************/
  2113. #if DBG_LINE
  2114. if (DbgLine >= 2) {
  2115. DbgPrint("\nCalculate GIQ parameters for line:\n");
  2116. DbgPrint("pptfxStart = %li.%li, %li.%li\n",
  2117. pptfxStart->x >> 4,
  2118. pptfxStart->x & 0x0f,
  2119. pptfxStart->y >> 4,
  2120. pptfxStart->y & 0x0f);
  2121. DbgPrint("pptxEnd = %li.%li, %li.%li\n\n",
  2122. pptfxEnd->x >> 4,
  2123. pptfxEnd->x & 0x0f,
  2124. pptfxEnd->y >> 4,
  2125. pptfxEnd->y & 0x0f);
  2126. }
  2127. #endif
  2128. fl = 0;
  2129. M0 = pptfxStart->x;
  2130. dM = pptfxEnd->x;
  2131. if ((LONG) dM < (LONG) M0)
  2132. {
  2133. //
  2134. // Line runs from right to left, so flip across x = 0:
  2135. //
  2136. M0 = -(LONG) M0;
  2137. dM = -(LONG) dM;
  2138. fl |= FL_SOL_FLIP_H;
  2139. }
  2140. //
  2141. // Compute the delta dx. The DDI says we can never have a valid delta
  2142. // with a magnitude more than 2^31 - 1, but the engine never actually
  2143. // checks its transforms. Check for that case and simply refuse to draw
  2144. // the line:
  2145. //
  2146. dM -= M0;
  2147. if ((LONG) dM < 0)
  2148. {
  2149. goto GIQEnd;
  2150. }
  2151. N0 = pptfxStart->y;
  2152. dN = pptfxEnd->y;
  2153. if ((LONG) dN < (LONG) N0)
  2154. {
  2155. //
  2156. // Line runs from bottom to top, so flip across y = 0
  2157. //
  2158. N0 = -(LONG) N0;
  2159. dN = -(LONG) dN;
  2160. fl |= FL_SOL_FLIP_V;
  2161. }
  2162. //
  2163. // Compute the delta dy
  2164. //
  2165. dN -= N0;
  2166. if ((LONG) dN < 0)
  2167. {
  2168. goto GIQEnd;
  2169. }
  2170. //
  2171. // check for y-major lines and lines with
  2172. // slope = 1
  2173. //
  2174. if (dN >= dM)
  2175. {
  2176. if (dN == dM)
  2177. {
  2178. //
  2179. // Have to special case slopes of one:
  2180. //
  2181. fl |= FL_SOL_FLIP_SLOPE_ONE;
  2182. }
  2183. else
  2184. {
  2185. //
  2186. // Since line has slope greater than 1, flip across x = y:
  2187. //
  2188. register ULONG ulTmp;
  2189. ulTmp = dM; dM = dN; dN = ulTmp;
  2190. ulTmp = M0; M0 = N0; N0 = ulTmp;
  2191. fl |= FL_SOL_FLIP_D;
  2192. }
  2193. }
  2194. //
  2195. // look up rounding for this line from the table
  2196. //
  2197. fl |= gaflHardwareRound[fl];
  2198. //
  2199. // Calculate the error term at Pixel 0
  2200. //
  2201. x = LFLOOR((LONG) M0);
  2202. y = LFLOOR((LONG) N0);
  2203. M0 = FXFRAC(M0);
  2204. N0 = FXFRAC(N0);
  2205. #if DBG_LINE
  2206. if (DbgLine >= 2) {
  2207. DbgPrint("Calc x = %li\n",x);
  2208. DbgPrint("Calc y = %li\n",y);
  2209. DbgPrint("Calc M0 = %li\n",M0);
  2210. DbgPrint("Calc N0 = %li\n",N0);
  2211. }
  2212. #endif
  2213. //
  2214. // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]. Note
  2215. // that M0 and N0 have at most 4 bits of significance (and if the
  2216. // arguments are properly ordered, on a 486 each multiply would be no
  2217. // more than 13 cycles):
  2218. //
  2219. //
  2220. // For the sake of speed, we're only going to do 32-bit multiplies
  2221. // in this routine. If the line is long enough though, we may
  2222. // need 38 bits for this calculation. Since at this point
  2223. // dM >= dN >= 0, and 0 <= N0 < 16, we'll just need to have 6 bits
  2224. // unused in 'dM':
  2225. //
  2226. if (dM <= (LONG_MAX >> 6))
  2227. {
  2228. lGamma = (N0 + F/2) * dM - M0 * dN;
  2229. if (fl & HW_Y_ROUND_DOWN)
  2230. lGamma--;
  2231. lGamma >>= FLOG2;
  2232. eqGamma = lGamma;
  2233. }
  2234. else
  2235. {
  2236. LONGLONG eq;
  2237. //
  2238. // Ugh, use safe 64-bit multiply code (cut and pasted from
  2239. // 'engline.cxx'):
  2240. //
  2241. eqGamma = Int32x32To64(N0 + F/2, dM);
  2242. eq = Int32x32To64(M0, dN);
  2243. eqGamma -= eq;
  2244. if (fl & FL_V_ROUND_DOWN)
  2245. eqGamma -= 1; // Adjust so y = 1/2 rounds down
  2246. eqGamma >>= FLOG2;
  2247. }
  2248. //
  2249. // Figure out which Pixels are at the ends of the line.
  2250. //
  2251. //
  2252. // The toughest part of GIQ is determining the start and end pels.
  2253. //
  2254. // Our approach here is to calculate x0 and x1 (the inclusive start
  2255. // and end columns of the line respectively, relative to our normalized
  2256. // origin). Then x1 - x0 + 1 is the number of pels in the line. The
  2257. // start point is easily calculated by plugging x0 into our line equation
  2258. // (which takes care of whether y = 1/2 rounds up or down in value)
  2259. // getting y0, and then undoing the normalizing flips to get back
  2260. // into device space.
  2261. //
  2262. // We look at the fractional parts of the coordinates of the start and
  2263. // end points, and call them (M0, N0) and (M1, N1) respectively, where
  2264. // 0 <= M0, N0, M1, N1 < 16. We plot (M0, N0) on the following grid
  2265. // to determine x0:
  2266. //
  2267. // +-----------------------> +x
  2268. // |
  2269. // | 0 1
  2270. // | 0123456789abcdef
  2271. // |
  2272. // | 0 ........?xxxxxxx
  2273. // | 1 ..........xxxxxx
  2274. // | 2 ...........xxxxx
  2275. // | 3 ............xxxx
  2276. // | 4 .............xxx
  2277. // | 5 ..............xx
  2278. // | 6 ...............x
  2279. // | 7 ................
  2280. // | 8 ................
  2281. // | 9 ......**........
  2282. // | a ........****...x
  2283. // | b ............****
  2284. // | c .............xxx****
  2285. // | d ............xxxx ****
  2286. // | e ...........xxxxx ****
  2287. // | f ..........xxxxxx
  2288. // |
  2289. // | 2 3
  2290. // v
  2291. //
  2292. // +y
  2293. //
  2294. // This grid accounts for the appropriate rounding of GIQ and last-pel
  2295. // exclusion. If (M0, N0) lands on an 'x', x0 = 2. If (M0, N0) lands
  2296. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  2297. // depending on what flips have been done to normalize the line.
  2298. //
  2299. // For the end point, if (M1, N1) lands on an 'x', x1 =
  2300. // floor((M0 + dM) / 16) + 1. If (M1, N1) lands on a '.', x1 =
  2301. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  2302. // depending on what flips have been done to normalize the line.
  2303. //
  2304. // Lines of exactly slope one require a special case for both the start
  2305. // and end. For example, if the line ends such that (M1, N1) is (9, 1),
  2306. // the line has gone exactly through (8, 0) -- which may be considered
  2307. // to be part of 'x' because of rounding! So slopes of exactly slope
  2308. // one going through (8, 0) must also be considered as belonging in 'x'
  2309. // when an x value of 1/2 is supposed to round up in value.
  2310. //
  2311. //
  2312. // Calculate x0, x1:
  2313. //
  2314. N1 = FXFRAC(N0 + dN);
  2315. M1 = FXFRAC(M0 + dM);
  2316. x1 = LFLOOR(M0 + dM);
  2317. //
  2318. // Line runs left-to-right
  2319. //
  2320. //
  2321. // Compute x1
  2322. //
  2323. x1--;
  2324. if (M1 > 0)
  2325. {
  2326. if (N1 == 0)
  2327. {
  2328. if (LROUND(M1, fl & HW_X_ROUND_DOWN))
  2329. x1++;
  2330. }
  2331. else if (ABS((LONG) (N1 - F/2)) <= (LONG) M1)
  2332. {
  2333. x1++;
  2334. }
  2335. }
  2336. if ((fl & (FL_SOL_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
  2337. == (FL_SOL_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
  2338. {
  2339. //
  2340. // Have to special-case diagonal lines going through our
  2341. // the point exactly equidistant between two horizontal
  2342. // Pixels, if we're supposed to round x=1/2 down:
  2343. //
  2344. if ((M1 > 0) && (N1 == M1 + 8))
  2345. x1--;
  2346. if ((M0 > 0) && (N0 == M0 + 8))
  2347. {
  2348. x0 = 0;
  2349. goto left_to_right_compute_y0;
  2350. }
  2351. }
  2352. //
  2353. // Compute x0:
  2354. //
  2355. x0 = 0;
  2356. if (M0 > 0)
  2357. {
  2358. if (N0 == 0)
  2359. {
  2360. if (LROUND(M0, fl & HW_X_ROUND_DOWN))
  2361. x0 = 1;
  2362. }
  2363. else if (ABS((LONG) (N0 - F/2)) <= (LONG) M0)
  2364. {
  2365. x0 = 1;
  2366. }
  2367. }
  2368. left_to_right_compute_y0:
  2369. //**********************************************************************
  2370. // Calculate the start Pixel.
  2371. //***********************************************************************
  2372. //
  2373. // We now compute y0 and adjust the error term. We know x0, and we know
  2374. // the current formula for the Pixels to be lit on the line:
  2375. //
  2376. // dN * x + eqGamma
  2377. // y(x) = floor( ---------------- )
  2378. // dM
  2379. //
  2380. // The remainder of this expression is the new error term at (x0, y0).
  2381. // Since x0 is going to be either 0 or 1, we don't actually have to do a
  2382. // multiply or divide to compute y0. Finally, we subtract dM from the
  2383. // new error term so that it is in the range [-dM, 0).
  2384. //
  2385. y0 = 0;
  2386. if ((eqGamma >= 0) &&
  2387. (eqGamma >= (dM - (dN & (-(LONG) x0)))))
  2388. {
  2389. y0 = 1;
  2390. }
  2391. //
  2392. // check to see if the line is NULL, this should only happen
  2393. // with a line of slope = 1.
  2394. //
  2395. if (x1 < x0) {
  2396. pDDALine->cPels = 0;
  2397. bReturn = TRUE;
  2398. goto GIQEnd;
  2399. }
  2400. //*******************************************************************
  2401. //
  2402. // Must perform rectangular clipping
  2403. //
  2404. //*******************************************************************
  2405. if (prclClip != (PRECTL) NULL)
  2406. {
  2407. ULONG y1;
  2408. LONG xRight;
  2409. LONG xLeft;
  2410. LONG yBottom;
  2411. LONG yTop;
  2412. LONGLONG euq;
  2413. LONGLONG eq;
  2414. LONGLONG eqBeta;
  2415. RECTL rclClip;
  2416. //
  2417. // Note that y0 and y1 are actually the lower and upper bounds,
  2418. // respectively, of the y coordinates of the line (the line may
  2419. // have actually shrunk due to first/last pel clipping).
  2420. //
  2421. // Also note that x0, y0 are not necessarily zero.
  2422. //
  2423. RECTL* prcl = &prclClip[(fl & FL_SOL_RECTLCLIP_MASK)];
  2424. //
  2425. // take flip_h into account
  2426. //
  2427. if (fl & FL_SOL_FLIP_H) {
  2428. if (fl & FL_SOL_FLIP_D) {
  2429. rclClip.top = -prcl->bottom + 1;
  2430. rclClip.bottom = -prcl->top + 1;
  2431. rclClip.left = prcl->left;
  2432. rclClip.right = prcl->right;
  2433. } else {
  2434. rclClip.left = -prcl->right + 1;
  2435. rclClip.right = -prcl->left + 1;
  2436. rclClip.top = prcl->top;
  2437. rclClip.bottom = prcl->bottom;
  2438. }
  2439. } else {
  2440. rclClip.left = prcl->left;
  2441. rclClip.right = prcl->right;
  2442. rclClip.top = prcl->top;
  2443. rclClip.bottom = prcl->bottom;
  2444. }
  2445. //
  2446. // Normalize to the same point we've normalized for the DDA
  2447. // calculations:
  2448. //
  2449. xRight = rclClip.right - x;
  2450. xLeft = rclClip.left - x;
  2451. yBottom = rclClip.bottom - y;
  2452. yTop = rclClip.top - y;
  2453. #if DBG_LINE
  2454. if (DbgLine >= 2) {
  2455. DbgPrint("Clipping line to rect %li,%li to %li,%li\n",
  2456. rclClip.left,
  2457. rclClip.top,
  2458. rclClip.right,
  2459. rclClip.bottom);
  2460. DbgPrint("Clipping Parameters: xLeft %li xRight %li yBottom %li yTop %li\n",
  2461. xLeft,
  2462. xRight,
  2463. yBottom,
  2464. yTop);
  2465. DbgPrint("normalized line before clip, x = %li, y = %li, x0 = %li, x1 = %li, y0 = %li\n",
  2466. x,y,x0,x1,y0);
  2467. DbgPrint("Line Params: dM = %li, dN = %li, eqGamma = %lx\n",dM,dN,(ULONG)eqGamma);
  2468. }
  2469. #endif
  2470. if (yBottom <= (LONG) y0 ||
  2471. xRight <= (LONG) x0 ||
  2472. xLeft > (LONG) x1)
  2473. {
  2474. Totally_Clipped:
  2475. #if DBG_LINE
  2476. if (DbgLine >= 2) {
  2477. DbgPrint("Line is totally clipped\n");
  2478. }
  2479. #endif
  2480. pDDALine->cPels = 0;
  2481. bReturn = TRUE;
  2482. goto GIQEnd;
  2483. }
  2484. if ((LONG) x1 >= xRight)
  2485. {
  2486. x1 = xRight - 1;
  2487. #if DBG_LINE
  2488. if (DbgLine >= 2) {
  2489. DbgPrint("Line clip x1 to %li\n",x1);
  2490. }
  2491. #endif
  2492. }
  2493. //
  2494. // We have to know the correct y1, which we haven't bothered to
  2495. // calculate up until now. This multiply and divide is quite
  2496. // expensive; we could replace it with code similar to that which
  2497. // we used for computing y0.
  2498. //
  2499. // The reason why we need the actual value, and not an upper
  2500. // bounds guess like y1 = LFLOOR(dM) + 2 is that we have to be
  2501. // careful when calculating x(y) that y0 <= y <= y1, otherwise
  2502. // we can overflow on the divide (which, needless to say, is very
  2503. // bad).
  2504. //
  2505. eqBeta = ~eqGamma;
  2506. euq = Int32x32To64(x1, dN);
  2507. euq += eqGamma;
  2508. y1 = DIV(euq, dM);
  2509. #if DBG_LINE
  2510. if (DbgLine >= 2) {
  2511. DbgPrint("Clipping: calculated y1 = %li eqBeta = 0x%lx 0x%lx\n",y1,(LONG)(eqBeta>>32),(ULONG)eqBeta);
  2512. }
  2513. #endif
  2514. //
  2515. // check for y1 less than the top of the clip rect
  2516. //
  2517. if (yTop > (LONG) y1)
  2518. goto Totally_Clipped;
  2519. //
  2520. // check for y1 > the bottom of the clip rect, clip if true
  2521. //
  2522. if (yBottom <= (LONG) y1)
  2523. {
  2524. y1 = yBottom;
  2525. euq = Int32x32To64(y1, dM);
  2526. euq += eqBeta;
  2527. x1 = DIV(euq,dN);
  2528. #if DBG_LINE
  2529. if (DbgLine >= 2) {
  2530. DbgPrint("Clipped y1 to %li, x1 = %li\n",y1,x1);
  2531. }
  2532. #endif
  2533. }
  2534. //
  2535. // At this point, we've taken care of calculating the intercepts
  2536. // with the right and bottom edges. Now we work on the left and
  2537. // top edges:
  2538. //
  2539. if (xLeft > (LONG) x0)
  2540. {
  2541. x0 = xLeft;
  2542. euq = Int32x32To64(x0, dN);
  2543. euq += eqGamma;
  2544. y0 = DIV(euq, dM);
  2545. if (yBottom <= (LONG) y0)
  2546. goto Totally_Clipped;
  2547. #if DBG_LINE
  2548. if (DbgLine >= 2) {
  2549. DbgPrint("Clipped x0 to %li, y0 = %li\n",x0,y0);
  2550. }
  2551. #endif
  2552. }
  2553. //
  2554. // check for y0 less than the top of the clip rect, clip if true
  2555. //
  2556. if (yTop > (LONG) y0)
  2557. {
  2558. y0 = yTop;
  2559. euq = Int32x32To64(y0, dM);
  2560. euq += eqBeta;
  2561. x0 = DIV(euq, dN) + 1;
  2562. if (xRight <= (LONG) x0)
  2563. goto Totally_Clipped;
  2564. #if DBG_LINE
  2565. if (DbgLine >= 2) {
  2566. DbgPrint("Clipped y0 to %li, x0 = %li\n",y0,x0);
  2567. }
  2568. #endif
  2569. }
  2570. euq = Int32x32To64(x0,dN);
  2571. eq = Int32x32To64(y0,dM);
  2572. euq -= eq;
  2573. eqGamma += euq;
  2574. eqGamma -= dM;
  2575. #if DBG_LINE
  2576. if (DbgLine >= 2) {
  2577. DbgPrint("Clipped line: x0 = %li, x1 = %li, y0 = %li, y1 = %li\n",
  2578. x0,
  2579. x1,
  2580. y0,
  2581. y1);
  2582. DbgPrint("eqGamma = %lx\n",eqGamma);
  2583. }
  2584. if (x0 > x1) {
  2585. DbgPrint("Clip Error: x0 > x1\n");
  2586. DbgPrint(" pptxStart = %li.%li, %li.%li\n",
  2587. pptfxStart->x >> 4,
  2588. pptfxStart->x & 0x0f,
  2589. pptfxStart->y >> 4,
  2590. pptfxStart->y & 0x0f);
  2591. DbgPrint(" pptxEnd = %li.%li, %li.%li\n",
  2592. pptfxEnd->x >> 4,
  2593. pptfxEnd->x & 0x0f,
  2594. pptfxEnd->y >> 4,
  2595. pptfxEnd->y & 0x0f);
  2596. DbgPrint(" prclClip = 0x%lx\n",prclClip);
  2597. DbgPrint(" x0 = %li\n",x0);
  2598. DbgPrint(" y0 = %li\n",y0);
  2599. DbgPrint(" x1 = %li\n",x1);
  2600. DbgPrint(" y1 = %li\n",y1);
  2601. DbgPrint(" dM = %li\n",dM);
  2602. DbgPrint(" dN = %li\n",dN);
  2603. DbgPrint(" lGamma = %li\n",lGamma);
  2604. DbgPrint(" Clipping line to rect %li,%li to %li,%li\n",
  2605. rclClip.left,
  2606. rclClip.top,
  2607. rclClip.right,
  2608. rclClip.bottom);
  2609. }
  2610. #endif
  2611. ASSERTGDI(x0 <= x1, "Improper rectangle clip");
  2612. } else {
  2613. //
  2614. // adjust lGamma
  2615. //
  2616. eqGamma += (dN & (-x0));
  2617. eqGamma -= dM;
  2618. if (eqGamma >= 0)
  2619. {
  2620. eqGamma -= dM;
  2621. }
  2622. }
  2623. //
  2624. // END of simple clipping
  2625. //
  2626. //
  2627. // Undo our flips to get the start coordinate:
  2628. //
  2629. x += x0;
  2630. y += y0;
  2631. if (fl & FL_SOL_FLIP_D)
  2632. {
  2633. register LONG lTmp;
  2634. lTmp = x; x = y; y = lTmp;
  2635. }
  2636. if (fl & FL_SOL_FLIP_V)
  2637. {
  2638. y = -y;
  2639. }
  2640. if (fl & FL_SOL_FLIP_H)
  2641. {
  2642. x = -x;
  2643. }
  2644. /***********************************************************************\
  2645. * Return the Bresenham terms:
  2646. \***********************************************************************/
  2647. //
  2648. // check values
  2649. //
  2650. pDDALine->ulFlags = fl;
  2651. pDDALine->ptlStart.x = x;
  2652. pDDALine->ptlStart.y = y;
  2653. pDDALine->cPels = x1 - x0 + 1; // NOTE: You'll have to check if cPels <= 0!
  2654. pDDALine->dMajor = dM;
  2655. pDDALine->dMinor = dN;
  2656. pDDALine->lErrorTerm = (LONG) eqGamma;
  2657. pDDALine->xInc = 1;
  2658. bReturn = TRUE;
  2659. //
  2660. // end routine
  2661. //
  2662. GIQEnd:
  2663. return(bReturn);
  2664. }