windows-nt/Source/XPSP1/NT/drivers/video/ms/w32/disp/intline.c
2020-09-26 16:20:57 +08:00

129 lines
3 KiB
C

/*************************************************************************\
* 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;
}