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.
 
 
 
 
 
 

160 lines
4.1 KiB

/*
* drc.c - Support Delta Row Compression
*/
#include "pdev.h"
// Support DRC
/*
* PutDRCData
*/
static PBYTE
PutDRCData(
PBYTE pData,
DWORD dwOffset,
DWORD dwSize,
PBYTE pOut,
PBYTE pOutEnd)
{
DWORD dwCount, dwOff;
while (dwSize > 0) {
dwCount = min(dwSize, 8);
// offset
if (dwOffset > 30) {
if (pOut >= pOutEnd)
return NULL;
*pOut++ = (BYTE)(((dwCount - 1) << 5) + 31);
dwOffset -= 31;
while (dwOffset >= 255) {
dwOff = min(dwOffset, 255);
if (pOut >= pOutEnd)
return NULL;
*pOut++ = (BYTE)dwOff;
dwOffset -= dwOff;
}
if (pOut >= pOutEnd)
return NULL;
*pOut++ = (BYTE)dwOffset;
} else {
if (pOut >= pOutEnd)
return NULL;
*pOut++ = (BYTE)(((dwCount - 1) << 5) + dwOffset);
}
dwOffset = 0;
// data
if (&pOut[dwCount] >= pOutEnd)
return NULL;
CopyMemory(pOut, pData, dwCount);
pOut += dwCount;
pData += dwCount;
dwSize -= dwCount;
}
return pOut;
}
/*
* OEMCompression
*/
INT APIENTRY
OEMCompression(
PDEVOBJ pdevobj,
PBYTE pInBuf,
PBYTE pOutBuf,
DWORD dwInLen,
DWORD dwOutLen)
{
PLIPSPDEV pOEM = (PLIPSPDEV)pdevobj->pdevOEM;
PBYTE pPre, pIn, pInEnd, pOut, pOutEnd, pStart, pBegin;
PBYTE pPre0, pIn0, pOutHead, pOut0, pOutEnd0;
DWORD dwI, dwLen, dwSize, dwOffset, dwCount;
INT rc;
#ifdef LBP_2030
if (pOEM->fcolor == COLOR) // DRC can't support on 8color mode.
return -1;
#endif
// NTRAID#NTBUG9-571824-2002/03/09-yasuho-:
// Possible buffer overrun if integer overflow was occured.
if (pOEM->dwBmpWidth == 0 || pOEM->dwBmpHeight == 0 ||
pOEM->dwBmpWidth > dwInLen || pOEM->dwBmpHeight > dwInLen ||
(pOEM->dwBmpWidth * pOEM->dwBmpHeight) != dwInLen)
return -1;
// Do DRC compression
rc = -1;
pPre = NULL;
pIn = pInBuf;
pOut = pOutBuf;
pOutEnd = &pOut[dwOutLen];
for (dwI = 0; dwI < pOEM->dwBmpHeight; dwI++) {
pStart = pBegin = pIn;
pInEnd = &pIn[pOEM->dwBmpWidth];
pOutHead = pOut;
while (pIn < pInEnd) {
if (pPre == NULL) {
if (*pIn == 0) {
pIn++;
continue;
}
} else if (*pPre == *pIn) {
pPre++, pIn++;
continue;
}
pIn0 = pIn;
if (pPre == NULL) {
do {
pIn++;
} while (pIn < pInEnd && *pIn);
} else {
do {
pPre++, pIn++;
} while (pIn < pInEnd && *pPre != *pIn);
}
dwOffset = (DWORD)(pIn0 - pStart);
dwSize = (DWORD)(pIn - pIn0);
if (!(pOut = PutDRCData(pIn0, dwOffset, dwSize, pOut, pOutEnd)))
goto out;
pStart = pIn;
}
// Insert length of raster data
if (pOut == pOutHead) {
// identical
if (pOut >= pOutEnd)
goto out;
*pOut++ = 0;
} else {
dwSize = (DWORD)(pOut - pOutHead);
dwCount = (dwSize / 255) + 1;
if (&pOut[dwCount] >= pOutEnd)
goto out;
pPre0 = pOut;
pOut0 = pOut = &pOut[dwCount];
while (pPre0 >= pOutHead)
*--pOut0 = *--pPre0;
pOut0 = pOutHead;
while (dwSize >= 255) {
dwLen = min(dwSize, 255);
*pOut0++ = (BYTE)dwLen;
dwSize -= dwLen;
}
*pOut0++ = (BYTE)dwSize;
}
// set to previous raster
pPre = pBegin;
}
rc = (INT)(pOut - pOutBuf);
out:
return rc;
}