880 lines
28 KiB
C
880 lines
28 KiB
C
/******************************************************************************\
|
||
*
|
||
* $Workfile: LineTo.c $
|
||
*
|
||
* Contents:
|
||
* This file contains the DrvLineTo function and simple line drawing code.
|
||
*
|
||
* Copyright (c) 1996 Cirrus Logic, Inc.
|
||
*
|
||
* $Log: V:/CirrusLogic/CL54xx/NT40/Archive/Display/LineTo.c_v $
|
||
*
|
||
* Rev 1.4 12 Aug 1996 16:53:50 frido
|
||
* Added NT 3.5x/4.0 auto detection.
|
||
*
|
||
* Rev 1.3 29 Jul 1996 12:23:04 frido
|
||
* Fixed bug in drawing horizontal lines from right to left.
|
||
*
|
||
* Rev 1.2 15 Jul 1996 15:56:12 frido
|
||
* Changed DST_ADDR into DST_ADDR_ABS.
|
||
*
|
||
* Rev 1.1 12 Jul 1996 16:02:06 frido
|
||
* Redefined some macros that caused irratic line drawing on device bitmaps.
|
||
*
|
||
* Rev 1.0 10 Jul 1996 17:53:40 frido
|
||
* New code.
|
||
*
|
||
\******************************************************************************/
|
||
|
||
#include "PreComp.h"
|
||
#if LINETO
|
||
|
||
#define LEFT 0x01
|
||
#define TOP 0x02
|
||
#define RIGHT 0x04
|
||
#define BOTTOM 0x08
|
||
|
||
bIoLineTo(
|
||
PDEV* ppdev,
|
||
LONG x1,
|
||
LONG y1,
|
||
LONG x2,
|
||
LONG y2,
|
||
ULONG ulSolidColor,
|
||
MIX mix,
|
||
ULONG ulDstAddr)
|
||
{
|
||
BYTE* pjPorts = ppdev->pjPorts;
|
||
LONG lDelta = ppdev->lDelta;
|
||
LONG dx, dy;
|
||
LONG cx, cy;
|
||
|
||
if (ulSolidColor != (ULONG) -1)
|
||
{
|
||
if (ppdev->cBpp == 1)
|
||
{
|
||
ulSolidColor |= ulSolidColor << 8;
|
||
ulSolidColor |= ulSolidColor << 16;
|
||
}
|
||
else if (ppdev->cBpp == 2)
|
||
{
|
||
ulSolidColor |= ulSolidColor << 16;
|
||
}
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_ROP(ppdev, pjPorts, gajHwMixFromMix[mix & 0x0F]);
|
||
CP_IO_SRC_ADDR(ppdev, pjPorts, ppdev->ulSolidColorOffset);
|
||
CP_IO_BLT_MODE(ppdev, pjPorts, ENABLE_COLOR_EXPAND |
|
||
ENABLE_8x8_PATTERN_COPY |
|
||
ppdev->jModeColor);
|
||
CP_IO_FG_COLOR(ppdev, pjPorts, ulSolidColor);
|
||
}
|
||
|
||
// Calculate deltas.
|
||
dx = x2 - x1;
|
||
dy = y2 - y1;
|
||
|
||
// Horizontal lines.
|
||
if (dy == 0)
|
||
{
|
||
if (dx < 0)
|
||
{
|
||
// From right to left.
|
||
ulDstAddr += PELS_TO_BYTES(x2 - 1) + (y2 * lDelta);
|
||
cx = PELS_TO_BYTES(-dx) - 1;
|
||
}
|
||
else if (dx > 0)
|
||
{
|
||
// From left to right.
|
||
ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
|
||
cx = PELS_TO_BYTES(dx) - 1;
|
||
}
|
||
else
|
||
{
|
||
// Nothing to do here!
|
||
return(TRUE);
|
||
}
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_XCNT(ppdev, pjPorts, cx);
|
||
CP_IO_YCNT(ppdev, pjPorts, 0);
|
||
CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
|
||
CP_IO_START_BLT(ppdev, pjPorts);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
// Vertical lines.
|
||
else if (dx == 0)
|
||
{
|
||
if (dy < 0)
|
||
{
|
||
// From bottom to top.
|
||
ulDstAddr += PELS_TO_BYTES(x2) + ((y2 + 1) * lDelta);
|
||
cy = -dy - 1;
|
||
}
|
||
else
|
||
{
|
||
// From top to bottom.
|
||
ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
|
||
cy = dy - 1;
|
||
}
|
||
|
||
cx = PELS_TO_BYTES(1) - 1;
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_XCNT(ppdev, pjPorts, cx);
|
||
CP_IO_YCNT(ppdev, pjPorts, cy);
|
||
CP_IO_DST_Y_OFFSET(ppdev, pjPorts, lDelta);
|
||
CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
|
||
CP_IO_START_BLT(ppdev, pjPorts);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
// Diagonal lines.
|
||
else if ((dx == dy) || (dx == -dy))
|
||
{
|
||
if (dy < 0)
|
||
{
|
||
if (dx < 0)
|
||
{
|
||
// Diagonal line from bottom-right to upper-left.
|
||
ulDstAddr += PELS_TO_BYTES(x2 + 1);
|
||
}
|
||
else
|
||
{
|
||
// Diagonal line from bottom-left to upper-right.
|
||
ulDstAddr += PELS_TO_BYTES(x2 - 1);
|
||
}
|
||
ulDstAddr += (y2 + 1) * lDelta;
|
||
cy = -dy - 1;
|
||
}
|
||
else
|
||
{
|
||
// Diagonal line from top to bottom, either from left to right or
|
||
// right to left.
|
||
ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
|
||
cy = dy - 1;
|
||
}
|
||
|
||
if (dx == dy)
|
||
{
|
||
// Diagonal line from top-left to bottom-right or vice versa.
|
||
lDelta += PELS_TO_BYTES(1);
|
||
}
|
||
else
|
||
{
|
||
// Diagonal line from top-right to bottom-left or vice versa.
|
||
lDelta -= PELS_TO_BYTES(1);
|
||
}
|
||
|
||
cx = PELS_TO_BYTES(1) - 1;
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_XCNT(ppdev, pjPorts, cx);
|
||
CP_IO_YCNT(ppdev, pjPorts, cy);
|
||
CP_IO_DST_Y_OFFSET(ppdev, pjPorts, lDelta);
|
||
CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
|
||
CP_IO_START_BLT(ppdev, pjPorts);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
// All other lines.
|
||
if (dx < 0)
|
||
{
|
||
dx = -dx;
|
||
}
|
||
if (dy < 0)
|
||
{
|
||
dy = -dy;
|
||
}
|
||
ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
|
||
|
||
// Horizontal major.
|
||
if (dx > dy)
|
||
{
|
||
LONG run = dy;
|
||
|
||
cy = (y1 > y2) ? -lDelta : lDelta;
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
|
||
//
|
||
// We would like to set the YCNT register once
|
||
// here (outside the loops below). However, on
|
||
// the CL5428, this register does not hold its value
|
||
// after one iteration through the loop. So, I'll
|
||
// have to set it inside the loop.
|
||
//
|
||
|
||
if (x1 < x2)
|
||
{
|
||
while (x1 < x2)
|
||
{
|
||
cx = 1 + (dx - run) / dy;
|
||
if ((x1 + cx) < x2)
|
||
{
|
||
run += cx * dy - dx;
|
||
}
|
||
else
|
||
{
|
||
cx = x2 - x1;
|
||
}
|
||
x1 += cx;
|
||
cx = PELS_TO_BYTES(cx);
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_YCNT(ppdev, pjPorts, 0);
|
||
CP_IO_XCNT(ppdev, pjPorts, cx - 1);
|
||
CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
|
||
CP_IO_START_BLT(ppdev, pjPorts);
|
||
|
||
ulDstAddr += cx + cy;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
cy -= PELS_TO_BYTES(1);
|
||
|
||
while (x1 > x2)
|
||
{
|
||
cx = 1 + (dx - run) / dy;
|
||
if ((x1 - cx) > x2)
|
||
{
|
||
run += cx * dy - dx;
|
||
}
|
||
else
|
||
{
|
||
cx = x1 - x2;
|
||
}
|
||
ulDstAddr -= PELS_TO_BYTES(cx - 1);
|
||
x1 -= cx;
|
||
cx = PELS_TO_BYTES(cx);
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_YCNT(ppdev, pjPorts, 0);
|
||
CP_IO_XCNT(ppdev, pjPorts, cx - 1);
|
||
CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
|
||
CP_IO_START_BLT(ppdev, pjPorts);
|
||
|
||
ulDstAddr += cy;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Vertical major.
|
||
else
|
||
{
|
||
LONG run = dx;
|
||
|
||
cx = (x1 > x2) ? PELS_TO_BYTES(-1) : PELS_TO_BYTES(1);
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_XCNT(ppdev, pjPorts, PELS_TO_BYTES(1) - 1);
|
||
CP_IO_DST_Y_OFFSET(ppdev, pjPorts, lDelta);
|
||
|
||
if (y1 < y2)
|
||
{
|
||
while (y1 < y2)
|
||
{
|
||
cy = 1 + (dy - run) / dx;
|
||
if ((y1 + cy) < y2)
|
||
{
|
||
run += cy * dx - dy;
|
||
}
|
||
else
|
||
{
|
||
cy = y2 - y1;
|
||
}
|
||
y1 += cy;
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_YCNT(ppdev, pjPorts, cy - 1);
|
||
CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
|
||
CP_IO_START_BLT(ppdev, pjPorts);
|
||
|
||
ulDstAddr += cx + cy * lDelta;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
cx -= lDelta;
|
||
|
||
while (y1 > y2)
|
||
{
|
||
cy = 1 + (dy - run) / dx;
|
||
if ((y1 - cy) > y2)
|
||
{
|
||
run += cy * dx - dy;
|
||
}
|
||
else
|
||
{
|
||
cy = y1 - y2;
|
||
}
|
||
ulDstAddr -= (cy - 1) * lDelta;
|
||
y1 -= cy;
|
||
|
||
CP_IO_WAIT_FOR_BLT_COMPLETE(ppdev, pjPorts);
|
||
CP_IO_YCNT(ppdev, pjPorts, cy - 1);
|
||
CP_IO_DST_ADDR_ABS(ppdev, pjPorts, ulDstAddr);
|
||
CP_IO_START_BLT(ppdev, pjPorts);
|
||
|
||
ulDstAddr += cx;
|
||
}
|
||
}
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
bMmLineTo(
|
||
PDEV* ppdev,
|
||
LONG x1,
|
||
LONG y1,
|
||
LONG x2,
|
||
LONG y2,
|
||
ULONG ulSolidColor,
|
||
MIX mix,
|
||
ULONG ulDstAddr)
|
||
{
|
||
BYTE* pjBase = ppdev->pjBase;
|
||
LONG lDelta = ppdev->lDelta;
|
||
LONG dx, dy;
|
||
LONG cx, cy;
|
||
|
||
if (ulSolidColor != (ULONG) -1)
|
||
{
|
||
if (ppdev->cBpp == 1)
|
||
{
|
||
ulSolidColor |= ulSolidColor << 8;
|
||
ulSolidColor |= ulSolidColor << 16;
|
||
}
|
||
else if (ppdev->cBpp == 2)
|
||
{
|
||
ulSolidColor |= ulSolidColor << 16;
|
||
}
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_ROP(ppdev, pjBase, gajHwMixFromMix[mix & 0x0F]);
|
||
CP_MM_SRC_ADDR(ppdev, pjBase, ppdev->ulSolidColorOffset);
|
||
CP_MM_BLT_MODE(ppdev, pjBase, ENABLE_COLOR_EXPAND |
|
||
ENABLE_8x8_PATTERN_COPY |
|
||
ppdev->jModeColor);
|
||
CP_MM_FG_COLOR(ppdev, pjBase, ulSolidColor);
|
||
|
||
// if (ppdev->flCaps & CAPS_IS_5436)
|
||
if (ppdev->flCaps & CAPS_AUTOSTART)
|
||
{
|
||
CP_MM_BLT_EXT_MODE(ppdev, pjBase, ENABLE_SOLID_FILL);
|
||
}
|
||
}
|
||
|
||
// Calculate deltas.
|
||
dx = x2 - x1;
|
||
dy = y2 - y1;
|
||
|
||
// Horizontal lines.
|
||
if (dy == 0)
|
||
{
|
||
if (dx < 0)
|
||
{
|
||
// From right to left.
|
||
ulDstAddr += PELS_TO_BYTES(x2 + 1) + (y2 * lDelta);
|
||
cx = PELS_TO_BYTES(-dx) - 1;
|
||
}
|
||
else if (dx > 0)
|
||
{
|
||
// From left to right.
|
||
ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
|
||
cx = PELS_TO_BYTES(dx) - 1;
|
||
}
|
||
else
|
||
{
|
||
// Nothing to do here!
|
||
return(TRUE);
|
||
}
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_XCNT(ppdev, pjBase, cx);
|
||
CP_MM_YCNT(ppdev, pjBase, 0);
|
||
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
|
||
CP_MM_START_BLT(ppdev, pjBase);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
// Vertical lines.
|
||
else if (dx == 0)
|
||
{
|
||
if (dy < 0)
|
||
{
|
||
// From bottom to top.
|
||
ulDstAddr += PELS_TO_BYTES(x2) + ((y2 + 1) * lDelta);
|
||
cy = -dy - 1;
|
||
}
|
||
else
|
||
{
|
||
// From top to bottom.
|
||
ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
|
||
cy = dy - 1;
|
||
}
|
||
|
||
cx = PELS_TO_BYTES(1) - 1;
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_XCNT(ppdev, pjBase, cx);
|
||
CP_MM_YCNT(ppdev, pjBase, cy);
|
||
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
||
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
|
||
CP_MM_START_BLT(ppdev, pjBase);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
// Diagonal lines.
|
||
else if ((dx == dy) || (dx == -dy))
|
||
{
|
||
if (dy < 0)
|
||
{
|
||
if (dx < 0)
|
||
{
|
||
// Diagonal line from bottom-right to upper-left.
|
||
ulDstAddr += PELS_TO_BYTES(x2 + 1);
|
||
}
|
||
else
|
||
{
|
||
// Diagonal line from bottom-left to upper-right.
|
||
ulDstAddr += PELS_TO_BYTES(x2 - 1);
|
||
}
|
||
ulDstAddr += (y2 + 1) * lDelta;
|
||
cy = -dy - 1;
|
||
}
|
||
else
|
||
{
|
||
// Diagonal line from top to bottom, either from left to right or
|
||
// right to left.
|
||
ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
|
||
cy = dy - 1;
|
||
}
|
||
|
||
if (dx == dy)
|
||
{
|
||
// Diagonal line from top-left to bottom-right or vice versa.
|
||
lDelta += PELS_TO_BYTES(1);
|
||
}
|
||
else
|
||
{
|
||
// Diagonal line from top-right to bottom-left or vice versa.
|
||
lDelta -= PELS_TO_BYTES(1);
|
||
}
|
||
|
||
cx = PELS_TO_BYTES(1) - 1;
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_XCNT(ppdev, pjBase, cx);
|
||
CP_MM_YCNT(ppdev, pjBase, cy);
|
||
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
||
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
|
||
CP_MM_START_BLT(ppdev, pjBase);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
// All other lines.
|
||
if (dx < 0)
|
||
{
|
||
dx = -dx;
|
||
}
|
||
if (dy < 0)
|
||
{
|
||
dy = -dy;
|
||
}
|
||
ulDstAddr += PELS_TO_BYTES(x1) + (y1 * lDelta);
|
||
|
||
// Horizontal major.
|
||
if (dx > dy)
|
||
{
|
||
LONG run = dy;
|
||
|
||
cy = (y1 > y2) ? -lDelta : lDelta;
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_YCNT(ppdev, pjBase, 0);
|
||
|
||
if (x1 < x2)
|
||
{
|
||
while (x1 < x2)
|
||
{
|
||
cx = 1 + (dx - run) / dy;
|
||
if ((x1 + cx) < x2)
|
||
{
|
||
run += cx * dy - dx;
|
||
}
|
||
else
|
||
{
|
||
cx = x2 - x1;
|
||
}
|
||
x1 += cx;
|
||
cx = PELS_TO_BYTES(cx);
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_XCNT(ppdev, pjBase, cx - 1);
|
||
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
|
||
CP_MM_START_BLT(ppdev, pjBase);
|
||
|
||
ulDstAddr += cx + cy;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
cy -= PELS_TO_BYTES(1);
|
||
|
||
while (x1 > x2)
|
||
{
|
||
cx = 1 + (dx - run) / dy;
|
||
if ((x1 - cx) > x2)
|
||
{
|
||
run += cx * dy - dx;
|
||
}
|
||
else
|
||
{
|
||
cx = x1 - x2;
|
||
}
|
||
ulDstAddr -= PELS_TO_BYTES(cx - 1);
|
||
x1 -= cx;
|
||
cx = PELS_TO_BYTES(cx);
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_XCNT(ppdev, pjBase, cx - 1);
|
||
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
|
||
CP_MM_START_BLT(ppdev, pjBase);
|
||
|
||
ulDstAddr += cy;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Vertical major.
|
||
else
|
||
{
|
||
LONG run = dx;
|
||
|
||
cx = (x1 > x2) ? PELS_TO_BYTES(-1) : PELS_TO_BYTES(1);
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_XCNT(ppdev, pjBase, PELS_TO_BYTES(1) - 1);
|
||
CP_MM_DST_Y_OFFSET(ppdev, pjBase, lDelta);
|
||
|
||
if (y1 < y2)
|
||
{
|
||
while (y1 < y2)
|
||
{
|
||
cy = 1 + (dy - run) / dx;
|
||
if ((y1 + cy) < y2)
|
||
{
|
||
run += cy * dx - dy;
|
||
}
|
||
else
|
||
{
|
||
cy = y2 - y1;
|
||
}
|
||
y1 += cy;
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_YCNT(ppdev, pjBase, cy - 1);
|
||
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
|
||
CP_MM_START_BLT(ppdev, pjBase);
|
||
|
||
ulDstAddr += cx + cy * lDelta;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
cx -= lDelta;
|
||
|
||
while (y1 > y2)
|
||
{
|
||
cy = 1 + (dy - run) / dx;
|
||
if ((y1 - cy) > y2)
|
||
{
|
||
run += cy * dx - dy;
|
||
}
|
||
else
|
||
{
|
||
cy = y1 - y2;
|
||
}
|
||
ulDstAddr -= (cy - 1) * lDelta;
|
||
y1 -= cy;
|
||
|
||
CP_MM_WAIT_FOR_BLT_COMPLETE(ppdev, pjBase);
|
||
CP_MM_YCNT(ppdev, pjBase, cy - 1);
|
||
CP_MM_DST_ADDR_ABS(ppdev, pjBase, ulDstAddr);
|
||
CP_MM_START_BLT(ppdev, pjBase);
|
||
|
||
ulDstAddr += cx;
|
||
}
|
||
}
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
BOOL bClipLine(LONG x1, LONG y1, LONG x2, LONG y2, RECTL* prcl)
|
||
{
|
||
ULONG ulCode1, ulCode2;
|
||
RECTL rclClip1, rclClip2;
|
||
LONG dx, dy;
|
||
|
||
// Set clipping rectangles.
|
||
rclClip1.left = prcl->left;
|
||
rclClip1.top = prcl->top;
|
||
rclClip1.right = prcl->right - 1;
|
||
rclClip1.bottom = prcl->bottom - 1;
|
||
|
||
rclClip2.left = prcl->left - 1;
|
||
rclClip2.top = prcl->top - 1;
|
||
rclClip2.right = prcl->right;
|
||
rclClip2.bottom = prcl->bottom;
|
||
|
||
// Set line deltas.
|
||
dx = x2 - x1;
|
||
dy = y2 - y1;
|
||
|
||
// Set line flags.
|
||
ulCode1 = 0;
|
||
if (x1 < rclClip1.left) ulCode1 |= LEFT;
|
||
if (y1 < rclClip1.top) ulCode1 |= TOP;
|
||
if (x1 > rclClip1.right) ulCode1 |= RIGHT;
|
||
if (y1 > rclClip1.bottom) ulCode1 |= BOTTOM;
|
||
|
||
ulCode2 = 0;
|
||
if (x2 < rclClip2.left) ulCode2 |= LEFT;
|
||
if (y2 < rclClip2.top) ulCode2 |= TOP;
|
||
if (x2 > rclClip2.right) ulCode2 |= RIGHT;
|
||
if (y2 > rclClip2.bottom) ulCode2 |= BOTTOM;
|
||
|
||
if ((ulCode1 & ulCode2) != 0)
|
||
{
|
||
// The line is completly clipped.
|
||
return(FALSE);
|
||
}
|
||
|
||
// Vertical lines.
|
||
if (dx == 0)
|
||
{
|
||
if (dy == 0)
|
||
{
|
||
return(FALSE);
|
||
}
|
||
|
||
if (ulCode1 & TOP)
|
||
{
|
||
y1 = rclClip1.top;
|
||
}
|
||
else if (ulCode1 & BOTTOM)
|
||
{
|
||
y1 = rclClip1.bottom;
|
||
}
|
||
|
||
if (ulCode2 & TOP)
|
||
{
|
||
y2 = rclClip2.top;
|
||
}
|
||
else if (ulCode2 & BOTTOM)
|
||
{
|
||
y2 = rclClip2.bottom;
|
||
}
|
||
|
||
goto ReturnTrue;
|
||
}
|
||
|
||
// Horizontal lines.
|
||
if (dy == 0)
|
||
{
|
||
if (ulCode1 & LEFT)
|
||
{
|
||
x1 = rclClip1.left;
|
||
}
|
||
else if (ulCode1 & RIGHT)
|
||
{
|
||
x1 = rclClip1.right;
|
||
}
|
||
|
||
if (ulCode2 & LEFT)
|
||
{
|
||
x2 = rclClip2.left;
|
||
}
|
||
else if (ulCode2 & RIGHT)
|
||
{
|
||
x2 = rclClip2.right;
|
||
}
|
||
|
||
goto ReturnTrue;
|
||
}
|
||
|
||
// Clip start point.
|
||
if (x1 < rclClip1.left)
|
||
{
|
||
y1 += dy * (rclClip1.left - x1) / dx;
|
||
x1 = rclClip1.left;
|
||
}
|
||
else if (x1 > rclClip1.right)
|
||
{
|
||
y1 += dy * (rclClip1.right - x1) / dx;
|
||
x1 = rclClip1.right;
|
||
}
|
||
if (y1 < rclClip1.top)
|
||
{
|
||
x1 += dx * (rclClip1.top - y1) / dy;
|
||
y1 = rclClip1.top;
|
||
}
|
||
else if (y1 > rclClip1.bottom)
|
||
{
|
||
x1 += dx * (rclClip1.bottom - y1) / dy;
|
||
y1 = rclClip1.bottom;
|
||
}
|
||
if ((x1 < rclClip1.left) || (y1 < rclClip1.top) || (x1 > rclClip1.right) ||
|
||
(y1 > rclClip1.bottom))
|
||
{
|
||
// Start point fully clipped.
|
||
return(FALSE);
|
||
}
|
||
|
||
// Clip end point.
|
||
if (x2 < rclClip2.left)
|
||
{
|
||
y2 += dy * (rclClip2.left - x2) / dx;
|
||
x2 = rclClip2.left;
|
||
}
|
||
else if (x2 > rclClip2.right)
|
||
{
|
||
y2 += dy * (rclClip2.right - x2) / dx;
|
||
x2 = rclClip2.right;
|
||
}
|
||
if (y2 < rclClip2.top)
|
||
{
|
||
x2 += dx * (rclClip2.top - y2) / dy;
|
||
y2 = rclClip2.top;
|
||
}
|
||
else if (y2 > rclClip2.bottom)
|
||
{
|
||
x2 += dx * (rclClip2.bottom - y2) / dy;
|
||
y2 = rclClip2.bottom;
|
||
}
|
||
if ((x2 < rclClip2.left) || (y2 < rclClip2.top) || (x2 > rclClip2.right) ||
|
||
(y2 > rclClip2.bottom))
|
||
{
|
||
// End point fully clipped.
|
||
return(FALSE);
|
||
}
|
||
|
||
ReturnTrue:
|
||
prcl->left = x1;
|
||
prcl->top = y1;
|
||
prcl->right = x2;
|
||
prcl->bottom = y2;
|
||
return(TRUE);
|
||
}
|
||
|
||
/******************************************************************************\
|
||
*
|
||
* Function: DrvLineTo
|
||
*
|
||
* This function draws a line between any two points. This function only draws
|
||
* lines in solod color and that are just 1 pixel wide. The end-point is not
|
||
* drawn.
|
||
*
|
||
* Parameters: pso Pointer to surface.
|
||
* pco Pointer to CLIPOBJ.
|
||
* pbo Pointer to BRUSHOBJ.
|
||
* x1 Starting x-coordinate.
|
||
* y1 Starting y-coordinate.
|
||
* x2 Ending x-coordinate.
|
||
* y2 Ending y-coordinate.
|
||
* prclBounds Pointer to an unclipped bounding rectangle.
|
||
* mix Mix to perform on the destination.
|
||
*
|
||
* Returns: TRUE if the line has been drawn, FALSE oftherwise.
|
||
*
|
||
\******************************************************************************/
|
||
BOOL DrvLineTo(
|
||
SURFOBJ* pso,
|
||
CLIPOBJ* pco,
|
||
BRUSHOBJ* pbo,
|
||
LONG x1,
|
||
LONG y1,
|
||
LONG x2,
|
||
LONG y2,
|
||
RECTL* prclBounds,
|
||
MIX mix)
|
||
{
|
||
PDEV* ppdev = (PPDEV)pso->dhpdev;
|
||
DSURF* pdsurf = (DSURF *)pso->dhsurf;
|
||
OH* poh;
|
||
BOOL bMore;
|
||
|
||
// If the device bitmap is a DIB, let GDI handle it.
|
||
if (pdsurf->dt == DT_DIB)
|
||
{
|
||
return(EngLineTo(pdsurf->pso, pco, pbo, x1, y1, x2, y2, prclBounds,
|
||
mix));
|
||
}
|
||
|
||
// Get the off-screen node.
|
||
poh = pdsurf->poh;
|
||
|
||
if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
|
||
{
|
||
// No clipping.
|
||
return(ppdev->pfnLineTo(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix,
|
||
poh->xy));
|
||
}
|
||
|
||
else if (pco->iDComplexity == DC_RECT)
|
||
{
|
||
// Clipped rectangle.
|
||
RECTL rcl;
|
||
|
||
rcl = pco->rclBounds;
|
||
if (bClipLine(x1, y1, x2, y2, &rcl))
|
||
{
|
||
return(ppdev->pfnLineTo(ppdev, rcl.left, rcl.top, rcl.right,
|
||
rcl.bottom, pbo->iSolidColor, mix,
|
||
poh->xy));
|
||
}
|
||
return(TRUE);
|
||
}
|
||
|
||
// Complex clipping.
|
||
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
|
||
|
||
do
|
||
{
|
||
CLIPENUM ce;
|
||
RECTL* prcl;
|
||
|
||
bMore = CLIPOBJ_bEnum(pco, sizeof(ce), &ce.c);
|
||
|
||
prcl = ce.arcl;
|
||
while (ce.c--)
|
||
{
|
||
if (bClipLine(x1, y1, x2, y2, prcl))
|
||
{
|
||
if (!ppdev->pfnLineTo(ppdev, prcl->left, prcl->top, prcl->right,
|
||
prcl->bottom, pbo->iSolidColor, mix,
|
||
poh->xy))
|
||
{
|
||
return(FALSE);
|
||
}
|
||
}
|
||
prcl++;
|
||
}
|
||
} while (bMore);
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
#endif // LINETO
|