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.
 
 
 
 
 
 

506 lines
15 KiB

/*++
Copyright (c) 1997-1999 Microsoft Corporation
--*/
// NTRAID#NTBUG9-553896-2002/03/19-yasuho-: mandatory changes
#include "pdev.h"
#include "lgcomp.h"
//
// File: LGCOMP.C
//
// Implementations of LG compression algprithms on the
// LG "Raster 1" printers.
//
// printer command:
// <9B>I{type}#{compressed data length}{compressed data}
//
// type can be:
// <01> RLE
// <02> MHE
//
// For MHE debugging.
#define MHEDEBUG 0
//#define MHEDEBUG 1
//#define MHEDEBUGPATTERN 0x81
#define MHEDEBUGPATTERN 0xff
//
// LG RLE compression. See comments for the details.
//
// You MUST call this function with @pOutBuf is NULL at first.
// Then you can get the enough size of @pOutBuf by the return value.
// Then you should make sure if the buffer size is enough.
// Then call this function again with the actual pointer of @pOutBuf.
INT
LGCompRLE(
PBYTE pOutBuf,
PBYTE pSrcBuf, DWORD iSrcBuf,
INT iMode)
{
PBYTE pMaxSrcBuf = pSrcBuf + iSrcBuf;
INT iOutLen = 0, iRun;
BYTE jTemp;
PBYTE pSize;
// Embedd print command if requested.
if (iMode == 1) {
// LG Raster 1
if (pOutBuf) {
*pOutBuf++ = (BYTE)'\x9B';
*pOutBuf++ = (BYTE)'I';
*pOutBuf++ = COMP_RLE;
pSize = pOutBuf++;
pOutBuf++;
}
iOutLen += 5;
}
while (pSrcBuf < pMaxSrcBuf) {
// Get Run length.
jTemp = *pSrcBuf;
for (iRun = 1; pSrcBuf + iRun < pMaxSrcBuf; iRun++) {
if (*(pSrcBuf + iRun) != jTemp)
break;
}
// iRun == N means N consective bytes
// of the same value exists.
if (iRun > 1) {
// Run > 1.
while (iRun >= 0x82) {
iRun -= 0x82;
iOutLen += 2;
if (pOutBuf) {
// Mark <- 0x80,
// length = 0x82.
*pOutBuf++ = 0x80;
*pOutBuf++ = jTemp;
}
pSrcBuf += 0x82;
}
// iRun less than 3 will be output as "copy" block.
if (iRun >= 3) {
iOutLen += 2;
if (pOutBuf) {
// Mark <- 0x81 to 0xff,
// length = 0x81 to 3.
*pOutBuf++ = (0x102 - iRun);
*pOutBuf++ = jTemp;
}
}
else if (iRun > 0) {
iOutLen += (1 + iRun);
if (pOutBuf) {
*pOutBuf++ = (iRun - 1);
memcpy(pOutBuf, pSrcBuf, iRun);
pOutBuf += iRun;
}
}
pSrcBuf += iRun;
// Go to the next around.
continue;
}
// Get "different" Run length. We already know
// pSrcBuf[0] != pSrcBuf[1].
for (iRun = 1; pSrcBuf + iRun < pMaxSrcBuf; iRun++) {
if ((pSrcBuf + iRun + 1 < pMaxSrcBuf) &&
(*(pSrcBuf + iRun) == *(pSrcBuf + iRun + 1))) {
break;
}
}
for (; iRun >= 0x80; iRun -= 0x80) {
iOutLen += (1 + 0x80);
if (pOutBuf) {
// Mark <- 0x7f,
// copy = 0x80.
*pOutBuf++ = 0x7f;
memcpy(pOutBuf, pSrcBuf, 0x80);
pOutBuf += 0x80;
}
pSrcBuf += 0x80;
}
if (iRun > 0) {
iOutLen += (1 + iRun);
if (pOutBuf) {
// Mark <- 0x7e to 0,
// copy = 0x7f to 1.
*pOutBuf++ = (iRun - 1);
memcpy(pOutBuf, pSrcBuf, iRun);
pOutBuf += iRun;
}
pSrcBuf += iRun;
}
}
// Embed size information if requested.
if (iMode == 1) {
if (pOutBuf) {
*pSize++ = (BYTE)((iOutLen - 5) >> 8);
*pSize++ = (BYTE)(iOutLen - 5);
}
}
return iOutLen;
}
//
// MHE compression. See comments for the details.
//
typedef struct {
DWORD cswd; /* compressing signed word */
INT vbln; /* cswd's valid bits length, count from MSB */
} ENCfm; /* ENC. form */
ENCfm pWhiteTermTbl[64] = { /* Terminating Code Table (White)*/
{0x35000000, 8},{0x1c000000, 6},{0x70000000, 4},{0x80000000, 4},
{0xb0000000, 4},{0xc0000000, 4},{0xe0000000, 4},{0xf0000000, 4},
{0x98000000, 5},{0xa0000000, 5},{0x38000000, 5},{0x40000000, 5},
{0x20000000, 6},{0x0c000000, 6},{0xd0000000, 6},{0xd4000000, 6},
{0xa8000000, 6},{0xac000000, 6},{0x4e000000, 7},{0x18000000, 7},
{0x10000000, 7},{0x2e000000, 7},{0x06000000, 7},{0x08000000, 7},
{0x50000000, 7},{0x56000000, 7},{0x26000000, 7},{0x48000000, 7},
{0x30000000, 7},{0x02000000, 8},{0x03000000, 8},{0x1a000000, 8},
{0x1b000000, 8},{0x12000000, 8},{0x13000000, 8},{0x14000000, 8},
{0x15000000, 8},{0x16000000, 8},{0x17000000, 8},{0x28000000, 8},
{0x29000000, 8},{0x2a000000, 8},{0x2b000000, 8},{0x2c000000, 8},
{0x2d000000, 8},{0x04000000, 8},{0x05000000, 8},{0x0a000000, 8},
{0x0b000000, 8},{0x52000000, 8},{0x53000000, 8},{0x54000000, 8},
{0x55000000, 8},{0x24000000, 8},{0x25000000, 8},{0x58000000, 8},
{0x59000000, 8},{0x5a000000, 8},{0x5b000000, 8},{0x4a000000, 8},
{0x4b000000, 8},{0x32000000, 8},{0x33000000, 8},{0x34000000, 8}
};
ENCfm pBlackTermTbl[64] = { /* Terminating Code Table (Black) */
{0x0dc00000, 10},{0x40000000, 3},{0xc0000000, 2},{0x80000000, 2},
{0x60000000, 3},{0x30000000, 4},{0x20000000, 4},{0x18000000, 5},
{0x14000000, 6},{0x10000000, 6},{0x08000000, 7},{0x0a000000, 7},
{0x0e000000, 7},{0x04000000, 8},{0x07000000, 8},{0x0c000000, 9},
{0x05c00000, 10},{0x06000000, 10},{0x02000000, 10},{0x0ce00000, 11},
{0x0d000000, 11},{0x0d800000, 11},{0x06e00000, 11},{0x05000000, 11},
{0x02e00000, 11},{0x03000000, 11},{0x0ca00000, 12},{0x0cb00000, 12},
{0x0cc00000, 12},{0x0cd00000, 12},{0x06800000, 12},{0x06900000, 12},
{0x06a00000, 12},{0x06b00000, 12},{0x0d200000, 12},{0x0d300000, 12},
{0x0d400000, 12},{0x0d500000, 12},{0x0d600000, 12},{0x0d700000, 12},
{0x06c00000, 12},{0x06d00000, 12},{0x0da00000, 12},{0x0db00000, 12},
{0x05400000, 12},{0x05500000, 12},{0x05600000, 12},{0x05700000, 12},
{0x06400000, 12},{0x06500000, 12},{0x05200000, 12},{0x05300000, 12},
{0x02400000, 12},{0x03700000, 12},{0x03800000, 12},{0x02700000, 12},
{0x02800000, 12},{0x05800000, 12},{0x05900000, 12},{0x02b00000, 12},
{0x02c00000, 12},{0x05a00000, 12},{0x06600000, 12},{0x06700000, 12}
};
ENCfm pWhiteMkupTbl[41] = { /* Make-up Code Table (White) */
{0x00100000, 12},{0xd8000000, 5},{0x90000000, 5},{0x5c000000, 6},
{0x6e000000, 7},{0x36000000, 8},{0x37000000, 8},{0x64000000, 8},
{0x65000000, 8},{0x68000000, 8},{0x67000000, 8},{0x66000000, 9},
{0x66800000, 9},{0x69000000, 9},{0x69800000, 9},{0x6a000000, 9},
{0x6a800000, 9},{0x6b000000, 9},{0x6b800000, 9},{0x6c000000, 9},
{0x6c800000, 9},{0x6d000000, 9},{0x6d800000, 9},{0x4c000000, 9},
{0x4c800000, 9},{0x4d000000, 9},{0x60000000, 6},{0x4d800000, 9},
{0x01000000, 11},{0x01800000, 11},{0x01a00000, 11},{0x01200000, 12},
{0x01300000, 12},{0x01400000, 12},{0x01500000, 12},{0x01600000, 12},
{0x01700000, 12},{0x01c00000, 12},{0x01d00000, 12},{0x01e00000, 12},
{0x01f00000, 12}
};
ENCfm pBlackMkupTbl[41] = { /* Make-up Code Table (Black) */
{0x00100000, 12},{0x03c00000, 10},{0x0c800000, 12},{0x0c900000, 12},
{0x05b00000, 12},{0x03300000, 12},{0x03400000, 12},{0x03500000, 12},
{0x03600000, 13},{0x03680000, 13},{0x02500000, 13},{0x02580000, 13},
{0x02600000, 13},{0x02680000, 13},{0x03900000, 13},{0x03980000, 13},
{0x03a00000, 13},{0x03a80000, 13},{0x03b00000, 13},{0x03b80000, 13},
{0x02900000, 13},{0x02980000, 13},{0x02a00000, 13},{0x02a80000, 13},
{0x02d00000, 13},{0x02d80000, 13},{0x03200000, 13},{0x03280000, 13},
{0x01000000, 11},{0x01800000, 11},{0x01a00000, 11},{0x01200000, 12},
{0x01300000, 12},{0x01400000, 12},{0x01500000, 12},{0x01600000, 12},
{0x01700000, 12},{0x01c00000, 12},{0x01d00000, 12},{0x01e00000, 12},
{0x01f00000, 12}
};
#define DIV8(k) ((k) >> 3)
#define MOD8(k) ((k) & 7)
#define MUL8(k) ((k) << 3)
#define DIV64(k) ((k) >> 6)
#define MOD64(k) ((k) & 63)
BOOL
ScanBits(
PBYTE pSrc,
INT iOffset,
DWORD dwMaxSrc,
PDWORD pdwRunLength
)
{
BOOL bBlack;
BYTE jTemp, jMask;
PBYTE pMaxSrc = pSrc + dwMaxSrc;
INT k;
DWORD dwRunLength = 0;
// The 1st byte.
jTemp = *pSrc++;
#if MHEDEBUG
jTemp = MHEDEBUGPATTERN;
#endif // MHEDEBUG
bBlack = ((jTemp & (0x80 >> iOffset)) != 0);
if (!bBlack) {
jTemp = ~jTemp;
}
// fill previous bits.
jTemp |= ~(0xff >> iOffset);
// ...interlim bytes.
jMask = 0xff;
for (; pSrc < pMaxSrc; pSrc++) {
if (jTemp != jMask)
break;
dwRunLength += 8;
jTemp = *pSrc;
#if MHEDEBUG
jTemp = MHEDEBUGPATTERN;
#endif // MHEDEBUG
if (!bBlack) {
jTemp = ~jTemp;
}
}
// The last byte.
jMask = ~0x80;
for (k = 0; k < 8; k++) {
if ((jTemp | jMask) != 0xff)
break;
jMask >>= 1;
}
dwRunLength += k;
// Return results to the caller.
*pdwRunLength = (dwRunLength - iOffset);
return bBlack;
}
VOID
CopyBits(
PBYTE pBuffer,
INT iOffset,
DWORD dwPattern,
INT iPatternLength
)
{
INT iNumberOfBytes, k;
DWORD dwTemp;
// Decide how many bytes we are to modify.
iNumberOfBytes = DIV8(iOffset + iPatternLength + 7);
// Make the pattern mask.
dwPattern >>= iOffset;
// Read in a byte if necessary.
if (iOffset > 0) {
dwTemp = (*pBuffer << 24);
dwTemp &= ~((DWORD)~0 >> iOffset);
}
else {
dwTemp = 0;
}
dwTemp |= dwPattern;
// Write back.
for (k = 3; k >= iNumberOfBytes; k--) {
dwTemp >>= 8;
}
for (; k >= 0; k--) {
*(pBuffer + k) = (BYTE)(dwTemp & 0xff);
dwTemp >>= 8;
}
}
// You MUST call this function with @pOutBuf is NULL at first.
// Then you can get the enough size of @pOutBuf by the return value.
// Then you should make sure if the buffer size is enough.
// Then call this function again with the actual pointer of @pOutBuf.
INT
LGCompMHE(
PBYTE pBuf,
PBYTE pSrcBuf,
DWORD dwMaxSrcBuf,
INT iMode)
{
DWORD dwSrcOffset = 0;
DWORD dwOffset = 0;
ENCfm *pMkupTbl, *pTermTbl;
DWORD dwRunLength;
INT k;
BOOL bBlack;
DWORD dwMaxSrcOffset = MUL8(dwMaxSrcBuf);
PBYTE pSize;
DWORD dwLength;
// Embed print command if requested.
if (iMode == 1) {
// LG Raster 1
if (pBuf) {
*(pBuf) = (BYTE)'\x9B';
*(pBuf + 1) = (BYTE)'I';
*(pBuf + 2) = COMP_MHE;
pSize = (pBuf + 3);
// 1 byte more.
}
dwOffset += 40;
}
while (dwSrcOffset < dwMaxSrcOffset) {
bBlack = ScanBits(
(pSrcBuf + DIV8(dwSrcOffset)),
MOD8(dwSrcOffset),
DIV8(dwMaxSrcOffset - dwSrcOffset + 7),
&dwRunLength);
VERBOSE(("LGCompMHE: %d, %d, %d (%d / %d)\n",
dwOffset, dwRunLength, bBlack,
dwSrcOffset, dwMaxSrcOffset));
if (dwSrcOffset == 0 && bBlack) {
// The 1st code in the data must be white encoding data.
// So, we will insert "0 byte white run" record when the
// data does not begin with white.
dwLength = pWhiteTermTbl[0].vbln;
if (pBuf) {
CopyBits(
(pBuf + DIV8(dwOffset)),
MOD8(dwOffset),
pWhiteTermTbl[0].cswd,
dwLength);
}
dwOffset += dwLength;
}
if (dwRunLength >= 2624) {
if (pBuf) {
CopyBits(
(pBuf + DIV8(dwOffset)),
MOD8(dwOffset),
0x01f00000, 12);
}
dwOffset += 12;
if (bBlack) {
if (pBuf) {
CopyBits(
(pBuf + DIV8(dwOffset)),
MOD8(dwOffset),
0x06700000, 12);
}
dwOffset += 12;
if (pBuf) {
CopyBits(
(pBuf + DIV8(dwOffset)),
MOD8(dwOffset),
0x35000000, 8);
}
dwOffset += 8;
}
else {
if (pBuf) {
CopyBits(
(pBuf + DIV8(dwOffset)),
MOD8(dwOffset),
0x34000000, 8);
}
dwOffset += 8;
if (pBuf) {
CopyBits(
(pBuf + DIV8(dwOffset)),
MOD8(dwOffset),
0x0dc00000, 10);
}
dwOffset += 10;
}
dwRunLength -= 2623;
}
if (bBlack) {
pMkupTbl = pBlackMkupTbl;
pTermTbl = pBlackTermTbl;
}
else {
pMkupTbl = pWhiteMkupTbl;
pTermTbl = pWhiteTermTbl;
}
if (dwRunLength >= 64) {
dwLength = pMkupTbl[DIV64(dwRunLength)].vbln;
if (pBuf) {
CopyBits((pBuf + DIV8(dwOffset)),
MOD8(dwOffset),
pMkupTbl[DIV64(dwRunLength)].cswd,
dwLength);
}
dwOffset += dwLength;
}
dwLength = pTermTbl[MOD64(dwRunLength)].vbln;
if (pBuf) {
CopyBits(
(pBuf + DIV8(dwOffset)),
MOD8(dwOffset),
pTermTbl[MOD64(dwRunLength)].cswd,
dwLength);
}
dwOffset += dwLength;
// Next
dwSrcOffset += dwRunLength;
}
// Convert unit into # of bytes.
dwOffset = DIV8(dwOffset + 7);
// Embed size information if requested.
if (iMode == 1) {
if (pBuf) {
*pSize++ = (BYTE)((dwOffset - 5) >> 8);
*pSize++ = (BYTE)(dwOffset - 5);
}
}
return (INT)dwOffset;
}