mirror of https://github.com/lianthony/NT4.0
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.
810 lines
19 KiB
810 lines
19 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bitmap.c
|
|
|
|
Abstract:
|
|
|
|
Implementation of brush and bitmap image related DDI entry points:
|
|
DrvRealizeBrush
|
|
DrvCopyBits
|
|
DrvBitBlt
|
|
DrvStretchBlt
|
|
|
|
Environment:
|
|
|
|
PCL-XL driver, kernel mode
|
|
|
|
Revision History:
|
|
|
|
11/08/95 -davidx-
|
|
Created it.
|
|
|
|
mm/dd/yy -author-
|
|
description
|
|
|
|
--*/
|
|
|
|
#include "xldrv.h"
|
|
|
|
BOOL
|
|
SelectBitmap(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDest,
|
|
POINTL *pptlSrc,
|
|
SIZEL *psizlSrc,
|
|
ROP4 rop4
|
|
);
|
|
|
|
|
|
BOOL
|
|
DrvRealizeBrush(
|
|
BRUSHOBJ *pbo,
|
|
SURFOBJ *psoTarget,
|
|
SURFOBJ *psoPattern,
|
|
SURFOBJ *psoMask,
|
|
XLATEOBJ *pxlo,
|
|
ULONG iHatch
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvRealizeBrush.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
pbo - BRUSHOBJ to be realized
|
|
psoTarget - Defines the surface for which the brush is to be realized
|
|
psoPattern - Defines the pattern for the brush
|
|
psoMask - Transparency mask for the brush
|
|
pxlo - Defines the interpretration of colors in the pattern
|
|
iHatch - Specifies whether psoPattern is one of the hatch brushes
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVDATA pdev;
|
|
LONG lineLen, paddedLen, height, x;
|
|
PBYTE pSrc, pDest;
|
|
SURFOBJ *psoTemp;
|
|
PDEVBRUSH pRbrush;
|
|
|
|
Verbose(("Entering DrvRealizeBrush...\n"));
|
|
|
|
//
|
|
// Valid input parameters
|
|
//
|
|
|
|
Assert(pbo && psoTarget && psoPattern);
|
|
|
|
if (psoPattern->iType != STYPE_BITMAP ||
|
|
!(pdev = (PDEVDATA) psoTarget->dhpdev) || !ValidDevData(pdev))
|
|
{
|
|
Error(("Invalid input parameters\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
#if DBG
|
|
|
|
//
|
|
// If there is a mask, its bitmap must be the same as the brush bitmap itself.
|
|
// This is currently always the case. So we don't need to use the mask parameter.
|
|
//
|
|
|
|
if (psoMask) {
|
|
|
|
Assert(psoMask->iType == STYPE_BITMAP &&
|
|
psoMask->iBitmapFormat == BMF_1BPP &&
|
|
psoMask->pvBits != NULL);
|
|
|
|
if (psoMask->sizlBitmap.cx != psoPattern->sizlBitmap.cx ||
|
|
psoMask->sizlBitmap.cy != psoPattern->sizlBitmap.cy ||
|
|
psoPattern->iBitmapFormat != BMF_1BPP)
|
|
{
|
|
Error(("Brush pattern != brush mask\n"));
|
|
}
|
|
}
|
|
|
|
if (iHatch < HS_DDI_MAX) {
|
|
Verbose(("Hatch brush: %d\n", iHatch));
|
|
}
|
|
|
|
if (psoPattern->sizlBitmap.cx > 8 || psoPattern->sizlBitmap.cy > 8) {
|
|
|
|
Verbose(("Large pattern size: %dx%d\n",
|
|
psoPattern->sizlBitmap.cx, psoPattern->sizlBitmap.cy));
|
|
}
|
|
|
|
#endif
|
|
|
|
Assert(pxlo->iDstType == PAL_RGB);
|
|
lineLen = psoPattern->sizlBitmap.cx;
|
|
height = psoPattern->sizlBitmap.cy;
|
|
|
|
//
|
|
// Generate a unique brush identifier
|
|
//
|
|
|
|
if (++pdev->nextBrushId == 0)
|
|
pdev->nextBrushId = 1;
|
|
|
|
//
|
|
// Acceleration for monochrome bitmaps
|
|
//
|
|
|
|
if (psoPattern->iBitmapFormat == BMF_1BPP) {
|
|
|
|
PULONG pulVector;
|
|
|
|
if (! (pulVector = XLATEOBJ_piVector(pxlo))) {
|
|
|
|
Error(("XLATEOBJ_piVector\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
if ((pulVector[0] == RGB_BLACK && pulVector[1] == RGB_WHITE) ||
|
|
(pulVector[1] == RGB_BLACK && pulVector[0] == RGB_WHITE))
|
|
{
|
|
BYTE invertMask;
|
|
|
|
// See if we have a negative monochrome bitmap
|
|
|
|
invertMask = (pulVector[0] == RGB_BLACK) ? 0 : 0xff;
|
|
lineLen = (lineLen + 7) / 8;
|
|
paddedLen = RoundUpDWord(lineLen);
|
|
|
|
//
|
|
// Allocate memory for a realized brush
|
|
//
|
|
|
|
if (! (pRbrush = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(DEVBRUSH) + paddedLen*height))) {
|
|
|
|
Error(("BRUSHOBJ_pvAllocRbrush\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
pRbrush->iUniq = pdev->nextBrushId;
|
|
pRbrush->size = psoPattern->sizlBitmap;
|
|
pRbrush->type = BMF_1BPP;
|
|
pRbrush->lDelta = paddedLen;
|
|
pDest = pRbrush->pBits = (PBYTE) pRbrush + sizeof(DEVBRUSH);
|
|
pSrc = psoPattern->pvScan0;
|
|
|
|
//
|
|
// Copy the bitmap data
|
|
//
|
|
|
|
while (height--) {
|
|
|
|
for (x=0; x < lineLen; x++)
|
|
*pDest++ = pSrc[x] ^ invertMask;
|
|
|
|
while (x++ < paddedLen)
|
|
*pDest++ = 0;
|
|
pSrc += psoPattern->lDelta;
|
|
}
|
|
|
|
pbo->pvRbrush = pRbrush;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the brush pattern is not in a format we can handle directly,
|
|
// let engine copy it into a temporary 24bpp surface.
|
|
//
|
|
|
|
psoTemp = NULL;
|
|
pRbrush = NULL;
|
|
|
|
if (psoPattern->iBitmapFormat != BMF_24BPP || pxlo->iSrcType != PAL_RGB) {
|
|
|
|
RECTL rclDest;
|
|
POINTL ptOrg;
|
|
|
|
Verbose(("Slow brush realization: bitmap format = %d, source type = %d\n",
|
|
psoPattern->iBitmapFormat, pxlo->iSrcType));
|
|
|
|
// #### This won't work by casting HBITMAP to SURFOBJ*
|
|
|
|
psoTemp = (SURFOBJ *) EngCreateBitmap(psoPattern->sizlBitmap,
|
|
RoundUpDWord(lineLen * 3),
|
|
BMF_24BPP,
|
|
BMF_TOPDOWN,
|
|
NULL);
|
|
|
|
rclDest.left = rclDest.top = 0;
|
|
rclDest.right = lineLen;
|
|
rclDest.bottom = height;
|
|
|
|
ptOrg.x = ptOrg.y = 0;
|
|
|
|
if (!psoTemp || !EngCopyBits(psoTemp, psoPattern, NULL, pxlo, &rclDest, &ptOrg)) {
|
|
|
|
Error(("Cannot copy brush bitmap\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
psoPattern = psoTemp;
|
|
}
|
|
|
|
pSrc = psoPattern->pvScan0;
|
|
|
|
if (pdev->colorFlag) {
|
|
|
|
//
|
|
// Use RGB color brush
|
|
//
|
|
|
|
lineLen *= 3;
|
|
paddedLen = RoundUpDWord(lineLen);
|
|
|
|
if (pRbrush = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(DEVBRUSH) + paddedLen*height)) {
|
|
|
|
pRbrush->type = BMF_24BPP;
|
|
pDest = pRbrush->pBits = (PBYTE) pRbrush + sizeof(DEVBRUSH);
|
|
|
|
while (height--) {
|
|
|
|
memcpy(pDest, pSrc, paddedLen);
|
|
pDest += paddedLen;
|
|
pSrc += psoPattern->lDelta;
|
|
}
|
|
|
|
} else {
|
|
Error(("BRUSHOBJ_pvAllocRbrush failed\n"));
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// Use grayscale brush
|
|
//
|
|
|
|
paddedLen = RoundUpDWord(lineLen);
|
|
|
|
if (pRbrush = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(DEVBRUSH) + paddedLen*height)) {
|
|
|
|
lineLen *= 3;
|
|
pRbrush->type = BMF_8BPP;
|
|
pDest = pRbrush->pBits = (PBYTE) pRbrush + sizeof(DEVBRUSH);
|
|
|
|
while (height--) {
|
|
|
|
for (x=0; x < lineLen; x += 3)
|
|
*pDest++ = RgbToGray(pSrc[x], pSrc[x+1], pSrc[x+2]);
|
|
|
|
for (x=lineLen/3; x < paddedLen; x++)
|
|
*pDest++ = 0;
|
|
|
|
pSrc += psoPattern->lDelta;
|
|
}
|
|
|
|
} else {
|
|
Error(("BRUSHOBJ_pvAllocRbrush failed\n"));
|
|
}
|
|
}
|
|
|
|
if (pRbrush != NULL) {
|
|
|
|
pRbrush->iUniq = pdev->nextBrushId;
|
|
pRbrush->size = psoPattern->sizlBitmap;
|
|
pRbrush->lDelta = paddedLen;
|
|
pbo->pvRbrush = pRbrush;
|
|
}
|
|
|
|
if (psoTemp)
|
|
EngDeleteSurface((HSURF) psoTemp);
|
|
|
|
return (pRbrush != NULL);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
DrvCopyBits(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDest,
|
|
POINTL *pptlSrc
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvCopyBits.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
psoDest - Points to the destination surface
|
|
psoSrc - Points to the source surface
|
|
pco - Defines a clipping region on the destination surface
|
|
pxlo - Defines the translation of color indices
|
|
between the source and target surfaces
|
|
prclDest - 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
|
|
|
|
--*/
|
|
|
|
{
|
|
Verbose(("Entering DrvCopyBits...\n"));
|
|
|
|
return SelectBitmap(psoDest, psoSrc, pco, pxlo, prclDest, pptlSrc, NULL, 0xCCCC);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
DrvBitBlt(
|
|
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 destination surface
|
|
rop4 - ROP code that defines how the mask, pattern, source, and
|
|
destination pixels are combined to write to the destination surface
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
ROP4 rop4Back;
|
|
|
|
Verbose(("Entering DrvBitBlt...\n"));
|
|
|
|
//
|
|
// NOTE: We only handle very limited masking operation:
|
|
// the mask has a transparent background (i.e. rop4 is 0xAAxx)
|
|
// and the mask bitmap is the same as the brush bitmap.
|
|
//
|
|
|
|
rop4Back = (rop4 >> 8) & 0xff;
|
|
rop4 &= 0xff;
|
|
|
|
if (rop4Back == 0xAA && psoMask == NULL) {
|
|
|
|
rop4 |= (0xAA << 8);
|
|
|
|
} else {
|
|
|
|
ErrorIf(rop4 != rop4Back, ("Unsupported rop4 code: %x/%x\n", rop4, rop4Back));
|
|
rop4 |= (rop4 << 8);
|
|
}
|
|
|
|
return SelectBitmap(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc, NULL, rop4);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
DrvStretchBlt(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
COLORADJUSTMENT *pca,
|
|
POINTL *pptlHTOrg,
|
|
RECTL *prclDest,
|
|
RECTL *prclSrc,
|
|
POINTL *pptlMask,
|
|
ULONG iMode
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvStretchBlt.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
psoDest - 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 destination
|
|
pxlo - Specifies how color indexes 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
|
|
prclDest - Defines the area to be modified on the destination 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
|
|
|
|
--*/
|
|
|
|
{
|
|
SIZEL sizlSrc;
|
|
POINTL ptlSrc;
|
|
|
|
Verbose(("Entering DrvStretchBlt...\n"));
|
|
|
|
ErrorIf(psoMask, ("StretchBlt with mask is not supported\n"));
|
|
Assert(prclSrc != NULL);
|
|
|
|
ptlSrc.x = prclSrc->left;
|
|
ptlSrc.y = prclSrc->top;
|
|
|
|
sizlSrc.cx = prclSrc->right - prclSrc->left;
|
|
sizlSrc.cy = prclSrc->bottom - prclSrc->top;
|
|
|
|
return SelectBitmap(psoDest, psoSrc, pco, pxlo, prclDest, &ptlSrc, &sizlSrc, 0xCCCC);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
SelectBitmap(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDest,
|
|
POINTL *pptlSrc,
|
|
SIZEL *psizlSrc,
|
|
ROP4 rop4
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Send a bitmap image to the printer
|
|
|
|
Arguments:
|
|
|
|
psoDest - Specifies the destination surface
|
|
psoSrc - Specifies the source surface
|
|
pco - Limits the affected area on the destination surface
|
|
pxlo - How to translate source color indices to destination color indices
|
|
prclDest - Specifies the destination rectangle
|
|
pptlSrc - Specifies the source location
|
|
psizlSrc - Specifies the source size
|
|
rop4 - Specfies the raster operation code
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVDATA pdev;
|
|
BYTE rop3;
|
|
SIZEL sizeDest, sizeSrc;
|
|
INT colorMapping, colorDepth;
|
|
INT srcBpp, destBpp, lineLen, padding;
|
|
BOOL xlateColor;
|
|
PBYTE pSrc, pDest, pDestBuf;
|
|
PULONG pulVector;
|
|
DWORD zeros = 0;
|
|
|
|
Assert(psoDest && psoSrc && pxlo && prclDest);
|
|
pdev = (PDEVDATA) psoDest->dhpdev;
|
|
|
|
if (!ValidDevData(pdev) ||
|
|
prclDest->left > prclDest->right ||
|
|
prclDest->top > prclDest->bottom)
|
|
{
|
|
Error(("Invalid parameters\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
rop3 = (BYTE) rop4;
|
|
rop4 = (rop4 >> 8) & 0xff;
|
|
|
|
if (rop4 == 0xAA && rop4 != rop3) {
|
|
|
|
//
|
|
// Transparent background
|
|
//
|
|
|
|
if (pdev->cgs.paintTxMode != eTransparent && !xl_setpainttxmode(pdev, eTransparent))
|
|
return FALSE;
|
|
|
|
pdev->cgs.paintTxMode = eTransparent;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Opaque background
|
|
//
|
|
|
|
if (pdev->cgs.paintTxMode != eOpaque && !xl_setpainttxmode(pdev, eOpaque))
|
|
return FALSE;
|
|
|
|
pdev->cgs.paintTxMode = eOpaque;
|
|
}
|
|
|
|
//
|
|
// Source transfer mode is always opaque
|
|
//
|
|
|
|
if (pdev->cgs.sourceTxMode != eOpaque && !xl_setsourcetxmode(pdev, eOpaque))
|
|
return FALSE;
|
|
|
|
pdev->cgs.sourceTxMode = eOpaque;
|
|
|
|
//
|
|
// Use the specified raster operation code
|
|
// Set up clipping path
|
|
//
|
|
|
|
if (! SelectRop3(pdev, rop3) || ! SelectClip(pdev, pco))
|
|
return FALSE;
|
|
|
|
//
|
|
// Calculate source and destination size
|
|
//
|
|
|
|
sizeDest.cx = prclDest->right - prclDest->left;
|
|
sizeDest.cy = prclDest->bottom - prclDest->top;
|
|
sizeSrc = psizlSrc ? *psizlSrc : sizeDest;
|
|
|
|
if (! xl_moveto(pdev, prclDest->left, prclDest->top))
|
|
return FALSE;
|
|
|
|
//
|
|
// Check out the source bitmap format
|
|
//
|
|
|
|
if (psoSrc->iType != STYPE_BITMAP) {
|
|
|
|
Error(("Source surface is not a bitmap: %d\n", psoSrc->iType));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
Assert(pxlo->iDstType == PAL_RGB);
|
|
|
|
if (psoSrc->iBitmapFormat == BMF_1BPP ||
|
|
psoSrc->iBitmapFormat == BMF_4BPP ||
|
|
psoSrc->iBitmapFormat == BMF_8BPP)
|
|
{
|
|
Assert(pxlo->flXlate & XO_TABLE);
|
|
|
|
if (! (pulVector = XLATEOBJ_piVector(pxlo))) {
|
|
|
|
Error(("XLATEOBJ_piVector failed\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
colorMapping = eIndexedPixel;
|
|
|
|
} else {
|
|
|
|
colorMapping = eDirectPixel;
|
|
colorDepth = e8Bit;
|
|
destBpp = 0;
|
|
}
|
|
|
|
switch (psoSrc->iBitmapFormat) {
|
|
|
|
case BMF_1BPP:
|
|
|
|
colorDepth = e1Bit;
|
|
destBpp = srcBpp = 1;
|
|
|
|
if (pulVector[0] == RGB_BLACK && pulVector[1] == RGB_WHITE)
|
|
colorMapping = eDirectPixel;
|
|
break;
|
|
|
|
case BMF_4BPP:
|
|
|
|
colorDepth = e4Bit;
|
|
destBpp = srcBpp = 4;
|
|
break;
|
|
|
|
case BMF_8BPP:
|
|
|
|
colorDepth = e8Bit;
|
|
destBpp = srcBpp = 8;
|
|
break;
|
|
|
|
case BMF_24BPP:
|
|
|
|
srcBpp = 24;
|
|
if (pxlo->iSrcType == PAL_RGB && pdev->colorFlag)
|
|
destBpp = 24;
|
|
break;
|
|
|
|
case BMF_16BPP:
|
|
|
|
srcBpp = 16;
|
|
break;
|
|
|
|
case BMF_32BPP:
|
|
|
|
srcBpp = 32;
|
|
break;
|
|
|
|
default:
|
|
|
|
Error(("Unsupported bitmap format: %d\n", psoSrc->iBitmapFormat));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (destBpp == 0) {
|
|
|
|
Verbose(("Slow bitblt: bpp = %d\n", srcBpp));
|
|
destBpp = pdev->colorFlag ? 24 : 8;
|
|
xlateColor = TRUE;
|
|
|
|
} else
|
|
xlateColor = FALSE;
|
|
|
|
//
|
|
// Download color palette if needed
|
|
//
|
|
|
|
if (colorMapping == eIndexedPixel &&
|
|
!xl_setcolorspace(pdev, srcBpp, pxlo->cEntries, pulVector))
|
|
{
|
|
Error(("Cannot download color palette\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Output image header data
|
|
//
|
|
|
|
if (!xl_beginimage(pdev, colorMapping, colorDepth, &sizeSrc, &sizeDest) ||
|
|
!xl_readimage(pdev, 0, sizeSrc.cy))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Output raster data
|
|
//
|
|
|
|
lineLen = destBpp * sizeSrc.cx;
|
|
padding = lineLen % 32;
|
|
lineLen = (lineLen + 7) / 8;
|
|
if (padding)
|
|
padding = (32 - padding) / 8;
|
|
|
|
pSrc = psoSrc->pvScan0;
|
|
pDestBuf = xlateColor ? MemAlloc(destBpp * sizeSrc.cx / 8) : NULL;
|
|
|
|
while (sizeSrc.cy-- > 0) {
|
|
|
|
if (xlateColor) {
|
|
|
|
ULONG srcColor, destColor;
|
|
PBYTE p, pRgb;
|
|
INT x = sizeSrc.cx;
|
|
|
|
//
|
|
// NOTE! This only works on little-endian machines.
|
|
//
|
|
|
|
pRgb = (PBYTE) &destColor;
|
|
|
|
p = pSrc;
|
|
pDest = pDestBuf;
|
|
|
|
while (x-- > 0) {
|
|
|
|
switch (srcBpp) {
|
|
|
|
case 16:
|
|
|
|
srcColor = *((PWORD) p);
|
|
break;
|
|
|
|
case 24:
|
|
|
|
srcColor = ((ULONG) p[0] ) |
|
|
((ULONG) p[1] << 8) |
|
|
((ULONG) p[2] << 16);
|
|
break;
|
|
|
|
case 32:
|
|
|
|
srcColor = *((PULONG) p);
|
|
break;
|
|
}
|
|
|
|
p += (srcBpp >> 3);
|
|
|
|
destColor = XLATEOBJ_iXlate(pxlo, srcColor);
|
|
|
|
if (destBpp == 8)
|
|
*pDest++ = RgbToGray(pRgb[0], pRgb[1], pRgb[2]);
|
|
else {
|
|
*pDest++ = pRgb[0];
|
|
*pDest++ = pRgb[1];
|
|
*pDest++ = pRgb[2];
|
|
}
|
|
}
|
|
|
|
pDest = pDestBuf;
|
|
|
|
} else
|
|
pDest = pSrc;
|
|
|
|
if (! splwrite(pdev, pDest, lineLen) ||
|
|
padding && ! splwrite(pdev, &zeros, padding))
|
|
{
|
|
MemFree(pDestBuf);
|
|
return FALSE;
|
|
}
|
|
|
|
pSrc += psoSrc->lDelta;
|
|
}
|
|
|
|
MemFree(pDestBuf);
|
|
|
|
if (! xl_endimage(pdev))
|
|
return FALSE;
|
|
|
|
//
|
|
// Restore default color space after we're done
|
|
//
|
|
|
|
return (colorMapping == eIndexedPixel) ? xl_setcolorspace(pdev, 0, 0, NULL) : TRUE;
|
|
}
|