Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1225 lines
28 KiB

/*++
Copyright (c) 1990-1993 Microsoft Corporation
Module Name:
compress.c
Abstract:
This module contains all data compression functions
Author:
18-Feb-1994 Fri 09:50:08 created -by- Daniel Chou (danielc)
[Environment:]
GDI Device Driver - Plotter.
[Notes:]
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define DBG_PLOTFILENAME DbgCompress
#define DBG_TIFF 0x00000001
#define DBG_DELTA 0x00000002
#define DBG_COMPRESS 0x00000004
#define DBG_OUTRTLSCAN 0x00000008
#define DBG_FLUSHADAPTBUF 0x00000010
#define DBG_ENTERRTLSCANS 0x00000020
#define DBG_DELTA_OFFSET0 0x00000040
#define DBG_NO_DELTA 0x40000000
#define DBG_NO_TIFF 0x80000000
DEFINE_DBGVAR(0);
#define TIFF_MIN_REPEATS 3
#define TIFF_MAX_REPEATS 128
#define TIFF_MAX_LITERAL 128
#define DELTA_MAX_ONE_REPLACE 8
#define DELTA_MAX_1ST_OFFSET 31
#define MIN_BLOCK_MODE_SIZE 8
//
// The MAX_ADAPT_SIZE is used to leave room for SET_ADAPT_CONTROL
//
#if (OUTPUT_BUFFER_SIZE >= (1024 * 32))
#define MAX_ADAPT_SIZE ((1024 * 32) - 16)
#else
#define MAX_ADAPT_SIZE (OUTPUT_BUFFER_SIZE - 16)
#endif
#define ADAPT_METHOD_ZERO 4
#define ADAPT_METHOD_DUP 5
#define SIZE_ADAPT_CONTROL 3
#define SET_ADAPT_CONTROL(pPDev, m, c) \
{ \
BYTE bAdaptCtrl[4]; \
\
bAdaptCtrl[0] = (BYTE)(m); \
bAdaptCtrl[1] = (BYTE)(((c) >> 8) & 0xFF); \
bAdaptCtrl[2] = (BYTE)(((c) ) & 0xFF); \
OutputBytes(pPDev, bAdaptCtrl, 3); \
}
BOOL
FlushAdaptBuf(
PPDEV pPDev,
PRTLSCANS pRTLScans,
BOOL FlushEmptyDup
)
/*++
Routine Description:
This function flush out the adaptive mode buffer
Arguments:
pPDev - Pointer to our PDEV
pRTLScans - Pointer to the RTLSCANS data structure
FlushEmptyDup - TRUE if cEmptyDup need to be flush out also
Return Value:
TRUE if OK,
Author:
09-Mar-1994 Wed 20:32:31 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
DWORD Count;
WORD cEmptyDup;
BOOL Ok = TRUE;
Count = pPDev->cbBufferBytes;
if (cEmptyDup = (FlushEmptyDup) ? pRTLScans->cEmptyDup : 0) {
Count += SIZE_ADAPT_CONTROL;
}
if (Count) {
DWORD cbBufferBytes;
BYTE TmpBuf[32];
PLOTDBG(DBG_FLUSHADAPTBUF, ("FlushAdaptBuf: Flush total %ld byte block",
Count));
//====================================================================
// SAVE the OutputBuffer for this temporary header
//====================================================================
CopyMemory(TmpBuf, pPDev->pOutBuffer, sizeof(TmpBuf));
cbBufferBytes = pPDev->cbBufferBytes;
pPDev->cbBufferBytes = 0;
//
// Now output the header
//
OutputBytes(pPDev, "\033*b", 3);
if (!pRTLScans->cAdaptBlk) {
pRTLScans->cAdaptBlk++;
OutputBytes(pPDev, "5m", 2);
}
OutputFormatStr(pPDev, "#dW", Count);
//====================================================================
// FLUSH OUTPUT BUFFER AND RESTORE BACK the OutputBuffer for this
// temporary header
//====================================================================
PLOTDBG(DBG_FLUSHADAPTBUF, ("FlushAdaptBuf: Flush TmpBuf[%ld] bytes of HEADER",
pPDev->cbBufferBytes));
FlushOutBuffer(pPDev);
CopyMemory(pPDev->pOutBuffer, TmpBuf, sizeof(TmpBuf));
pPDev->cbBufferBytes = cbBufferBytes;
if (cEmptyDup) {
PLOTDBG(DBG_FLUSHADAPTBUF, ("FlushAdaptBuf: Add %ld EmptyDup [%ld]",
(DWORD)cEmptyDup, (DWORD)pRTLScans->AdaptMethod));
SET_ADAPT_CONTROL(pPDev, pRTLScans->AdaptMethod, cEmptyDup);
pRTLScans->cEmptyDup = 0;
}
Ok = FlushOutBuffer(pPDev);
//
// After the block been sent the seed row is back to zero
//
ZeroMemory(pRTLScans->pbSeedRows[0],
(DWORD)pRTLScans->cxBytes * (DWORD)pRTLScans->Planes);
}
return(Ok);
}
VOID
ExitRTLScans(
PPDEV pPDev,
PRTLSCANS pRTLScans
)
/*++
Routine Description:
This function initialize the RTLSCANS structure and decideds what compress
mode will be the best
Arguments:
pPDev - Pointer to our PDEV
pRTLScans - Pointer to the RTLSCANS data structure to be initialized
cxSize - Width of pixel per scans
Return Value:
TRUE if sucessful, FALSE if failed
Author:
22-Feb-1994 Tue 12:14:17 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
if (pRTLScans->CompressMode == COMPRESS_MODE_ADAPT) {
FlushAdaptBuf(pPDev, pRTLScans, TRUE);
}
if (pRTLScans->pbCompress) {
LocalFree(pRTLScans->pbCompress);
}
ZeroMemory(pRTLScans, sizeof(RTLSCANS));
}
VOID
EnterRTLScans(
PPDEV pPDev,
PRTLSCANS pRTLScans,
DWORD cx,
DWORD cy,
BOOL MonoBmp
)
/*++
Routine Description:
This function initialize the RTLSCANS structure and decideds what compress
mode will be the best
Arguments:
pPDev - Pointer to our PDEV
pRTLScans - Pointer to the RTLSCANS data structure to be initialized
cxSize - Width of pixel per scans
Return Value:
TRUE if sucessful, FALSE if failed
Author:
22-Feb-1994 Tue 12:14:17 created -by- Daniel Chou (danielc)
11-Mar-1994 Fri 19:23:34 updated -by- Daniel Chou (danielc)
Only flush the output buffer if we are really in ADAPTIVE mode
Revision History:
--*/
{
RTLSCANS RTLScans;
DWORD AllocSize;
DWORD MinBlkSize;
RTLScans.Flags = (RTLScans.cScans = cy) ? RTLSF_MORE_SCAN : 0;
RTLScans.pbCompress =
RTLScans.pbSeedRows[0] =
RTLScans.pbSeedRows[1] =
RTLScans.pbSeedRows[2] = NULL;
RTLScans.cEmptyDup = 0;
RTLScans.AdaptMethod = 0xFF;
RTLScans.cAdaptBlk = 0;
RTLScans.cxBytes = (DWORD)((cx + 7) >> 3);
RTLScans.CompressMode = COMPRESS_MODE_ROW;
RTLScans.MaxAdaptBufSize = MAX_ADAPT_SIZE;
if (!(RTLScans.Mask = (BYTE)(~(0xFF >> (cx & 0x07))))) {
//
// Exact at byte boundary
//
RTLScans.Mask = 0xFF;
}
MinBlkSize = 8;
if (MonoBmp) {
RTLScans.Planes = 1;
AllocSize = (DWORD)(RTLScans.cxBytes << 1);
if (RTLMONOENCODE_5(pPDev)) {
PLOTDBG(DBG_ENTERRTLSCANS, ("EnterRTLScans: Using Adaptive Mode Compression"));
RTLScans.CompressMode = COMPRESS_MODE_ADAPT;
MinBlkSize = 4;
}
} else {
RTLScans.Planes = 3;
AllocSize = (DWORD)(RTLScans.cxBytes << 2);
}
if ((RTLScans.cxBytes <= MinBlkSize) ||
(!(RTLScans.pbCompress = (LPBYTE)LocalAlloc(LPTR, AllocSize)))) {
BYTE Buf[4];
RTLScans.CompressMode = COMPRESS_MODE_BLOCK;
OutputFormatStr(pPDev,
"\033*b4m#dW",
4 + (RTLScans.cxBytes * RTLScans.Planes * cy));
Buf[0] = (BYTE)((cx >> 24) & 0xFF);
Buf[1] = (BYTE)((cx >> 16) & 0xFF);
Buf[2] = (BYTE)((cx >> 8) & 0xFF);
Buf[3] = (BYTE)((cx ) & 0xFF);
OutputBytes(pPDev, Buf, 4);
} else if (RTLScans.CompressMode == COMPRESS_MODE_ADAPT) {
//
// We must first flush current output buffer to let room for the
// Adapt method
//
FlushOutBuffer(pPDev);
}
if (RTLScans.pbCompress) {
RTLScans.pbSeedRows[0] = RTLScans.pbCompress + RTLScans.cxBytes;
if (!MonoBmp) {
RTLScans.pbSeedRows[1] = RTLScans.pbSeedRows[0] + RTLScans.cxBytes;
RTLScans.pbSeedRows[2] = RTLScans.pbSeedRows[1] + RTLScans.cxBytes;
}
}
*pRTLScans = RTLScans;
}
LONG
CompressToDelta(
LPBYTE pbSrc,
LPBYTE pbSeedRow,
LPBYTE pbDst,
LONG Size
)
/*++
Routine Description:
This function compress the input data to delta type from the seed row
Arguments:
pbSrc - Pointer to the source to be compressed
pbSeedRow - Pointer to the previous seed row
pbDst - Pointer to the compress buffer
Size - Size of three pointers
Return Value:
LONG - the compress buffer size
>0 - Size of the buffer
=0 - The data is same as previouse line
<0 - Size is larger than the Size passed
Author:
22-Feb-1994 Tue 14:41:18 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LPBYTE pbDstBeg;
LPBYTE pbDstEnd;
LPBYTE pbTmp;
LONG cSrcBytes;
LONG Offset;
UINT cReplace;
BOOL DoReplace;
#if DBG
if (DBG_PLOTFILENAME & DBG_NO_DELTA) {
return(-Size);
}
#endif
cSrcBytes = Size;
pbDstBeg = pbDst;
pbDstEnd = pbDst + Size;
cReplace = 0;
pbTmp = pbSrc;
while (cSrcBytes--) {
//
// We need to do byte replacement now
//
if (*pbSrc != *pbSeedRow) {
if (++cReplace == 1) {
//
// The pbTmp is the next byte to the last replacement byte and
// after we find the first different, it become the first byte
// of source to be copied as different data.
//
Offset = pbSrc - pbTmp;
pbTmp = pbSrc;
}
DoReplace = (BOOL)((cReplace >= DELTA_MAX_ONE_REPLACE) ||
(!cSrcBytes));
} else {
DoReplace = (BOOL)cReplace;
}
if (DoReplace) {
//
// Minimum we need one Command Byte and Replace Count Byte
//
if ((LONG)(pbDstEnd - pbDst) <= (LONG)cReplace) {
PLOTDBG(DBG_DELTA, ("CompressToDelta: 1ST_OFF: Dest Size is larger, give up"));
return(-Size);
}
PLOTDBG(DBG_DELTA, ("CompressToDelta: Replace=%ld, Offset=%ld",
(DWORD)cReplace, (DWORD)Offset));
//
// Set commmand byte to replacement count
//
*pbDst = (BYTE)((cReplace - 1) << 5);
//
// Add in the offset to the same destination byte
//
if (Offset < DELTA_MAX_1ST_OFFSET) {
*pbDst++ |= (BYTE)Offset;
} else {
//
// We need to send more than one offset, REMEMBER: We must
// send extra 0 if the ofset is eqaul to 31 or 255
//
*pbDst++ |= (BYTE)DELTA_MAX_1ST_OFFSET;
Offset -= DELTA_MAX_1ST_OFFSET;
do {
if (!Offset) {
PLOTDBG(DBG_DELTA_OFFSET0,
("CompressToDelta: Extra 0 offset SENT"));
}
if (pbDst >= pbDstEnd) {
PLOTDBG(DBG_DELTA, ("CompressToDelta: Dest Size is larger, give up"));
return(-Size);
}
*pbDst++ = (BYTE)((Offset >= 255) ? 255 : Offset);
} while ((Offset -= 255) >= 0);
}
//
// Now copy down the replacement bytes, if we mess up then this
// pb1stDiff will be NULL
//
CopyMemory(pbDst, pbTmp, cReplace);
pbDst += cReplace;
pbTmp += cReplace;
cReplace = 0;
}
//
// Advanced source/seed row pointers
//
++pbSrc;
++pbSeedRow;
}
PLOTDBG(DBG_DELTA, ("CompressToDelta: Compress from %ld to %ld, save=%ld",
Size, (DWORD)(pbDst - pbDstBeg),
Size - (DWORD)(pbDst - pbDstBeg)));
return((LONG)(pbDst - pbDstBeg));
}
LONG
CompressToTIFF(
LPBYTE pbSrc,
LPBYTE pbDst,
LONG Size
)
/*++
Routine Description:
This function take the source data and compress them into the TIFF packbits
format at pbDst.
The TIFF packbits compression always consists a CONTROL byte and follow
by the byte data, the CONTROL byte has following range
-1 to -127 - The data byte follow the control byte is repeated this many
time. Repeat Count = -(Control Byte) + 1
0 to 127 - There are 1 to 128 literal data byte follow the control byte,
literal data count = (Control Byte) + 1
-128 - NOP
Arguments:
pbSrc - The source data to be compressed
pbDst - The compressed TIFF packbits format data
Size - Count of the data in the source and destination
Return Value:
>0 - Compress sucessful and return value is the total bytes in pbDst
=0 - All bytes are zero nothing to be compressed.
<0 - Compress data is larger than the source, compression failed and
pbDst has no valid data.
Author:
18-Feb-1994 Fri 09:54:47 created -by- Daniel Chou (danielc)
24-Feb-1994 Thu 10:43:01 updated -by- Daniel Chou (danielc)
Changed the logic so when multiple MAX repeats count is sent and last
repeat chunck is less than TIFF_MIN_REPEATS then we will treat that as
literal to save more spaces
Revision History:
--*/
{
LPBYTE pbSrcBeg;
LPBYTE pbSrcEnd;
LPBYTE pbDstBeg;
LPBYTE pbDstEnd;
LPBYTE pbLastRepeat;
LPBYTE pbTmp;
LONG RepeatCount;
LONG LiteralCount;
LONG CurSize;
BYTE LastSrc;
#if DBG
if (DBG_PLOTFILENAME & DBG_NO_TIFF) {
return(-Size);
}
#endif
pbSrcBeg = pbSrc;
pbSrcEnd = pbSrc + Size;
pbDstBeg = pbDst;
pbDstEnd = pbDst + Size;
pbLastRepeat = pbSrc;
while (pbSrcBeg < pbSrcEnd) {
pbTmp = pbSrcBeg;
LastSrc = *pbTmp++;
while ((pbTmp < pbSrcEnd) &&
(*pbTmp == LastSrc)) {
++pbTmp;
}
if (((RepeatCount = (LONG)(pbTmp - pbSrcBeg)) >= TIFF_MIN_REPEATS) ||
(pbTmp >= pbSrcEnd)) {
//
// Checking if we are repeat ZEROs to the end of the line, if so
// then make if auto zero fill and exit
//
LiteralCount = (LONG)(pbSrcBeg - pbLastRepeat);
if ((pbTmp >= pbSrcEnd) &&
(RepeatCount) &&
(LastSrc == 0)) {
if (RepeatCount == Size) {
PLOTDBG(DBG_TIFF,
("CompressToTIFF: All data = 0, size=%ld", Size));
return(0);
}
PLOTDBG(DBG_TIFF,
("CompressToTIFF: Last Chunck of Repeats (%ld) is Zeros, Skip it",
RepeatCount));
RepeatCount = 0;
} else if (RepeatCount < TIFF_MIN_REPEATS) {
//
// If repeats is not good enough to make it into repeat control
// then add it to the literal count
//
LiteralCount += RepeatCount;
RepeatCount = 0;
}
PLOTDBG(DBG_TIFF, ("CompressToTIFF: Literal=%ld, Repeats=%ld",
LiteralCount, RepeatCount));
//
// Setting literal count
//
while (LiteralCount) {
if ((CurSize = LiteralCount) > TIFF_MAX_LITERAL) {
CurSize = TIFF_MAX_LITERAL;
}
if ((pbDstEnd - pbDst) <= CurSize) {
PLOTDBG(DBG_TIFF,
("CompressToTIFF: [LITERAL] Dest Size is larger, give up"));
return(-Size);
}
//
// Set literal control bytes from 0-127
//
*pbDst++ = (BYTE)(CurSize - 1);
CopyMemory(pbDst, pbLastRepeat, CurSize);
pbDst += CurSize;
pbLastRepeat += CurSize;
LiteralCount -= CurSize;
}
//
// Setting repeat count if any
//
while (RepeatCount) {
if ((CurSize = RepeatCount) > TIFF_MAX_REPEATS) {
CurSize = TIFF_MAX_REPEATS;
}
if ((pbDstEnd - pbDst) < 2) {
PLOTDBG(DBG_TIFF,
("CompressToTIFF: [REPEATS] Dest Size is larger, give up"));
return(-Size);
}
//
// Set Repeat Control bytes from -1 to -127
//
*pbDst++ = (BYTE)(1 - CurSize);
*pbDst++ = (BYTE)LastSrc;
//
// If we have more than TIFF_MAX_REPEATS then we want to make
// sure we used most efficient method to send. If we have
// remaining repeated bytes less than TIFF_MIN_REPEATS then
// we want to skip that and use literal for the next run
//
if ((RepeatCount -= CurSize) < TIFF_MIN_REPEATS) {
PLOTDBG(DBG_TIFF,
("CompressToTIFF: Replaced Last REPEATS (%ld) for LITERAL",
RepeatCount));
pbTmp -= RepeatCount;
RepeatCount = 0;
}
}
pbLastRepeat = pbTmp;
}
pbSrcBeg = pbTmp;
}
PLOTDBG(DBG_TIFF, ("CompressToTIFF: Compress from %ld to %ld, save=%ld",
Size, (DWORD)(pbDst - pbDstBeg),
Size - (DWORD)(pbDst - pbDstBeg)));
return((LONG)(pbDst - pbDstBeg));
}
LONG
RTLCompression(
LPBYTE pbSrc,
LPBYTE pbSeedRow,
LPBYTE pbDst,
LONG Size,
LPBYTE pCompressMode
)
/*++
Routine Description:
This function decides which RTL compress method is the best and then
compress to that method
Arguments:
pbSrc - pointer to the source scan
pbSeedRow - Pointer to the seed row for the current source scan
pbDst - Pointer to the compressed result will be stored
Size - size in bytes for pbSrc/pbSeedRow/pbDst
pCompressMode - Pointer to current compression mode, it will ALWAYS
updated to a new compress mode when it returned
Return Value:
>0 - Use *pCompressMode returned and output that many bytes
=0 - Use *pCompressMode returned and output ZERO byte
<0 - Use *pCompressMode returned and output original source and size
Author:
25-Feb-1994 Fri 12:49:29 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LONG cDelta;
LONG cTiff;
LONG RetSize;
BYTE CompressMode;
if ((cDelta = CompressToDelta(pbSrc, pbSeedRow, pbDst, Size)) == 0) {
//
// Exact duplicate the preious row and seed row remained same
//
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Duplicate the ROW"));
*pCompressMode = (BYTE)COMPRESS_MODE_DELTA;
return(0);
}
if ((cTiff = CompressToTIFF(pbSrc, pbDst, Size)) == 0) {
//
// Since a '*0W' for the delta means repeat last row so we must change
// to other mode, but we just want reset seed rows to all zeros
//
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Row is all ZEROs"));
if (*pCompressMode == (BYTE)COMPRESS_MODE_DELTA) {
*pCompressMode = (BYTE)COMPRESS_MODE_ROW;
}
ZeroMemory(pbSeedRow, Size);
return(0);
}
if (cTiff < 0) {
if (cDelta < 0) {
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Using COMPRESS_MODE_ROW"));
CompressMode = (BYTE)COMPRESS_MODE_ROW;
RetSize = -Size;
} else {
CompressMode = (BYTE)COMPRESS_MODE_DELTA;
}
} else {
//
// At here cTiff is greater than zero
//
CompressMode = (BYTE)(((cDelta < 0) || (cTiff <= cDelta)) ?
COMPRESS_MODE_TIFF : COMPRESS_MODE_DELTA);
}
if ((*pCompressMode = CompressMode) == COMPRESS_MODE_DELTA) {
//
// We must redo the DELTA again, since pbDst already destroy by the
// TIFF compression
//
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Using COMPRESS_MODE_DELTA"));
RetSize = CompressToDelta(pbSrc, pbSeedRow, pbDst, Size);
} else if (CompressMode == COMPRESS_MODE_TIFF) {
PLOTDBG(DBG_COMPRESS, ("RTLCompression: Using COMPRESS_MODE_TIFF"));
RetSize = cTiff;
}
//
// We need to have curreent source (Original SIZE) as new seed rows
//
CopyMemory(pbSeedRow, pbSrc, Size);
return(RetSize);
}
BOOL
AdaptCompression(
PPDEV pPDev,
PRTLSCANS pRTLScans,
LPBYTE pbSrc,
LPBYTE pbSeedRow,
LPBYTE pbDst,
LONG Size
)
/*++
Routine Description:
This function decides which RTL compress method is the best and then
compress to that method
Arguments:
pbSrc - pointer to the source scan
pbSeedRow - Pointer to the seed row for the current source scan
pbDst - Pointer to the compressed result will be stored
Size - size in bytes for pbSrc/pbSeedRow/pbDst
Return Value:
>0 - Use *pCompressMode returned and output that many bytes
=0 - Use *pCompressMode returned and output ZERO byte
<0 - Use *pCompressMode returned and output original source and size
Author:
25-Feb-1994 Fri 12:49:29 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LPBYTE pbOrgDst;
LONG Count;
BOOL Ok;
BYTE AdaptMethod;
pbOrgDst = pbDst;
if (Count = RTLCompression(pbSrc, pbSeedRow, pbDst, Size, &AdaptMethod)) {
if (Count < 0) {
pbDst = pbSrc;
Count = -Count;
}
} else {
AdaptMethod = (AdaptMethod == COMPRESS_MODE_DELTA) ? ADAPT_METHOD_DUP :
ADAPT_METHOD_ZERO;
}
if ((Ok = (BOOL)(pRTLScans->cEmptyDup == 0xFFFF)) ||
((pPDev->cbBufferBytes + Count) > MAX_ADAPT_SIZE)) {
if (!(Ok = FlushAdaptBuf(pPDev, pRTLScans, Ok))) {
return(FALSE);
}
//
// Because the Seed ROW back to zero, we must re-do again
//
if (Count = RTLCompression(pbSrc,
pbSeedRow,
pbOrgDst,
Size,
&AdaptMethod)) {
if (Count < 0) {
pbDst = pbSrc;
Count = -Count;
}
} else {
AdaptMethod = (AdaptMethod == COMPRESS_MODE_DELTA) ?
ADAPT_METHOD_DUP : ADAPT_METHOD_ZERO;
}
} else {
Ok = TRUE;
}
if (AdaptMethod != pRTLScans->AdaptMethod) {
if (pRTLScans->cEmptyDup) {
SET_ADAPT_CONTROL(pPDev,
pRTLScans->AdaptMethod,
pRTLScans->cEmptyDup);
pRTLScans->cEmptyDup = 0;
}
pRTLScans->AdaptMethod = AdaptMethod;
}
if (Count) {
SET_ADAPT_CONTROL(pPDev, pRTLScans->AdaptMethod, Count);
OutputBytes(pPDev, pbDst, Count);
} else {
++(pRTLScans->cEmptyDup);
}
return(Ok);
}
BOOL
OutputRTLScans(
PPDEV pPDev,
LPBYTE pbPlane1,
LPBYTE pbPlane2,
LPBYTE pbPlane3,
PRTLSCANS pRTLScans
)
/*++
Routine Description:
This function will output one scan line of RTL data and compressed if
necessary
Arguments:
pPDev - Pointer to our PDEV
pbPlane1 - First plane scan data
pbPlane2 - 2nd plane scan data
pbPlane3 - 3rd plane scan data
Return Value:
BOOLEAN
Author:
18-Feb-1994 Fri 15:52:42 created -by- Daniel Chou (danielc)
21-Feb-1994 Mon 13:20:00 updated -by- Daniel Chou (danielc)
Make if output faster in scan line output
16-Mar-1994 Wed 15:38:23 updated -by- Daniel Chou (danielc)
Update so the source mask is restored after mask
Revision History:
--*/
{
LPBYTE pbCurScan;
LPBYTE pbCompress;
LPBYTE pbScans[3];
RTLSCANS RTLScans;
LONG Count;
UINT i;
BYTE EndGrafCH;
static BYTE BegGrafCmd[] = { 0x1B, '*', 'b' };
if (PLOT_CANCEL_JOB(pPDev)) {
PLOTWARN(("OutputRTLScans: JOB CANCELD. exit NOW"));
pRTLScans->Flags &= ~RTLSF_MORE_SCAN;
return(TRUE);
}
//
// If we are at last scan line then turn the flag off so that we can exit
//
if (!(--pRTLScans->cScans)) {
pRTLScans->Flags &= ~RTLSF_MORE_SCAN;
}
RTLScans = *pRTLScans;
Count = (LONG)(RTLScans.cxBytes - 1);
*(pbPlane1 + Count) &= RTLScans.Mask;
if ((i = (UINT)RTLScans.Planes) > 1) {
*(pbPlane2 + Count) &= RTLScans.Mask;
*(pbPlane3 + Count) &= RTLScans.Mask;
pbScans[2] = pbPlane1;
pbScans[1] = pbPlane2;
pbScans[0] = pbPlane3;
} else {
pbScans[0] = pbPlane1;
}
while (i--) {
EndGrafCH = (i) ? 'V' : 'W';
pbCurScan = pbScans[i];
if (RTLScans.CompressMode == COMPRESS_MODE_BLOCK) {
OutputBytes(pPDev, pbCurScan, RTLScans.cxBytes);
} else if (RTLScans.CompressMode == COMPRESS_MODE_ADAPT) {
AdaptCompression(pPDev,
pRTLScans,
pbCurScan,
RTLScans.pbSeedRows[i],
RTLScans.pbCompress,
RTLScans.cxBytes);
} else {
if ((Count = RTLCompression(pbCurScan,
RTLScans.pbSeedRows[i],
pbCompress = RTLScans.pbCompress,
RTLScans.cxBytes,
&(pRTLScans->CompressMode))) < 0) {
pbCompress = pbCurScan;
Count = RTLScans.cxBytes;
}
//
// Now output graphic header
//
OutputBytes(pPDev, BegGrafCmd, sizeof(BegGrafCmd));
//
// If we change compress mode then do it now and record the change
//
if (pRTLScans->CompressMode != RTLScans.CompressMode) {
PLOTDBG(DBG_OUTRTLSCAN, ("OutputRTLScan: Switch CompressMode from %ld to %ld",
(DWORD)RTLScans.CompressMode,
(DWORD)pRTLScans->CompressMode));
RTLScans.CompressMode = pRTLScans->CompressMode;
OutputFormatStr(pPDev, "#dm", (LONG)RTLScans.CompressMode);
}
OutputLONGParams(pPDev, &Count, 1, 'd');
OutputBytes(pPDev, &EndGrafCH, 1);
if (Count) {
OutputBytes(pPDev, pbCompress, Count);
}
}
}
return(TRUE);
}