|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name: xlraster.cpp
Abstract:
Implementation of PCLXL raster mode
Functions:
PCLXLSetCursor PCLXLSendBitmap PCLXLFreeRaster PCLXLResetPalette
Environment:
Windows Whistler
Revision History:
09/22/00 Created it.
--*/
#include "lib.h"
#include "gpd.h"
#include "winres.h"
#include "pdev.h"
#include "common.h"
#include "xlpdev.h"
#include "pclxle.h"
#include "pclxlcmd.h"
#include "xldebug.h"
#include "xlgstate.h"
#include "xloutput.h"
#include "xlbmpcvt.h"
#include "pclxlcmn.h"
#include "xlraster.h"
//
// XLRASTER data structure
// The pointer is stored in pPDev->pVectorPDEV in case of kPCLXL_RASTER.
//
typedef struct _XLRASTER { XLOutput *pOutput; PBYTE pubDstBuff; DWORD dwDstBuffSize; PBYTE pubRLEBuff; DWORD dwRLEBuffSize; BOOL bSentPalette; } XLRASTER, *PXLRASTER;
//
// Local function prototypes
//
extern BOOL BFindWhetherColor( IN PDEV *pPDev);
//
// Functions
//
extern "C" HRESULT PCLXLSendBitmap( PDEVOBJ pdevobj, ULONG ulInputBPP, LONG lHeight, LONG lcbScanlineWidth, INT iLeft, INT iRight, PBYTE pbData, PDWORD pdwcbOut) /*++
Routine Description:
Send bitmap
Arguments:
pdevobj - a pointer to DEVOBJ ulInputBPP - input bits per pixel lHeight - height in pixel lcbScanlineWidth - scanline with in byte iLeft - left edge of scaline to print iRight - right edge of scanline to print pbData - a pointer to bitmap data pdwcbOut - a pointer to a DWORD buffer to store the size of written data
Return Value:
S_OK if succeeded. Otherwise S_FALSE or E_UNEXPECTED.
Note:
--*/ { LONG lScanline, lWidth; ULONG ulOutputBPP; DWORD dwI, dwBufSize, dwLenNormal, dwLenRLE, dwcbLineSize, dwcbBmpSize; PDWORD pdwLen; PBYTE pubSrc, pBufNormal, pBufRLE, pBuf, pBmpSize; ColorMapping CMapping; XLOutput *pOutput; INT iBitmapFormat; OutputFormat OutputF; HRESULT hRet;
//
// Parameter varidation
//
if (NULL == pdevobj || NULL == pdwcbOut) { ERR(("PCLXLSendBitmap: Invalid parameters.\n")); return E_UNEXPECTED; }
PXLRASTER pXLRaster = (PXLRASTER)(((PPDEV)pdevobj)->pVectorPDEV);
//
// Allocate XLRASTER
// Will be freed in RMDisablePDEV.
//
if (NULL == pXLRaster) { pXLRaster = (PXLRASTER)MemAllocZ(sizeof(XLRASTER)); ((PPDEV)pdevobj)->pVectorPDEV = (PVOID) pXLRaster;
if (NULL == pXLRaster) { ERR(("PCLXLSendBitmap: Memory allocation failed.\n")); return E_UNEXPECTED; }
pXLRaster->pOutput = new XLOutput;
if (NULL == pXLRaster->pOutput) { ERR(("PCLXLSendBitmap: XLOutput initialization failed.\n")); return E_UNEXPECTED; }
pOutput = pXLRaster->pOutput; pOutput->SetResolutionForBrush(((PPDEV)pdevobj)->ptGrxRes.x);
ColorDepth CD; if (BFindWhetherColor((PDEV*)pdevobj)) { if (((PDEV*)pdevobj)->pColorModeEx && ((PDEV*)pdevobj)->pColorModeEx->dwPrinterBPP == 24) { CD = e24Bit; } else { CD = e8Bit; } } else { CD = e8Bit; }
pOutput->SetDeviceColorDepth(CD); } else { pOutput = pXLRaster->pOutput; }
//
// Set source transparent mode
//
pOutput->SetPaintTxMode(eOpaque); pOutput->SetSourceTxMode(eOpaque);
//
// Get Output format and input format
//
iBitmapFormat = (INT)NumToBPP(ulInputBPP); DetermineOutputFormat(NULL, pOutput->GetDeviceColorDepth(), iBitmapFormat, &OutputF, &ulOutputBPP);
//
// DetermineOutputFormat check if pxlo is available. In this raster case,
// pxlo is always NULL and it needs to use 1bpp output.
//
if (iBitmapFormat == e1bpp) { OutputF = eOutputPal; ulOutputBPP = 1; }
//
// Set CMapping.
// Send palette for 1BPP halftone image for B&W printers.
// Palette is sent per page for XL Raster mode.
//
if (ulOutputBPP == 1) { if (!pXLRaster->bSentPalette) { ColorDepth CDepth = e8Bit; //
// Hardcoded black and white palette for XL RASTER.
//
DWORD adwColorTable[2] = {0x00ffffff, 0x0}; pOutput->SetColorSpace(eGray); pOutput->SetPaletteDepth(CDepth); pOutput->SetPaletteData(CDepth, 2, adwColorTable); pOutput->Send_cmd(eSetColorSpace); pXLRaster->bSentPalette = TRUE;
}
//
// Set index pixel (palette) for black and white printer
//
CMapping = eIndexedPixel; } else { //
// Initialize pixel mapping.
//
CMapping = eDirectPixel; }
//
// Get height, width, and scanline size.
//
// The number of bytes in a scaline.
//
dwcbLineSize = lcbScanlineWidth;
//
// The number of pixel in a scanline
// lWidth = lcbScanlineWidth / (ulInputBPP / 8);
//
lWidth = lcbScanlineWidth * 8 / ulInputBPP;
//
// Buffer size
// The size of scaline has to be DWORD align.
//
// height x width + header + endimage
// width has to be DWORD-aligned.
//
dwBufSize = lHeight * (((lWidth * ulOutputBPP + 31) >> 5 ) << 2) + DATALENGTH_HEADER_SIZE + sizeof(PCLXL_EndImage);
//
// BeginImage
//
pOutput->BeginImage( CMapping, ulOutputBPP, lWidth, lHeight, lWidth, lHeight);
//
// Normal and RLE destination bitmap buffer allocation.
//
// Check if the normal and RLE destination buffer is available and the size
// is larger than required size. Otherwise, we can reused the buffer.
//
if (NULL == pXLRaster->pubDstBuff || NULL == pXLRaster->pubRLEBuff || pXLRaster->dwDstBuffSize < dwBufSize) { if (NULL != pXLRaster->pubDstBuff && pXLRaster->dwDstBuffSize < dwBufSize) { MemFree(pXLRaster->pubDstBuff); pXLRaster->pubDstBuff = NULL; pXLRaster->dwDstBuffSize = 0; } if (NULL != pXLRaster->pubRLEBuff && pXLRaster->dwRLEBuffSize < dwBufSize) { MemFree(pXLRaster->pubRLEBuff); pXLRaster->pubRLEBuff = NULL; pXLRaster->dwRLEBuffSize = 0; } if (NULL == (pBufNormal = (PBYTE)MemAllocZ(dwBufSize))) { ERR(("PCLXLSendBitmap: Memory allocation failed.\n")); pOutput->Delete(); pXLRaster->dwDstBuffSize = 0; return E_UNEXPECTED; } else { pXLRaster->pubDstBuff = pBufNormal; pXLRaster->dwDstBuffSize = dwBufSize; } if (NULL == (pBufRLE = (PBYTE)MemAllocZ(dwBufSize))) { ERR(("PCLXLSendBitmap: Memory allocation failed.\n")); if (NULL != pBufNormal) { MemFree(pXLRaster->pubDstBuff); pXLRaster->pubDstBuff = NULL; } pOutput->Delete(); pXLRaster->dwRLEBuffSize = 0; return E_UNEXPECTED; } else { pXLRaster->pubRLEBuff = pBufRLE; pXLRaster->dwRLEBuffSize = dwBufSize; } } else { pBufNormal = pXLRaster->pubDstBuff; pBufRLE = pXLRaster->pubRLEBuff; }
//
// Convert src bitmap to dst bitmap
//
CompressMode CMode; BMPConv BMPC; PBYTE pubDst; DWORD dwSize;
//
// Setup BMPConv
//
BMPC.BSetInputBPP((BPP)iBitmapFormat); BMPC.BSetOutputBPP(NumToBPP(ulOutputBPP)); BMPC.BSetOutputBMPFormat(OutputF);
//
// Conversion.
// Take two steps. No compression and RLE compression. At the end, compare
// the size of buffers and decide which one we take.
//
#define NO_COMPRESSION 0
#define RLE_COMPRESSION 1
for (dwI = 0; dwI < 2; dwI ++) { if (NO_COMPRESSION == dwI) { VERBOSE(("PCLXLSendBitmap(): No-compres\n")); pBuf = pBufNormal; pdwLen = &dwLenNormal; CMode = eNoCompression; } else if (RLE_COMPRESSION == dwI) { VERBOSE(("PCLXLSendBitmap(): RLE-compres\n")); pBuf = pBufRLE; pdwLen = &dwLenRLE; CMode = eRLECompression; }
lScanline = lHeight;
hRet = S_OK;
//
// Set pubSrc
//
pubSrc = pbData;
//
// Set dataLength tag
//
*pBuf = PCLXL_dataLength;
//
// Get the pointer to the buffer where we store the size of data.
//
pBmpSize = pBuf + 1; pBuf += DATALENGTH_HEADER_SIZE; *pdwLen = DATALENGTH_HEADER_SIZE;
//
// Set compression flag in BMPConv
//
BMPC.BSetCompressionType(CMode);
dwcbBmpSize = 0;
//
// Scaline base conversion
//
while (lScanline-- > 0 && dwcbBmpSize + *pdwLen < dwBufSize) { pubDst = BMPC.PubConvertBMP(pubSrc , dwcbLineSize); dwSize = BMPC.DwGetDstSize(); VERBOSE(("PCLXLSendBitmap[0x%x]: dwDstSize=0x%x\n", lScanline, dwSize));
if ( dwcbBmpSize + dwSize + DATALENGTH_HEADER_SIZE + sizeof(PCLXL_EndImage) > dwBufSize || NULL == pubDst) { VERBOSE(("PCLXLSendBitmap: Mode(%d) buffer size is too small.\n", dwI)); hRet = E_UNEXPECTED; break; }
memcpy(pBuf, pubDst, dwSize); dwcbBmpSize += dwSize; pBuf += dwSize;
pubSrc += lcbScanlineWidth; }
if (hRet == S_OK && lScanline > 0 || hRet != S_OK) { hRet = S_FALSE; VERBOSE(("ComonRopBlt: Mode(%d) conversion failed.\n", dwI)); }
if (hRet == S_OK) { if (dwI == NO_COMPRESSION) { //
// Scanline on PCL-XL has to be DWORD align.
//
// count byte of scanline = lWidth * ulOutputBPP / 8
//
dwcbBmpSize = lHeight * (((lWidth * ulOutputBPP + 31) >> 5 ) << 2); }
//
// Set the size of bitmap
//
CopyMemory(pBmpSize, &dwcbBmpSize, sizeof(dwcbBmpSize)); *pdwLen += dwcbBmpSize;
//
// Set endimage command
//
*pBuf = PCLXL_EndImage; (*pdwLen) ++; } else { //
// Conversion failed!
//
*pdwLen = 0; } } #undef NO_COMPRESSION
#undef RLE_COMPRESSION
//
// Compare which mode is smaller, RLE or non-compression.
// Take smaller one.
//
DWORD dwBitmapSize;
if (dwLenRLE != 0 && dwLenRLE < dwLenNormal) { VERBOSE(("PCLXLSendBitmap RLE: dwSize=0x%x\n", dwLenRLE)); pBuf = pBufRLE; pdwLen = &dwLenRLE; CMode = eRLECompression; hRet = S_OK; } else if (dwLenNormal != 0) { VERBOSE(("PCLXLSendBitmap Normal: dwSize=0x%x\n", dwLenNormal)); pBuf = pBufNormal; pdwLen = &dwLenNormal; CMode = eNoCompression; hRet = S_OK; } else { pBuf = NULL; pdwLen = NULL; CMode = eInvalidValue; hRet = E_FAIL; }
if (pBuf) { //
// ReadImage and send the bitmap.
//
pOutput->ReadImage(lHeight, CMode); pOutput->Flush(pdevobj);
CopyMemory(&dwBitmapSize, pBuf + 1, sizeof(DWORD));
if (dwBitmapSize > 0xff) { //
// dataLength
// size (uin32) (bitmap size)
// DATA
// EndImage
//
WriteSpoolBuf((PPDEV)pdevobj, pBuf, *pdwLen); } else { //
// dataLength
// size (byte) (bitmap size)
// DATA
// EndImage
//
pBuf += 3; *pBuf = PCLXL_dataLengthByte; *(pBuf + 1) = (BYTE)dwBitmapSize; WriteSpoolBuf((PPDEV)pdevobj, pBuf, (*pdwLen) - 3); }
*pdwcbOut = *pdwLen;
} else { pOutput->Delete(); } return hRet; }
extern "C" HRESULT PCLXLSetCursor( PDEVOBJ pdevobj, ULONG ulX, ULONG ulY) /*++
Routine Description:
Send cursor move command
Arguments:
pdevobj - a pointer to DEVOBJ ulX - X position ulY - Y position
Return Value:
S_OK if succeeded. Otherwise S_FALSE or E_UNEXPECTED.
Note:
--*/ { //
// Parameter varidation
//
if (NULL == pdevobj) { return E_UNEXPECTED; }
PXLRASTER pXLRaster = (PXLRASTER)(((PPDEV)pdevobj)->pVectorPDEV);
//
// Allocate XLRASTER
// Will be freed in RMDisablePDEV.
//
if (NULL == pXLRaster) { pXLRaster = (PXLRASTER)MemAllocZ(sizeof(XLRASTER)); ((PPDEV)pdevobj)->pVectorPDEV = (PVOID) pXLRaster;
if (NULL == pXLRaster) { return E_UNEXPECTED; }
pXLRaster->pOutput = new XLOutput;
if (NULL == pXLRaster->pOutput) { ERR(("PCLXLSendBitmap: XLOutput initialization failed.\n")); return E_UNEXPECTED; }
pXLRaster->pOutput->SetResolutionForBrush(((PPDEV)pdevobj)->ptGrxRes.x);
ColorDepth CD; if (BFindWhetherColor((PDEV*)pdevobj)) { if (((PDEV*)pdevobj)->pColorModeEx && ((PDEV*)pdevobj)->pColorModeEx->dwPrinterBPP == 24) { CD = e24Bit; } else { CD = e8Bit; } } else { CD = e8Bit; } pXLRaster->pOutput->SetDeviceColorDepth(CD); }
//
// Send cusor move command
//
return pXLRaster->pOutput->SetCursor(ulX, ulY); }
extern "C" HRESULT PCLXLFreeRaster( PDEVOBJ pdevobj) /*++
Routine Description:
Free XLRASTER
Arguments:
pdevobj - a pointer to DEVOBJ
Return Value:
S_OK if succeeded. Otherwise S_FALSE or E_UNEXPECTED.
Note:
--*/ { //
// Parameter varidation
//
if (NULL == pdevobj) { return E_UNEXPECTED; }
PXLRASTER pXLRaster = (PXLRASTER)(((PPDEV)pdevobj)->pVectorPDEV);
if (pXLRaster->pubRLEBuff) { MemFree(pXLRaster->pubRLEBuff); pXLRaster->pubRLEBuff = NULL; } if (pXLRaster->pubDstBuff) { MemFree(pXLRaster->pubDstBuff); pXLRaster->pubDstBuff = NULL; }
delete pXLRaster->pOutput;
MemFree(pXLRaster); ((PPDEV)pdevobj)->pVectorPDEV = NULL;
return S_OK; }
extern "C" HRESULT PCLXLResetPalette( PDEVOBJ pdevobj) /*++
Routine Description:
Reset palette flag in XLRASTER Palette has to be set per page.
Arguments:
pdevobj - a pointer to DEVOBJ
Return Value:
S_OK if succeeded. Otherwise S_FALSE or E_UNEXPECTED.
Note:
--*/ { //
// Parameter varidation
//
if (NULL == pdevobj) { return E_UNEXPECTED; }
PXLRASTER pXLRaster = (PXLRASTER)(((PPDEV)pdevobj)->pVectorPDEV);
if (pXLRaster) { pXLRaster->bSentPalette = FALSE; return S_OK; } else { return S_FALSE; } }
|