|
|
/*************************************************************************\
* Module Name: intline.c * * Copyright (c) 1993-1994 Microsoft Corporation * Copyright (c) 1992 Digital Equipment Corporation \**************************************************************************/
#include "precomp.h"
/******************************************************************************
* bIntegerLine * * This routine attempts to draw a line segment between two points. It * will only draw if both end points are whole integers: it does not support * fractional endpoints. * * Returns: * TRUE if the line segment is drawn * FALSE otherwise *****************************************************************************/
BOOL bIntegerLine ( PDEV* ppdev, ULONG x1, ULONG y1, ULONG x2, ULONG y2 ) { BYTE* pjBase = ppdev->pjBase; LONG cBpp = ppdev->cBpp; LONG lDelta = ppdev->lDelta; LONG xyOffset = ppdev->xyOffset; ULONG ulDst; LONG dx; LONG dy; LONG fudge; BYTE jLineDrawCmd = (LINE_DRAW | LINE_USE_ERROR_TERM); LONG ErrorTerm;
//
// This code assumes that CP_PEL_DEPTH()
// has been set to ((cBpp - 1) << 4)
//
// This is done in stroke.c before this routine is called.
//
// Unfortunately, I can't verify it with an ASSERT because values
// in the queue cannot be read back.
//
x1 >>= 4; y1 >>= 4; x2 >>= 4; y2 >>= 4;
dx = x2 - x1; dy = y2 - y1;
if ((dx == 0) && (dy == 0)) { goto ReturnTrue; }
ulDst = (y1 * lDelta) + (cBpp * x1); ulDst += xyOffset;
//
// If dx and dy have different signs and the line is Y Major then
// we'll have to adjust the Error Term by 1.
//
fudge = ((dx ^ dy) < 0)? 1:0;
if (dx < 0) { ulDst += (cBpp-1); CP_PAT_ADDR(ppdev, pjBase, (ppdev->ulSolidColorOffset + cBpp -1)); jLineDrawCmd |= LINE_X_NEG; dx = -dx; }
if (dy < 0) { fudge = -fudge; jLineDrawCmd |= LINE_Y_NEG; dy = -dy; }
WAIT_FOR_EMPTY_ACL_QUEUE(ppdev, pjBase); CP_DST_Y_OFFSET(ppdev, pjBase, (lDelta - 1));
if (dx > dy) { // x major
jLineDrawCmd |= LINE_X_MAJOR; ErrorTerm = dx;
CP_XCNT(ppdev, pjBase, ((dx - 1) * cBpp)); CP_YCNT(ppdev, pjBase, 0xfff); CP_DELTA_MINOR(ppdev, pjBase, dy); CP_DELTA_MAJOR(ppdev, pjBase, dx); } else { // y major
ErrorTerm = dy - fudge;
CP_XCNT(ppdev, pjBase, 0xfff); CP_YCNT(ppdev, pjBase, (dy - 1)); CP_DELTA_MINOR(ppdev, pjBase, dx); CP_DELTA_MAJOR(ppdev, pjBase, dy); }
CP_XY_DIR(ppdev, pjBase, jLineDrawCmd); CP_ERR_TERM(ppdev, pjBase, ErrorTerm); CP_DST_ADDR(ppdev, pjBase, ulDst);
WAIT_FOR_EMPTY_ACL_QUEUE(ppdev, pjBase); CP_XY_DIR(ppdev, pjBase, 0); CP_PAT_ADDR(ppdev, pjBase, (ppdev->ulSolidColorOffset));
ReturnTrue: return TRUE; }
|