|
|
/*************************************************************************\
* Module Name: dda.cxx * * DDA calculations for clipping. * * Created: 20-Mar-1991 * Author: Paul Butzi * * Copyright (c) 1991-1999 Microsoft Corporation * \**************************************************************************/
#include "precomp.hxx"
FLONG gaflRound[] = { FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // no flips
FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // FLIP_D
FL_H_ROUND_DOWN, // FLIP_V
FL_V_ROUND_DOWN, // FLIP_V | FLIP_D
FL_V_ROUND_DOWN, // SLOPE_ONE
0xffffffff, // SLOPE_ONE | FLIP_D
FL_H_ROUND_DOWN, // SLOPE_ONE | FLIP_V
0xffffffff, // SLOPE_ONE | FLIP_V | FLIP_D
// These entries are used only by the complex line clipping component, which
// actually does a left-to-right flip about x = 0 (the line drawing code
// only does a left-for-right exchange and so doesn't need these extra
// bits):
FL_V_ROUND_DOWN, // FLIP_H
FL_H_ROUND_DOWN, // FLIP_H | FLIP_D
0, // FLIP_H | FLIP_V
0, // FLIP_H | FLIP_V | FLIP_D
FL_V_ROUND_DOWN, // FLIP_H | SLOPE_ONE
0xffffffff, // FLIP_H | SLOPE_ONE | FLIP_D
FL_H_ROUND_DOWN, // FLIP_H | SLOPE_ONE | FLIP_V
0xffffffff // FLIP_H | SLOPE_ONE | FLIP_V | FLIP_D
};
/******************************Public*Routine******************************\
* BOOL bInit(pptfx0, pptfx1) * * Does DDA setup for line clipping. * * Return: * TRUE - ok. * FALSE - zero length line. * * History: * 27-Aug-1992 -by- J. Andrew Goossen [andrewgo] * Rewrote it. * * 20-Feb-1992 -by- J. Andrew Goossen [andrewgo] * Made lines exclusive of the end-point. * * 4-Apr-1991 -by- Paul Butzi [paulb] * Wrote it. \**************************************************************************/
BOOL DDA_CLIPLINE::bInit( POINTFIX* pptfx0, POINTFIX* pptfx1) { ULONG M0; ULONG N0; ULONG x0; ULONG x1; ULONG y0;
fl = 0;
M0 = pptfx0->x; dM = pptfx1->x;
if ((LONG) dM < (LONG) M0) { // Line runs from right to left, so flip across x = 0:
M0 = -(LONG) M0; dM = -(LONG) dM; fl |= FL_FLIP_H; }
// Compute the delta. The DDI says we can never have a valid delta
// with a magnitude more than 2^31 - 1, but the engine never actually
// checks its transforms. To ensure that we'll never puke on our shoes,
// we check for that case and simply refuse to draw the line:
dM -= M0; if ((LONG) dM < 0) return(FALSE);
N0 = pptfx0->y; dN = pptfx1->y;
if ((LONG) dN < (LONG) N0) { // Line runs from bottom to top, so flip across y = 0:
N0 = -(LONG) N0; dN = -(LONG) dN; fl |= FL_FLIP_V; }
// Compute another delta:
dN -= N0; if ((LONG) dN < 0) return(FALSE);
if (dN >= dM) { if (dN == dM) { // Have to special case slopes of one:
fl |= FL_FLIP_SLOPE_ONE; } else { // Since line has slope greater than 1, flip across x = y:
register ULONG ulTmp; SWAPL(dM, dN, ulTmp); SWAPL(M0, N0, ulTmp); fl |= FL_FLIP_D; } }
fl |= gaflRound[(fl & FL_CLIPLINE_ROUND_MASK) >> FL_CLIPLINE_ROUND_SHIFT];
ptlOrg.x = LFLOOR((LONG) M0); ptlOrg.y = LFLOOR((LONG) N0);
M0 = FXFRAC(M0); N0 = FXFRAC(N0);
{ // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]
eqGamma = Int32x32To64((LONG) dM, N0 + F/2) - Int32x32To64((LONG) dN, M0); if (fl & FL_V_ROUND_DOWN) eqGamma--; // Adjust so y = 1/2 rounds down
eqGamma >>= FLOG2; }
/***********************************************************************\
* Figure out which pixels are at the ends of the line. * \***********************************************************************/
// Calculate x0, x1:
ULONG N1 = FXFRAC(N0 + dN); ULONG M1 = FXFRAC(M0 + dM);
x1 = LFLOOR(M0 + dM);
// Line runs left-to-right:
// Compute x1:
x1--; if (M1 > 0) { if (N1 == 0) { if (LROUND(M1, fl & FL_H_ROUND_DOWN)) x1++; } else if (ABS((LONG) (N1 - F/2)) <= (LONG) M1) { x1++; } }
if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN)) == (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN)) { // Have to special-case diagonal lines going through our
// the point exactly equidistant between two horizontal
// pixels, if we're supposed to round x=1/2 down:
if ((M1 > 0) && (N1 == M1 + 8)) x1--;
if ((M0 > 0) && (N0 == M0 + 8)) { x0 = 0; goto left_to_right_compute_y0; } }
// Compute x0:
x0 = 0; if (M0 > 0) { if (N0 == 0) { if (LROUND(M0, fl & FL_H_ROUND_DOWN)) x0 = 1; } else if (ABS((LONG) (N0 - F/2)) <= (LONG) M0) { x0 = 1; } }
// Compute y0:
left_to_right_compute_y0:
y0 = 0; if ((eqGamma >> 32) >= 0 && ((ULONG) eqGamma >= dM - (dN & (-(LONG) x0)))) { y0 = 1; }
if ((LONG) x1 < (LONG) x0) return(FALSE);
lX0 = x0 + ptlOrg.x; lX1 = x1 + ptlOrg.x; lY0 = y0 + ptlOrg.y;
// Calculate y1 from the slope (this could be simplified so we wouldn't
// have to do a divide):
LONGLONG eq = Int32x32To64((LONG) dN, x1) + eqGamma; lY1 = (LONG) DIV(eq,dM) + ptlOrg.y;
return(TRUE); }
|