129 lines
3 KiB
C
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;
|
|
}
|