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
|