Sample Code
Windows Driver Samples/ MSPLOT Plotter Driver Sample/ C++/ plotter/ compress.c/
/*++ 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( _In_reads_bytes_(Size) LPBYTE pbSrc, _In_reads_bytes_(Size) LPBYTE pbSeedRow, _Out_writes_bytes_(Size) 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 = 0; 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 // if ((pbDstEnd < pbDst ) || (pbDstEnd - pbDst < (LONG_PTR)cReplace) ) { PLOTDBG(DBG_DELTA, ("CompressToDelta: Destination buffer size not big enough, give up")); return(-Size); } 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( _In_reads_bytes_(Size) LPBYTE pbSrc, _Out_writes_bytes_(Size) 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( _In_reads_bytes_(Size) LPBYTE pbSrc, _Inout_updates_bytes_(Size) LPBYTE pbSeedRow, _Out_writes_bytes_(Size) 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 = 0; 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, _In_reads_bytes_(Size) LPBYTE pbSrc, _Inout_updates_bytes_(Size) LPBYTE pbSeedRow, _Out_writes_bytes_(Size) 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 if (1 == i) { pbScans[0] = pbPlane1; } else { return (FALSE); } 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); }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials