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
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;
|
|
}
|
|
|