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.
2995 lines
77 KiB
2995 lines
77 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
xlddi.cpp
|
|
|
|
Abstract:
|
|
|
|
Implementation of PCLXL drawing DDI entry points
|
|
|
|
Functions:
|
|
|
|
PCLXLBitBlt
|
|
PCLXLStretchBlt
|
|
PCLXLStretchBltROP
|
|
PCLXLCopyBits
|
|
PCLXLPlgBlt
|
|
PCLXLAlphaBlend
|
|
PCLXLGradientFill
|
|
PCLXLTextOut
|
|
PCLXLStrokePath
|
|
PCLXLFillPath
|
|
PCLXLStrokeAndFillPath
|
|
PCLXLRealizeBrush
|
|
PCLXLStartPage
|
|
PCLXLSendPage
|
|
PCLXLEscape
|
|
PCLXLStartDcc
|
|
PCLXLEndDoc
|
|
|
|
|
|
Environment:
|
|
|
|
Windows XP/Windows Server 2003 family.
|
|
|
|
Revision History:
|
|
|
|
08/23/99
|
|
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 "xlbmpcvt.h"
|
|
#include "xlgstate.h"
|
|
#include "xloutput.h"
|
|
#include "pclxlcmd.h"
|
|
#include "pclxlcmn.h"
|
|
#include "xltt.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Globals
|
|
//
|
|
extern const LINEATTRS *pgLineAttrs;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Local function prototypes
|
|
//
|
|
|
|
HRESULT
|
|
CommonRopBlt(
|
|
IN PDEVOBJ pdevobj,
|
|
IN SURFOBJ *psoSrc,
|
|
IN CLIPOBJ *pco,
|
|
IN XLATEOBJ *pxlo,
|
|
IN BRUSHOBJ *pbo,
|
|
IN RECTL *prclSrc,
|
|
IN RECTL *prclDst,
|
|
IN POINTL *pptlBrush,
|
|
IN ROP4 rop4);
|
|
|
|
BOOL
|
|
BSendReadImageData(
|
|
IN PDEVOBJ pdevobj,
|
|
IN CompressMode CMode,
|
|
IN PBYTE pBuf,
|
|
IN LONG lStart,
|
|
IN LONG lHeight,
|
|
IN DWORD dwcbSize);
|
|
|
|
PDWORD
|
|
PdwChangeTransparentPalette(
|
|
ULONG iTransColor,
|
|
PDWORD pdwColorTable,
|
|
DWORD dwEntries);
|
|
|
|
HRESULT hrChangePixelColorInScanLine(
|
|
IN PBYTE pubSrc,
|
|
IN ULONG ulBPP,
|
|
IN ULONG ulNumPixels,
|
|
IN ULONG ulTransColor,
|
|
IN OUT PBYTE pubChanged,
|
|
IN ULONG ulNumBytes);
|
|
|
|
extern "C" BOOL
|
|
CreateMaskSurface(
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMsk,
|
|
ULONG iTransColor);
|
|
|
|
extern "C" SURFOBJ *
|
|
CreateBitmapSURFOBJ(
|
|
PDEV *pPDev,
|
|
HBITMAP *phBmp,
|
|
LONG cxSize,
|
|
LONG cySize,
|
|
DWORD Format);
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Drawing DDI entries
|
|
//
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLBitBlt(
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
POINTL *pptlMask,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrush,
|
|
ROP4 rop4)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvBitBlt.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
psoTrg - Describes the target surface
|
|
psoSrc - Describes the source surface
|
|
psoMask - Describes the mask for rop4
|
|
pco - Limits the area to be modified
|
|
pxlo - Specifies how color indices are translated between the source
|
|
and target surfaces
|
|
prclTrg - Defines the area to be modified
|
|
pptlSrc - Defines the upper left corner of the source rectangle
|
|
pptlMask - Defines which pixel in the mask corresponds
|
|
to the upper left corner of the source rectangle
|
|
pbo - Defines the pattern for bitblt
|
|
pptlBrush - Defines the origin of the brush in the Dstination surface
|
|
rop4 - ROP code that defines how the mask, pattern, source, and
|
|
Dstination pixels are combined to write to the Dstination surface
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)psoTrg->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
|
|
VERBOSE(("PCLXLBitBlt() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
{
|
|
RECTL rclSrc;
|
|
|
|
//
|
|
// create prclSrc (source rectangle)
|
|
//
|
|
|
|
if (pptlSrc)
|
|
{
|
|
rclSrc.left = pptlSrc->x;
|
|
rclSrc.top = pptlSrc->y;
|
|
rclSrc.right = pptlSrc->x + RECT_WIDTH(prclTrg);
|
|
rclSrc.bottom = pptlSrc->y + RECT_HEIGHT(prclTrg);
|
|
}
|
|
else
|
|
{
|
|
rclSrc.left = 0;
|
|
rclSrc.top = 0;
|
|
rclSrc.right = RECT_WIDTH(prclTrg);
|
|
rclSrc.bottom = RECT_HEIGHT(prclTrg);
|
|
}
|
|
|
|
if (S_OK == CommonRopBlt(pdevobj, psoSrc, pco, pxlo, pbo, &rclSrc, prclTrg, pptlBrush, rop4))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLStretchBlt(
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
COLORADJUSTMENT *pca,
|
|
POINTL *pptlHTOrg,
|
|
RECTL *prclDst,
|
|
RECTL *prclSrc,
|
|
POINTL *pptlMask,
|
|
ULONG iMode)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvStretchBlt.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
psoDst - Defines the surface on which to draw
|
|
psoSrc - Defines the source for blt operation
|
|
psoMask - Defines a surface that provides a mask for the source
|
|
pco - Limits the area to be modified on the Dstination
|
|
pxlo - Specifies how color dwIndexes are to be translated
|
|
between the source and target surfaces
|
|
pca - Defines color adjustment values to be applied to the source bitmap
|
|
pptlHTOrg - Specifies the origin of the halftone brush
|
|
prclDst - Defines the area to be modified on the Dstination surface
|
|
prclSrc - Defines the area to be copied from the source surface
|
|
pptlMask - Specifies which pixel in the given mask corresponds to
|
|
the upper left pixel in the source rectangle
|
|
iMode - Specifies how source pixels are combined to get output pixels
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)psoDst->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
|
|
VERBOSE(("PCLXLStretchBlt() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
if (S_OK == CommonRopBlt(pdevobj, psoSrc, pco, pxlo, NULL, prclSrc, prclDst, NULL, 0xCC))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLStretchBltROP(
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
COLORADJUSTMENT *pca,
|
|
POINTL *pptlHTOrg,
|
|
RECTL *prclDst,
|
|
RECTL *prclSrc,
|
|
POINTL *pptlMask,
|
|
ULONG iMode,
|
|
BRUSHOBJ *pbo,
|
|
ROP4 rop4)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvStretchBltROP.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
psoDst - Specifies the target surface
|
|
psoSrc - Specifies the source surface
|
|
psoMask - Specifies the mask surface
|
|
pco - Limits the area to be modified
|
|
pxlo - Specifies how color indices are translated
|
|
between the source and target surfaces
|
|
pca - Defines color adjustment values to be applied to the source bitmap
|
|
prclHTOrg - Specifies the halftone origin
|
|
prclDst - Area to be modified on the destination surface
|
|
prclSrc - Rectangle area on the source surface
|
|
prclMask - Rectangle area on the mask surface
|
|
pptlMask - Defines which pixel in the mask corresponds to
|
|
the upper left corner of the source rectangle
|
|
iMode - Specifies how source pixels are combined to get output pixels
|
|
pbo - Defines the pattern for bitblt
|
|
rop4 - ROP code that defines how the mask, pattern, source, and
|
|
destination pixels are combined on the destination surface
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)psoDst->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
|
|
VERBOSE(("PCLXLStretchBltROP() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
if (S_OK == CommonRopBlt(pdevobj, psoSrc, pco, pxlo, pbo, prclSrc, prclDst, NULL, rop4))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLCopyBits(
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDst,
|
|
POINTL *pptlSrc)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvCopyBits.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
psoDst - Points to the Dstination surface
|
|
psoSrc - Points to the source surface
|
|
pxlo - XLATEOBJ provided by the engine
|
|
pco - Defines a clipping region on the Dstination surface
|
|
pxlo - Defines the translation of color indices
|
|
between the source and target surfaces
|
|
prclDst - Defines the area to be modified
|
|
pptlSrc - Defines the upper-left corner of the source rectangle
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)psoDst->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
|
|
RECTL rclSrc;
|
|
|
|
VERBOSE(("PCLXLCopyBits() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
//
|
|
// create prclSrc (source rectangle)
|
|
//
|
|
|
|
rclSrc.top = pptlSrc->y;
|
|
rclSrc.left = pptlSrc->x;
|
|
rclSrc.bottom = pptlSrc->y + RECT_HEIGHT(prclDst);
|
|
rclSrc.right = pptlSrc->x + RECT_WIDTH(prclDst);
|
|
|
|
if (S_OK == CommonRopBlt(pdevobj, psoSrc, pco, pxlo, NULL, &rclSrc, prclDst, NULL, 0xCC))
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLPlgBlt(
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
COLORADJUSTMENT *pca,
|
|
POINTL *pptlBrushOrg,
|
|
POINTFIX *pptfixDst,
|
|
RECTL *prclSrc,
|
|
POINTL *pptlMask,
|
|
ULONG iMode)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvPlgBlt.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
psoDst - Defines the surface on which to draw
|
|
psoSrc - Defines the source for blt operation
|
|
psoMask - Defines a surface that provides a mask for the source
|
|
pco - Limits the area to be modified on the Dstination
|
|
pxlo - Specifies how color dwIndexes are to be translated
|
|
between the source and target surfaces
|
|
pca - Defines color adjustment values to be applied to the source bitmap
|
|
pptlBrushOrg - Specifies the origin of the halftone brush
|
|
ppfixDest - Defines the area to be modified on the Dstination surface
|
|
prclSrc - Defines the area to be copied from the source surface
|
|
pptlMask - Specifies which pixel in the given mask corresponds to
|
|
the upper left pixel in the source rectangle
|
|
iMode - Specifies how source pixels are combined to get output pixels
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
{
|
|
VERBOSE(("PCLXLBltBlt() entry.\n"));
|
|
|
|
return EngPlgBlt(psoDst, psoSrc, psoMask, pco, pxlo, pca, pptlBrushOrg,
|
|
pptfixDst, prclSrc, pptlMask, iMode);
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLAlphaBlend(
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDst,
|
|
RECTL *prclSrc,
|
|
BLENDOBJ *pBlendObj)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
VERBOSE(("PCLXLAlphaBlend() entry.\n"));
|
|
PDEV *pPDev = (PDEV*)psoDst->dhpdev;
|
|
BOOL bRet;
|
|
|
|
if (NULL == pPDev)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pPDev->fMode2 |= PF2_WHITEN_SURFACE;
|
|
bRet = EngAlphaBlend(psoDst,
|
|
psoSrc,
|
|
pco,
|
|
pxlo,
|
|
prclDst,
|
|
prclSrc,
|
|
pBlendObj);
|
|
pPDev->fMode2 &= ~(PF2_WHITEN_SURFACE|PF2_SURFACE_WHITENED);
|
|
return bRet;
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLGradientFill(
|
|
SURFOBJ *psoDst,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
TRIVERTEX *pVertex,
|
|
ULONG nVertex,
|
|
PVOID pMesh,
|
|
ULONG nMesh,
|
|
RECTL *prclExtents,
|
|
POINTL *pptlDitherOrg,
|
|
ULONG ulMode)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
VERBOSE(("PCLXLGradientFill() entry.\n"));
|
|
PDEV *pPDev = (PDEV*) psoDst->dhpdev;
|
|
BOOL bRet;
|
|
|
|
if (NULL == pPDev)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (ulMode == GRADIENT_FILL_TRIANGLE)
|
|
{
|
|
pPDev->fMode2 |= PF2_WHITEN_SURFACE;
|
|
}
|
|
bRet = EngGradientFill(psoDst,
|
|
pco,
|
|
pxlo,
|
|
pVertex,
|
|
nVertex,
|
|
pMesh,
|
|
nMesh,
|
|
prclExtents,
|
|
pptlDitherOrg,
|
|
ulMode);
|
|
pPDev->fMode2 &= ~(PF2_WHITEN_SURFACE|PF2_SURFACE_WHITENED);
|
|
return bRet;
|
|
}
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLTransparentBlt(
|
|
SURFOBJ *psoDst,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDst,
|
|
RECTL *prclSrc,
|
|
ULONG iTransColor,
|
|
ULONG ulReserved)
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ) psoDst->dhpdev;
|
|
PDEV *pPDev = (PDEV*) psoDst->dhpdev;
|
|
PXLPDEV pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
HRESULT hr = E_FAIL;
|
|
ULONG ulXlate[2] = {0x0, RGB_WHITE}; //2 colors in psoMsk. Black and White.
|
|
XLATEOBJ xlo;
|
|
|
|
ZeroMemory ( &xlo, sizeof (XLATEOBJ) );
|
|
xlo.cEntries = 2;
|
|
xlo.pulXlate = (PULONG)ulXlate;
|
|
xlo.flXlate = XO_TABLE; // use the entries in pulXlate table.
|
|
|
|
|
|
if ( NULL == pxlpdev ||
|
|
NULL == psoSrc )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Step 1. Create a mask and download it to printer using ROP DSO (238 = 0xEE).
|
|
// The mask is a 1bpp image created out of the image in psoSrc. Wherever
|
|
// the TransColor is present
|
|
// in the image, the corresponding pixel in the mask gets value 0. At all other places
|
|
// the pixel will get value of 1.
|
|
// if we copy the mask to a color printer (using ROP of SRC_COPY),
|
|
// you will notice that the image is black and white,
|
|
// and black is present on the same place where the Transparent Color should be there.
|
|
// Instead of SRC_COPY if we use rop=238 which is (SOURCE | DESTINATION), the white color
|
|
// of the mask will get OR'ed with destinaion and the region becomes white. The black
|
|
// color
|
|
// of the mask will not be printed and instead whatever is there already on the sheet
|
|
// (if something is present) will be visible
|
|
// Assuming x is the pixel already present on the sheet.
|
|
// 0 | x = x (ORing anything with 0 is anything)
|
|
// 1 | x = 1
|
|
// 1 represents white color (RGB_WHITE = 0xFFFFFF = all 1s).
|
|
//
|
|
// Step 2.
|
|
// In the image, wherever the TransColor is present, change it to white.
|
|
// Now the image has 2 kinds of white colors. Those that
|
|
// are originally present in the image, and those that we just put in there.
|
|
// Step 3.
|
|
// Download the image with rop DSAnd (=136 = 0x88).
|
|
// Assuming x is the pixel already present on the sheet
|
|
// and y be the pixel in the image and 1 represents white color
|
|
// (RGB_WHITE = 0xFFFFFF = all 1s).
|
|
// 1 & y = y Image falling on the area that we whited in step 1.
|
|
// 1 & x = x The white parts of the image (that was earlier TransColor) falling in
|
|
// the area.
|
|
// that is supposed to be visible from under the image.
|
|
//
|
|
|
|
//
|
|
//
|
|
// Step 1 Create appropriate mask.
|
|
// For images that are greater than 1bpp
|
|
// Use unidrv's CreateMaskSurface to create mask. The logic of a mask surface
|
|
// is explained above.
|
|
// For images that are 1bpp
|
|
// CreateMaskSurface does not create mask for 1bpp image. So for that we'll
|
|
// create mask ourselves. Since mask is 1bpp and so is the image, we can simply
|
|
// use the image as the mask, except that we might need to manipulate the palette.
|
|
// The benefit here is that we are using the same image as mask, instead of
|
|
// creating a new image and using memory.
|
|
//
|
|
|
|
if ( BMF_1BPP == psoSrc->iBitmapFormat )
|
|
{
|
|
|
|
//
|
|
// For paletted images (1bpp images have palette), iTransColor is actually the index into
|
|
// the palette, and not the actual RGB color itself.
|
|
// As explained above, the transparent color should be black in the mask, while the
|
|
// non-transparent color should be white. Black is
|
|
// index 0 in xlo.pulXlate = (PULONG)ulXlate. So if TransColor is 0, then
|
|
// we can simply use the xlo that we created above.
|
|
// If not, we need to switch black and white in the palette.
|
|
// (To repeat. While sending the mask, iTransColor should be sent as black and
|
|
// the color that is to be printed should be sent as white).
|
|
//
|
|
if ( 0 != iTransColor )
|
|
{
|
|
//
|
|
// Reverse Colors.
|
|
//
|
|
ulXlate[0] = RGB_WHITE;
|
|
ulXlate[1] = RGB_BLACK;
|
|
}
|
|
hr = CommonRopBlt(pdevobj, psoSrc, pco, &xlo, NULL, prclSrc, prclDst, NULL, 0xEE);
|
|
|
|
}
|
|
else
|
|
{
|
|
SURFOBJ *psoMsk = NULL;
|
|
HBITMAP hBmpMsk = NULL;
|
|
|
|
if (psoMsk = CreateBitmapSURFOBJ(pPDev,
|
|
&hBmpMsk,
|
|
psoSrc->sizlBitmap.cx,
|
|
psoSrc->sizlBitmap.cy,
|
|
BMF_1BPP) )
|
|
{
|
|
if ( CreateMaskSurface(psoSrc,psoMsk,iTransColor) )
|
|
{
|
|
|
|
hr = CommonRopBlt(pdevobj, psoMsk, pco, &xlo, NULL, prclSrc, prclDst, NULL, 0xEE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Release allocated objects.
|
|
//
|
|
if ( psoMsk )
|
|
{
|
|
EngUnlockSurface(psoMsk);
|
|
psoMsk = NULL;
|
|
}
|
|
|
|
if (hBmpMsk)
|
|
{
|
|
EngDeleteSurface((HSURF)hBmpMsk);
|
|
hBmpMsk = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
if ( FAILED (hr) )
|
|
{
|
|
ERR(("PCLXLTransparentBlt: Mask could not be created or rendered.\n"));
|
|
goto Cleanup;
|
|
}
|
|
|
|
//
|
|
// Step 2 and 3.
|
|
// Set the flags and call CommonRopBlt. CommonRopBlt is the function that
|
|
// dumps images to printer. CommonRopBlt will look at the
|
|
// flags and know that for this image, it has to replace
|
|
// the colored pixels with White
|
|
//
|
|
|
|
pxlpdev->dwFlags |= XLPDEV_FLAGS_SUBST_TRNCOLOR_WITH_WHITE;
|
|
pxlpdev->ulTransColor = iTransColor;
|
|
|
|
//
|
|
// ROP is DSAnd = 136 = 0x88.
|
|
//
|
|
hr = CommonRopBlt(pdevobj, psoSrc, pco, pxlo, NULL, prclSrc, prclDst, NULL, 136);
|
|
|
|
pxlpdev->ulTransColor = 0;
|
|
pxlpdev->dwFlags &= ~XLPDEV_FLAGS_SUBST_TRNCOLOR_WITH_WHITE;
|
|
|
|
Cleanup:
|
|
|
|
if ( SUCCEEDED (hr) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLTextOut(
|
|
SURFOBJ *pso,
|
|
STROBJ *pstro,
|
|
FONTOBJ *pfo,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclExtra,
|
|
RECTL *prclOpaque,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlOrg,
|
|
MIX mix)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
|
|
VERBOSE(("PCLXLTextOut() entry.\n"));
|
|
|
|
PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM;
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
|
|
//
|
|
// Clip
|
|
//
|
|
if (!SUCCEEDED(pOutput->SetClip(pco)))
|
|
return FALSE;
|
|
|
|
ROP4 rop = GET_FOREGROUND_ROP3(UlVectMixToRop4(mix));
|
|
|
|
if (!ROP3_NEED_SOURCE(rop))
|
|
rop = 0x00fc;
|
|
|
|
|
|
//
|
|
// Set ROP and TxMode.
|
|
// Send NewPath to flush memory.
|
|
//
|
|
pOutput->SetROP3(rop);
|
|
pOutput->Send_cmd(eNewPath);
|
|
pOutput->SetPaintTxMode(eOpaque);
|
|
pOutput->SetSourceTxMode(eOpaque);
|
|
|
|
//
|
|
// Opaque Rectangle
|
|
//
|
|
if (prclOpaque)
|
|
{
|
|
pOutput->SetPenColor(NULL, NULL);
|
|
pOutput->SetBrush(pboOpaque, pptlOrg);
|
|
pOutput->Send_cmd(eNewPath);
|
|
pOutput->RectanglePath(prclOpaque);
|
|
pOutput->Paint();
|
|
}
|
|
|
|
//
|
|
// Draw underline, strikeout, etc.
|
|
//
|
|
if (prclExtra)
|
|
{
|
|
pOutput->SetPenColor(NULL, NULL);
|
|
pOutput->SetBrush(pboFore, pptlOrg);
|
|
pOutput->Send_cmd(eNewPath);
|
|
while(NULL != prclExtra)
|
|
{
|
|
pOutput->RectanglePath(prclExtra++);
|
|
}
|
|
pOutput->Paint();
|
|
}
|
|
|
|
//
|
|
// Text Color
|
|
//
|
|
pOutput->SetBrush(pboFore, pptlOrg);
|
|
pOutput->Flush(pdevobj);
|
|
|
|
//
|
|
// Device font/TrueType download
|
|
//
|
|
DrvTextOut(
|
|
pso,
|
|
pstro,
|
|
pfo,
|
|
pco,
|
|
prclExtra,
|
|
prclOpaque,
|
|
pboFore,
|
|
pboOpaque,
|
|
pptlOrg,
|
|
mix);
|
|
|
|
//
|
|
// Bug reported by HP.
|
|
// Plug-in could have command callback and DrvStartPage sets plug-in's
|
|
// pdev in pdevOEM.
|
|
// Need to reset it.
|
|
//
|
|
((PPDEV)pdevobj)->devobj.pdevOEM = ((PPDEV)pdevobj)->pVectorPDEV;
|
|
|
|
//
|
|
// Flush cached text before changing font
|
|
//
|
|
FlushCachedText(pdevobj);
|
|
|
|
//
|
|
// Reset text angle
|
|
//
|
|
pxlpdev->dwTextAngle = 0;
|
|
|
|
//
|
|
// Close TrueType font
|
|
//
|
|
pxlpdev->pTTFile->CloseTTFile();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLLineTo(
|
|
SURFOBJ *pso,
|
|
CLIPOBJ *pco,
|
|
BRUSHOBJ *pbo,
|
|
LONG x1,
|
|
LONG y1,
|
|
LONG x2,
|
|
LONG y2,
|
|
RECTL *prclBounds,
|
|
MIX mix)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
POINTFIX Pointfix;
|
|
LINEATTRS lineattrs;
|
|
|
|
VERBOSE(("PCLXLLineTo() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
Pointfix.x = x2 << 4;
|
|
Pointfix.y = y2 << 4;
|
|
lineattrs = *pgLineAttrs;
|
|
lineattrs.elWidth.e = FLOATL_IEEE_1_0F;
|
|
|
|
ROP4 rop = GET_FOREGROUND_ROP3(UlVectMixToRop4(mix));
|
|
TxMode TxModeValue;
|
|
|
|
//
|
|
// Quick return in the case of AA (destination).
|
|
//
|
|
if (rop == 0xAA)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// If there is any Pattern involved, set TxMode to Opaque.
|
|
//
|
|
if (ROP3_NEED_PATTERN(rop))
|
|
{
|
|
TxModeValue = eOpaque;
|
|
}
|
|
else
|
|
{
|
|
TxModeValue = eTransparent;
|
|
}
|
|
|
|
BOOL bRet;
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
|
|
if (S_OK == pOutput->SetClip(pco) &&
|
|
S_OK == pOutput->SetROP3(rop) &&
|
|
S_OK == pOutput->SetPaintTxMode(TxModeValue) &&
|
|
S_OK == pOutput->SetSourceTxMode(TxModeValue) &&
|
|
S_OK == pOutput->SetPen(&lineattrs, NULL) &&
|
|
S_OK == pOutput->SetPenColor(pbo, NULL) &&
|
|
S_OK == pOutput->SetBrush(NULL, NULL) &&
|
|
S_OK == pOutput->Send_cmd(eNewPath) &&
|
|
S_OK == pOutput->SetCursor(x1, y1) &&
|
|
S_OK == pOutput->LinePath(&Pointfix, 1) &&
|
|
S_OK == pOutput->Paint() &&
|
|
S_OK == pOutput->Flush(pdevobj))
|
|
bRet = TRUE;
|
|
else
|
|
{
|
|
pOutput->Delete();
|
|
bRet = FALSE;
|
|
}
|
|
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLStrokePath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
XFORMOBJ *pxo,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
LINEATTRS *plineattrs,
|
|
MIX mix)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
TxMode TxModeValue;
|
|
|
|
VERBOSE(("PCLXLStokePath() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
BOOL bRet;
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
|
|
ROP4 rop = GET_FOREGROUND_ROP3(UlVectMixToRop4(mix));
|
|
|
|
//
|
|
// Quick return in the case of AA (destination).
|
|
//
|
|
if (rop == 0xAA)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// If there is any Pattern involved, set TxMode to Opaque.
|
|
//
|
|
if (ROP3_NEED_PATTERN(rop))
|
|
{
|
|
TxModeValue = eOpaque;
|
|
}
|
|
else
|
|
{
|
|
TxModeValue = eTransparent;
|
|
}
|
|
|
|
if (S_OK == pOutput->SetClip(pco) &&
|
|
S_OK == pOutput->SetROP3(rop) &&
|
|
S_OK == pOutput->SetPaintTxMode(TxModeValue) &&
|
|
S_OK == pOutput->SetSourceTxMode(TxModeValue) &&
|
|
S_OK == pOutput->SetPen(plineattrs, pxo) &&
|
|
S_OK == pOutput->SetPenColor(pbo, pptlBrushOrg) &&
|
|
S_OK == pOutput->SetBrush(NULL, NULL) &&
|
|
S_OK == pOutput->Path(ppo) &&
|
|
S_OK == pOutput->Paint() &&
|
|
S_OK == pOutput->Flush(pdevobj))
|
|
bRet = TRUE;
|
|
else
|
|
{
|
|
pOutput->Delete();
|
|
bRet = FALSE;
|
|
}
|
|
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLFillPath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mix,
|
|
FLONG flOptions)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
|
|
VERBOSE(("PCLXLFillPath() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
BOOL bRet;
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
|
|
ROP4 rop = GET_FOREGROUND_ROP3(UlVectMixToRop4(mix));
|
|
TxMode TxModeValue;
|
|
|
|
//
|
|
// Quick return in the case of AA (destination).
|
|
//
|
|
if (rop == 0xAA)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Performance fix suggested by HP.
|
|
// Fix the performance problem on CD9T_LET.cdr.
|
|
//
|
|
if (pco && pco->iFComplexity == FC_COMPLEX)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// If there is any Pattern involved, set TxMode to Opaque.
|
|
//
|
|
if (ROP3_NEED_PATTERN(rop))
|
|
{
|
|
TxModeValue = eOpaque;
|
|
}
|
|
else
|
|
{
|
|
TxModeValue = eTransparent;
|
|
}
|
|
|
|
//
|
|
// Setup fill mode
|
|
//
|
|
FillMode FM;
|
|
if (flOptions == FP_ALTERNATEMODE)
|
|
{
|
|
FM = eFillEvenOdd;
|
|
}
|
|
else if (flOptions == FP_WINDINGMODE)
|
|
{
|
|
FM = eFillNonZeroWinding;
|
|
}
|
|
|
|
if (S_OK == pOutput->SetClip(pco) &&
|
|
S_OK == pOutput->SetROP3(rop) &&
|
|
S_OK == pOutput->SetPaintTxMode(TxModeValue) &&
|
|
S_OK == pOutput->SetSourceTxMode(TxModeValue) &&
|
|
S_OK == pOutput->SetFillMode(FM) &&
|
|
S_OK == pOutput->SetPenColor(NULL, NULL) &&
|
|
S_OK == pOutput->SetBrush(pbo, pptlBrushOrg) &&
|
|
S_OK == pOutput->Path(ppo) &&
|
|
S_OK == pOutput->Paint() &&
|
|
S_OK == pOutput->Flush(pdevobj))
|
|
bRet = TRUE;
|
|
else
|
|
{
|
|
pOutput->Delete();
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLStrokeAndFillPath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
XFORMOBJ *pxo,
|
|
BRUSHOBJ *pboStroke,
|
|
LINEATTRS *plineattrs,
|
|
BRUSHOBJ *pboFill,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mixFill,
|
|
FLONG flOptions)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
|
|
VERBOSE(("PCLXLStrokeAndFillPath() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
BOOL bRet;
|
|
ROP4 rop = GET_FOREGROUND_ROP3(UlVectMixToRop4(mixFill));
|
|
TxMode TxModeValue;
|
|
|
|
//
|
|
// Quick return in the case of AA (destination).
|
|
//
|
|
if (rop == 0xAA)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// If there is any Pattern involved, set TxMode to Opaque.
|
|
//
|
|
if (ROP3_NEED_PATTERN(rop))
|
|
{
|
|
TxModeValue = eOpaque;
|
|
}
|
|
else
|
|
{
|
|
TxModeValue = eTransparent;
|
|
}
|
|
|
|
//
|
|
// Setup fill mode
|
|
//
|
|
FillMode FM;
|
|
if (flOptions == FP_ALTERNATEMODE)
|
|
{
|
|
FM = eFillEvenOdd;
|
|
}
|
|
else if (flOptions == FP_WINDINGMODE)
|
|
{
|
|
FM = eFillNonZeroWinding;
|
|
}
|
|
|
|
if (S_OK == pOutput->SetClip(pco) &&
|
|
S_OK == pOutput->SetROP3(rop) &&
|
|
S_OK == pOutput->SetPaintTxMode(TxModeValue) &&
|
|
S_OK == pOutput->SetSourceTxMode(TxModeValue) &&
|
|
S_OK == pOutput->SetFillMode(FM) &&
|
|
S_OK == pOutput->SetPen(plineattrs, pxo) &&
|
|
S_OK == pOutput->SetPenColor(pboStroke, pptlBrushOrg) &&
|
|
S_OK == pOutput->SetBrush(pboFill, pptlBrushOrg) &&
|
|
S_OK == pOutput->Path(ppo) &&
|
|
S_OK == pOutput->Paint() &&
|
|
S_OK == pOutput->Flush(pdevobj))
|
|
bRet = TRUE;
|
|
else
|
|
{
|
|
pOutput->Delete();
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLRealizeBrush(
|
|
BRUSHOBJ *pbo,
|
|
SURFOBJ *psoTarget,
|
|
SURFOBJ *psoPattern,
|
|
SURFOBJ *psoMask,
|
|
XLATEOBJ *pxlo,
|
|
ULONG iHatch)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)psoTarget->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
XLBRUSH *pBrush;
|
|
BOOL bRet;
|
|
OutputFormat OutputF;
|
|
|
|
VERBOSE(("PCLXLRealizeBrush() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
//
|
|
// the OEM DLL should NOT hook out this function unless it wants to draw
|
|
// graphics directly to the device surface. In that case, it calls
|
|
// EngRealizeBrush which causes GDI to call DrvRealizeBrush.
|
|
// Note that it cannot call back into Unidrv since Unidrv doesn't hook it.
|
|
//
|
|
|
|
if (iHatch >= HS_DDI_MAX)
|
|
{
|
|
LONG lHeight, lWidth, lScanline;
|
|
ULONG ulOutputBPP, ulInputBPP;
|
|
DWORD dwI, dwBufSize, dwLenNormal, dwLenRLE,dwLenDRC, dwcbLineSize, dwcbBmpSize;
|
|
PDWORD pdwLen;
|
|
PBYTE pubSrc, pBufNormal, pBufRLE, pBufDRC, pBuf, pBmpSize;
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
|
|
DetermineOutputFormat(pxlo, pOutput->GetDeviceColorDepth(), psoPattern->iBitmapFormat, &OutputF, &ulOutputBPP);
|
|
|
|
//
|
|
// Get Info
|
|
//
|
|
ulInputBPP = UlBPPtoNum((BPP)psoPattern->iBitmapFormat);
|
|
lHeight = psoPattern->sizlBitmap.cy;
|
|
lWidth = psoPattern->sizlBitmap.cx;
|
|
|
|
dwcbLineSize = ((lWidth * ulInputBPP) + 7) >> 3;
|
|
dwBufSize = lHeight * (((lWidth * ulOutputBPP + 31) >> 5 ) << 2) +
|
|
DATALENGTH_HEADER_SIZE + sizeof(PCLXL_EndRastPattern);
|
|
|
|
VERBOSE(("PCLXLRealizeBrush():InBPP=%d,Width=%d,Height=%d,Line=%d,Size=%d.\n",
|
|
ulInputBPP, lWidth, lHeight, dwcbLineSize, dwBufSize));
|
|
|
|
//
|
|
// Allocate output buffer
|
|
//
|
|
pBufNormal = pBufRLE = pBufDRC = NULL;
|
|
if (COMMANDPTR(((PPDEV)pdevobj)->pDriverInfo,CMD_ENABLEDRC))
|
|
{
|
|
if (NULL == (pBufDRC = (PBYTE)MemAlloc(dwBufSize)))
|
|
{
|
|
ERR(("PCLXLRealizeBrush: MemAlloc failed.\n"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
if (NULL == (pBufNormal = (PBYTE)MemAlloc(dwBufSize)) ||
|
|
NULL == (pBufRLE = (PBYTE)MemAlloc(dwBufSize)) )
|
|
{
|
|
if (pBufNormal != NULL)
|
|
MemFree(pBufNormal);
|
|
if (pBufRLE != NULL)
|
|
MemFree(pBufRLE);
|
|
ERR(("PCLXLRealizeBrush: MemAlloc failed.\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
CompressMode CMode;
|
|
BMPConv BMPC;
|
|
PBYTE pubDst;
|
|
DWORD dwDstSize;
|
|
|
|
#if DBG
|
|
BMPC.SetDbgLevel(BRUSHDBG);
|
|
#endif
|
|
BMPC.BSetInputBPP((BPP)psoPattern->iBitmapFormat);
|
|
BMPC.BSetOutputBPP(NumToBPP(ulOutputBPP));
|
|
BMPC.BSetOutputBMPFormat(OutputF);
|
|
BMPC.BSetXLATEOBJ(pxlo);
|
|
|
|
dwLenNormal = dwLenRLE = dwLenDRC = 0;
|
|
|
|
#define NO_COMPRESSION 0
|
|
#define RLE_COMPRESSION 1
|
|
#define DRC_COMPRESSION 2
|
|
DWORD dwComp;
|
|
|
|
if (COMMANDPTR(((PPDEV)pdevobj)->pDriverInfo,CMD_ENABLEDRC))
|
|
{
|
|
//
|
|
// Try DRC compression.
|
|
//
|
|
dwComp = 3;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Only non and RLE comp.
|
|
//
|
|
dwComp = 2;
|
|
}
|
|
for (dwI = 0; dwI < dwComp; dwI ++)
|
|
{
|
|
bRet = TRUE;
|
|
|
|
if (NO_COMPRESSION == dwI)
|
|
{
|
|
pBuf = pBufNormal;
|
|
pdwLen = &dwLenNormal;
|
|
CMode = eNoCompression;
|
|
}
|
|
else
|
|
if (RLE_COMPRESSION == dwI)
|
|
{
|
|
pBuf = pBufRLE;
|
|
pdwLen = &dwLenRLE;
|
|
CMode = eRLECompression;
|
|
}
|
|
else
|
|
if (DRC_COMPRESSION == dwI)
|
|
{
|
|
pBuf = pBufDRC;
|
|
pdwLen = &dwLenDRC;
|
|
CMode = eDeltaRowCompression;
|
|
}
|
|
|
|
BMPC.BSetCompressionType(CMode);
|
|
|
|
lScanline = lHeight;
|
|
pubSrc = (PBYTE)psoPattern->pvScan0;
|
|
|
|
*pBuf = PCLXL_dataLength;
|
|
pBmpSize = pBuf + 1; // DWORD bitmap size
|
|
pBuf += DATALENGTH_HEADER_SIZE;
|
|
(*pdwLen) = DATALENGTH_HEADER_SIZE;
|
|
|
|
dwcbBmpSize = 0;
|
|
|
|
while (lScanline-- > 0 && dwcbBmpSize + *pdwLen < dwBufSize)
|
|
{
|
|
pubDst = BMPC.PubConvertBMP(pubSrc, dwcbLineSize);
|
|
dwDstSize = BMPC.DwGetDstSize();
|
|
VERBOSE(("PCLXLRealizeBrush[0x%x]: dwDstSize=0x%x\n", lScanline, dwDstSize));
|
|
|
|
if ( dwcbBmpSize +
|
|
dwDstSize +
|
|
DATALENGTH_HEADER_SIZE +
|
|
sizeof(PCLXL_EndRastPattern) > dwBufSize || NULL == pubDst)
|
|
{
|
|
ERR(("PCLXLRealizeBrush: Buffer size is too small.(%d)\n", dwI));
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
memcpy(pBuf, pubDst, dwDstSize);
|
|
dwcbBmpSize += dwDstSize;
|
|
pBuf += dwDstSize;
|
|
pubSrc += psoPattern->lDelta;
|
|
|
|
}
|
|
|
|
if (lScanline > 0)
|
|
{
|
|
bRet = FALSE;
|
|
#if DBG
|
|
ERR(("PCLXLRealizeBrush: Conversion failed.\n"));
|
|
#endif
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
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);
|
|
}
|
|
|
|
CopyMemory(pBmpSize, &dwcbBmpSize, sizeof(dwcbBmpSize));
|
|
(*pdwLen) += dwcbBmpSize;
|
|
|
|
*pBuf = PCLXL_EndRastPattern;
|
|
(*pdwLen) ++;
|
|
}
|
|
else
|
|
{
|
|
*pdwLen = 0;
|
|
}
|
|
}
|
|
#undef NO_COMPRESSION
|
|
#undef RLE_COMPRESSION
|
|
#undef DRC_COMPRESSION
|
|
|
|
if (dwLenRLE == 0 && dwLenDRC != 0 && dwLenDRC < dwLenNormal ||
|
|
dwLenRLE != 0 && dwLenDRC != 0 && dwLenDRC < dwLenRLE &&
|
|
dwLenDRC < dwLenNormal )
|
|
{
|
|
pBuf = pBufDRC;
|
|
pdwLen = &dwLenDRC;
|
|
CMode = eDeltaRowCompression;
|
|
|
|
MemFree(pBufNormal);
|
|
MemFree(pBufRLE);
|
|
}
|
|
else
|
|
if (dwLenRLE != 0 && dwLenRLE < dwLenNormal)
|
|
{
|
|
pBuf = pBufRLE;
|
|
pdwLen = &dwLenRLE;
|
|
CMode = eRLECompression;
|
|
|
|
MemFree(pBufNormal);
|
|
MemFree(pBufDRC);
|
|
}
|
|
else
|
|
if (dwLenNormal != 0)
|
|
{
|
|
pBuf = pBufNormal;
|
|
pdwLen = &dwLenNormal;
|
|
CMode = eNoCompression;
|
|
|
|
MemFree(pBufRLE);
|
|
MemFree(pBufDRC);
|
|
}
|
|
else
|
|
{
|
|
MemFree(pBufNormal);
|
|
MemFree(pBufRLE);
|
|
MemFree(pBufDRC);
|
|
ERR(("PCLXLRealizeBrush: Conversion failed. Return FALSE.\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Output
|
|
//
|
|
ColorMapping CMapping;
|
|
DWORD dwScale;
|
|
|
|
//
|
|
// Pattern scaling factor
|
|
// Scale the destination size of pattern.
|
|
// Resolution / 150 seems to be a good scaling factor.
|
|
//
|
|
dwScale = (pOutput->GetResolutionForBrush() + 149)/ 150;
|
|
|
|
if (pOutput->GetDeviceColorDepth() == e24Bit)
|
|
{
|
|
pOutput->SetColorSpace(eRGB);
|
|
}
|
|
else
|
|
{
|
|
pOutput->SetColorSpace(eGray);
|
|
}
|
|
if (OutputF == eOutputPal)
|
|
{
|
|
DWORD *pdwColorTable;
|
|
|
|
if ((pdwColorTable = GET_COLOR_TABLE(pxlo)))
|
|
{
|
|
pOutput->SetPalette(ulOutputBPP, pxlo->cEntries, pdwColorTable);
|
|
CMapping = eIndexedPixel;
|
|
}
|
|
else
|
|
{
|
|
CMapping = eDirectPixel;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CMapping = eDirectPixel;
|
|
}
|
|
pOutput->Send_cmd(eSetColorSpace);
|
|
|
|
pOutput->SetOutputBPP(CMapping, ulOutputBPP);
|
|
pOutput->SetSourceWidth((uint16)lWidth);
|
|
pOutput->SetSourceHeight((uint16)lHeight);
|
|
pOutput->SetDestinationSize((uint16)(lWidth * dwScale), (uint16)(lHeight * dwScale));
|
|
pOutput->SetPatternDefineID((sint16)pxlpdev->dwLastBrushID);
|
|
pOutput->SetPatternPersistence(eSessionPattern);
|
|
pOutput->Send_cmd(eBeginRastPattern);
|
|
pOutput->Flush(pdevobj);
|
|
pOutput->ReadRasterPattern(lHeight, CMode);
|
|
pOutput->Flush(pdevobj);
|
|
|
|
DWORD dwBitmapSize;
|
|
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
|
|
//
|
|
PBYTE pTmp = pBuf;
|
|
|
|
pBuf += 3;
|
|
*pBuf = PCLXL_dataLengthByte;
|
|
*(pBuf + 1) = (BYTE)dwBitmapSize;
|
|
WriteSpoolBuf((PPDEV)pdevobj, pBuf, (*pdwLen) - 3);
|
|
|
|
//
|
|
// Restore the original pointer
|
|
//
|
|
pBuf = pTmp;
|
|
}
|
|
MemFree(pBuf);
|
|
|
|
}
|
|
|
|
DWORD dwBrushSize;
|
|
if (pxlo->cEntries)
|
|
{
|
|
dwBrushSize = sizeof(XLBRUSH) + (pxlo->cEntries + 1) * sizeof(DWORD);
|
|
}
|
|
else
|
|
{
|
|
dwBrushSize = sizeof(XLBRUSH) + sizeof(DWORD);
|
|
}
|
|
|
|
if (pBrush = (XLBRUSH*)BRUSHOBJ_pvAllocRbrush(pbo, dwBrushSize))
|
|
{
|
|
|
|
pBrush->dwSig = XLBRUSH_SIG;
|
|
pBrush->dwHatch = iHatch;
|
|
|
|
if (iHatch >= HS_DDI_MAX)
|
|
{
|
|
pBrush->dwPatternID = pxlpdev->dwLastBrushID++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set 0 for hatch brush case
|
|
//
|
|
pBrush->dwPatternID = 0;
|
|
}
|
|
|
|
DWORD *pdwColorTable;
|
|
|
|
pdwColorTable = GET_COLOR_TABLE(pxlo);
|
|
|
|
//
|
|
// get color for Graphics state cache for either palette case or
|
|
// solid color.
|
|
//
|
|
pBrush->dwColor = BRUSHOBJ_ulGetBrushColor(pbo);
|
|
|
|
if (pdwColorTable && pxlo->cEntries != 0)
|
|
{
|
|
//
|
|
// Copy palette table.
|
|
//
|
|
CopyMemory(pBrush->adwColor, pdwColorTable, pxlo->cEntries * sizeof(DWORD));
|
|
pBrush->dwCEntries = pxlo->cEntries;
|
|
}
|
|
else
|
|
{
|
|
pBrush->dwCEntries = 0;
|
|
}
|
|
|
|
pBrush->dwOutputFormat = (DWORD)OutputF;
|
|
|
|
pbo->pvRbrush = (PVOID)pBrush;
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLStartPage(
|
|
SURFOBJ *pso)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
BOOL bRet;
|
|
|
|
VERBOSE(("PCLXLStartPage() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
|
|
pxlpdev->dwFlags |= XLPDEV_FLAGS_STARTPAGE_CALLED;
|
|
|
|
bRet = DrvStartPage(pso);
|
|
|
|
|
|
//
|
|
// Bug reported by HP.
|
|
// Plug-in could have command callback and DrvStartPage sets plug-in's
|
|
// pdev in pdevOEM.
|
|
// Need to reset it.
|
|
//
|
|
((PPDEV)pdevobj)->devobj.pdevOEM = ((PPDEV)pdevobj)->pVectorPDEV;
|
|
|
|
//
|
|
// Reset printing mode.
|
|
// SourceTxMode, PaintTxMode
|
|
// ROP
|
|
//
|
|
pOutput->SetPaintTxMode(eOpaque);
|
|
pOutput->SetSourceTxMode(eOpaque);
|
|
pOutput->SetROP3(0xCC);
|
|
|
|
pOutput->Flush(pdevobj);
|
|
|
|
//
|
|
// Needs to reset attribute when EndPage and BeginPage are sent.
|
|
//
|
|
if (!(pxlpdev->dwFlags & XLPDEV_FLAGS_FIRSTPAGE))
|
|
{
|
|
BSaveFont(pdevobj);
|
|
|
|
//
|
|
// Reset graphcis state each page.
|
|
//
|
|
pOutput->ResetGState();
|
|
|
|
}
|
|
else
|
|
{
|
|
pxlpdev->dwFlags &= ~XLPDEV_FLAGS_FIRSTPAGE;
|
|
}
|
|
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLSendPage(
|
|
SURFOBJ *pso)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
XLOutput *pOutput;
|
|
|
|
VERBOSE(("PCLXLEndPage() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
pxlpdev->dwFlags &= ~XLPDEV_FLAGS_STARTPAGE_CALLED;
|
|
|
|
pOutput = pxlpdev->pOutput;
|
|
pOutput->Flush(pdevobj);
|
|
|
|
return DrvSendPage(pso);
|
|
}
|
|
|
|
|
|
extern "C" ULONG APIENTRY
|
|
PCLXLEscape(
|
|
SURFOBJ *pso,
|
|
ULONG iEsc,
|
|
ULONG cjIn,
|
|
PVOID pvIn,
|
|
ULONG cjOut,
|
|
PVOID pvOut)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
VERBOSE(("PCLXLEscape() entry.\n"));
|
|
|
|
return DrvEscape(
|
|
pso,
|
|
iEsc,
|
|
cjIn,
|
|
pvIn,
|
|
cjOut,
|
|
pvOut);
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLStartDoc(
|
|
SURFOBJ *pso,
|
|
PWSTR pwszDocName,
|
|
DWORD dwJobId)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
|
|
VERBOSE(("PCLXLStartDoc() entry.\n"));
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
//
|
|
// Initialize flag
|
|
//
|
|
pxlpdev->dwFlags |= XLPDEV_FLAGS_FIRSTPAGE;
|
|
|
|
return DrvStartDoc(
|
|
pso,
|
|
pwszDocName,
|
|
dwJobId);
|
|
}
|
|
|
|
|
|
extern "C" BOOL APIENTRY
|
|
PCLXLEndDoc(
|
|
SURFOBJ *pso,
|
|
FLONG fl)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev;
|
|
PXLPDEV pxlpdev;
|
|
BOOL bRet;
|
|
|
|
VERBOSE(("PCLXLEndDoc() entry.\n"));
|
|
|
|
if (NULL == pdevobj->pdevOEM)
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
{
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
if (S_OK == RemoveAllFonts(pdevobj))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
|
|
pxlpdev->dwFlags |= XLPDEV_FLAGS_ENDDOC_CALLED;
|
|
|
|
return bRet && DrvEndDoc(pso, fl);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Sub functions
|
|
//
|
|
|
|
HRESULT
|
|
RemoveAllFonts(
|
|
PDEVOBJ pdevobj)
|
|
{
|
|
PXLPDEV pxlpdev;
|
|
XLOutput *pOutput;
|
|
DWORD dwI;
|
|
HRESULT hResult;
|
|
|
|
pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
pOutput = pxlpdev->pOutput;
|
|
|
|
hResult = S_OK;
|
|
|
|
for (dwI = 0; dwI < pxlpdev->dwNumOfTTFont; dwI++)
|
|
{
|
|
if (S_OK != pOutput->Send_ubyte_array_header(PCLXL_FONTNAME_SIZE) ||
|
|
S_OK != pOutput->Write(PubGetFontName(pdevobj, dwI+1), PCLXL_FONTNAME_SIZE)||
|
|
S_OK != pOutput->Send_attr_ubyte(eFontName) ||
|
|
S_OK != pOutput->Send_cmd(eRemoveFont))
|
|
{
|
|
hResult = S_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
pOutput->Flush(pdevobj);
|
|
pxlpdev->dwNumOfTTFont = 0;
|
|
return hResult;
|
|
}
|
|
|
|
HRESULT
|
|
CommonRopBlt(
|
|
IN PDEVOBJ pdevobj,
|
|
IN SURFOBJ *psoSrc,
|
|
IN CLIPOBJ *pco,
|
|
IN XLATEOBJ *pxlo,
|
|
IN BRUSHOBJ *pbo,
|
|
IN RECTL *prclSrc,
|
|
IN RECTL *prclDst,
|
|
IN POINTL *pptlBrush,
|
|
IN ROP4 rop4)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
HRESULT hRet;
|
|
|
|
VERBOSE(("CommonRopBlt() entry.\n"));
|
|
|
|
//
|
|
// Error check
|
|
//
|
|
|
|
if (pdevobj == NULL ||
|
|
prclDst == NULL )
|
|
{
|
|
ERR(("CommonRopBlt: one of parameters is NULL.\n"));
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
|
|
hRet = S_OK;
|
|
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
OutputFormat OutputF;
|
|
|
|
//
|
|
// Set Clip
|
|
//
|
|
if (!SUCCEEDED(pOutput->SetClip(pco)))
|
|
return S_FALSE;
|
|
|
|
//
|
|
// Set Cursor
|
|
//
|
|
pOutput->SetCursor(prclDst->left, prclDst->top);
|
|
|
|
//
|
|
// 1. ROP conversion
|
|
//
|
|
// (1) Fill Dstination
|
|
// 0x00 BLACKNESS
|
|
// 0xFF WHITENESS
|
|
//
|
|
// (2) Pattern copy -> P
|
|
// 0xF0 PATCOPY P
|
|
//
|
|
// (3) SRC/NOTSRCOPY -> S or ~S
|
|
// 0x11 ~( S | D)
|
|
// 0x33 ~S
|
|
// 0x44 ( S & ~D)
|
|
// 0x66 ( D ^ S)
|
|
// 0x77 ~( D & S)
|
|
// 0x99 ~( S ^ D)
|
|
// 0xCC S
|
|
// 0xDD ( S | ~D)
|
|
//
|
|
// (4) Misc ROP support
|
|
// 0xAA D
|
|
// 0x0F PATNOT ~P
|
|
//
|
|
//
|
|
ROP3 rop3 = GET_FOREGROUND_ROP3(rop4);
|
|
DWORD dwCase = 0;
|
|
|
|
#define ROP_BLACKWHITE 0x1
|
|
#define ROP_PATTERN 0x2
|
|
#define ROP_BITMAP 0x4
|
|
#define ROP_DEST 0x8
|
|
|
|
|
|
//
|
|
// Set ROP3
|
|
//
|
|
pOutput->SetROP3(GET_FOREGROUND_ROP3(rop4));
|
|
|
|
switch (rop3)
|
|
{
|
|
case 0x00:
|
|
case 0xFF:
|
|
dwCase = ROP_BLACKWHITE;
|
|
break;
|
|
|
|
case 0xF0:
|
|
dwCase = ROP_PATTERN;
|
|
break;
|
|
|
|
case 0x11:
|
|
case 0x33:
|
|
case 0x44:
|
|
case 0x66:
|
|
case 0x77:
|
|
case 0x99:
|
|
case 0xCC:
|
|
case 0xDD:
|
|
dwCase = ROP_BITMAP;
|
|
break;
|
|
|
|
case 0xAA:
|
|
dwCase = ROP_DEST;
|
|
break;
|
|
|
|
case 0x0F:
|
|
dwCase = ROP_PATTERN;
|
|
break;
|
|
|
|
default:
|
|
if (ROP3_NEED_SOURCE(rop3))
|
|
{
|
|
dwCase |= ROP_BITMAP;
|
|
}
|
|
if (ROP3_NEED_PATTERN(rop3))
|
|
{
|
|
dwCase |= ROP_PATTERN;
|
|
}
|
|
if (ROP3_NEED_DEST(rop3))
|
|
{
|
|
dwCase |= ROP_DEST;
|
|
}
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Black & White case
|
|
//
|
|
if (dwCase & ROP_BLACKWHITE)
|
|
{
|
|
VERBOSE(("CommonRopBlt(): BlackWhite.\n"));
|
|
//
|
|
// SetBrushSource
|
|
// NewPath
|
|
// RectanglePath
|
|
// PaintPath
|
|
//
|
|
|
|
CMNBRUSH CmnBrush;
|
|
CmnBrush.dwSig = BRUSH_SIGNATURE;
|
|
CmnBrush.BrushType = kBrushTypeSolid;
|
|
CmnBrush.ulSolidColor = 0x00;
|
|
CmnBrush.ulHatch = 0xFFFFFFFF;
|
|
CmnBrush.dwColor = 0x00FFFFFF;
|
|
CmnBrush.dwPatternBrushID = 0xFFFFFFFF;
|
|
|
|
pOutput->SetSourceTxMode(eOpaque);
|
|
pOutput->SetPaintTxMode(eOpaque);
|
|
|
|
if(rop3 == 0x00)
|
|
{
|
|
if (e24Bit == pOutput->GetDeviceColorDepth())
|
|
{
|
|
pOutput->SetRGBColor(0);
|
|
CmnBrush.dwColor = 0x00;
|
|
}
|
|
else
|
|
{
|
|
pOutput->SetGrayLevel(0x00);
|
|
CmnBrush.dwColor = 0x00;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (e24Bit == pOutput->GetDeviceColorDepth())
|
|
{
|
|
pOutput->SetRGBColor(0x00ffffff);
|
|
CmnBrush.dwColor = 0x00ffffff;
|
|
}
|
|
else
|
|
{
|
|
pOutput->SetGrayLevel(0xff);
|
|
CmnBrush.dwColor = 0x00ffffff;
|
|
}
|
|
}
|
|
|
|
((XLBrush*)pOutput)->SetBrush(&CmnBrush);
|
|
|
|
pOutput->Send_cmd(eSetBrushSource);
|
|
pOutput->SetPenColor(NULL, NULL);
|
|
if (!(dwCase & ROP_BITMAP))
|
|
{
|
|
pOutput->Send_cmd(eNewPath);
|
|
pOutput->RectanglePath(prclDst);
|
|
pOutput->Send_cmd(ePaintPath);
|
|
}
|
|
pOutput->Flush(pdevobj);
|
|
}
|
|
|
|
//
|
|
// Pattern fill case
|
|
//
|
|
if (dwCase & (ROP_DEST|ROP_PATTERN))
|
|
{
|
|
VERBOSE(("CommonRopBlt(): Pattern.\n"));
|
|
|
|
//
|
|
// SetPaintTxMode
|
|
// SetSourceTxMode
|
|
// SetBrushSource
|
|
// NewPath
|
|
// RectanglePath
|
|
// PaintPath
|
|
//
|
|
pOutput->SetSourceTxMode(eOpaque);
|
|
pOutput->SetPaintTxMode(eOpaque);
|
|
pOutput->SetBrush(pbo, pptlBrush);
|
|
pOutput->SetPenColor(NULL, NULL);
|
|
if (!(dwCase & ROP_BITMAP))
|
|
{
|
|
pOutput->Send_cmd(eNewPath);
|
|
pOutput->RectanglePath(prclDst);
|
|
pOutput->Send_cmd(ePaintPath);
|
|
}
|
|
pOutput->Flush(pdevobj);
|
|
}
|
|
|
|
//
|
|
// Bitmap case
|
|
//
|
|
if (dwCase & ROP_BITMAP)
|
|
{
|
|
LONG lHeight, lWidth, lScanline;
|
|
ULONG ulOutputBPP, ulInputBPP;
|
|
DWORD dwI, dwBufSize, dwLen, dwcbLineSize, dwcbBmpSize;
|
|
PDWORD pdwLen;
|
|
PBYTE pubSrc, pBuf, pBufOrg = NULL, pBmpSize, pBufEnd;
|
|
ColorMapping CMapping;
|
|
SURFOBJ *psoBmp;
|
|
HBITMAP hBitmap = NULL;
|
|
PBYTE pubChanged = NULL;
|
|
// temporary rectangle used if the image is downscaled by the engine
|
|
RECTL rctlBitmap;
|
|
|
|
// zero out the temporary rectangle
|
|
memset( &rctlBitmap, 0, sizeof(RECTL) );
|
|
|
|
|
|
VERBOSE(("CommonRopBlt(): Bitmap\n"));
|
|
|
|
if (psoSrc == NULL ||
|
|
prclSrc == NULL )
|
|
{
|
|
ERR(("UNIDRV:CommonRopBlt:psoSrc, pxlo, or prclSrc == NULL.\n"));
|
|
pOutput->Flush(pdevobj);
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
//
|
|
// Input BPP
|
|
//
|
|
|
|
ulInputBPP = UlBPPtoNum((BPP)psoSrc->iBitmapFormat);
|
|
|
|
psoBmp = NULL;
|
|
|
|
//
|
|
// If the source image is larger than it will appear on the
|
|
// destination surface, shrink it to the target size. No point
|
|
// in sending extra bits.
|
|
//
|
|
// This optimization could be further optimized by building up a clip
|
|
// object here if one is specified. How much of a gain this is
|
|
// worth I don't know.
|
|
//
|
|
if (prclDst->right - prclDst->left < prclSrc->right - prclSrc->left ||
|
|
prclDst->bottom - prclDst->top < prclSrc->bottom - prclSrc->top )
|
|
{
|
|
|
|
//
|
|
// Shrink source bitmap.
|
|
//
|
|
PDEV *pPDev = (PDEV*)pdevobj;
|
|
SIZEL sizlDest;
|
|
DWORD dwScanlineLength;
|
|
POINTL ptlBrushOrg;
|
|
|
|
// Translate destination rectangle to origin 0,0 and same dimensions as before
|
|
rctlBitmap.left = 0;
|
|
rctlBitmap.top = 0;
|
|
rctlBitmap.right = prclDst->right - prclDst->left;
|
|
rctlBitmap.bottom = prclDst->bottom - prclDst->top;
|
|
|
|
|
|
sizlDest.cx = prclDst->right - prclDst->left;
|
|
sizlDest.cy = prclDst->bottom - prclDst->top;
|
|
dwScanlineLength = (sizlDest.cx * ulInputBPP + 7 ) >> 3;
|
|
|
|
if (pptlBrush)
|
|
{
|
|
ptlBrushOrg = *pptlBrush;
|
|
}
|
|
else
|
|
{
|
|
ptlBrushOrg.x = ptlBrushOrg.y = 0;
|
|
}
|
|
|
|
// When we do the transfer, don't do color translation because that will be handled by the printer.
|
|
// Also, don't pass the clip object, because it's in the wrong coordinate space. We could build a
|
|
// a new clip object, but the value of doing so is questionable, and it would take a lot more testing.
|
|
if ((psoBmp = CreateBitmapSURFOBJ(pPDev,
|
|
&hBitmap,
|
|
sizlDest.cx,
|
|
sizlDest.cy,
|
|
psoSrc->iBitmapFormat)) &&
|
|
EngStretchBlt(psoBmp, psoSrc, NULL, NULL, NULL, NULL, &ptlBrushOrg, &rctlBitmap, prclSrc, NULL, HALFTONE))
|
|
{
|
|
psoSrc = psoBmp;
|
|
prclSrc = &rctlBitmap;
|
|
}
|
|
else
|
|
{
|
|
ERR(("CreateBitmapSURFOBJ or EngStretchBlt failed.\n"));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set source opaque mode
|
|
// GDI bug. CopyBits is called recursively.
|
|
//
|
|
{
|
|
PDEV *pPDev = (PDEV*)pdevobj;
|
|
if (pPDev->fMode2 & PF2_SURFACE_WHITENED)
|
|
{
|
|
pOutput->SetSourceTxMode(eTransparent);
|
|
}
|
|
else
|
|
{
|
|
pOutput->SetSourceTxMode(eOpaque);
|
|
}
|
|
}
|
|
pOutput->SetPaintTxMode(eOpaque);
|
|
|
|
//
|
|
// Bitmap output
|
|
//
|
|
DetermineOutputFormat(pxlo, pOutput->GetDeviceColorDepth(), psoSrc->iBitmapFormat, &OutputF, &ulOutputBPP);
|
|
|
|
if (pOutput->GetDeviceColorDepth() == e24Bit)
|
|
{
|
|
pOutput->SetColorSpace(eRGB);
|
|
}
|
|
else
|
|
{
|
|
pOutput->SetColorSpace(eGray);
|
|
}
|
|
if (OutputF == eOutputPal)
|
|
{
|
|
DWORD *pdwColorTable = NULL;
|
|
|
|
if (pdwColorTable = GET_COLOR_TABLE(pxlo))
|
|
{
|
|
if ( pxlpdev->dwFlags & XLPDEV_FLAGS_SUBST_TRNCOLOR_WITH_WHITE )
|
|
{
|
|
|
|
ULONG ulTransColor = pxlpdev->ulTransColor;
|
|
pdwColorTable = PdwChangeTransparentPalette(ulTransColor, pdwColorTable, pxlo->cEntries);
|
|
if (pdwColorTable)
|
|
{
|
|
pOutput->SetPalette(ulOutputBPP, pxlo->cEntries, pdwColorTable);
|
|
MemFree (pdwColorTable);
|
|
pdwColorTable = NULL;
|
|
}
|
|
else
|
|
{
|
|
ERR(("CommonRopBlt: PdwChangeTransparentPalette returned NULL.\n"));
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
pOutput->SetPalette(ulOutputBPP, pxlo->cEntries, pdwColorTable);
|
|
}
|
|
}
|
|
CMapping = eIndexedPixel;
|
|
}
|
|
else
|
|
{
|
|
CMapping = eDirectPixel;
|
|
}
|
|
|
|
pOutput->Send_cmd(eSetColorSpace);
|
|
|
|
//
|
|
// Get height, width, and scanline size.
|
|
//
|
|
lWidth = prclSrc->right - prclSrc->left;
|
|
lHeight = prclSrc->bottom - prclSrc->top;
|
|
dwcbLineSize = ((lWidth * ulInputBPP) + 7) >> 3;
|
|
|
|
//
|
|
// Allocates memory to hold whole bitmap.
|
|
//
|
|
dwBufSize = lHeight * (((lWidth * ulOutputBPP + 31) >> 5 ) << 2);
|
|
|
|
//
|
|
// Limit Buffer Size to 16k, else if the scan line is big, huge memory will
|
|
// be allocated. But the size has to be at least able to hold one scanline.
|
|
//
|
|
#define BMPBUFSIZE 16384
|
|
if (dwBufSize > BMPBUFSIZE)
|
|
{
|
|
if (dwcbLineSize > BMPBUFSIZE)
|
|
dwBufSize = dwcbLineSize;
|
|
else
|
|
dwBufSize = BMPBUFSIZE;
|
|
}
|
|
|
|
|
|
//
|
|
// Allocate appropriate buffers before doing BeginImage.
|
|
// PCLXL expects certain things to happen after BeginImage.
|
|
// If we attempt to allocate within BeginImage and then allocation
|
|
// fails, and we try to exit midway, PCLXL will not be able to handle
|
|
// the resulting output properly.
|
|
//
|
|
// When doing TransparentBlt, we need to change colors of pixels. Instead of
|
|
// altering memory within psoSrc, we'll make copy of scan line and then alter images.
|
|
// So memory needs to be allocated for that.
|
|
//
|
|
if ( pxlpdev->dwFlags & XLPDEV_FLAGS_SUBST_TRNCOLOR_WITH_WHITE &&
|
|
eDirectPixel == CMapping )
|
|
{
|
|
if ( NULL == (pubChanged = (PBYTE) MemAlloc(dwcbLineSize)) )
|
|
{
|
|
ERR(("CommonRopBlt: Cannot allocate memory for pubChanged.\n"));
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allocate output buffer
|
|
//
|
|
if (NULL == (pBuf = (PBYTE)MemAlloc(dwBufSize)))
|
|
{
|
|
ERR(("CommonRopBlt: MemAlloc failed.\n"));
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// BeginImage
|
|
//
|
|
pOutput->BeginImage(
|
|
CMapping,
|
|
ulOutputBPP,
|
|
lWidth,
|
|
lHeight,
|
|
prclDst->right - prclDst->left,
|
|
prclDst->bottom - prclDst->top);
|
|
pOutput->Flush(pdevobj);
|
|
|
|
|
|
VERBOSE(("CommonRopBlt: ulInputBPP=%d, ulOutputBPP=%d, lWidth=0x%x, lHeight=0x%x, dwcbLineSize=0x%x, dwBufSize=0x%x\n",ulInputBPP, ulOutputBPP, lWidth, lHeight, dwcbLineSize, dwBufSize));
|
|
|
|
pBufOrg = pBuf;
|
|
pBufEnd = pBuf + (ULONG_PTR)(dwBufSize); //point pBufEnd to byte after last allocatted byte.
|
|
|
|
CompressMode CurrentCMode, PreviousCMode;
|
|
BMPConv BMPC;
|
|
PBYTE pubDst;
|
|
DWORD dwSize;
|
|
|
|
LONG lScans, //number of scan lines stored in pBufOrg
|
|
lStart; //From which scan line do we start sending scan lines to printer.
|
|
//e.g. if lStart=5, it means 0-4 scan lines have been sent, now 5th scan line (and may be more) has to be sent
|
|
|
|
#if DBG
|
|
BMPC.SetDbgLevel(BITMAPDBG);
|
|
#endif
|
|
BMPC.BSetInputBPP((BPP)psoSrc->iBitmapFormat);
|
|
BMPC.BSetOutputBPP(NumToBPP(ulOutputBPP));
|
|
BMPC.BSetOutputBMPFormat(OutputF);
|
|
BMPC.BSetXLATEOBJ(pxlo);
|
|
|
|
lScanline = lHeight;
|
|
|
|
//
|
|
// Set pubSrc
|
|
//
|
|
pubSrc = (PBYTE)psoSrc->pvScan0;
|
|
if (!psoBmp)
|
|
{
|
|
pubSrc += (LONG_PTR) prclSrc->top * psoSrc->lDelta + ((ulInputBPP * prclSrc->left) >> 3);
|
|
}
|
|
|
|
dwcbBmpSize = 0;
|
|
lScans = 0;
|
|
lStart = 0;
|
|
|
|
PreviousCMode = eInvalidValue;
|
|
|
|
while (lScanline-- > 0)
|
|
{
|
|
PBYTE pubSrcLocal = pubSrc;
|
|
|
|
//
|
|
// When this is called from TransparentBlt, the Transparent Color
|
|
// has to be replaced by white. This is to be done only for
|
|
// direct images, not for paletted images.
|
|
//
|
|
if ( (pxlpdev->dwFlags & XLPDEV_FLAGS_SUBST_TRNCOLOR_WITH_WHITE) &&
|
|
eDirectPixel == CMapping )
|
|
{
|
|
hRet = hrChangePixelColorInScanLine( pubSrc,
|
|
ulInputBPP,
|
|
lWidth,
|
|
pxlpdev->ulTransColor,
|
|
pubChanged,
|
|
dwcbLineSize);
|
|
if ( FAILED (hRet) )
|
|
{
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
pubSrcLocal = pubChanged;
|
|
|
|
}
|
|
|
|
//
|
|
// First try compression and see if the compress data is smaller
|
|
// than the original data. If it's smaller, go ahead to use the
|
|
// compression. Otherwise, use original data.
|
|
//
|
|
// While it is permitted to mix eRLECompression and eNoCompression
|
|
// blocks of ReadImage data, XL does not allow mixing JPEG or
|
|
// DeltaRow image blocks with any other compression method.
|
|
//
|
|
|
|
//
|
|
// DRC Compression
|
|
//
|
|
if (COMMANDPTR(((PPDEV)pdevobj)->pDriverInfo,CMD_ENABLEDRC))
|
|
{
|
|
CurrentCMode = eDeltaRowCompression;
|
|
BMPC.BSetCompressionType(CurrentCMode);
|
|
pubDst = BMPC.PubConvertBMP(pubSrcLocal, dwcbLineSize);
|
|
dwSize = BMPC.DwGetDstSize();
|
|
VERBOSE(("CommonRopBlt: Comp(DRC:0x%x)\n", dwSize));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// RLE compression
|
|
//
|
|
BMPC.BSetCompressionType(eRLECompression);
|
|
pubDst = BMPC.PubConvertBMP(pubSrcLocal, dwcbLineSize);
|
|
dwSize = BMPC.DwGetDstSize();
|
|
VERBOSE(("CommonRopBlt: Comp(RLE:0x%x)\n", dwSize));
|
|
|
|
if (dwSize < dwcbLineSize)
|
|
{
|
|
CurrentCMode = eRLECompression;
|
|
}
|
|
else
|
|
{
|
|
CurrentCMode = eNoCompression;
|
|
BMPC.BSetCompressionType(eNoCompression);
|
|
pubDst = BMPC.PubConvertBMP(pubSrcLocal, dwcbLineSize);
|
|
dwSize = BMPC.DwGetDstSize();
|
|
VERBOSE(("CommonRopBlt: Comp(NO:0x%x)\n", dwSize));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Output bitmap.
|
|
// 1. Mostly we try to store the data bits in pBufOrg and send them
|
|
// all at once after processing has been done on the full image.
|
|
// This storage is done on a per scan line basis.
|
|
// But if image is really big, pBufOrg gets filled up and more
|
|
// scan lines cannot be copied. So we empty pBufOrg to make place
|
|
// for remaining scan lines. If either of these is true, pBufOrg
|
|
// needs to be flushed. (Both these conditions are essentially the same).
|
|
// dwcbBmpSize + dwSize > dwBufSize
|
|
// pBuf + dwSize > pBufEnd
|
|
//
|
|
// 2. If the compression has to change, we dump the data bits
|
|
// using the older compression method that have been stored in
|
|
// pBufOrg and/or pbDst.
|
|
//
|
|
|
|
if (dwcbBmpSize + dwSize > dwBufSize ||
|
|
PreviousCMode != eInvalidValue && PreviousCMode != CurrentCMode)
|
|
{
|
|
if (PreviousCMode == eInvalidValue)
|
|
{
|
|
PreviousCMode = CurrentCMode;
|
|
}
|
|
|
|
//
|
|
// Four possible cases
|
|
// 1&2. dwcbBmpSize == 0 i.e. nothing is present in pBufOrg
|
|
// So just dump whatever is present in pubDst.
|
|
// This covers both cases i.e. whether dwSize > dwBufSize or not.
|
|
// 3. dwcmBmpSize is not zero
|
|
// dump the image in pBufOrg, clean pBufOrg, and then later
|
|
// on put the contents of pubDst in pBufOrg(pBuf).
|
|
// 4. dwcbBmpSize is not zero and dwSize > dwBufSize
|
|
// i.e. somehow the compression caused the size of the
|
|
// scan line to increase beyond the dwBufSize.
|
|
// Because pBufOrg is at most dwBufSize, we cannot
|
|
// copy pubDst to pBufOrg. So we have to dump pubDst here.
|
|
//
|
|
|
|
if (dwcbBmpSize == 0)
|
|
{
|
|
//
|
|
// Case 1&2
|
|
//
|
|
BSendReadImageData(pdevobj,
|
|
PreviousCMode,
|
|
pubDst,
|
|
lStart,
|
|
1,
|
|
dwSize);
|
|
dwSize = 0;
|
|
lStart++; //One line emitted. Therefore increment lStart
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// There is some image data stored in the pBufOrg buffer.
|
|
// Emit that data. (case 3)
|
|
//
|
|
BSendReadImageData(pdevobj,
|
|
PreviousCMode,
|
|
pBufOrg,
|
|
lStart,
|
|
lScans,
|
|
dwcbBmpSize);
|
|
lStart += lScans; //lScans lines emitted
|
|
|
|
if ( dwSize > dwBufSize )
|
|
{
|
|
//
|
|
// Case 4.
|
|
//
|
|
BSendReadImageData(pdevobj,
|
|
PreviousCMode,
|
|
pubDst,
|
|
lStart,
|
|
1,
|
|
dwSize);
|
|
dwSize = 0;
|
|
lStart++;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// Reset parameters
|
|
//
|
|
dwcbBmpSize = 0;
|
|
lScans = 0;
|
|
pBuf = pBufOrg;
|
|
|
|
}
|
|
|
|
if (NULL == pubDst)
|
|
{
|
|
ERR(("CommonRopBlt: Conversion failed. pubDst is NULL.\n"));
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// If post-compression size of image is more than zero, AND
|
|
// if destination buffer(pBuf) has enough space, then copy the compressed
|
|
// data to the destination. (Data can also be in uncompressed format if
|
|
// compression does not result in size saving).
|
|
// Increment lScans to indicicate that we are putting one more scan
|
|
// line worth of data in pBufOrg
|
|
//
|
|
if (dwSize > 0 &&
|
|
pBuf + dwSize <= pBufEnd)
|
|
{
|
|
memcpy(pBuf, pubDst, dwSize);
|
|
dwcbBmpSize += dwSize;
|
|
pBuf += dwSize;
|
|
lScans ++;
|
|
}
|
|
|
|
PreviousCMode = CurrentCMode;
|
|
|
|
if (CurrentCMode == eNoCompression)
|
|
{
|
|
DWORD dwDiff = (((lWidth * ulOutputBPP + 31) >> 5) << 2) - dwSize;
|
|
if (dwDiff)
|
|
{
|
|
memset(pBuf, 0, dwDiff);
|
|
dwcbBmpSize += dwDiff;
|
|
pBuf += dwDiff;
|
|
}
|
|
}
|
|
|
|
|
|
pubSrc += psoSrc->lDelta;
|
|
}
|
|
|
|
if (dwcbBmpSize > 0)
|
|
{
|
|
BSendReadImageData(pdevobj, CurrentCMode, pBufOrg, lStart, lScans, dwcbBmpSize);
|
|
}
|
|
pOutput->Send_cmd(eEndImage);
|
|
pOutput->Flush(pdevobj);
|
|
}
|
|
|
|
ErrorReturn:
|
|
if (pBufOrg != NULL)
|
|
MemFree(pBufOrg);
|
|
|
|
if ( NULL != pubChanged )
|
|
{
|
|
MemFree(pubChanged);
|
|
}
|
|
|
|
if (NULL != psoBmp)
|
|
{
|
|
EngUnlockSurface(psoBmp);
|
|
if (hBitmap && !EngDeleteSurface((HSURF)hBitmap))
|
|
{
|
|
ERR(("CommonRopBlt: EngDeleteSurface failed.\n"));
|
|
hRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hRet;
|
|
}
|
|
|
|
BOOL
|
|
BSendReadImageData(
|
|
IN PDEVOBJ pdevobj,
|
|
IN CompressMode CMode,
|
|
IN PBYTE pBuf,
|
|
IN LONG lStart,
|
|
IN LONG lHeight,
|
|
IN DWORD dwcbSize)
|
|
{
|
|
VERBOSE(("BSendReadImageData(CMode=%d, lHeight=0x%x, dwcbSize=0x%x\n", CMode, lHeight, dwcbSize));
|
|
//
|
|
// dataLength (1)
|
|
// size (byte or long) (1 or 4)
|
|
//
|
|
DWORD dwHeaderSize;
|
|
BYTE aubHeader[DATALENGTH_HEADER_SIZE];
|
|
PXLPDEV pxlpdev = (PXLPDEV)pdevobj->pdevOEM;
|
|
|
|
XLOutput *pOutput = pxlpdev->pOutput;
|
|
//
|
|
// Print the converted data.
|
|
//
|
|
pOutput->ReadImage(lStart, lHeight, CMode);
|
|
pOutput->Flush(pdevobj);
|
|
|
|
if (dwcbSize > 0xff)
|
|
{
|
|
//
|
|
// dataLength
|
|
// size (uin32) (bitmap size)
|
|
//
|
|
aubHeader[0] = PCLXL_dataLength;
|
|
dwHeaderSize = DATALENGTH_HEADER_SIZE;
|
|
CopyMemory(aubHeader + 1, &dwcbSize, sizeof(dwcbSize));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// dataLength
|
|
// size (byte) (bitmap size)
|
|
//
|
|
aubHeader[0] = PCLXL_dataLengthByte;
|
|
dwHeaderSize = DATALENGTH_HEADER_SIZE - 3;
|
|
CopyMemory(aubHeader + 1, &dwcbSize, sizeof(BYTE));
|
|
}
|
|
|
|
//
|
|
// dataLength
|
|
// size (byte/uint32)
|
|
// DATA
|
|
// EndImage
|
|
//
|
|
WriteSpoolBuf((PPDEV)pdevobj, aubHeader, dwHeaderSize);
|
|
WriteSpoolBuf((PPDEV)pdevobj, pBuf, dwcbSize);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
inline
|
|
VOID
|
|
DetermineOutputFormat(
|
|
XLATEOBJ *pxlo,
|
|
ColorDepth DeviceColorDepth,
|
|
INT iBitmapFormat,
|
|
OutputFormat *pOutputF,
|
|
ULONG *pulOutputBPP)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
switch ((BPP)iBitmapFormat)
|
|
{
|
|
case e1bpp:
|
|
case e4bpp:
|
|
*pOutputF = eOutputPal;
|
|
break;
|
|
|
|
case e8bpp:
|
|
case e16bpp:
|
|
//
|
|
// Color device or not?
|
|
//
|
|
if (DeviceColorDepth == e24Bit)
|
|
*pOutputF = eOutputPal;
|
|
else
|
|
*pOutputF = eOutputGray;
|
|
break;
|
|
|
|
case e24bpp:
|
|
case e32bpp:
|
|
//
|
|
// Color device or not?
|
|
//
|
|
if (DeviceColorDepth == e24Bit)
|
|
*pOutputF = eOutputRGB;
|
|
else
|
|
*pOutputF = eOutputGray;
|
|
break;
|
|
}
|
|
|
|
switch (*pOutputF)
|
|
{
|
|
case eOutputGray:
|
|
*pulOutputBPP = 8;
|
|
break;
|
|
|
|
case eOutputPal:
|
|
*pulOutputBPP = UlBPPtoNum((BPP)iBitmapFormat);
|
|
break;
|
|
|
|
case eOutputRGB:
|
|
case eOutputCMYK:
|
|
*pulOutputBPP = 24;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Make sure that color table is available for palette output.
|
|
//
|
|
if (*pOutputF == eOutputPal)
|
|
{
|
|
if (!(GET_COLOR_TABLE(pxlo)))
|
|
{
|
|
if (DeviceColorDepth == e24Bit)
|
|
{
|
|
*pOutputF = eOutputRGB;
|
|
*pulOutputBPP = 24;
|
|
}
|
|
else
|
|
{
|
|
*pOutputF = eOutputGray;
|
|
*pulOutputBPP = 8;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
PDWORD
|
|
PdwChangeTransparentPalette(
|
|
ULONG iTransColor,
|
|
PDWORD pdwColorTable,
|
|
DWORD dwEntries)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Creates another copy of palatte and replace the transparent color by white
|
|
Returns the pointer of a new palette.
|
|
The calling function has responsibility to release the palette.
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
{
|
|
PDWORD pdwNewPalette = NULL;
|
|
|
|
//
|
|
// Parameter check
|
|
//
|
|
if (NULL == pdwColorTable ||
|
|
dwEntries == 0 )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (NULL == (pdwNewPalette = (PDWORD)MemAlloc(sizeof(DWORD) * dwEntries)))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
CopyMemory(pdwNewPalette, pdwColorTable, sizeof(DWORD) * dwEntries);
|
|
|
|
//
|
|
// When printing in palette mode, iTransColor indicates the index into
|
|
// the palette, instead of the color in the palette. The palette entry
|
|
// at that index is the color.
|
|
//
|
|
pdwNewPalette[iTransColor] = RGB_WHITE;
|
|
|
|
|
|
return pdwNewPalette;
|
|
}
|
|
|
|
|
|
/*++
|
|
|
|
Routine Name
|
|
hrChangePixelColorInScanLine
|
|
|
|
Routine Description:
|
|
Changes the pixels in scan line that match a certain color to White
|
|
|
|
Arguments:
|
|
pubSrc : The original scan line.
|
|
ulBPP : Bits Per Pixel of scan line.
|
|
ulNumPixels : Number of Pixels in the scan line.
|
|
ulTransColor: The color that needs to be changed.
|
|
pubChanged : The memory where the new(changed) scan line should be put.
|
|
ulNumBytes : Number of bytes in pubChanged buffer.
|
|
|
|
Return Value:
|
|
S_OK : if success
|
|
E_FAIL: Otherwise
|
|
|
|
|
|
Note:
|
|
|
|
|
|
--*/
|
|
HRESULT hrChangePixelColorInScanLine(
|
|
IN PBYTE pubSrc,
|
|
IN ULONG ulBPP,
|
|
IN ULONG ulNumPixels,
|
|
IN ULONG ulTransColor,
|
|
IN OUT PBYTE pubChanged,
|
|
IN ULONG ulNumBytes )//NumBytes in pubChanged
|
|
|
|
{
|
|
|
|
ULONG ulBytesPerPixel = 3; //24bpp is more common that 16 or 32bpp
|
|
ULONG ulColor = 0;
|
|
ULONG ulDestSize = 0; //Required destination number of bytes.
|
|
HRESULT hr = S_OK;
|
|
|
|
//
|
|
// First do input validation
|
|
//
|
|
if ( NULL == pubSrc ||
|
|
NULL == pubChanged )
|
|
{
|
|
ASSERT(("Null Parameter\n"));
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
//
|
|
// Make sure pubChanged has enough memory to hold
|
|
// the changed scan line.
|
|
//
|
|
|
|
ulBytesPerPixel = ulBPP >> 3; //8 bits per pixel.
|
|
ulDestSize = ulBytesPerPixel * ulNumPixels;
|
|
|
|
if ( ulNumBytes < ulDestSize )
|
|
{
|
|
ASSERT((FALSE, "Insufficient size of destination buffer\n"));
|
|
return E_FAIL;
|
|
}
|
|
|
|
//
|
|
// Copy Scanline from Source to Destination. Then go through the scan line and
|
|
// change the transparent color to white
|
|
// Go through each pixel (there are ulNumPixels pixels).
|
|
// Whenever the pixels's color is same as ulTransColor, replace it
|
|
// with white.
|
|
//
|
|
// Only direct images are supported in this function.
|
|
// No palletes.
|
|
// 8bpp images are mostly palettes. But when printing to monochrome
|
|
// pclxl device, they are being treated as direct images.
|
|
//
|
|
CopyMemory (pubChanged, pubSrc, ulNumBytes);
|
|
|
|
switch (ulBPP)
|
|
{
|
|
case 8:
|
|
{
|
|
for (ULONG ul = 0; ul < ulNumPixels ; ul++, pubChanged += ulBytesPerPixel)
|
|
{
|
|
ulColor = (ULONG) pubChanged[0] ;
|
|
|
|
if ( ulTransColor == ulColor )
|
|
{
|
|
pubChanged[0] = 0xFF;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 16:
|
|
{
|
|
for (ULONG ul = 0; ul < ulNumPixels ; ul++, pubChanged += ulBytesPerPixel)
|
|
{
|
|
ulColor = ((ULONG) pubChanged[0]) | ((ULONG) pubChanged[1] << 8);
|
|
|
|
if ( ulTransColor == ulColor )
|
|
{
|
|
pubChanged[0] = 0xFF;
|
|
pubChanged[1] = 0xFF;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 24:
|
|
{
|
|
|
|
for (ULONG ul = 0; ul < ulNumPixels ; ul++, pubChanged += ulBytesPerPixel)
|
|
{
|
|
ulColor = ((ULONG) pubChanged[0]) |
|
|
((ULONG) pubChanged[1] << 8) |
|
|
((ULONG) pubChanged[2] << 16);
|
|
|
|
if ( ulTransColor == ulColor )
|
|
{
|
|
//
|
|
// White is 0xFFFFFF (3 bytes of FF)
|
|
//
|
|
pubChanged[0] = 0xFF;
|
|
pubChanged[1] = 0xFF;
|
|
pubChanged[2] = 0xFF;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 32:
|
|
{
|
|
for (ULONG ul = 0; ul < ulNumPixels ; ul++, pubChanged += ulBytesPerPixel)
|
|
{
|
|
ulColor = *(PDWORD)pubChanged;
|
|
if ( ulTransColor == ulColor )
|
|
{
|
|
*(PDWORD)pubChanged |= 0x00FFFFFF; //This modifies only RGB. Alpha channel info retained.
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
ASSERT((FALSE, "Unsupported bpp value %d\n", ulBPP));
|
|
hr = E_FAIL;
|
|
|
|
} //switch
|
|
|
|
return hr;
|
|
}
|