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.
716 lines
16 KiB
716 lines
16 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
}
|