windows-nt/Source/XPSP1/NT/drivers/video/ms/compaq.qv/disp/strips.c

1088 lines
27 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/******************************Module*Header*******************************\
* Module Name: Strips.c
*
* These are the line rendering routines of last resort, and are called
* by 'bLines' when a line is clipped or otherwise cannot be drawn
* directly by the hardware.
*
* Note that we don't take advantage in the strip routines of the QVision's
* capability for automatically starting when the Y1 register is written,
* because that requires different state from what is required for the
* integer line special case in 'bLines' -- and we want that integer line
* special case to be as fast as possible, at cost to these strip routines.
*
* Copyright (c) 1992-1995 Microsoft Corporation
\**************************************************************************/
#include "precomp.h"
/******************************Public*Routine******************************\
* VOID vIoStripSolidHorizontal
*
* Draws left-to-right x-major near-horizontal lines using radial lines.
*
\**************************************************************************/
VOID vIoStripSolidHorizontal(
PDEV* ppdev,
STRIP* pStrip,
LINESTATE* pLineState)
{
BYTE* pjIoBase;
LONG x;
LONG y;
LONG yDir;
LONG* pStrips;
LONG cStrips;
LONG i;
pjIoBase = ppdev->pjIoBase;
x = pStrip->ptlStart.x;
y = pStrip->ptlStart.y;
yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
pStrips = pStrip->alStrips;
cStrips = pStrip->cStrips;
for (i = cStrips; i != 0; i--)
{
IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
IO_X0_Y0(ppdev, pjIoBase, x, y);
x += *pStrips++;
IO_X1_Y1(ppdev, pjIoBase, x - 1, y);
y += yDir;
IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
}
pStrip->ptlStart.x = x;
pStrip->ptlStart.y = y;
}
/******************************Public*Routine******************************\
* VOID vIoStripSolidVertical
*
* Draws left-to-right y-major near-vertical lines using radial lines.
*
\**************************************************************************/
VOID vIoStripSolidVertical(
PDEV* ppdev,
STRIP* pStrip,
LINESTATE* pLineState)
{
BYTE* pjIoBase;
LONG x;
LONG y;
LONG yDir;
LONG* pStrips;
LONG cStrips;
LONG i;
pjIoBase = ppdev->pjIoBase;
x = pStrip->ptlStart.x;
y = pStrip->ptlStart.y;
yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
pStrips = pStrip->alStrips;
cStrips = pStrip->cStrips;
for (i = cStrips; i != 0; i--)
{
IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
IO_X0_Y0(ppdev, pjIoBase, x, y);
y += (yDir > 0) ? *pStrips : -*pStrips;
pStrips++;
IO_X1_Y1(ppdev, pjIoBase, x, y - yDir);
x++;
IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
}
pStrip->ptlStart.x = x;
pStrip->ptlStart.y = y;
}
/******************************Public*Routine******************************\
* VOID vIoStripSolidDiagonalHorizontal
*
* Draws left-to-right x-major near-diagonal lines using radial lines.
*
\**************************************************************************/
VOID vIoStripSolidDiagonalHorizontal(
PDEV* ppdev,
STRIP* pStrip,
LINESTATE* pLineState)
{
BYTE* pjIoBase;
LONG x;
LONG y;
LONG yDir;
LONG* pStrips;
LONG cStrips;
LONG i;
pjIoBase = ppdev->pjIoBase;
x = pStrip->ptlStart.x;
y = pStrip->ptlStart.y;
yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
pStrips = pStrip->alStrips;
cStrips = pStrip->cStrips;
for (i = cStrips; i != 0; i--)
{
IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
IO_X0_Y0(ppdev, pjIoBase, x, y);
x += *pStrips;
y += (yDir > 0) ? *pStrips : -*pStrips;
pStrips++;
IO_X1_Y1(ppdev, pjIoBase, x - 1, y - yDir);
y -= yDir;
IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
}
pStrip->ptlStart.x = x;
pStrip->ptlStart.y = y;
}
/******************************Public*Routine******************************\
* VOID vIoStripSolidDiagonalVertical
*
* Draws left-to-right y-major near-diagonal lines using radial lines.
*
\**************************************************************************/
VOID vIoStripSolidDiagonalVertical(
PDEV* ppdev,
STRIP* pStrip,
LINESTATE* pLineState)
{
BYTE* pjIoBase;
LONG x;
LONG y;
LONG yDir;
LONG* pStrips;
LONG cStrips;
LONG i;
pjIoBase = ppdev->pjIoBase;
x = pStrip->ptlStart.x;
y = pStrip->ptlStart.y;
yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
pStrips = pStrip->alStrips;
cStrips = pStrip->cStrips;
for (i = cStrips; i != 0; i--)
{
IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
IO_X0_Y0(ppdev, pjIoBase, x, y);
x += *pStrips;
y += (yDir > 0) ? *pStrips : -*pStrips;
pStrips++;
IO_X1_Y1(ppdev, pjIoBase, x - 1, y - yDir);
x--;
IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
}
pStrip->ptlStart.x = x;
pStrip->ptlStart.y = y;
}
/******************************Public*Routine******************************\
* VOID vIoStripStyledHorizontal
*
* 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 vIoStripStyledHorizontal(
PDEV* ppdev,
STRIP* pstrip,
LINESTATE* pls)
{
BYTE* pjIoBase;
LONG x;
LONG y;
LONG dy;
LONG* plStrip;
LONG cStrips;
LONG cStyle;
LONG cStrip;
LONG cThis;
ULONG bIsGap;
pjIoBase = ppdev->pjIoBase;
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):
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):
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
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;
// If 'cStrip' is zero, we also need a new strip.
if (cStrip != 0)
{
// There's more to be done in the current strip:
goto OutputADash;
}
// We've finished with the current strip:
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;
// 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:
IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
IO_X0_Y0(ppdev, pjIoBase, x, y);
x += cThis;
IO_X1_Y1(ppdev, pjIoBase, x - 1, y);
IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
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 vIoStripStyledVertical
*
* 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 vIoStripStyledVertical(
PDEV* ppdev,
STRIP* pstrip,
LINESTATE* pls)
{
BYTE* pjIoBase;
LONG x;
LONG y;
LONG dy;
LONG* plStrip;
LONG cStrips;
LONG cStyle;
LONG cStrip;
LONG cThis;
ULONG bIsGap;
pjIoBase = ppdev->pjIoBase;
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):
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):
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
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;
// If 'cStrip' is zero, we also need a new strip.
if (cStrip != 0)
{
// There's more to be done in the current strip:
goto OutputADash;
}
// We've finished with the current strip:
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;
IO_WAIT_FOR_IDLE(ppdev, pjIoBase);
IO_X0_Y0(ppdev, pjIoBase, x, y);
y += (dy > 0) ? cThis : -cThis;
IO_X1_Y1(ppdev, pjIoBase, x, y - dy);
IO_LINE_CMD(ppdev, pjIoBase, DEFAULT_LINE_CMD);
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 vMmStripSolidHorizontal
*
* Draws left-to-right x-major near-horizontal lines using radial lines.
*
\**************************************************************************/
VOID vMmStripSolidHorizontal(
PDEV* ppdev,
STRIP* pStrip,
LINESTATE* pLineState)
{
BYTE* pjMmBase;
LONG x;
LONG y;
LONG yDir;
LONG* pStrips;
LONG cStrips;
LONG i;
pjMmBase = ppdev->pjMmBase;
x = pStrip->ptlStart.x;
y = pStrip->ptlStart.y;
yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
pStrips = pStrip->alStrips;
cStrips = pStrip->cStrips;
for (i = cStrips; i != 0; i--)
{
MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
MM_X0_Y0(ppdev, pjMmBase, x, y);
x += *pStrips++;
MM_X1_Y1(ppdev, pjMmBase, x - 1, y);
y += yDir;
MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
}
pStrip->ptlStart.x = x;
pStrip->ptlStart.y = y;
}
/******************************Public*Routine******************************\
* VOID vMmStripSolidVertical
*
* Draws left-to-right y-major near-vertical lines using radial lines.
*
\**************************************************************************/
VOID vMmStripSolidVertical(
PDEV* ppdev,
STRIP* pStrip,
LINESTATE* pLineState)
{
BYTE* pjMmBase;
LONG x;
LONG y;
LONG yDir;
LONG* pStrips;
LONG cStrips;
LONG i;
pjMmBase = ppdev->pjMmBase;
x = pStrip->ptlStart.x;
y = pStrip->ptlStart.y;
yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
pStrips = pStrip->alStrips;
cStrips = pStrip->cStrips;
for (i = cStrips; i != 0; i--)
{
MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
MM_X0_Y0(ppdev, pjMmBase, x, y);
y += (yDir > 0) ? *pStrips : -*pStrips;
pStrips++;
MM_X1_Y1(ppdev, pjMmBase, x, y - yDir);
x++;
MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
}
pStrip->ptlStart.x = x;
pStrip->ptlStart.y = y;
}
/******************************Public*Routine******************************\
* VOID vMmStripSolidDiagonalHorizontal
*
* Draws left-to-right x-major near-diagonal lines using radial lines.
*
\**************************************************************************/
VOID vMmStripSolidDiagonalHorizontal(
PDEV* ppdev,
STRIP* pStrip,
LINESTATE* pLineState)
{
BYTE* pjMmBase;
LONG x;
LONG y;
LONG yDir;
LONG* pStrips;
LONG cStrips;
LONG i;
pjMmBase = ppdev->pjMmBase;
x = pStrip->ptlStart.x;
y = pStrip->ptlStart.y;
yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
pStrips = pStrip->alStrips;
cStrips = pStrip->cStrips;
for (i = cStrips; i != 0; i--)
{
MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
MM_X0_Y0(ppdev, pjMmBase, x, y);
x += *pStrips;
y += (yDir > 0) ? *pStrips : -*pStrips;
pStrips++;
MM_X1_Y1(ppdev, pjMmBase, x - 1, y - yDir);
y -= yDir;
MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
}
pStrip->ptlStart.x = x;
pStrip->ptlStart.y = y;
}
/******************************Public*Routine******************************\
* VOID vMmStripSolidDiagonalVertical
*
* Draws left-to-right y-major near-diagonal lines using radial lines.
*
\**************************************************************************/
VOID vMmStripSolidDiagonalVertical(
PDEV* ppdev,
STRIP* pStrip,
LINESTATE* pLineState)
{
BYTE* pjMmBase;
LONG x;
LONG y;
LONG yDir;
LONG* pStrips;
LONG cStrips;
LONG i;
pjMmBase = ppdev->pjMmBase;
x = pStrip->ptlStart.x;
y = pStrip->ptlStart.y;
yDir = (pStrip->flFlips & FL_FLIP_V) ? -1 : 1;
pStrips = pStrip->alStrips;
cStrips = pStrip->cStrips;
for (i = cStrips; i != 0; i--)
{
MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
MM_X0_Y0(ppdev, pjMmBase, x, y);
x += *pStrips;
y += (yDir > 0) ? *pStrips : -*pStrips;
pStrips++;
MM_X1_Y1(ppdev, pjMmBase, x - 1, y - yDir);
x--;
MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
}
pStrip->ptlStart.x = x;
pStrip->ptlStart.y = y;
}
/******************************Public*Routine******************************\
* VOID vMmStripStyledHorizontal
*
* 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 vMmStripStyledHorizontal(
PDEV* ppdev,
STRIP* pstrip,
LINESTATE* pls)
{
BYTE* pjMmBase;
LONG x;
LONG y;
LONG dy;
LONG* plStrip;
LONG cStrips;
LONG cStyle;
LONG cStrip;
LONG cThis;
ULONG bIsGap;
pjMmBase = ppdev->pjMmBase;
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):
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):
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
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;
// If 'cStrip' is zero, we also need a new strip.
if (cStrip != 0)
{
// There's more to be done in the current strip:
goto OutputADash;
}
// We've finished with the current strip:
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;
// 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:
MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
MM_X0_Y0(ppdev, pjMmBase, x, y);
x += cThis;
MM_X1_Y1(ppdev, pjMmBase, x - 1, y);
MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
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 vMmStripStyledVertical
*
* 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 vMmStripStyledVertical(
PDEV* ppdev,
STRIP* pstrip,
LINESTATE* pls)
{
BYTE* pjMmBase;
LONG x;
LONG y;
LONG dy;
LONG* plStrip;
LONG cStrips;
LONG cStyle;
LONG cStrip;
LONG cThis;
ULONG bIsGap;
pjMmBase = ppdev->pjMmBase;
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):
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):
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
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;
// If 'cStrip' is zero, we also need a new strip.
if (cStrip != 0)
{
// There's more to be done in the current strip:
goto OutputADash;
}
// We've finished with the current strip:
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;
MM_WAIT_FOR_IDLE(ppdev, pjMmBase);
MM_X0_Y0(ppdev, pjMmBase, x, y);
y += (dy > 0) ? cThis : -cThis;
MM_X1_Y1(ppdev, pjMmBase, x, y - dy);
MM_LINE_CMD(ppdev, pjMmBase, DEFAULT_LINE_CMD);
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;
}