Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1251 lines
29 KiB

/*++
Copyright (c) 1990-2003 Microsoft Corporation
Module Name:
compress.c
Abstract:
This module contains all data compression functions which analyze source
scan line data and determines which compressin method (if any) is best to
send the RTL data to the target device with a minimum number of bytes.
Author:
18-Feb-1994 Fri 09:50:08 created
[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 flushes the adaptive encoding buffer mode.
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
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 completes processing of the SCANS data.
Arguments:
pPDev - Pointer to our PDEV
pRTLScans - Pointer to the RTLSCANS data structure to be initialized
Return Value:
TRUE if sucessful, FALSE if failed
Author:
22-Feb-1994 Tue 12:14:17 created
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 initializes the RTLSCANS structure and determines which
compression of the available compressions is best.
Arguments:
pPDev - Pointer to our PDEV
pRTLScans - Pointer to the RTLSCANS data structure to be initialized
cx - Width of pixel per scans
cy - Height of pixel data
MonoBmp - True if a monochrome bitmap.
Return Value:
TRUE if sucessful, FALSE if failed
Author:
22-Feb-1994 Tue 12:14:17 created
11-Mar-1994 Fri 19:23:34 updated
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 first need to flush the current output buffer in order to make
// room for the Adaptive 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 compresses the input scan data with delta encoding, by
determining the differences from the current 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 the 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
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.
// After we find the first difference, between the seed row
// and the current row pbTmp becomes the first byte of the
// source data that is different than the seed.
//
Offset = (LONG)(pbSrc - pbTmp);
pbTmp = pbSrc;
}
DoReplace = (BOOL)((cReplace >= DELTA_MAX_ONE_REPLACE) ||
(!cSrcBytes));
} else {
DoReplace = (BOOL)cReplace;
}
if (DoReplace) {
//
// At the very least we need one command byte and a 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, NOTE: We must
// send an extra 0 if the offset is equal 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 takes the source data and compresses it into the TIFF
packbits format into the destination buffer pbDst.
The TIFF packbits compression format consists of a CONTROL byte followed
by the BYTE data. The CONTROL byte has the following range.
-1 to -127 = The data byte followed by the control byte is repeated
( -(Control Byte) + 1 ) times.
0 to 127 = There are 1 to 128 literal bytes following the CONTROL byte.
The count is = (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
24-Feb-1994 Thu 10:43:01 updated
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 space
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)) {
//
// Check to see if we are repeating ZERO's to the end of the
// scan line, if such is the case. Simply mark the line as
// autofill ZERO to the end, 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 we have repeating data, but not enough to make it
// worthwhile to encode, then treat the data as literal and
// don't compress.
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 the most efficient method to send. If we have
// remaining repeated bytes less than TIFF_MIN_REPEATS then
// we want to skip those bytes and use literal for the next run
// since that is more efficient.
//
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 determines which RTL compression method results in the
least number of bytes to send to the target device and uses 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 be
updated to a new compression mode upon return
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
Revision History:
--*/
{
LONG cDelta;
LONG cTiff;
LONG RetSize;
BYTE CompressMode;
if ((cDelta = CompressToDelta(pbSrc, pbSeedRow, pbDst, Size)) == 0) {
//
// Exact duplicate of the previous row, and seed row remained the 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 {
//
// If we are 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 was destroyed 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 current source (Original SIZE) as the new seed row
//
CopyMemory(pbSeedRow, pbSrc, Size);
return(RetSize);
}
BOOL
AdaptCompression(
PPDEV pPDev,
PRTLSCANS pRTLScans,
LPBYTE pbSrc,
LPBYTE pbSeedRow,
LPBYTE pbDst,
LONG Size
)
/*++
Routine Description:
This function implements adaptive compression, which allows the mixing
of different compression types in a higher level compression mode that
is defined ahead of time.
Arguments:
pPDev - Pointer to our PDEV
pRTLScans - Pointer to the RTLSCANS data structure
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
Revision History:
--*/
{
LPBYTE pbOrgDst;
LONG Count;
BOOL Ok;
BYTE AdaptMethod;
pbOrgDst = pbDst;
AdaptMethod = COMPRESS_MODE_ROW;
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 was reset to zero, we must recalculate it.
//
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 we are switching compression modes, do it now.
//
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 compress it if
it can.
Arguments:
pPDev - Pointer to our PDEV
pbPlane1 - First plane of scan data
pbPlane2 - 2nd plane of scan data
pbPlane3 - 3rd plane of scan data
pRTLScans - Pointer to the RTLSCANS data structure
Return Value:
BOOLEAN
Author:
18-Feb-1994 Fri 15:52:42 created
21-Feb-1994 Mon 13:20:00 updated
Make if output faster in scan line output
16-Mar-1994 Wed 15:38:23 updated
Update so the source mask so it 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 the last scan line, turn the flag off so we are forced to
// 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 changed compression modes then send the command out
// 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);
}