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.

234 lines
5.9 KiB

  1. /*************************************************************************\
  2. * Module Name: dda.cxx
  3. *
  4. * DDA calculations for clipping.
  5. *
  6. * Created: 20-Mar-1991
  7. * Author: Paul Butzi
  8. *
  9. * Copyright (c) 1991-1999 Microsoft Corporation
  10. *
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. FLONG gaflRound[] = {
  14. FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // no flips
  15. FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // FLIP_D
  16. FL_H_ROUND_DOWN, // FLIP_V
  17. FL_V_ROUND_DOWN, // FLIP_V | FLIP_D
  18. FL_V_ROUND_DOWN, // SLOPE_ONE
  19. 0xffffffff, // SLOPE_ONE | FLIP_D
  20. FL_H_ROUND_DOWN, // SLOPE_ONE | FLIP_V
  21. 0xffffffff, // SLOPE_ONE | FLIP_V | FLIP_D
  22. // These entries are used only by the complex line clipping component, which
  23. // actually does a left-to-right flip about x = 0 (the line drawing code
  24. // only does a left-for-right exchange and so doesn't need these extra
  25. // bits):
  26. FL_V_ROUND_DOWN, // FLIP_H
  27. FL_H_ROUND_DOWN, // FLIP_H | FLIP_D
  28. 0, // FLIP_H | FLIP_V
  29. 0, // FLIP_H | FLIP_V | FLIP_D
  30. FL_V_ROUND_DOWN, // FLIP_H | SLOPE_ONE
  31. 0xffffffff, // FLIP_H | SLOPE_ONE | FLIP_D
  32. FL_H_ROUND_DOWN, // FLIP_H | SLOPE_ONE | FLIP_V
  33. 0xffffffff // FLIP_H | SLOPE_ONE | FLIP_V | FLIP_D
  34. };
  35. /******************************Public*Routine******************************\
  36. * BOOL bInit(pptfx0, pptfx1)
  37. *
  38. * Does DDA setup for line clipping.
  39. *
  40. * Return:
  41. * TRUE - ok.
  42. * FALSE - zero length line.
  43. *
  44. * History:
  45. * 27-Aug-1992 -by- J. Andrew Goossen [andrewgo]
  46. * Rewrote it.
  47. *
  48. * 20-Feb-1992 -by- J. Andrew Goossen [andrewgo]
  49. * Made lines exclusive of the end-point.
  50. *
  51. * 4-Apr-1991 -by- Paul Butzi [paulb]
  52. * Wrote it.
  53. \**************************************************************************/
  54. BOOL DDA_CLIPLINE::bInit(
  55. POINTFIX* pptfx0,
  56. POINTFIX* pptfx1)
  57. {
  58. ULONG M0;
  59. ULONG N0;
  60. ULONG x0;
  61. ULONG x1;
  62. ULONG y0;
  63. fl = 0;
  64. M0 = pptfx0->x;
  65. dM = pptfx1->x;
  66. if ((LONG) dM < (LONG) M0)
  67. {
  68. // Line runs from right to left, so flip across x = 0:
  69. M0 = -(LONG) M0;
  70. dM = -(LONG) dM;
  71. fl |= FL_FLIP_H;
  72. }
  73. // Compute the delta. The DDI says we can never have a valid delta
  74. // with a magnitude more than 2^31 - 1, but the engine never actually
  75. // checks its transforms. To ensure that we'll never puke on our shoes,
  76. // we check for that case and simply refuse to draw the line:
  77. dM -= M0;
  78. if ((LONG) dM < 0)
  79. return(FALSE);
  80. N0 = pptfx0->y;
  81. dN = pptfx1->y;
  82. if ((LONG) dN < (LONG) N0)
  83. {
  84. // Line runs from bottom to top, so flip across y = 0:
  85. N0 = -(LONG) N0;
  86. dN = -(LONG) dN;
  87. fl |= FL_FLIP_V;
  88. }
  89. // Compute another delta:
  90. dN -= N0;
  91. if ((LONG) dN < 0)
  92. return(FALSE);
  93. if (dN >= dM)
  94. {
  95. if (dN == dM)
  96. {
  97. // Have to special case slopes of one:
  98. fl |= FL_FLIP_SLOPE_ONE;
  99. }
  100. else
  101. {
  102. // Since line has slope greater than 1, flip across x = y:
  103. register ULONG ulTmp;
  104. SWAPL(dM, dN, ulTmp);
  105. SWAPL(M0, N0, ulTmp);
  106. fl |= FL_FLIP_D;
  107. }
  108. }
  109. fl |= gaflRound[(fl & FL_CLIPLINE_ROUND_MASK) >> FL_CLIPLINE_ROUND_SHIFT];
  110. ptlOrg.x = LFLOOR((LONG) M0);
  111. ptlOrg.y = LFLOOR((LONG) N0);
  112. M0 = FXFRAC(M0);
  113. N0 = FXFRAC(N0);
  114. {
  115. // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]
  116. eqGamma = Int32x32To64((LONG) dM, N0 + F/2) - Int32x32To64((LONG) dN, M0);
  117. if (fl & FL_V_ROUND_DOWN)
  118. eqGamma--; // Adjust so y = 1/2 rounds down
  119. eqGamma >>= FLOG2;
  120. }
  121. /***********************************************************************\
  122. * Figure out which pixels are at the ends of the line. *
  123. \***********************************************************************/
  124. // Calculate x0, x1:
  125. ULONG N1 = FXFRAC(N0 + dN);
  126. ULONG M1 = FXFRAC(M0 + dM);
  127. x1 = LFLOOR(M0 + dM);
  128. // Line runs left-to-right:
  129. // Compute x1:
  130. x1--;
  131. if (M1 > 0)
  132. {
  133. if (N1 == 0)
  134. {
  135. if (LROUND(M1, fl & FL_H_ROUND_DOWN))
  136. x1++;
  137. }
  138. else if (ABS((LONG) (N1 - F/2)) <= (LONG) M1)
  139. {
  140. x1++;
  141. }
  142. }
  143. if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  144. == (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  145. {
  146. // Have to special-case diagonal lines going through our
  147. // the point exactly equidistant between two horizontal
  148. // pixels, if we're supposed to round x=1/2 down:
  149. if ((M1 > 0) && (N1 == M1 + 8))
  150. x1--;
  151. if ((M0 > 0) && (N0 == M0 + 8))
  152. {
  153. x0 = 0;
  154. goto left_to_right_compute_y0;
  155. }
  156. }
  157. // Compute x0:
  158. x0 = 0;
  159. if (M0 > 0)
  160. {
  161. if (N0 == 0)
  162. {
  163. if (LROUND(M0, fl & FL_H_ROUND_DOWN))
  164. x0 = 1;
  165. }
  166. else if (ABS((LONG) (N0 - F/2)) <= (LONG) M0)
  167. {
  168. x0 = 1;
  169. }
  170. }
  171. // Compute y0:
  172. left_to_right_compute_y0:
  173. y0 = 0;
  174. if ((eqGamma >> 32) >= 0 &&
  175. ((ULONG) eqGamma >= dM - (dN & (-(LONG) x0))))
  176. {
  177. y0 = 1;
  178. }
  179. if ((LONG) x1 < (LONG) x0)
  180. return(FALSE);
  181. lX0 = x0 + ptlOrg.x;
  182. lX1 = x1 + ptlOrg.x;
  183. lY0 = y0 + ptlOrg.y;
  184. // Calculate y1 from the slope (this could be simplified so we wouldn't
  185. // have to do a divide):
  186. LONGLONG eq = Int32x32To64((LONG) dN, x1) + eqGamma;
  187. lY1 = (LONG) DIV(eq,dM) + ptlOrg.y;
  188. return(TRUE);
  189. }