957 lines
23 KiB
C
957 lines
23 KiB
C
/******************************Module*Header*******************************\
|
|
*
|
|
* *******************
|
|
* * GDI SAMPLE CODE *
|
|
* *******************
|
|
*
|
|
* Module Name: Strips.c
|
|
*
|
|
* Copyright (c) 1992-1998 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vssSolidHorizontal
|
|
*
|
|
* Draws left-to-right x-major near-horizontal lines using short-stroke
|
|
* vectors. Is faster than using the radial-line routine, but only works
|
|
* when every strip is 15 pels in length or less.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vssSolidHorizontal(
|
|
PDEV* ppdev,
|
|
STRIP* pStrip,
|
|
LINESTATE* pLineState)
|
|
{
|
|
LONG i, cStrips;
|
|
PLONG pStrips;
|
|
LONG xPels, xSumPels, yDir;
|
|
USHORT Cmd, ssCmd, dirDraw, dirSkip;
|
|
|
|
Cmd = DRAW | WRITE | MULTIPLE_PIXELS |
|
|
DIR_TYPE_RADIAL | LAST_PIXEL_OFF |
|
|
BUS_SIZE_16 | BYTE_SWAP;
|
|
|
|
cStrips = pStrip->cStrips;
|
|
|
|
IO_FIFO_WAIT(ppdev, 3);
|
|
|
|
IO_CUR_X(ppdev, pStrip->ptlStart.x);
|
|
IO_CUR_Y(ppdev, pStrip->ptlStart.y);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
// Setup the drawing direction and the skip direction.
|
|
|
|
dirDraw = 0x10;
|
|
|
|
if (!(pStrip->flFlips & FL_FLIP_V))
|
|
{
|
|
yDir = 1;
|
|
dirSkip = 0xC100;
|
|
}
|
|
else
|
|
{
|
|
dirSkip = 0x4100;
|
|
yDir = -1;
|
|
}
|
|
|
|
// Output the short stroke commands.
|
|
|
|
xSumPels = 0;
|
|
pStrips = pStrip->alStrips;
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
xPels = *pStrips++;
|
|
xSumPels += xPels;
|
|
ssCmd = (USHORT) (dirSkip | dirDraw | xPels);
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
IO_SHORT_STROKE(ppdev, ssCmd);
|
|
}
|
|
|
|
pStrip->ptlStart.x += xSumPels;
|
|
pStrip->ptlStart.y += cStrips * yDir;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vrlSolidHorizontal
|
|
*
|
|
* Draws left-to-right x-major near-horizontal lines using radial lines.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vrlSolidHorizontal(
|
|
PDEV* ppdev,
|
|
STRIP* pStrip,
|
|
LINESTATE* pLineState)
|
|
{
|
|
LONG cStrips;
|
|
USHORT Cmd;
|
|
LONG i, yInc, x, y;
|
|
PLONG pStrips;
|
|
|
|
|
|
Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
|
|
LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_0 |
|
|
WRITE;
|
|
|
|
cStrips = pStrip->cStrips;
|
|
|
|
x = pStrip->ptlStart.x;
|
|
y = pStrip->ptlStart.y;
|
|
|
|
yInc = 1;
|
|
if (pStrip->flFlips & FL_FLIP_V)
|
|
yInc = -1;
|
|
|
|
pStrips = pStrip->alStrips;
|
|
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
x += *pStrips++;
|
|
y += yInc;
|
|
}
|
|
|
|
pStrip->ptlStart.x = x;
|
|
pStrip->ptlStart.y = y;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vssSolidVertical
|
|
*
|
|
* Draws left-to-right y-major near-vertical lines using short-stroke
|
|
* vectors. Is faster than using the radial-line routine, but only works
|
|
* when every strip is 15 pels in length or less.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vssSolidVertical(
|
|
PDEV* ppdev,
|
|
STRIP* pStrip,
|
|
LINESTATE* pLineState)
|
|
{
|
|
LONG i, cStrips;
|
|
PLONG pStrips;
|
|
LONG yPels, ySumPels, yDir;
|
|
USHORT Cmd, ssCmd, dirDraw, dirSkip;
|
|
|
|
Cmd = DRAW | WRITE | MULTIPLE_PIXELS |
|
|
DIR_TYPE_RADIAL | LAST_PIXEL_OFF |
|
|
BUS_SIZE_16 | BYTE_SWAP;
|
|
|
|
cStrips = pStrip->cStrips;
|
|
|
|
IO_FIFO_WAIT(ppdev, 3);
|
|
|
|
IO_CUR_X(ppdev, pStrip->ptlStart.x);
|
|
IO_CUR_Y(ppdev, pStrip->ptlStart.y);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
// Setup the drawing direction and the skip direction.
|
|
|
|
if (!(pStrip->flFlips & FL_FLIP_V))
|
|
{
|
|
yDir = 1;
|
|
dirDraw = 0xD0;
|
|
}
|
|
else
|
|
{
|
|
yDir = -1;
|
|
dirDraw = 0x50;
|
|
}
|
|
|
|
dirSkip = 0x0100;
|
|
|
|
// Output the short stroke commands.
|
|
|
|
ySumPels = 0;
|
|
pStrips = pStrip->alStrips;
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
yPels = *pStrips++;
|
|
ySumPels += yPels;
|
|
ssCmd = (USHORT) (dirSkip | dirDraw | yPels);
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
IO_SHORT_STROKE(ppdev, ssCmd);
|
|
}
|
|
|
|
pStrip->ptlStart.x += cStrips;
|
|
pStrip->ptlStart.y += ySumPels * yDir;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vrlSolidVertical
|
|
*
|
|
* Draws left-to-right y-major near-vertical lines using radial lines.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vrlSolidVertical(
|
|
PDEV* ppdev,
|
|
STRIP* pStrip,
|
|
LINESTATE* pLineState)
|
|
{
|
|
LONG cStrips;
|
|
USHORT Cmd;
|
|
LONG i, x, y;
|
|
PLONG pStrips;
|
|
|
|
cStrips = pStrip->cStrips;
|
|
pStrips = pStrip->alStrips;
|
|
|
|
x = pStrip->ptlStart.x;
|
|
y = pStrip->ptlStart.y;
|
|
|
|
if (!(pStrip->flFlips & FL_FLIP_V))
|
|
{
|
|
Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
|
|
LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_270 |
|
|
WRITE;
|
|
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
y += *pStrips++;
|
|
x++;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
|
|
LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_90 |
|
|
WRITE;
|
|
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
y -= *pStrips++;
|
|
x++;
|
|
}
|
|
}
|
|
|
|
pStrip->ptlStart.x = x;
|
|
pStrip->ptlStart.y = y;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vssSolidDiagonalHorizontal
|
|
*
|
|
* Draws left-to-right x-major near-diagonal lines using short-stroke
|
|
* vectors. Is faster than using the radial-line routine, but only
|
|
* works when every strip is 15 pels in length or less.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vssSolidDiagonalHorizontal(
|
|
PDEV* ppdev,
|
|
STRIP* pStrip,
|
|
LINESTATE* pLineState)
|
|
{
|
|
LONG i, cStrips;
|
|
PLONG pStrips;
|
|
LONG Pels, SumPels, yDir;
|
|
USHORT Cmd, ssCmd, dirDraw, dirSkip;
|
|
|
|
Cmd = DRAW | WRITE | MULTIPLE_PIXELS |
|
|
DIR_TYPE_RADIAL | LAST_PIXEL_OFF |
|
|
BUS_SIZE_16 | BYTE_SWAP;
|
|
|
|
cStrips = pStrip->cStrips;
|
|
|
|
IO_FIFO_WAIT(ppdev, 3);
|
|
|
|
IO_CUR_X(ppdev, pStrip->ptlStart.x);
|
|
IO_CUR_Y(ppdev, pStrip->ptlStart.y);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
// Setup the drawing direction and the skip direction.
|
|
|
|
if (!(pStrip->flFlips & FL_FLIP_V))
|
|
{
|
|
yDir = 1;
|
|
dirDraw = 0xF0;
|
|
dirSkip = 0x4100;
|
|
|
|
}
|
|
else
|
|
{
|
|
yDir = -1;
|
|
dirDraw = 0x30;
|
|
dirSkip = 0xC100;
|
|
|
|
}
|
|
|
|
// Output the short stroke commands.
|
|
|
|
SumPels = 0;
|
|
pStrips = pStrip->alStrips;
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
Pels = *pStrips++;
|
|
SumPels += Pels;
|
|
ssCmd = (USHORT)(dirSkip | dirDraw | Pels);
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
IO_SHORT_STROKE(ppdev, ssCmd);
|
|
}
|
|
|
|
pStrip->ptlStart.x += SumPels;
|
|
pStrip->ptlStart.y += (SumPels - cStrips) * yDir;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vrlSolidDiagonalHorizontal
|
|
*
|
|
* Draws left-to-right x-major near-diagonal lines using radial lines.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vrlSolidDiagonalHorizontal(
|
|
PDEV* ppdev,
|
|
STRIP* pStrip,
|
|
LINESTATE* pLineState)
|
|
{
|
|
LONG cStrips;
|
|
USHORT Cmd;
|
|
LONG i, x, y;
|
|
PLONG pStrips;
|
|
|
|
cStrips = pStrip->cStrips;
|
|
pStrips = pStrip->alStrips;
|
|
|
|
x = pStrip->ptlStart.x;
|
|
y = pStrip->ptlStart.y;
|
|
|
|
if (!(pStrip->flFlips & FL_FLIP_V))
|
|
{
|
|
Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
|
|
LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_315 |
|
|
WRITE;
|
|
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
y += *pStrips - 1;
|
|
x += *pStrips++;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
|
|
LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_45 |
|
|
WRITE;
|
|
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
y -= *pStrips - 1;
|
|
x += *pStrips++;
|
|
}
|
|
}
|
|
|
|
pStrip->ptlStart.x = x;
|
|
pStrip->ptlStart.y = y;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vssSolidDiagonalVertical
|
|
*
|
|
* Draws left-to-right y-major near-diagonal lines using short-stroke
|
|
* vectors. Is faster than using the radial-line routine, but only
|
|
* works when every strip is 15 pels in length or less.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vssSolidDiagonalVertical(
|
|
PDEV* ppdev,
|
|
STRIP* pStrip,
|
|
LINESTATE* pLineState)
|
|
{
|
|
LONG i, cStrips;
|
|
PLONG pStrips;
|
|
LONG Pels, SumPels, yDir;
|
|
USHORT Cmd, ssCmd, dirDraw, dirSkip;
|
|
|
|
Cmd = DRAW | WRITE | MULTIPLE_PIXELS |
|
|
DIR_TYPE_RADIAL | LAST_PIXEL_OFF |
|
|
BUS_SIZE_16 | BYTE_SWAP;
|
|
|
|
cStrips = pStrip->cStrips;
|
|
|
|
IO_FIFO_WAIT(ppdev, 3);
|
|
|
|
IO_CUR_X(ppdev, pStrip->ptlStart.x);
|
|
IO_CUR_Y(ppdev, pStrip->ptlStart.y);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
// Setup the drawing direction and the skip direction.
|
|
|
|
if (!(pStrip->flFlips & FL_FLIP_V))
|
|
{
|
|
yDir = 1;
|
|
dirDraw = 0xF0;
|
|
}
|
|
else
|
|
{
|
|
yDir = -1;
|
|
dirDraw = 0x30;
|
|
}
|
|
|
|
dirSkip = 0x8100;
|
|
|
|
// Output the short stroke commands.
|
|
|
|
SumPels = 0;
|
|
pStrips = pStrip->alStrips;
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
Pels = *pStrips++;
|
|
SumPels += Pels;
|
|
ssCmd = (USHORT)(dirSkip | dirDraw | Pels);
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
IO_SHORT_STROKE(ppdev, ssCmd);
|
|
}
|
|
|
|
pStrip->ptlStart.x += SumPels - cStrips;
|
|
pStrip->ptlStart.y += SumPels * yDir;
|
|
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vrlSolidDiagonalVertical
|
|
*
|
|
* Draws left-to-right y-major near-diagonal lines using radial lines.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vrlSolidDiagonalVertical(
|
|
PDEV* ppdev,
|
|
STRIP* pStrip,
|
|
LINESTATE* pLineState)
|
|
{
|
|
LONG cStrips;
|
|
USHORT Cmd;
|
|
LONG i, x, y;
|
|
PLONG pStrips;
|
|
|
|
cStrips = pStrip->cStrips;
|
|
pStrips = pStrip->alStrips;
|
|
|
|
x = pStrip->ptlStart.x;
|
|
y = pStrip->ptlStart.y;
|
|
|
|
if (!(pStrip->flFlips & FL_FLIP_V))
|
|
{
|
|
Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
|
|
LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_315 |
|
|
WRITE;
|
|
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
y += *pStrips;
|
|
x += *pStrips++ - 1;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
Cmd = DRAW_LINE | DRAW | DIR_TYPE_RADIAL |
|
|
LAST_PIXEL_OFF | MULTIPLE_PIXELS | DRAWING_DIRECTION_45 |
|
|
WRITE;
|
|
|
|
for (i = 0; i < cStrips; i++)
|
|
{
|
|
IO_FIFO_WAIT(ppdev, 4);
|
|
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_MAJ_AXIS_PCNT(ppdev, *pStrips);
|
|
IO_CMD(ppdev, Cmd);
|
|
|
|
y -= *pStrips;
|
|
x += *pStrips++ - 1;
|
|
}
|
|
}
|
|
|
|
|
|
pStrip->ptlStart.x = x;
|
|
pStrip->ptlStart.y = y;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vStripStyledHorizontal
|
|
*
|
|
* Takes the list of strips that define the pixels that would be lit for
|
|
* a solid line, and breaks them into styling chunks according to the
|
|
* styling information that is passed in.
|
|
*
|
|
* This particular routine handles x-major lines that run left-to-right,
|
|
* and are comprised of horizontal strips. It draws the dashes using
|
|
* short-stroke vectors.
|
|
*
|
|
* The performance of this routine could be improved significantly if
|
|
* anyone cared enough about styled lines improve it.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vStripStyledHorizontal(
|
|
PDEV* ppdev,
|
|
STRIP* pstrip,
|
|
LINESTATE* pls)
|
|
{
|
|
LONG x;
|
|
LONG y;
|
|
ULONG dirSkip;
|
|
LONG dy;
|
|
LONG* plStrip;
|
|
LONG cStrips;
|
|
LONG cStyle;
|
|
LONG cStrip;
|
|
LONG cThis;
|
|
ULONG bIsGap;
|
|
|
|
if (pstrip->flFlips & FL_FLIP_V)
|
|
{
|
|
// The minor direction of the line is 90 degrees, and the major
|
|
// direction is 0 (it's a left-to-right x-major line going up):
|
|
|
|
dirSkip = 0x4110;
|
|
dy = -1;
|
|
}
|
|
else
|
|
{
|
|
// The minor direction of the line is 270 degrees, and the major
|
|
// direction is 0 (it's a left-to-right x-major line going down):
|
|
|
|
dirSkip = 0xc110;
|
|
dy = 1;
|
|
}
|
|
|
|
cStrips = pstrip->cStrips; // Total number of strips we'll do
|
|
plStrip = pstrip->alStrips; // Points to current strip
|
|
x = pstrip->ptlStart.x; // x position of start of first strip
|
|
y = pstrip->ptlStart.y; // y position of start of first strip
|
|
|
|
// Warm up the hardware so that it will know we'll be outputing
|
|
// short-stroke vectors, and so that it will have the current position
|
|
// correctly set if we're starting in the middle of a 'dash':
|
|
|
|
IO_FIFO_WAIT(ppdev, 3);
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_CMD(ppdev, DRAW | WRITE | MULTIPLE_PIXELS |
|
|
DIR_TYPE_RADIAL | LAST_PIXEL_OFF | BUS_SIZE_16 |
|
|
BYTE_SWAP);
|
|
|
|
cStrip = *plStrip; // Number of pels in first strip
|
|
|
|
cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
|
|
bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
|
|
|
|
// ulStyleMask is non-zero if we're in the middle of a 'gap',
|
|
// and zero if we're in the middle of a 'dash':
|
|
|
|
if (bIsGap)
|
|
goto SkipAGap;
|
|
else
|
|
goto OutputADash;
|
|
|
|
PrepareToSkipAGap:
|
|
|
|
// Advance in the style-state array, so that we can find the next
|
|
// 'dot' that we'll have to display:
|
|
|
|
bIsGap = ~bIsGap;
|
|
pls->psp++;
|
|
if (pls->psp > pls->pspEnd)
|
|
pls->psp = pls->pspStart;
|
|
|
|
cStyle = *pls->psp;
|
|
|
|
// If 'cStrip' is zero, we also need a new strip:
|
|
|
|
if (cStrip != 0)
|
|
goto SkipAGap;
|
|
|
|
// Here, we're in the middle of a 'gap' where we don't have to
|
|
// display anything. We simply cycle through all the strips
|
|
// we can, keeping track of the current position, until we run
|
|
// out of 'gap':
|
|
|
|
while (TRUE)
|
|
{
|
|
// Each time we loop, we move to a new scan and need a new strip:
|
|
|
|
y += dy;
|
|
|
|
plStrip++;
|
|
cStrips--;
|
|
if (cStrips == 0)
|
|
goto AllDone;
|
|
|
|
cStrip = *plStrip;
|
|
|
|
SkipAGap:
|
|
|
|
cThis = min(cStrip, cStyle);
|
|
cStyle -= cThis;
|
|
cStrip -= cThis;
|
|
|
|
x += cThis;
|
|
|
|
if (cStyle == 0)
|
|
goto PrepareToOutputADash;
|
|
}
|
|
|
|
PrepareToOutputADash:
|
|
|
|
// Advance in the style-state array, so that we can find the next
|
|
// 'dot' that we'll have to display:
|
|
|
|
bIsGap = ~bIsGap;
|
|
pls->psp++;
|
|
if (pls->psp > pls->pspEnd)
|
|
pls->psp = pls->pspStart;
|
|
|
|
cStyle = *pls->psp;
|
|
|
|
// We're gonna need the current position to be correct when we
|
|
// start outputing short-stroke vectors:
|
|
|
|
IO_FIFO_WAIT(ppdev, 2);
|
|
IO_CUR_X(ppdev, x);
|
|
|
|
// If 'cStrip' is zero, we also need a new strip.
|
|
|
|
if (cStrip != 0)
|
|
{
|
|
// There's more to be done in the current strip, so set 'y'
|
|
// to be the current scan:
|
|
|
|
IO_CUR_Y(ppdev, y);
|
|
goto OutputADash;
|
|
}
|
|
|
|
// Set 'y' to be the scan we're about to move to, because we've
|
|
// finished with the current strip:
|
|
|
|
IO_CUR_Y(ppdev, y + dy);
|
|
|
|
while (TRUE)
|
|
{
|
|
// Each time we loop, we move to a new scan and need a new strip:
|
|
|
|
y += dy;
|
|
|
|
plStrip++;
|
|
cStrips--;
|
|
if (cStrips == 0)
|
|
goto AllDone;
|
|
|
|
cStrip = *plStrip;
|
|
|
|
OutputADash:
|
|
|
|
cThis = min(cStrip, cStyle);
|
|
cStyle -= cThis;
|
|
cStrip -= cThis;
|
|
|
|
x += cThis;
|
|
|
|
// Short stroke vectors can handle lines that are a maximum of
|
|
// 15 pels long. When we have to draw a longer consecutive
|
|
// segment than that, we simply break it into 16 pel portions:
|
|
|
|
while (cThis > 15)
|
|
{
|
|
// Draw two horizontal strokes together to make up one 16 pel
|
|
// segment:
|
|
|
|
IO_FIFO_WAIT(ppdev, 1);
|
|
IO_SHORT_STROKE(ppdev, 0x1f11);
|
|
cThis -= 16;
|
|
}
|
|
|
|
// Draw the remaining lit part of the strip:
|
|
|
|
IO_FIFO_WAIT(ppdev, 1);
|
|
IO_SHORT_STROKE(ppdev, dirSkip | cThis);
|
|
|
|
if (cStyle == 0)
|
|
goto PrepareToSkipAGap;
|
|
}
|
|
|
|
AllDone:
|
|
|
|
// Update our state variables so that the next line can continue
|
|
// where we left off:
|
|
|
|
pls->spRemaining = cStyle;
|
|
pls->ulStyleMask = bIsGap;
|
|
pstrip->ptlStart.x = x;
|
|
pstrip->ptlStart.y = y;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* VOID vStripStyledVertical
|
|
*
|
|
* Takes the list of strips that define the pixels that would be lit for
|
|
* a solid line, and breaks them into styling chunks according to the
|
|
* styling information that is passed in.
|
|
*
|
|
* This particular routine handles y-major lines that run left-to-right,
|
|
* and are comprised of vertical strips. It draws the dashes using
|
|
* short-stroke vectors.
|
|
*
|
|
* The performance of this routine could be improved significantly if
|
|
* anyone cared enough about styled lines improve it.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID vStripStyledVertical(
|
|
PDEV* ppdev,
|
|
STRIP* pstrip,
|
|
LINESTATE* pls)
|
|
{
|
|
LONG x;
|
|
LONG y;
|
|
ULONG dirSkip;
|
|
ULONG dirSkip16;
|
|
LONG dy;
|
|
LONG* plStrip;
|
|
LONG cStrips;
|
|
LONG cStyle;
|
|
LONG cStrip;
|
|
LONG cThis;
|
|
ULONG bIsGap;
|
|
|
|
if (pstrip->flFlips & FL_FLIP_V)
|
|
{
|
|
// The minor direction of the line is 0 degrees, and the major
|
|
// direction is 90 (it's a left-to-right y-major line going up):
|
|
|
|
dirSkip = 0x0150;
|
|
dirSkip16 = 0x5f51; // For drawing 16 pels straight up
|
|
dy = -1;
|
|
}
|
|
else
|
|
{
|
|
// The minor direction of the line is 0 degrees, and the major
|
|
// direction is 270 (it's a left-to-right y-major line going down):
|
|
|
|
dirSkip = 0x01d0;
|
|
dirSkip16 = 0xdfd1; // For drawing 16 pels straight down
|
|
dy = 1;
|
|
}
|
|
|
|
cStrips = pstrip->cStrips; // Total number of strips we'll do
|
|
plStrip = pstrip->alStrips; // Points to current strip
|
|
x = pstrip->ptlStart.x; // x position of start of first strip
|
|
y = pstrip->ptlStart.y; // y position of start of first strip
|
|
|
|
// Warm up the hardware so that it will know we'll be outputing
|
|
// short-stroke vectors, and so that it will have the current position
|
|
// correctly set if we're starting in the middle of a 'dash':
|
|
|
|
IO_FIFO_WAIT(ppdev, 3);
|
|
IO_CUR_X(ppdev, x);
|
|
IO_CUR_Y(ppdev, y);
|
|
IO_CMD(ppdev, DRAW | WRITE | MULTIPLE_PIXELS |
|
|
DIR_TYPE_RADIAL | LAST_PIXEL_OFF | BUS_SIZE_16 |
|
|
BYTE_SWAP);
|
|
|
|
cStrip = *plStrip; // Number of pels in first strip
|
|
|
|
cStyle = pls->spRemaining; // Number of pels in first 'gap' or 'dash'
|
|
bIsGap = pls->ulStyleMask; // Tells whether in a 'gap' or a 'dash'
|
|
|
|
// ulStyleMask is non-zero if we're in the middle of a 'gap',
|
|
// and zero if we're in the middle of a 'dash':
|
|
|
|
if (bIsGap)
|
|
goto SkipAGap;
|
|
else
|
|
goto OutputADash;
|
|
|
|
PrepareToSkipAGap:
|
|
|
|
// Advance in the style-state array, so that we can find the next
|
|
// 'dot' that we'll have to display:
|
|
|
|
bIsGap = ~bIsGap;
|
|
pls->psp++;
|
|
if (pls->psp > pls->pspEnd)
|
|
pls->psp = pls->pspStart;
|
|
|
|
cStyle = *pls->psp;
|
|
|
|
// If 'cStrip' is zero, we also need a new strip:
|
|
|
|
if (cStrip != 0)
|
|
goto SkipAGap;
|
|
|
|
// Here, we're in the middle of a 'gap' where we don't have to
|
|
// display anything. We simply cycle through all the strips
|
|
// we can, keeping track of the current position, until we run
|
|
// out of 'gap':
|
|
|
|
while (TRUE)
|
|
{
|
|
// Each time we loop, we move to a new column and need a new strip:
|
|
|
|
x++;
|
|
|
|
plStrip++;
|
|
cStrips--;
|
|
if (cStrips == 0)
|
|
goto AllDone;
|
|
|
|
cStrip = *plStrip;
|
|
|
|
SkipAGap:
|
|
|
|
cThis = min(cStrip, cStyle);
|
|
cStyle -= cThis;
|
|
cStrip -= cThis;
|
|
|
|
y += (dy > 0) ? cThis : -cThis;
|
|
|
|
if (cStyle == 0)
|
|
goto PrepareToOutputADash;
|
|
}
|
|
|
|
PrepareToOutputADash:
|
|
|
|
// Advance in the style-state array, so that we can find the next
|
|
// 'dot' that we'll have to display:
|
|
|
|
bIsGap = ~bIsGap;
|
|
pls->psp++;
|
|
if (pls->psp > pls->pspEnd)
|
|
pls->psp = pls->pspStart;
|
|
|
|
cStyle = *pls->psp;
|
|
|
|
// We're gonna need the current position to be correct when we
|
|
// start outputing short-stroke vectors:
|
|
|
|
IO_FIFO_WAIT(ppdev, 2);
|
|
IO_CUR_Y(ppdev, y);
|
|
|
|
// If 'cStrip' is zero, we also need a new strip.
|
|
|
|
if (cStrip != 0)
|
|
{
|
|
// There's more to be done in the current strip, so set 'x'
|
|
// to be the current column:
|
|
|
|
IO_CUR_X(ppdev, x);
|
|
goto OutputADash;
|
|
}
|
|
|
|
// Set 'x' to be the column we're about to move to, because we've
|
|
// finished with the current strip:
|
|
|
|
IO_CUR_X(ppdev, x + 1);
|
|
|
|
while (TRUE)
|
|
{
|
|
// Each time we loop, we move to a new column and need a new strip:
|
|
|
|
x++;
|
|
|
|
plStrip++;
|
|
cStrips--;
|
|
if (cStrips == 0)
|
|
goto AllDone;
|
|
|
|
cStrip = *plStrip;
|
|
|
|
OutputADash:
|
|
|
|
cThis = min(cStrip, cStyle);
|
|
cStyle -= cThis;
|
|
cStrip -= cThis;
|
|
|
|
y += (dy > 0) ? cThis : -cThis;
|
|
|
|
// Short stroke vectors can handle lines that are a maximum of
|
|
// 15 pels long. When we have to draw a longer consecutive
|
|
// segment than that, we simply break it into 16 pel portions:
|
|
|
|
while (cThis > 15)
|
|
{
|
|
// Draw two vertical strokes together to make up one 16 pel
|
|
// segment:
|
|
|
|
IO_FIFO_WAIT(ppdev, 1);
|
|
IO_SHORT_STROKE(ppdev, dirSkip16);
|
|
cThis -= 16;
|
|
}
|
|
|
|
// Draw the remaining lit part of the strip:
|
|
|
|
IO_FIFO_WAIT(ppdev, 1);
|
|
IO_SHORT_STROKE(ppdev, dirSkip | cThis);
|
|
|
|
if (cStyle == 0)
|
|
goto PrepareToSkipAGap;
|
|
}
|
|
|
|
AllDone:
|
|
|
|
// Update our state variables so that the next line can continue
|
|
// where we left off:
|
|
|
|
pls->spRemaining = cStyle;
|
|
pls->ulStyleMask = bIsGap;
|
|
pstrip->ptlStart.x = x;
|
|
pstrip->ptlStart.y = y;
|
|
}
|