2025-04-27 07:49:33 -04:00

2199 lines
50 KiB
C++

/*++
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 Whistler
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
//
inline
VOID
DetermineOutputFormat(
INT iBitmapFormat,
OutputFormat *pOutputF,
ULONG *pulOutputBPP);
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);
////////////////////////////////////////////////////////////////////////////////
//
// 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(("PCLXLPlgBlt() 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
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);
//
// 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;
}
//
// 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 = TRUE;
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, dwcbLineSize, dwcbBmpSize;
PDWORD pdwLen;
PBYTE pubSrc, pBufNormal, pBufRLE, pBuf, pBmpSize;
DetermineOutputFormat(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
//
if (NULL == (pBufNormal = (PBYTE)MemAlloc(dwBufSize)) ||
NULL == (pBufRLE = (PBYTE)MemAlloc(dwBufSize)) )
{
if (pBufNormal != NULL)
MemFree(pBufNormal);
ERR(("PCLXLRealizeBrush: MemAlloc failed.\n"));
return FALSE;
}
CompressMode CMode;
BMPConv BMPC;
PBYTE pubDst;
DWORD dwDstSize;
LONG lDelta;
if (psoPattern->lDelta > 0)
{
lDelta = psoPattern->lDelta;
}
else
{
lDelta = -psoPattern->lDelta;
}
#if DBG
BMPC.SetDbgLevel(BRUSHDBG);
#endif
BMPC.BSetInputBPP((BPP)psoPattern->iBitmapFormat);
BMPC.BSetOutputBPP(NumToBPP(ulOutputBPP));
BMPC.BSetOutputBMPFormat(OutputF);
BMPC.BSetXLATEOBJ(pxlo);
#define NO_COMPRESSION 0
#define RLE_COMPRESSION 1
for (dwI = 0; dwI < 2; dwI ++)
{
if (NO_COMPRESSION == dwI)
{
pBuf = pBufNormal;
pdwLen = &dwLenNormal;
}
else
{
pBuf = pBufRLE;
pdwLen = &dwLenRLE;
}
BMPC.BSetRLECompress(dwI == RLE_COMPRESSION);
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;
if (psoPattern->lDelta > 0)
{
pubSrc += lDelta;
}
else
{
pubSrc -= 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
if (dwLenRLE != 0 && dwLenRLE < dwLenNormal)
{
pBuf = pBufRLE;
pdwLen = &dwLenRLE;
CMode = eRLECompression;
MemFree(pBufNormal);
}
else
if (dwLenNormal != 0)
{
pBuf = pBufNormal;
pdwLen = &dwLenNormal;
CMode = eNoCompression;
MemFree(pBufRLE);
}
else
{
MemFree(pBufNormal);
MemFree(pBufRLE);
ERR(("PCLXLRealizeBrush: Conversion failed. Return FALSE.\n"));
return FALSE;
}
//
// Output
//
XLOutput *pOutput = pxlpdev->pOutput;
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;
pOutput->SetColorSpace(eGray);
if (OutputF == eOutputPal)
{
DWORD *pdwColorTable;
if (pxlo && (pdwColorTable = GET_COLOR_TABLE(pxlo)))
{
CMapping = eIndexedPixel;
pOutput->SetPalette(ulOutputBPP, e8Bit, pxlo->cEntries, pdwColorTable);
}
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;
OutputF = eOutputGray;
if (pxlo)
{
pdwColorTable = GET_COLOR_TABLE(pxlo);
}
else
{
pdwColorTable = NULL;
}
//
// 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);
//
// 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(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);
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)
{
pOutput->SetGrayLevel(0x00);
CmnBrush.dwColor = 0x00;
}
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, dwLenNormal, dwLenRLE, dwcbLineSize, dwcbBmpSize;
PDWORD pdwLen;
PBYTE pubSrc, pBufNormal, pBufRLE, pBuf, pBmpSize;
ColorMapping CMapping;
VERBOSE(("CommonRopBlt(): Bitmap\n"));
if (psoSrc == NULL ||
pxlo == 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);
//
// 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(psoSrc->iBitmapFormat, &OutputF, &ulOutputBPP);
pOutput->SetColorSpace(eGray);
if (OutputF == eOutputPal)
{
DWORD *pdwColorTable;
if (pxlo && (pdwColorTable = GET_COLOR_TABLE(pxlo)) &&
S_OK == pOutput->SetPalette(ulOutputBPP, e8Bit, pxlo->cEntries, pdwColorTable))
{
CMapping = eIndexedPixel;
}
else
{
CMapping = eDirectPixel;
}
}
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;
dwBufSize = lHeight * (((lWidth * ulOutputBPP + 31) >> 5 ) << 2) +
DATALENGTH_HEADER_SIZE + sizeof(PCLXL_EndImage);
//
// BeginImage
//
pOutput->BeginImage(
CMapping,
ulOutputBPP,
lWidth,
lHeight,
prclDst->right - prclDst->left,
prclDst->bottom - prclDst->top);
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));
//
// Allocate output buffer
//
if (NULL == (pBufNormal = (PBYTE)MemAlloc(dwBufSize)) ||
NULL == (pBufRLE = (PBYTE)MemAlloc(dwBufSize)) )
{
if (pBufNormal != NULL)
MemFree(pBufNormal);
ERR(("PCLXLRealizeBrush: MemAlloc failed.\n"));
pOutput->Delete();
return FALSE;
}
CompressMode CMode;
BMPConv BMPC;
PBYTE pubDst;
DWORD dwSize;
LONG lDelta;
if (psoSrc->lDelta > 0)
{
lDelta = psoSrc->lDelta;
}
else
{
lDelta = -psoSrc->lDelta;
}
#if DBG
BMPC.SetDbgLevel(BITMAPDBG);
#endif
BMPC.BSetInputBPP((BPP)psoSrc->iBitmapFormat);
BMPC.BSetOutputBPP(NumToBPP(ulOutputBPP));
BMPC.BSetOutputBMPFormat(OutputF);
BMPC.BSetXLATEOBJ(pxlo);
#define NO_COMPRESSION 0
#define RLE_COMPRESSION 1
for (dwI = 0; dwI < 2; dwI ++)
{
if (NO_COMPRESSION == dwI)
{
VERBOSE(("CommonRopBlt(): No-compres\n"));
pBuf = pBufNormal;
pdwLen = &dwLenNormal;
}
else
{
VERBOSE(("CommonRopBlt(): RLE-compres\n"));
pBuf = pBufRLE;
pdwLen = &dwLenRLE;
}
lScanline = lHeight;
//
// Set pubSrc
//
pubSrc = (PBYTE)psoSrc->pvScan0;
if (psoSrc->lDelta > 0)
{
pubSrc += prclSrc->top * lDelta + ((ulInputBPP * prclSrc->left) >> 3);
}
else
{
pubSrc = pubSrc - prclSrc->top * lDelta + ((ulInputBPP * prclSrc->left) >> 3);
}
*pBuf = PCLXL_dataLength;
pBmpSize = pBuf + 1;
pBuf += DATALENGTH_HEADER_SIZE;
*pdwLen = DATALENGTH_HEADER_SIZE;
BMPC.BSetRLECompress(dwI == RLE_COMPRESSION);
dwcbBmpSize = 0;
while (lScanline-- > 0 && dwcbBmpSize + *pdwLen < dwBufSize)
{
pubDst = BMPC.PubConvertBMP(pubSrc, dwcbLineSize);
dwSize = BMPC.DwGetDstSize();
VERBOSE(("CommonRopBlt[0x%x]: dwDstSize=0x%x\n", lScanline, dwSize));
if ( dwcbBmpSize +
dwSize +
DATALENGTH_HEADER_SIZE +
sizeof(PCLXL_EndImage) > dwBufSize || NULL == pubDst)
{
VERBOSE(("CommonRopBlt: Buffer size is too small.\n"));
hRet = E_UNEXPECTED;
break;
}
memcpy(pBuf, pubDst, dwSize);
dwcbBmpSize += dwSize;
pBuf += dwSize;
if (psoSrc->lDelta > 0)
{
pubSrc += lDelta;
}
else
{
pubSrc -= lDelta;
}
}
if (lScanline > 0)
{
hRet = S_FALSE;
WARNING(("ComonRopBlt: Conversion failed.\n"));
}
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);
}
CopyMemory(pBmpSize, &dwcbBmpSize, sizeof(dwcbBmpSize));
*pdwLen += dwcbBmpSize;
*pBuf = PCLXL_EndImage;
(*pdwLen) ++;
}
else
{
//
// Conversion failed!
//
*pdwLen = 0;
}
}
#undef NO_COMPRESSION
#undef RLE_COMPRESSION
//
// ReadImage
//
if (dwLenRLE != 0 && dwLenRLE < dwLenNormal)
{
VERBOSE(("CommonRopBlt RLE: dwSize=0x%x\n", dwLenRLE));
pBuf = pBufRLE;
pdwLen = &dwLenRLE;
CMode = eRLECompression;
MemFree(pBufNormal);
}
else
{
VERBOSE(("CommonRopBlt Normal: dwSize=0x%x\n", dwLenRLE));
pBuf = pBufNormal;
pdwLen = &dwLenNormal;
CMode = eNoCompression;
MemFree(pBufRLE);
}
pOutput->ReadImage(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);
}
return hRet;
}
inline
VOID
DetermineOutputFormat(
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:
case e24bpp:
case e32bpp:
*pOutputF = eOutputGray;
break;
}
switch (*pOutputF)
{
case eOutputGray:
*pulOutputBPP = 8;
break;
case eOutputPal:
*pulOutputBPP = UlBPPtoNum((BPP)iBitmapFormat);
break;
case eOutputRGB:
case eOutputCMYK:
ERR(("eOutputRGB and eOutputCMYK are not supported yet.\n"));
break;
}
}