Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

3081 lines
79 KiB

//--------------------------------------------------------------------------
//
// Module Name: BITBLT.C
//
// Brief Description: This module contains the PSCRIPT driver's BitBlt
// functions and related routines.
//
// Author: Kent Settle (kentse)
// Created: 03-Dec-1990
//
// 26-Mar-1992 Thu 23:54:07 updated -by- Daniel Chou (danielc)
// 2) Remove 'pco' parameter and replaced it with prclClipBound parameter,
// since pco is never referenced, prclClipBound is used for the
// halftone.
// 3) Add another parameter to do NOTSRCCOPY
//
// 11-Feb-1993 Thu 21:32:07 updated -by- Daniel Chou (danielc)
// Major re-write to have DrvStretchBlt(), DrvCopyBits() do the right
// things.
//
// 29-Apr-1994 updated -by- James Bratsanos (v-jimbr,mcrafts!jamesb)
// Added filter / rle / ASCII85 compression for level two printers.
//
//
// Copyright (c) 1990-1992 Microsoft Corporation
//
// This module contains DrvBitBlt, DrvStretchBlt and related routines.
//--------------------------------------------------------------------------
#include "stdlib.h"
#include "pscript.h"
#include "halftone.h"
#include "filter.h"
#if DBG
BOOL DbgPSBitBlt = FALSE;
BOOL DbgPSSrcCopy = FALSE;
#endif
#define SWAP(a,b,tmp) tmp=a; a=b; b=tmp
#define PAL_MIN_I 0x00
#define PAL_MAX_I 0xff
#define HTXB_R(htxb) htxb.b4.b1st
#define HTXB_G(htxb) htxb.b4.b2nd
#define HTXB_B(htxb) htxb.b4.b3rd
#define HTXB_I(htxb) htxb.b4.b4th
#define SRC8PELS_TO_3P_DW(dwRet,pHTXB,pSrc8Pels) \
(dwRet) = (DWORD)((pHTXB[pSrc8Pels->b4.b1st].dw & (DWORD)0xc0c0c0c0) | \
(pHTXB[pSrc8Pels->b4.b2nd].dw & (DWORD)0x30303030) | \
(pHTXB[pSrc8Pels->b4.b3rd].dw & (DWORD)0x0c0c0c0c) | \
(pHTXB[pSrc8Pels->b4.b4th].dw & (DWORD)0x03030303)); \
++pSrc8Pels
#define INTENSITY(r,g,b) (BYTE)(((WORD)((r)*30) + (WORD)((g)*59) + (WORD)((b)*11))/100)
BYTE rgbm[] = "rgbm";
#define SC_LSHIFT 0x01
#define SC_XLATE 0x02
#define SC_SWAP_RB 0x04
#define SC_IDENTITY 0x08
typedef union _DW4B {
DWORD dw;
BYTE b4[4];
} DW4B;
//
// declarations of routines residing within this module.
//
VOID
BeginImage(
PDEVDATA pdev,
BOOL Mono,
int x,
int y,
int cx,
int cy,
int cxBytes,
PFILTER pFilter
);
BOOL DoPatCopy(PDEVDATA, SURFOBJ *, PRECTL, BRUSHOBJ *, PPOINTL, ROP4, BOOL);
BOOL
HalftoneBlt(
PDEVDATA pdev,
SURFOBJ *psoDest,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
COLORADJUSTMENT *pca,
POINTL *pptlBrushOrg,
PRECTL prclDest,
PRECTL prclSrc,
PPOINTL pptlMask,
BOOL NotSrcCopy
);
BOOL
IsHTCompatibleSurfObj(
PDEVDATA pdev,
SURFOBJ *pso,
XLATEOBJ *pxlo
);
BOOL
OutputHTCompatibleBits(
PDEVDATA pdev,
SURFOBJ *psoHT,
CLIPOBJ *pco,
DWORD xDest,
DWORD yDest
);
BOOL BeginImageEx(
PDEVDATA pdev,
SIZEL sizlSrc,
ULONG ulSrcFormat,
DWORD cbSrcWidth,
PRECTL prclDest,
BOOL bNotSrcCopy,
XLATEOBJ *pxlo,
PFILTER pFilter
);
BOOL bOutputBitmapAsMask(
PDEVDATA pdev,
SURFOBJ *pso,
PPOINTL pptlSrc,
PRECTL prclDst,
CLIPOBJ *pco);
//
//********** Code start here
//
BOOL
HalftoneBlt(
PDEVDATA pdev,
SURFOBJ *psoDest,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
COLORADJUSTMENT *pca,
POINTL *pptlBrushOrg,
PRECTL prclDest,
PRECTL prclSrc,
PPOINTL pptlMask,
BOOL NotSrcCopy
)
/*++
Routine Description:
This function blt the soruces bitmap using halftone mode
Arguments:
Same as DrvStretchBlt() except pdev and NotSrcCopy flag
Return Value:
BOOLEAN
Author:
17-Feb-1993 Wed 21:31:24 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PDRVHTINFO pDrvHTInfo;
POINTL ZeroOrigin = {0, 0};
BOOL Ok;
if (!(pDrvHTInfo = (PDRVHTINFO)(pdev->pvDrvHTData))) {
DBGMSG(DBG_LEVEL_ERROR, "pDrvHTInfo = NULL?!\n");
return(FALSE);
}
if (pDrvHTInfo->Flags & DHIF_IN_STRETCHBLT) {
DBGMSG(DBG_LEVEL_ERROR,
"EngStretchBlt() recursive calls not allowed!\n");
return(FALSE);
}
//
// Setup these data before calling EngStretchBlt(), these are used at later
// DrvCopyBits() call
//
pdev->dwFlags &= ~(PDEV_DOIMAGEMASK | PDEV_NOTSRCBLT);
pDrvHTInfo->Flags |= DHIF_IN_STRETCHBLT;
pDrvHTInfo->HTPalXor = (NotSrcCopy) ? HTPALXOR_NOTSRCCOPY :
HTPALXOR_SRCCOPY;
if (!pptlBrushOrg) {
pptlBrushOrg = &ZeroOrigin;
}
if (!pca) {
pca = &(pDrvHTInfo->ca);
}
#if DBG
if (DbgPSBitBlt) {
if (pco) {
DBGPRINT("PSCRIPT!HalftoneBlt: CLIP: Complex=%ld\n",
(DWORD)pco->iDComplexity);
DBGPRINT("Clip rclBounds = (%ld, %ld) - (%ld, %ld)\n",
pco->rclBounds.left,
pco->rclBounds.top,
pco->rclBounds.right,
pco->rclBounds.bottom);
} else {
DBGPRINT("PSCRIPT!HalftoneBlt: pco = NULL\n");
}
}
#endif
if (!(Ok = EngStretchBlt(psoDest, // Dest
psoSrc, // SRC
psoMask, // MASK
pco, // CLIPOBJ
pxlo, // XLATEOBJ
pca, // COLORADJUSTMENT
pptlBrushOrg, // BRUSH ORG
prclDest, // DEST RECT
prclSrc, // SRC RECT
pptlMask, // MASK POINT
HALFTONE))) // HALFTONE MODE
{
DBGERRMSG("EngStretchBlt");
}
//
// Clear These before we return
//
pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
pDrvHTInfo->Flags &= ~DHIF_IN_STRETCHBLT;
return(Ok);
}
BOOL
IsHTCompatibleSurfObj(
PDEVDATA pdev,
SURFOBJ *pso,
XLATEOBJ *pxlo
)
/*++
Routine Description:
This function determine if the surface obj is compatble with postscript
halftone output format.
Arguments:
pdev - Pointer to the PDEVDATA data structure to determine what
type of postscript output for current device
pso - engine SURFOBJ to be examine
pxlo - engine XLATEOBJ for source -> postscript translation
Return Value:
BOOLEAN true if the pso is compatible with halftone output format, if
return value is true, the pDrvHTInfo->pHTXB is a valid trnaslation from
indices to 3 planes
Author:
11-Feb-1993 Thu 18:49:55 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PSRGB *prgb;
PDRVHTINFO pDrvHTInfo;
UINT BmpFormat;
UINT cPal;
if (!(pDrvHTInfo = (PDRVHTINFO)(pdev->pvDrvHTData))) {
DBGMSG(DBG_LEVEL_ERROR, "pDrvHTInfo = NULL?!\n");
return(FALSE);
}
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("** IsHTCompatibleSurfObj **\n");
DBGPRINT("iType=%ld, BmpFormat=%ld\n",
(DWORD)pso->iType,
(DWORD)pso->iBitmapFormat);
if (pxlo) {
DBGPRINT("pxlo: flXlate=%08lx, cPal=%ld, pulXlate=%08lx\n",
(DWORD)pxlo->flXlate,
(DWORD)pxlo->cEntries,
(DWORD)pxlo->pulXlate);
} else {
DBGPRINT("pxlo = NULL\n");
}
}
#endif
//
// Make sure these fields' value are valid before create translation
//
// 1. pso->iBitmapFormat is one of 1BPP or 4BPP depends on current
// pscript's surface
// 2. pxlo is non null
// 3. pxlo->fXlate is XO_TABLE
// 4. pxlo->cPal is less or equal to the halftone palette count
// 5. pxlo->pulXlate is valid
// 6. source color table is within the range of halftone palette
//
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("pso->iType = %x, pso->iBitmapFormat = %x.\n",
pso->iType, pso->iBitmapFormat);
DBGPRINT("pDrvHTInfo->HTBmpFormat = %x.\n",
pDrvHTInfo->HTBmpFormat);
DBGPRINT("pDrvHTInfo->AltBmpFormat = %x, pxlo = %x.\n",
pDrvHTInfo->AltBmpFormat, pxlo);
DBGPRINT("pxlo->flXlate = %x, pxlo->cEntries = %d.\n",
pxlo->flXlate, pxlo->cEntries);
DBGPRINT("pxlo->pulXlate = %x.\n", pxlo->pulXlate);
}
#endif
if ((pso->iType == STYPE_BITMAP) &&
(((BmpFormat = (UINT)pso->iBitmapFormat) ==
(UINT)pDrvHTInfo->HTBmpFormat) ||
(BmpFormat == (UINT)pDrvHTInfo->AltBmpFormat)) &&
(pxlo) &&
(pxlo->flXlate & XO_TABLE) &&
((cPal = (UINT)pxlo->cEntries) <= (UINT)pDrvHTInfo->HTPalCount) &&
(prgb = (PSRGB *)pxlo->pulXlate)) {
ULONG HTPalXor;
UINT i;
HTXB htXB;
HTXB PalNibble[HTPAL_XLATE_COUNT];
BOOL GenHTXB = FALSE;
BYTE PalXlate[HTPAL_XLATE_COUNT];
HTPalXor = pDrvHTInfo->HTPalXor;
pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("HTPalXor=%08lx\n", HTPalXor);
}
#endif
for (i = 0; i < cPal; i++, prgb++) {
HTXB_R(htXB) = prgb->red;
HTXB_G(htXB) = prgb->green;
HTXB_B(htXB) = prgb->blue;
htXB.dw ^= HTPalXor;
if (((HTXB_R(htXB) != PAL_MAX_I) &&
(HTXB_R(htXB) != PAL_MIN_I)) ||
((HTXB_G(htXB) != PAL_MAX_I) &&
(HTXB_G(htXB) != PAL_MIN_I)) ||
((HTXB_B(htXB) != PAL_MAX_I) &&
(HTXB_B(htXB) != PAL_MIN_I))) {
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("SrcPal has NON 0xff/0x00 intensity, NOT HTPalette\n");
}
#endif
return(FALSE);
}
PalXlate[i] =
HTXB_I(htXB) = (BYTE)((HTXB_R(htXB) & 0x01) |
(HTXB_G(htXB) & 0x02) |
(HTXB_B(htXB) & 0x04));
PalNibble[i] = htXB;
if (pDrvHTInfo->PalXlate[i] != HTXB_I(htXB)) {
GenHTXB = TRUE;
}
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("%d - %02x:%02x:%02x -> %02x:%02x:%02x, Idx=%d, PalXlate=%d\n",
i,
(BYTE)prgb->red,
(BYTE)prgb->green,
(BYTE)prgb->blue,
(BYTE)HTXB_R(htXB),
(BYTE)HTXB_G(htXB),
(BYTE)HTXB_B(htXB),
(INT)PalXlate[i],
(INT)pDrvHTInfo->PalXlate[i]);
}
#endif
}
if (BmpFormat == (UINT)BMF_1BPP) {
if (((PalXlate[0] != 0) && (PalXlate[0] != 7)) ||
((PalXlate[1] != 0) && (PalXlate[1] != 7))) {
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("NON-BLACK/WHITE MONO BITMAP, NOT HTPalette\n");
}
#endif
return(FALSE);
}
}
if (GenHTXB) {
//
// Copy down the pal xlate
//
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("--- Copy XLATE TABLE ---\n");
}
#endif
memcpy(pDrvHTInfo->PalXlate, PalXlate, sizeof(PalXlate));
//
// We only really generate 4bpp to 3 planes if the destination
// format is BMF_4BPP
//
if (BmpFormat == (UINT)BMF_4BPP) {
PHTXB pTmpHTXB;
UINT h;
UINT l;
DWORD HighNibble;
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("--- Generate 4bpp --> 3 planes xlate ---\n");
}
#endif
if (pDrvHTInfo->pHTXB == NULL) {
DBGMSG(DBG_LEVEL_ERROR, "pDrvHTInfo->pHTXB = NULL?!\n");
if (!(pDrvHTInfo->pHTXB =
(PHTXB) HEAPALLOC(pdev->hheap, HTXB_TABLE_SIZE)))
{
DBGERRMSG("HEAPALLOC");
return(FALSE);
}
}
//
// Generate 4bpp to 3 planes xlate table
//
for (h = 0, pTmpHTXB = pDrvHTInfo->pHTXB;
h < HTXB_H_NIBBLE_MAX;
h++, pTmpHTXB += HTXB_L_NIBBLE_DUP) {
HighNibble = (DWORD)(PalNibble[h].dw & 0xaaaaaaaaL);
for (l = 0; l < HTXB_L_NIBBLE_MAX; l++, pTmpHTXB++) {
pTmpHTXB->dw = (DWORD)((HighNibble) |
(PalNibble[l].dw & 0x55555555L));
}
//
// Duplicate low nibble high order bit, 8 of them
//
memcpy(pTmpHTXB,
pTmpHTXB - HTXB_L_NIBBLE_MAX,
sizeof(HTXB) * HTXB_L_NIBBLE_DUP);
}
//
// Copy high nibble duplication, 128 of them
//
memcpy(pTmpHTXB,
pDrvHTInfo->pHTXB,
sizeof(HTXB) * HTXB_H_NIBBLE_DUP);
}
}
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("******* IsHTCompatibleSurfObj = YES *******\n");
}
#endif
return(TRUE);
} else {
return(FALSE);
}
}
BOOL
OutputHTCompatibleBits(
PDEVDATA pdev,
SURFOBJ *psoHT,
CLIPOBJ *pco,
DWORD xDest,
DWORD yDest
)
/*++
Routine Description:
This function output a compatible halftoned surface to the pscript device
Arguments:
pdev - Pointer to the PDEVDATA data structure to determine what
type of postscript output for current device
pso - engine SURFOBJ to be examine
psoHT - compatible halftoned surface object
xDest - the X bitmap start on the destination
yDest - the Y bitmap start on the destination
Return Value:
BOOLEAN if function sucessful, failed if cannot allocate memory to do
the otuput.
Author:
09-Feb-1993 Tue 20:45:37 created -by- Daniel Chou (danielc)
Revision History:
27-Feb-1995 Mon 15:21:38 updated -by- Daniel Chou (danielc)
Update for the Mono MaskBlt case
--*/
{
PDRVHTINFO pDrvHTInfo;
LPBYTE pbHTBits;
LPBYTE pbOutput;
SIZEL SizeBlt;
LONG cbToNextScan;
DWORD AllocSize;
DWORD cxDestBytes;
DWORD cxDestDW;
DWORD xLoop;
DWORD yLoop;
BOOL Mono;
DWORD dwBlack = RGB_BLACK;
FILTER filter;
pDrvHTInfo = (PDRVHTINFO)(pdev->pvDrvHTData);
SizeBlt = psoHT->sizlBitmap;
cxDestBytes = (DWORD)((SizeBlt.cx + 7) >> 3);
if (Mono = (BOOL)(psoHT->iBitmapFormat == BMF_1BPP)) {
//
// Our 1bpp bit 0 is BLACK, so if it is a WHITE then allocate memory
// and flip the outcome, also check for mono mask blt case
//
if ((pDrvHTInfo->PalXlate[0] != 0) ^
((pdev->dwFlags & PDEV_NOTSRCBLT) != 0)) {
cxDestDW = (DWORD)((cxDestBytes + 3) >> 2);
AllocSize = cxDestDW * sizeof(DWORD);
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("OutputHTCompatibleBits: MONO -- INVERT\n");
}
#endif
} else {
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("OutputHTCompatibleBits: MONO\n");
}
#endif
AllocSize = 0;
}
} else {
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("OutputHTCompatibleBits: 4 BIT --> 3 PLANES\n");
}
#endif
AllocSize = (DWORD)(cxDestBytes * 3);
}
if (AllocSize) {
if (!(pbOutput = (LPBYTE) HEAPALLOC(pdev->hheap, AllocSize))) {
DBGERRMSG("HEAPALLOC");
return(FALSE);
}
} else {
pbOutput = NULL;
}
//
// 1. Must clip the bitmap if 'pco' has clipping, and will send it down
// to the printer
// 2. Must do ps_save() before sending the image to the printer
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("OutputHTCompatibleBits: pco = %08lx\n", (DWORD)pco);
}
#endif
pbHTBits = (LPBYTE)psoHT->pvScan0;
if (! bDoClipObj(pdev, pco, NULL, NULL)) {
// Do a gsave if it's not already done when setting
// up the clipping path
ps_save(pdev, TRUE, FALSE);
}
//
// Now we can start xlate the bits into 3 planes
//
cbToNextScan = (LONG)psoHT->lDelta;
yLoop = (DWORD)SizeBlt.cy;
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("\n**** OutputHTCompatibleBits *****");
DBGPRINT("\nSizeBlt = %ld x %ld, Left/Top = (%ld, %ld)",
SizeBlt.cx, SizeBlt.cy, xDest, yDest);
DBGPRINT("\ncxDestBytes = %ld, AllocSize = %ld",
cxDestBytes,
AllocSize);
}
#endif
//
// Initialize a filter object so we can write to it when
// we output the source bits.
//
FilterInit( pdev, &filter, FilterGenerateFlags(pdev));
BeginImage(pdev, Mono, xDest, yDest, SizeBlt.cx, SizeBlt.cy,
cxDestBytes, &filter);
//
// Turn off the mono mask blt flags now
//
pdev->dwFlags &= ~(PDEV_DOIMAGEMASK | PDEV_NOTSRCBLT);
if (Mono) {
//
// For 1BPP we output directly from the source bitmap buffer
//
if (pbOutput) {
//
// We need to invert each bit, since each scan line is DW aligned
// we can do it in 32-bit increment
//
LPDWORD pdwMonoBits;
LPDWORD pdwFlipBits;
while (yLoop--) {
pdwFlipBits = (LPDWORD)pbOutput;
pdwMonoBits = (LPDWORD)pbHTBits;
pbHTBits += cbToNextScan;
xLoop = cxDestDW;
while (xLoop--) {
*pdwFlipBits++ = (DWORD)~(*pdwMonoBits++);
}
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
FILTER_WRITE( &filter, (PBYTE) pbOutput, cxDestBytes);
}
} else {
while (yLoop--) {
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
FILTER_WRITE( &filter, (PBYTE) pbHTBits, cxDestBytes);
pbHTBits += cbToNextScan;
}
}
} else {
PHTXB pHTXB;
PHTXB pSrc8Pels;
LPBYTE pbScanR0;
LPBYTE pbScanG0;
LPBYTE pbScanB0;
LPBYTE pbScanR;
LPBYTE pbScanG;
LPBYTE pbScanB;
HTXB htXB;
pHTXB = pDrvHTInfo->pHTXB;
pbScanR0 = pbOutput;
pbScanG0 = pbScanR0 + cxDestBytes;
pbScanB0 = pbScanG0 + cxDestBytes;
while (yLoop--) {
pSrc8Pels = (PHTXB)pbHTBits;
pbHTBits += cbToNextScan;
pbScanR = pbScanR0;
pbScanG = pbScanG0;
pbScanB = pbScanB0;
xLoop = cxDestBytes;
while (xLoop--) {
SRC8PELS_TO_3P_DW(htXB.dw, pHTXB, pSrc8Pels);
*pbScanR++ = HTXB_R(htXB);
*pbScanG++ = HTXB_G(htXB);
*pbScanB++ = HTXB_B(htXB);
}
//
// Write the Red
//
FILTER_WRITE( &filter, pbScanR0, cxDestBytes);
//
// Write the Green
//
FILTER_WRITE( &filter, pbScanG0, cxDestBytes);
//
// Write hte Blue
//
FILTER_WRITE( &filter, pbScanB0, cxDestBytes);
}
}
//
// Flush
//
FILTER_WRITE( &filter, (PBYTE) NULL, 0);
psputs(pdev,"\n");
//
// After ps_save() we better have ps_restore() to match it
//
ps_restore(pdev, TRUE, FALSE);
//
// Release scan line buffers if we did allocate one
//
if (pbOutput) {
HEAPFREE(pdev->hheap, pbOutput);
}
return(TRUE);
}
DWORD
CheckXlateObj(
XLATEOBJ *pxlo,
DWORD Srcbpp
)
/*++
Routine Description:
This function check the XLATEOBJ provided and determined the translate
method.
Arguments:
pxlo - XLATEOBJ provided by the engine
Srcbpp - Source bits per pixel
Return Value:
SCFlags with SC_XXXX to identify the translation method and accel.
Author:
07-Nov-1994 Mon 16:19:34 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
DWORD Ret;
//
// Only set the SC_XXX if has xlate object and source is 16bpp or greater
//
if ((pxlo) && (Srcbpp >= 16)) {
DWORD Dst[4];
#if DBG
if (DbgPSSrcCopy) {
DBGPRINT("PS: Srcbpp=%ld\n", Srcbpp);
}
#endif
Ret = SC_XLATE;
switch (Srcbpp) {
case 24:
case 32:
//
// Translate all 4 bytes from the DWORD
//
Dst[0] = XLATEOBJ_iXlate(pxlo, 0x000000FF);
Dst[1] = XLATEOBJ_iXlate(pxlo, 0x0000FF00);
Dst[2] = XLATEOBJ_iXlate(pxlo, 0x00FF0000);
Dst[3] = XLATEOBJ_iXlate(pxlo, 0xFF000000);
#if DBG
if (DbgPSSrcCopy) {
DBGPRINT("PS: XlateDst: %08lx:%08lx:%08lx:%08lx\n",
Dst[0], Dst[1], Dst[2], Dst[3]);
}
#endif
if ((Dst[0] == 0x000000FF) &&
(Dst[1] == 0x0000FF00) &&
(Dst[2] == 0x00FF0000) &&
(Dst[3] == 0x00000000)) {
//
// If translate result is same (4th byte will be zero) then
// we done with it except if 32bpp then we have to skip one
// source byte for every 3 bytes
//
Ret = (Srcbpp == 24) ? 0 : SC_IDENTITY;
} else if ((Dst[0] == 0x00FF0000) &&
(Dst[1] == 0x0000FF00) &&
(Dst[2] == 0x000000FF) &&
(Dst[3] == 0x00000000)) {
//
// Simply swap the R and B component
//
Ret |= SC_SWAP_RB;
}
}
} else {
Ret = 0;
}
return(Ret);
}
VOID
ShiftLeft(
LPBYTE pbSrc,
LPBYTE pbDst,
LONG DstBits,
INT LShift
)
/*++
Routine Description:
This function composed the destination by shift the source to the left
LShift bits until DstBits is exausted
Arguments:
pbSrc - Pointer to the first byte of the source to be shifted
pbDst - Pointer to the destination buffer
DstBits - Total bits count of the destination
LShift - Total bits to be shift (must be 1-7)
Return Value:
VOID
Author:
07-Nov-1994 Mon 18:58:06 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
INT RShift;
BYTE bCur;
BYTE bNext;
bCur = (BYTE)(*pbSrc++ << LShift);
RShift = (INT)(8 - LShift);
//
// We compose first all the destination bits from two source byte first
//
while (DstBits > RShift) {
bNext = *pbSrc++;
*pbDst++ = (BYTE)(bCur | (bNext >> RShift));
bCur = (BYTE)(bNext << LShift);
DstBits -= 8;
}
//
// If we still has desination bits left then pick it up form current byte
//
if (DstBits > 0) {
*pbDst = bCur;
}
}
VOID
XlateColor(
LPBYTE pbSrc,
LPBYTE pbDst,
XLATEOBJ *pxlo,
DWORD SCFlags,
DWORD Srcbpp,
DWORD cPels
)
/*++
Routine Description:
This function will translate source color to our device RGB color space by
using pxlo with SCFlags.
Arguments:
pbSrc - Pointer to the source color must 16/24/32 bpp (include bitfields)
pbDst - Translated device RGB buffer
pxlo - XLATEOBJ provided by the engine
SCFlags - The SOURCE COLOR flags, the flags is returned by CheckXlateObj
Srcbpp - Bits per pixel of the source provided by the pbSrc
cPels - Total Source pixels to be translated
Return Value:
VOID
Author:
07-Nov-1994 Mon 19:46:54 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LPWORD pw;
DW4B dw4b;
switch (Srcbpp) {
case 16:
//
// Translate every WORD (16 bits) to a 3 bytes RGB by calling engine
//
pw = (LPWORD)pbSrc;
while (cPels--) {
dw4b.dw = XLATEOBJ_iXlate(pxlo, *pw++);
*pbDst++ = dw4b.b4[0];
*pbDst++ = dw4b.b4[1];
*pbDst++ = dw4b.b4[2];
}
break;
case 24:
case 32:
if (SCFlags & SC_SWAP_RB) {
UINT SrcInc = (UINT)(Srcbpp >> 3);
//
// Just swap first byte with third byte, and skip the source by
// the SrcBpp
//
while (cPels--) {
*pbDst++ = *(pbSrc + 2);
*pbDst++ = *(pbSrc + 1);
*pbDst++ = *(pbSrc + 0);
pbSrc += SrcInc;
}
} else if (SCFlags & SC_IDENTITY) {
//
// If no color translate for 32bpp is needed then we need to
// remove 4th byte from the source
//
if (Srcbpp == 32) {
while (cPels--) {
*pbDst++ = *pbSrc++;
*pbDst++ = *pbSrc++;
*pbDst++ = *pbSrc++;
pbSrc++;
}
} else {
DBGMSG(DBG_LEVEL_ERROR, "SC_IDENTITY = 24bpp?!\n");
}
} else if (Srcbpp == 24) {
//
// At here only engine know how to translate 24bpp color from the
// source to our RGB format. (may be bitfields)
//
while (cPels--) {
dw4b.b4[0] = *pbSrc++;
dw4b.b4[1] = *pbSrc++;
dw4b.b4[2] = *pbSrc++;
dw4b.b4[3] = 0;
dw4b.dw = XLATEOBJ_iXlate(pxlo, dw4b.dw);
*pbDst++ = dw4b.b4[0];
*pbDst++ = dw4b.b4[1];
*pbDst++ = dw4b.b4[2];
}
} else {
LPDWORD pdw = (LPDWORD)pbSrc;
//
// At here only engine know how to translate 32bpp color from the
// source to our RGB format. (may be bitfields)
//
while (cPels--) {
dw4b.dw = XLATEOBJ_iXlate(pxlo, *pdw++);
*pbDst++ = dw4b.b4[0];
*pbDst++ = dw4b.b4[1];
*pbDst++ = dw4b.b4[2];
}
}
break;
default:
DBGMSG1(DBG_LEVEL_ERROR,
"XlateColor passed non 16/24/32 (%ld)",
Srcbpp);
break;
}
}
BOOL
PSSourceCopy(
PDEVDATA pDev,
SURFOBJ *psoSrc,
SIZEL szlSrc,
POINTL *pptlSrc,
PRECTL prclDest,
XLATEOBJ *pxlo
)
/*++
Routine Description:
This function copy the source image to the destination rectangle area by
sending the source image to the postscript devices, it will handle 1, 4,
8, 16, 24 and 32bpp bitmap
Arguments:
pDev - Pointer to our PDEV
psoSrc - Source surface object
szlSrc - Size of the source image to be sent
pptlSrc - Top/left corner of the source image
prclDest - Destination rectangle area
pxlo - XLATEOBJ provided by the engine
Return Value:
TRUE/FALSE
Author:
07-Nov-1994 Mon 17:22:30 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
LPBYTE pbSrc;
LPBYTE pbDst;
LPBYTE pbBuf;
LONG cbSrcScanLine;
DWORD cbDstScanLine;
DWORD Srcbpp;
DWORD Dstbpp;
DWORD DstBits;
DWORD SrcOffBits;
DWORD SCFlags;
FILTER filter;
//
// send out the bitmap data one scanline at a time.
// and compute DWORD aligned scanline width in bytes
//
switch (psoSrc->iBitmapFormat) {
case BMF_1BPP:
Srcbpp =
Dstbpp = 1;
break;
case BMF_4BPP:
Srcbpp =
Dstbpp = 4;
break;
case BMF_8BPP:
Srcbpp =
Dstbpp = 8;
break;
case BMF_16BPP:
Srcbpp = 16;
Dstbpp = 24;
break;
case BMF_24BPP:
Srcbpp =
Dstbpp = 24;
break;
case BMF_32BPP:
Srcbpp = 32;
Dstbpp = 24;
break;
default:
return(FALSE); /* other formats not supported */
}
//
// calculate the destination width in bytes from the width in bits.
// Note that the PS image routines only require scans to be padded to
// byte boundaries.
//
// NOTE: The SC_LSHIFT will only occurred if 1bpp or 4bpp sources and
// SC_XLATE will only happened if 16/24/32 bpp sources
//
DstBits = szlSrc.cx * Dstbpp;
SrcOffBits = pptlSrc->x * Srcbpp;
cbDstScanLine = (DWORD)((DstBits + 7) >> 3);
cbSrcScanLine = psoSrc->lDelta;
pbSrc = (LPBYTE)psoSrc->pvScan0 + (cbSrcScanLine * pptlSrc->y) +
(SrcOffBits >> 3);
SCFlags = (DWORD)(CheckXlateObj(pxlo, Srcbpp) |
((SrcOffBits &= 0x07) ? SC_LSHIFT : 0));
#if DBG
if (DbgPSSrcCopy) {
DBGPRINT("PS pxlo: Flags=%08x, Src=%ld, Dst=%ld, cEntries=%ld\n",
pxlo->flXlate, pxlo->iSrcType, pxlo->iDstType,
pxlo->cEntries);
DBGPRINT("PS: Flags=%04lx, szlSrc=%ld x %ld, DstBits=%ld, cbSrc=%ld, cbDst=%ld\n",
SCFlags, szlSrc.cx, szlSrc.cy, DstBits,
cbSrcScanLine, cbDstScanLine);
DBGPRINT("PS: pbSrc=%08lx, pptlSrc=(%ld, %ld)\n",
pbSrc, pptlSrc->x, pptlSrc->y);
}
#endif
//
// Initialized the postscript filter
//
FilterInit(pDev, &filter, FilterGenerateFlags(pDev));
//
// Output the PostScript beginimage operator.
// The Dstbpp is the final source we will send to the devices, 16/24/32bpp
// will always translate to our 24bpp format before sending
//
if (! BeginImageEx(pDev,
szlSrc,
Dstbpp,
cbDstScanLine,
prclDest,
FALSE,
pxlo,
&filter))
{
DBGERRMSG("BeginImageEx");
return(FALSE);
}
if (SCFlags) {
if (!(pbBuf = (LPBYTE) HEAPALLOC(pDev->hheap, cbDstScanLine))) {
DBGERRMSG("HEAPALLOC");
return(FALSE);
}
#if DBG
if (DbgPSSrcCopy) {
DBGPRINT("PS: Allocate LShift/Xlate Buffer = %08lx - %ld bytes\n",
pbBuf, cbDstScanLine);
}
#endif
} else {
pbBuf = NULL;
}
//
// Loop through each source scan line and shift the source or xlate the
// source
//
while (szlSrc.cy--) {
if (SCFlags & SC_LSHIFT) {
ShiftLeft(pbSrc, pbDst = pbBuf, DstBits, (INT)SrcOffBits);
} else if (SCFlags & SC_XLATE) {
XlateColor(pbSrc, pbDst = pbBuf, pxlo, SCFlags, Srcbpp, szlSrc.cx);
} else {
pbDst = pbSrc;
}
FILTER_WRITE(&filter, pbDst, cbDstScanLine);
pbSrc += cbSrcScanLine;
}
//
// Flush & free up the buffer if we did allocated one
//
FILTER_WRITE(&filter, (PBYTE) NULL, 0);
psputs(pDev, "\nendimage\n");
if (pbBuf) {
HEAPFREE(pDev->hheap, pbBuf);
}
return(TRUE);
}
BOOL
DoSourceCopy(
PDEVDATA pDev,
CLIPOBJ *pco,
SURFOBJ *psoSrc,
SIZEL szlSrc,
POINTL *pptlSrc,
PRECTL prclDest,
XLATEOBJ *pxlo
)
/*++
Routine Description:
This function copy the source bitmap to the destination
Arguments:
pDev - Pointer to our PDEV
pco - CLIP OBJ
psoSrc - Source surface object
szlSrc - Size of the source image to be sent
pptlSrc - Top/left corner of the source image
prclDest - Destination rectangle area
pxlo - XLATEOBJ provided by the engine
Return Value:
BOOLEAN
Author:
21-Feb-1995 Tue 13:27:50 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
BOOL bClipping, bOk;
POINTL ptlSrc;
//
// Make sure the source rectangle is within the source surface
//
if ((ptlSrc.x = pptlSrc->x) < 0) {
ptlSrc.x = 0;
szlSrc.cx += pptlSrc->x;
}
if ((ptlSrc.y = pptlSrc->y) < 0) {
ptlSrc.y = 0;
szlSrc.cy += pptlSrc->y;
}
if (szlSrc.cx > psoSrc->sizlBitmap.cx - ptlSrc.x)
szlSrc.cx = psoSrc->sizlBitmap.cx - ptlSrc.x;
if (szlSrc.cy > psoSrc->sizlBitmap.cy - ptlSrc.y)
szlSrc.cy = psoSrc->sizlBitmap.cy - ptlSrc.y;
//
// We don't need to emit any PS code if the source is empty
//
if (szlSrc.cx > 0 && szlSrc.cy > 0) {
bClipping = bDoClipObj(pDev, pco, NULL, prclDest);
bOk = PSSourceCopy(pDev, psoSrc, szlSrc, &ptlSrc, prclDest, pxlo);
if (bClipping) {
ps_restore(pDev, TRUE, FALSE);
}
} else
bOk = TRUE;
//
// Turn off the mono mask blt flags
//
pDev->dwFlags &= ~(PDEV_DOIMAGEMASK | PDEV_NOTSRCBLT);
return(bOk);
}
BOOL
DrvCopyBits(
SURFOBJ *psoDest,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclDest,
POINTL *pptlSrc
)
/*++
Routine Description:
Convert between two bitmap formats
Arguments:
Per Engine spec.
Return Value:
BOOLEAN
Author:
11-Feb-1993 Thu 21:00:43 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PDEVDATA pdev;
RECTL rclSrc;
RECTL rclDest;
RECTL rclClip;
BOOL bClipping;
BOOL bsuccess;
TRACEDDIENTRY("DrvCopyBits");
//
// The DrvCopyBits() function let application convert between bitmap and
// device format.
//
// BUT... for our postscript device we cannot read the printer surface
// bitmap back, so tell the caller that we cannot do it if they
// really called with these type of operations.
//
if (psoSrc->iType != STYPE_BITMAP)
return(EngEraseSurface(psoDest, prclDest, 0xffffffff));
if (psoDest->iType != STYPE_DEVICE) {
//
// Someone try to copy to bitmap surface, ie STYPE_BITMAP
//
DBGMSG(DBG_LEVEL_ERROR, "Cannot copy to NON-DEVICE destination\n");
SETLASTERROR(ERROR_INVALID_PARAMETER);
return(FALSE);
}
pdev = (PDEVDATA)psoDest->dhpdev;
if (!bValidatePDEV(pdev)) {
DBGERRMSG("bValidatePDEV");
SETLASTERROR(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (pdev->dwFlags & PDEV_CANCELDOC)
return FALSE;
if (pdev->dwFlags & PDEV_IGNORE_GDI)
return TRUE;
if (! (pdev->pPrinterData->dwFlags & PSDEV_HOST_HALFTONE)) {
SIZEL szlSrc;
//
// Printer halftoning is on, portion of source to copy limited by size
// of destination rect
//
szlSrc.cx = prclDest->right - prclDest->left;
szlSrc.cy = prclDest->bottom - prclDest->top;
return(DoSourceCopy(pdev,
pco,
psoSrc,
szlSrc,
pptlSrc,
prclDest,
pxlo));
} else {
//
// First validate everything to see if this one is the halftoned result
// or compatible with halftoned result, otherwise call HalftoneBlt() to
// halftone the sources then it will eventually come back to this
// function to output the halftoned result.
//
if ((pptlSrc->x == 0) &&
(pptlSrc->y == 0) &&
(prclDest->left >= 0) &&
(prclDest->top >= 0) &&
(prclDest->right <= psoDest->sizlBitmap.cx) &&
(prclDest->bottom <= psoDest->sizlBitmap.cy) &&
((prclDest->right - prclDest->left) == psoSrc->sizlBitmap.cx) &&
((prclDest->bottom - prclDest->top) == psoSrc->sizlBitmap.cy) &&
(IsHTCompatibleSurfObj(pdev, psoSrc, pxlo))) {
return(OutputHTCompatibleBits(pdev,
psoSrc,
pco,
prclDest->left,
prclDest->top));
} else {
rclDest = *prclDest;
rclSrc.left = pptlSrc->x;
rclSrc.top = pptlSrc->y;
rclSrc.right = rclSrc.left + (rclDest.right - rclDest.left);
rclSrc.bottom = rclSrc.top + (rclDest.bottom - rclDest.top);
//
// Validate that we only BLT the available source size
//
if ((rclSrc.right > psoSrc->sizlBitmap.cx) ||
(rclSrc.bottom > psoSrc->sizlBitmap.cy)) {
DBGMSG(DBG_LEVEL_WARNING,
"Engine passed SOURCE != DEST size, CLIP IT");
rclSrc.right = psoSrc->sizlBitmap.cx;
rclSrc.bottom = psoSrc->sizlBitmap.cy;
rclDest.right = (LONG)(rclSrc.right - rclSrc.left + rclDest.left);
rclDest.bottom = (LONG)(rclSrc.bottom - rclSrc.top + rclDest.top);
}
#if DBG
if (DbgPSBitBlt) {
DBGPRINT("\nDrvCopyBits CALLING HalftoneBlt().");
}
#endif
return(HalftoneBlt(pdev,
psoDest,
psoSrc,
NULL, // no source mask
pco,
pxlo,
NULL, // Default color adjustment
NULL, // Brush origin at (0,0)
&rclDest,
&rclSrc,
NULL, // No source mask
FALSE)); // SRCCOPY
}
}
}
BOOL
DrvStretchBlt(
SURFOBJ *psoDest,
SURFOBJ *psoSrc,
SURFOBJ *psoMask,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
COLORADJUSTMENT *pca,
POINTL *pptlBrushOrg,
PRECTL prclDest,
PRECTL prclSrc,
PPOINTL pptlMask,
ULONG iMode
)
/*++
Routine Description:
This function halfotne a soource rectangle area to the destination
rectangle area with options of invver source, and source masking
Provides stretching Blt capabilities between any combination of device
managed and GDI managed surfaces. We want the device driver to be able
to write on GDI bitmaps especially when it can do halftoning. This
allows us to get the same halftoning algorithm applied to GDI bitmaps
and device surfaces.
This function is optional. It can also be provided to handle only some
kinds of stretching, for example by integer multiples. This function
should return FALSE if it gets called to perform some operation it
doesn't know how to do.
Arguments:
psoDest
This is a pointer to a SURFOBJ. It identifies the surface on which
to draw.
psoSrc
This SURFOBJ defines the source for the Blt operation. The driver
must call GDI Services to find out if this is a device managed
surface or a bitmap managed by GDI.
psoMask
This optional surface provides a mask for the source. It is defined
by a logic map, i.e. a bitmap with one bit per pel.
The mask is used to limit the area of the source that is copied.
When a mask is provided there is an implicit rop4 of 0xCCAA, which
means that the source should be copied wherever the mask is 1, but
the destination should be left alone wherever the mask is 0.
When this argument is NULL there is an implicit rop4 of 0xCCCC,
which means that the source should be copied everywhere in the
source rectangle.
The mask will always be large enough to contain the source
rectangle, tiling does not need to be done.
pco
This is a pointer to a CLIPOBJ. GDI Services are provided to
enumerate the clipping region as a set of rectangles or trapezoids.
This limits the area of the destination that will be modified.
Whenever possible, GDI will simplify the clipping involved.
However, unlike DrvBitBlt, DrvStretchBlt may be called with a
single clipping rectangle. This is necessary to prevent roundoff
errors in clipping the output.
pxlo
This is a pointer to an XLATEOBJ. It tells how color indices should
be translated between the source and target surfaces.
The XLATEOBJ can also be queried to find the RGB color for any source
index. A high quality stretching Blt will need to interpolate colors
in some cases.
pca
This is a pointer to COLORADJUSTMENT structure, if NULL it specified
that appiclation did not set any color adjustment for this DC, and is
up to the driver to provide default adjustment
pptlBrushOrg
Pointer to the POINT structure to specified the location where halftone
brush should alignment to, if this pointer is NULL then it assume that
(0, 0) as origin of the brush
prclDest
This RECTL defines the area in the coordinate system of the
destination surface that can be modified.
The rectangle is defined by two points. These points are not well
ordered, i.e. the coordinates of the second point are not necessarily
larger than those of the first point. The rectangle they describe
does not include the lower and right edges. DrvStretchBlt will never
be called with an empty destination rectangle.
DrvStretchBlt can do inversions in both x and y, this happens when
the destination rectangle is not well ordered.
prclSrc
This RECTL defines the area in the coordinate system of the source
surface that will be copied. The rectangle is defined by two points,
and will map onto the rectangle defined by prclDest. The points of
the source rectangle are well ordered. DrvStretch will never be given
an empty source rectangle.
Note that the mapping to be done is defined by prclSrc and prclDest.
To be precise, the given points in prclDest and prclSrc lie on
integer coordinates, which we consider to correspond to pel centers.
A rectangle defined by two such points should be considered a
geometric rectangle with two vertices whose coordinates are the given
points, but with 0.5 subtracted from each coordinate. (The POINTLs
should just be considered a shorthand notation for specifying these
fractional coordinate vertices.) Note thate the edges of any such
rectangle never intersect a pel, but go around a set of pels. Note
also that the pels that are inside the rectangle are just what you
would expect for a "bottom-right exclusive" rectangle. The mapping
to be done by DrvStretchBlt will map the geometric source rectangle
exactly onto the geometric destination rectangle.
pptlMask
This POINTL specifies which pel in the given mask corresponds to
the upper left pel in the source rectangle. Ignore this argument
if there is no given mask.
iMode
This defines how source pels should be combined to get output pels.
The methods SB_OR, SB_AND, and SB_IGNORE are all simple and fast.
They provide compatibility for old applications, but don't produce
the best looking results for color surfaces.
SB_OR On a shrinking Blt the pels should be combined with an
OR operation. On a stretching Blt pels should be
replicated.
SB_AND On a shrinking Blt the pels should be combined with an
AND operation. On a stretching Blt pels should be
replicated.
SB_IGNORE On a shrinking Blt enough pels should be ignored so that
pels don't need to be combined. On a stretching Blt pels
should be replicated.
SB_BLEND RGB colors of output pels should be a linear blending of
the RGB colors of the pels that get mapped onto them.
SB_HALFTONE The driver may use groups of pels in the output surface
to best approximate the color or gray level of the input.
For this function we will ignored this parameter and always output
the SB_HALFTONE result
Return Value:
BOOLEAN
Author:
11-Feb-1993 Thu 19:52:29 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
PDEVDATA pdev;
UNREFERENCED_PARAMETER(iMode); // we always do HALFTONE
TRACEDDIENTRY("DrvStretchBlt");
//
// get the pointer to our DEVDATA structure and make sure it is ours.
//
pdev = (PDEVDATA)psoDest->dhpdev;
if (!bValidatePDEV(pdev)) {
DBGERRMSG("bValidatePDEV");
SETLASTERROR(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (pdev->dwFlags & PDEV_CANCELDOC)
return FALSE;
if (pdev->dwFlags & PDEV_IGNORE_GDI)
return TRUE;
if (! (pdev->pPrinterData->dwFlags & PSDEV_HOST_HALFTONE)) {
SIZEL szlSrc;
szlSrc.cx = prclSrc->right - prclSrc->left;
szlSrc.cy = prclSrc->bottom - prclSrc->top;
return(DoSourceCopy(pdev,
pco,
psoSrc,
szlSrc,
(PPOINTL)prclSrc,
prclDest,
pxlo));
} else {
return(HalftoneBlt(pdev, // pdev
psoDest, // Dest
psoSrc, // SRC
psoMask, // ----- psoMask
pco, // CLIPOBJ
pxlo, // XLATEOBJ
pca, // COLORADJUSTMENT
pptlBrushOrg, // BRUSH ORG
prclDest, // DEST RECT
prclSrc, // SRC RECT
pptlMask, // ----- pptlMask
FALSE)); // SrcCopy
}
}
//--------------------------------------------------------------------------
// VOID DrvBitBlt(
// PSURFOBJ psoTrg, // Target surface
// PSURFOBJ psoSrc, // Source surface
// PSURFOBJ psoMask, // Mask
// PCLIPOBJ pco, // Clip through this
// PXLATEOBJ pxlo, // Color translation
// PRECTL prclTrg, // Target offset and extent
// PPOINTL pptlSrc, // Source offset
// PPOINTL pptlMask, // Mask offset
// PBRUSHOBJ pbo, // Brush data
// PPOINTL pptlBrush, // Brush offset
// ROP4 rop4); // Raster operation
//
// Provides general Blt capabilities to device managed surfaces. The Blt
// might be from an Engine managed bitmap. In that case, the bitmap is
// one of the standard format bitmaps. The driver will never be asked
// to Blt to an Engine managed surface.
//
// This function is required if any drawing is done to device managed
// surfaces. The basic functionality required is:
//
// 1 Blt from any standard format bitmap or device surface to a device
// surface,
//
// 2 with any ROP,
//
// 3 optionally masked,
//
// 4 with color index translation,
//
// 5 with arbitrary clipping.
//
// Engine services allow the clipping to be reduced to a series of clip
// rectangles. A translation vector is provided to assist in color index
// translation for palettes.
//
// This is a large and complex function. It represents most of the work
// in writing a driver for a raster display device that does not have
// a standard format frame buffer. The Microsoft VGA driver provides
// example code that supports the basic function completely for a planar
// device.
//
// NOTE: PostScript printers do not support copying from device bitmaps.
// Nor can they perform raster operations on bitmaps. Therefore,
// it is not possible to support ROPs which interact with the
// destination (ie inverting the destination). The driver will
// do its best to map these ROPs into ROPs utilizing functions on
// the Source or Pattern.
//
// This driver supports the bitblt cases indicated below:
//
// Device -> Memory No
// Device -> Device No
// Memory -> Memory No
// Memory -> Device Yes
// Brush -> Memory No
// Brush -> Device Yes
//
// Parameters:
// <psoDest>
// This is a pointer to a device managed SURFOBJ. It identifies the
// surface on which to draw.
//
// <psoSrc>
// If the rop requires it, this SURFOBJ defines the source for the
// Blt operation. The driver must call the Engine Services to find out
// if this is a device managed surface or a bitmap managed by the
// Engine.
//
// <psoMask>
// This optional surface provides another input for the rop4. It is
// defined by a logic map, i.e. a bitmap with one bit per pel.
//
// The mask is typically used to limit the area of the destination that
// should be modified. This masking is accomplished by a rop4 whose
// lower byte is AA, leaving the destination unaffected when the mask
// is 0.
//
// This mask, like a brush, may be of any size and is assumed to tile
// to cover the destination of the Blt.
//
// If this argument is NULL and a mask is required by the rop4, the
// implicit mask in the brush will be used.
//
// <pco>
// This is a pointer to a CLIPOBJ. Engine Services are provided to
// enumerate the clipping region as a set of rectangles or trapezoids.
// This limits the area of the destination that will be modified.
//
// Whenever possible, the Graphics Engine will simplify the clipping
// involved. For example, vBitBlt will never be called with exactly
// one clipping rectangle. The Engine will have clipped the destination
// rectangle before calling, so that no clipping needs to be considered.
//
// <pxlo>
// This is a pointer to an XLATEOBJ. It tells how color indices should
// be translated between the source and target surfaces.
//
// If the source surface is palette managed, then its colors are
// represented by indices into a list of RGB colors. In this case, the
// XLATEOBJ can be queried to get a translate vector that will allow
// the device driver to quickly translate any source index into a color
// index for the destination.
//
// The situation is more complicated when the source is, for example,
// RGB but the destination is palette managed. In this case a closest
// match to each source RGB must be found in the destination palette.
// The XLATEOBJ provides a service routine to do this matching. (The
// device driver is allowed to do the matching itself when the target
// palette is the default device palette.)
//
// <prclDest>
// This RECTL defines the area in the coordinate system of the
// destination surface that will be modified. The rectangle is defined
// as two points, upper left and lower right. The lower and right edges
// of this rectangle are not part of the Blt, i.e. the rectangle is
// lower right exclusive. vBitBlt will never be called with an empty
// destination rectangle, and the two points of the rectangle will
// always be well ordered.
//
// <pptlSrc>
// This POINTL defines the upper left corner of the source rectangle, if
// there is a source. Ignore this argument if there is no source.
//
// <pptlMask>
// This POINTL defines which pel in the mask corresponds to the upper
// left corner of the destination rectangle. Ignore this argument if
// no mask is provided with psoMask.
//
// <pdbrush>
// This is a pointer to the device's realization of the brush to be
// used in the Blt. The pattern for the Blt is defined by this brush.
// Ignore this argument if the rop4 does not require a pattern.
//
// <pptlBrushOrigin>
// This is a pointer to a POINTL which defines the origin of the brush.
// The upper left pel of the brush is aligned here and the brush repeats
// according to its dimensions. Ignore this argument if the rop4 does
// not require a pattern.
//
// <rop4>
// This raster operation defines how the mask, pattern, source, and
// destination pels should be combined to determine an output pel to be
// written on the destination surface.
//
// This is a quaternary raster operation, which is a natural extension
// of the usual ternary rop3. There are 16 relevant bits in the rop4,
// these are like the 8 defining bits of a rop3. (We ignore the other
// bits of the rop3, which are redundant.) The simplest way to
// implement a rop4 is to consider its two bytes separately. The lower
// byte specifies a rop3 that should be computed wherever the mask
// is 0. The high byte specifies a rop3 that should then be computed
// and applied wherever the mask is 1.
//
// NOTE: The PostScript driver cannot do anything with any raster ops
// which utilize the destination. This means we only support the following
// 17 raster ops:
//
// BLACKNESS_ROP 0x00
// SRCORPATNOT_ROP 0x03
// PATNOTSRCAND_ROP 0x0C
// PATNOT_ROP 0x0F
// SRCNOTPATAND_ROP 0x30
// SRCNOT_ROP 0x33
// SRCXORPAT_ROP 0x3C
// SRCANDPATNOT_ROP 0x3F
// DST_ROP 0xAA
// SRCANDPAT_ROP 0xC0
// SRCXORPATNOT_ROP 0xC3
// SRC_ROP 0xCC
// PATNOTSRCOR_ROP 0xCF
// PAT_ROP 0xF0
// SRCNOTPATOR_ROP 0xF3
// SRCORPAT_ROP 0xFC
// WHITENESS_ROP 0xFF
//
// NOTE: PostScript printers cannot handle bitmap masking. What this
// translates to is that if the background rop3 is AA (Destination)
// there is no way for the printer to not overwrite the background.
//
// Returns:
// This function returns TRUE if successful.
//
// History:
//
// 27-Feb-1995 Mon 20:28:23 updated -by- Daniel Chou (danielc)
// Updated for image mask case
//
// 17-Mar-1993 Thu 21:29:15 updated -by- Rob Kiesler
// Added a code path to allow the PS Interpreter to do halftoning when
// the option is selected by the user.
//
// 11-Feb-1993 Thu 21:29:15 updated -by- Daniel Chou (danielc)
// Modified so that it call DrvStretchBlt(HALFTONE) when it can.
//
// 27-Mar-1992 Fri 00:08:43 updated -by- Daniel Chou (danielc)
// 1) Remove 'pco' parameter and replaced it with prclClipBound parameter,
// since pco is never referenced, prclClipBound is used for the
// halftone.
// 2) Add another parameter to do NOTSRCCOPY
// 04-Dec-1990 -by- Kent Settle (kentse)
// Wrote it.
//--------------------------------------------------------------------------
BOOL DrvBitBlt(
SURFOBJ *psoTrg, // Target surface
SURFOBJ *psoSrc, // Source surface
SURFOBJ *psoMask, // Mask
CLIPOBJ *pco, // Clip through this
XLATEOBJ *pxlo, // Color translation
PRECTL prclTrg, // Target offset and extent
PPOINTL pptlSrc, // Source offset
PPOINTL pptlMask, // Mask offset
BRUSHOBJ *pbo, // Brush data
PPOINTL pptlBrush, // Brush offset
ROP4 rop4) // Raster operation
{
PDEVDATA pdev;
PDRVHTINFO pDrvHTInfo;
RECTL rclSrc;
ULONG ulColor;
BOOL bInvertPat;
BOOL bClipping;
RECTL rclTmp;
TRACEDDIENTRY("DrvBitBlt");
// make sure none of the high bits are set.
ASSERTMSG((rop4 & 0xffff0000) == 0, "DrvBitBlt: invalid ROP.\n");
//
// get the pointer to our DEVDATA structure and make sure it is ours.
//
pdev = (PDEVDATA)psoTrg->dhpdev;
if (!bValidatePDEV(pdev)) {
DBGERRMSG("bValidatePDEV");
SETLASTERROR(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (pdev->dwFlags & PDEV_CANCELDOC)
return FALSE;
if (pdev->dwFlags & PDEV_IGNORE_GDI)
return TRUE;
//
// Do DrvStretchBlt(HALFTONE) first if we can, notices that we do not
// handle source masking case, because we cannot read back whatever on
// the printer surface, also we can just output it to the printer
// if the source bitmap/color is same or compatible with halftoned palette
//
if (!(pDrvHTInfo = (PDRVHTINFO)(pdev->pvDrvHTData))) {
DBGMSG(DBG_LEVEL_ERROR, "pDrvHTInfo = NULL?!\n");
return(FALSE);
}
pdev->dwFlags &= ~(PDEV_DOIMAGEMASK | PDEV_NOTSRCBLT);
//
// Any ROP that uses the dest should be converted to another ROP since the dest
// will always come back as all 1's.
//
switch (rop4) {
case 0xA0A0:
rop4 = 0xF0F0; // P & D ==> P
break;
case 0x2222: // (~S & D)
case 0xBBBB: // (~S | D)
case 0x8888: // ( S & D) ==> S if not masked
if ((psoSrc) &&
(psoSrc->iType == STYPE_BITMAP) &&
(psoSrc->iBitmapFormat == BMF_1BPP)) {
pdev->dwFlags |= PDEV_DOIMAGEMASK;
} else if (bOutputBitmapAsMask(pdev,psoSrc,pptlSrc,prclTrg,pco)) {
return(TRUE);
}
break;
}
//
// Following are the one involve with source and destination. each rop4
// will have two version, one for rop3/rop3 other for rop3/mask
//
switch (rop4) {
//----------------------------------------------------------------------
// Rop4 Request Op. SrcMASK Pscript Result Op.
//----------------------------------------------------------------------
case 0x1111: // ~( S | D) ~S
case 0x11AA: // ~( S | D) + SrcMask ~S
case 0x2222: // (~S & D) ~S
case 0x22AA: // (~S & D) + SrcMask ~S
case 0x3333: // (~S ) ~S
case 0x33AA: // (~S ) + SrcMask ~S
case 0x9999: // ~( S ^ D) ~S
case 0x99AA: // ~( S ^ D) + SrcMask ~S
case 0xBBBB: // (~S | D) ~S
case 0xBBAA: // (~S | D) + SrcMask ~S
case 0x7777: // ~( S & D) ~S
case 0x77AA: // ~( S & D) + SrcMask ~S
pdev->dwFlags |= PDEV_NOTSRCBLT;
case 0x4444: // ( S & ~D) S
case 0x44AA: // ( S & ~D) + SrcMask S
case 0x6666: // ( S ^ D) S
case 0x66AA: // ( S ^ D) + SrcMask S
case 0x8888: // ( S & D) S
case 0x88AA: // ( S & D) + SrcMask S
case 0xCCCC: // ( S ) S
case 0xCCAA: // ( S ) + SrcMask S
case 0xDDDD: // ( S | ~D) S
case 0xDDAA: // ( S | ~D) + SrcMask S
case 0xEEEE: // ( S | D) S
case 0xEEAA: // ( S | D) + SrcMask S
if (! (pdev->pPrinterData->dwFlags & PSDEV_HOST_HALFTONE)) {
//
// Printer halftoning, Source inversion is in pdev->dwFlags
//
return(DrvCopyBits(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc));
}
//
// We will output the bitmap directly to the surface if following
// conditions are all met
//
// 1. SRC = STYPE_BITMAP
// 2. No source mask
// 3. Source left/top = { 0, 0 }
// 4. Destination RECTL is visible on the destination surface
// 5. Destination RECTL size same as source bitmap size
//
if ((psoSrc->iType == STYPE_BITMAP) &&
((rop4 & 0xff) != 0xAA) &&
(pptlSrc->x == 0) &&
(pptlSrc->y == 0) &&
(prclTrg->left >= 0) &&
(prclTrg->top >= 0) &&
(prclTrg->right <= psoTrg->sizlBitmap.cx) &&
(prclTrg->bottom <= psoTrg->sizlBitmap.cy) &&
((prclTrg->right - prclTrg->left) == psoSrc->sizlBitmap.cx) &&
((prclTrg->bottom - prclTrg->top) == psoSrc->sizlBitmap.cy) &&
(IsHTCompatibleSurfObj(pdev, psoSrc, pxlo))) {
return(OutputHTCompatibleBits(pdev,
psoSrc,
pco,
prclTrg->left,
prclTrg->top));
}
//
// If we did not met above conditions then passed it to the
// HalftoneBlt(HALFTONE) and eventually it will come back to BitBlt()
// with (0xCCCC) or DrvCopyBits()
//
// The reason we pass the source mask to the HalftoneBlt() function is
// that when GDI engine create a shadow bitmap it will ask driver to
// provide the current destination surface bits but since we cannot
// read back from destination surface we will return FAILED in
// DrvCopyBits(FROM DEST) and engine will just WHITE OUT shadow bitmap
// (by DrvBitBlt(WHITENESS) before it doing SRC MASK COPY.
//
if ((rop4 & 0xFF) != 0xAA) {
psoMask = NULL;
pptlMask = NULL;
}
rclSrc.left = pptlSrc->x;
rclSrc.top = pptlSrc->y;
rclSrc.right = rclSrc.left + (prclTrg->right - prclTrg->left);
rclSrc.bottom = rclSrc.top + (prclTrg->bottom - prclTrg->top);
return(HalftoneBlt(pdev,
psoTrg,
psoSrc,
psoMask, // no mask
pco,
pxlo,
&(pDrvHTInfo->ca), // default clradj
NULL, // Brush Origin = (0,0)
prclTrg,
&rclSrc,
pptlMask,
pdev->dwFlags & PDEV_NOTSRCBLT));
}
//
// Now following are not HalftoneBlt() cases
// update the SURFOBJ pointer in our PDEV.
//
//
// set some flags concerning the bitmap.
// rop4 is a quaternary raster operation, which is a natural extension
// of the usual ternary rop3. There are 16 relevant bits in the rop4,
// these are like the 8 defining bits of a rop3. (We ignore the other
// bits of the rop3, which are redundant.) The simplest way to
// implement a rop4 is to consider its two bytes separately. The lower
// byte specifies a rop3 that should be computed wherever the mask
// is 0. The high byte specifies a rop3 that should then be computed
// and applied wherever the mask is 1. if both of the rop3s are the
// same, then a mask is not needed. otherwise a mask is necessary.
#if 0
if ((rop4 >> 8) != (rop4 & 0xff))
{
DBGMSG(DBG_LEVEL_ERROR, "Mask needed.\n");
return(FALSE);
}
#endif
// assume patterns will not be inverted.
bInvertPat = FALSE;
switch(rop4) {
case 0xFFFF: // WHITENESS.
case 0xFFAA: // WHITENESS.
case 0x0000: // BLACKNESS.
case 0x00AA: // BLACKNESS.
if ((rop4 == 0xFFFF) || (rop4 == 0xFFAA))
ulColor = RGB_WHITE;
else
ulColor = RGB_BLACK;
// handle the clip object passed in.
bClipping = bDoClipObj(pdev, pco, NULL, prclTrg);
ps_setrgbcolor(pdev, (PSRGB *)&ulColor);
// position the image on the page, remembering to flip the image
// from top to bottom.
// remember, with bitblt, the target rectangle is bottom/right
// exclusive.
rclTmp = *prclTrg;
rclTmp.right--;
rclTmp.bottom--;
ps_newpath(pdev);
ps_box(pdev, &rclTmp, FALSE);
psputs(pdev, "f\n");
if (bClipping) {
ps_restore(pdev, TRUE, FALSE);
}
break;
case 0x5A5A:
case 0x5AAA:
// we can't do the right thing, so we are done.
break;
case 0xF0F0: // PATCOPY opaque.
case 0xF0AA: // PATCOPY transparent.
case 0xAAF0:
// !!!
// The high-order byte is for background and the
// low-order byte is for foreground. So rop4 for
// transparent PATCOPY should be 0xAAF0 instead
// of F0AA.
// handle the clip object passed in.
bClipping = bDoClipObj(pdev, pco, NULL, prclTrg);
if (! DoPatCopy(pdev, psoTrg, prclTrg, pbo,
pptlBrush, rop4, bInvertPat))
{
return(FALSE);
}
if (bClipping) {
ps_restore(pdev, TRUE, FALSE);
}
break;
case 0xAAAA: /* Do nothing case */
rclTmp = *prclTrg;
rclTmp.right--;
rclTmp.bottom--;
bClipping = bDoClipObj(pdev, pco, NULL, prclTrg);
ps_box(pdev, (PRECTL) &rclTmp, FALSE);
if (bClipping) ps_restore(pdev, TRUE, FALSE);
break;
default:
return (EngBitBlt(
psoTrg,
psoSrc,
psoMask,
pco,
pxlo,
prclTrg,
pptlSrc,
pptlMask,
pbo,
pptlBrush,
rop4));
}
return(TRUE);
}
VOID
BeginImage(
PDEVDATA pdev,
BOOL Mono,
int x,
int y,
int cx,
int cy,
int cxBytes,
PFILTER pFilter
)
/*++
Routine Description:
This routine copy sorce image using PostScript code for the image command
appropriate for the bitmap format.
Arguments:
pdev - pointer to PDEVDATA
Mono - true if output is B/W monochrome
x - starting destination location in x
y - starting destination location in y
cx - bitmap width
cy - bitmap height
cxBytes - bytes count per single color scan line
Return Value:
void
Author:
16-Feb-1993 Tue 12:43:03 created -by- Daniel Chou (danielc)
Revision History:
--*/
{
#if 1
LPBYTE prgbm;
int cy1;
int i;
if (Mono) {
psprintf(pdev, "%d g",
(INT)((pdev->dwFlags & PDEV_NOTSRCBLT) ? 1 : 0));
i = 1;
prgbm = &rgbm[3];
} else {
i = 3;
prgbm = rgbm;
}
while (i--) {
psprintf(pdev, "/%cstr %d string def\n", *prgbm++, cxBytes);
}
//
// Generate a filter file object if necessary.
//
FilterGenerateFilterProc( pFilter );
//
// position the image on the page, remembering to flip the image
// from top to bottom. output PostScript user coordinates to the printer.
//
//
// 22-Feb-1993 Mon 21:44:22 updated -by- Daniel Chou (danielc)
// If application do their own banding then this computation could
// run into problems by missing 1 device pel because 1/64 accuracy
// is not good enough for full size banding
//
psprintf(pdev, "%d %d translate %d %d scale\n", x, y, cx, cy);
cy1 = cy;
psprintf(pdev, "%d %d ",cx, cy);
if (pdev->dwFlags & PDEV_DOIMAGEMASK) {
psprintf(pdev, "%b", (BOOL)(pdev->dwFlags & PDEV_NOTSRCBLT));
} else {
psputs(pdev, "1");
}
psprintf(pdev, " [%d 0 0 %d 0 0]\n", cx, cy1);
//
// Ask the filter level to create the correct imageproc and procs
//
FilterGenerateImageProc( pFilter, !Mono );
#else
//
// create the necessary string(s) on the printer's stack to read
// in the bitmap data.
//
if (Mono) {
psprintf(pdev, "0 g/mstr %d string def\n", cxBytes);
} else {
psprintf(pdev, "/rstr %d string def\n", cxBytes);
psprintf(pdev, "/gstr %d string def\n", cxBytes);
psprintf(pdev, "/bstr %d string def\n", cxBytes);
}
//
// Generate a filter file object if necessary.
//
FilterGenerateFilterProc( pFilter );
//
// position the image on the page, remembering to flip the image
// from top to bottom. output PostScript user coordinates to the printer.
//
//
// 22-Feb-1993 Mon 21:44:22 updated -by- Daniel Chou (danielc)
// If application do their own banding then this computation could
// run into problems by missing 1 device pel because 1/64 accuracy
// is not good enough for full size banding
//
psprintf(pdev, "%d %d translate\n", x, y);
//
// scale the image.
//
psprintf(pdev, "%d %d scale\n", cx, cy);
//
// Output the image operator and the scan data.
// We will always send in as TOPDOWN when we calling this function
//
psprintf(pdev, "%d %d 1 [%d 0 0 %d 0 0] ", cx, cy, cx, cy);
//
// Ask the filter level to create the correct imageproc and procs
//
FilterGenerateImageProc( pFilter, !Mono );
#endif
}
//--------------------------------------------------------------------
// BOOL DoPatCopy(pdev, pso, prclTrg, pbo, pptlBrush, rop4, bInvertPat)
// PDEVDATA pdev;
// SURFOBJ *pso;
// PRECTL prclTrg;
// BRUSHOBJ *pbo;
// PPOINTL pptlBrush;
// ROP4 rop4;
// BOOL bInvertPat;
//
// This routine determines which pattern we are to print from the
// BRUSHOBJ passed in, and will output the PostScript commands to
// do the pattern fill. It is assumed the clipping will have been
// set up at this point.
//
// History:
// Thu May 23, 1991 -by- Kent Settle [kentse]
// Wrote it.
//--------------------------------------------------------------------
BOOL DoPatCopy(pdev, pso, prclTrg, pbo, pptlBrush, rop4, bInvertPat)
PDEVDATA pdev;
SURFOBJ *pso;
PRECTL prclTrg;
BRUSHOBJ *pbo;
PPOINTL pptlBrush;
ROP4 rop4;
BOOL bInvertPat;
{
RECTL rclTmp;
BOOL bUserPat;
DEVBRUSH *pBrush;
// remember, with bitblt, the target rectangle is bottom/right
// exclusive.
rclTmp.left = prclTrg->left;
rclTmp.top = prclTrg->top;
rclTmp.right = prclTrg->right;
rclTmp.bottom = prclTrg->bottom;
rclTmp.right -= 1;
rclTmp.bottom -= 1;
// if we have a user defined pattern, don't output the bounding box since
// it will not be used.
bUserPat = FALSE;
if (pbo->iSolidColor != NOT_SOLID_COLOR)
bUserPat = FALSE;
else
{
pBrush = (DEVBRUSH *)BRUSHOBJ_pvGetRbrush(pbo);
if (!pBrush)
bUserPat = FALSE;
else
{
if ((pBrush->iPatIndex < HS_HORIZONTAL) ||
(pBrush->iPatIndex >= HS_DDI_MAX))
bUserPat = TRUE;
}
}
if (!bUserPat) {
ps_newpath(pdev);
ps_box(pdev, &rclTmp, FALSE);
}
// now fill the target rectangle with the given pattern.
return(ps_patfill(pdev, pso, (FLONG)FP_WINDINGMODE, pbo, pptlBrush, rop4,
prclTrg, bInvertPat, FALSE));
}
//--------------------------------------------------------------------
// BOOL BeginImageEx(pdev, sizlSrc, ulSrcFormat, cbSrcWidth, prclDest,
// bNotSrcCopy, pxlo)
// PDEVDATA pdev;
// SIZEL sizlSrc;
// ULONG ulSrcFormat;
// DWORD cbSrcWidth;
// PRECTL prclDest;
// BOOL bNotSrcCopy;
// XLATEOBJ *pxlo;VOID
//
// Routine Description:
//
// This routine will output the appropriate operators to set up the PS
// interprter to receive a source image from the host. This routine is
// called only when the PS Interpreter is being asked to perform
// halftoning.
//
// Return Value:
//
// FALSE if an error occurred.
//
// Author:
//
// 17-Mar-1993 created -by- Rob Kiesler
//
//
// Revision History:
//--------------------------------------------------------------------
BOOL BeginImageEx(pdev, sizlSrc, ulSrcFormat, cbSrcWidth, prclDest,
bNotSrcCopy, pxlo, pFilter)
PDEVDATA pdev;
SIZEL sizlSrc;
ULONG ulSrcFormat;
DWORD cbSrcWidth;
PRECTL prclDest;
BOOL bNotSrcCopy;
XLATEOBJ *pxlo;
PFILTER pFilter;
{
PSRGB *prgb;
DWORD i;
CHAR bmpTypeStr[2];
BYTE intensity;
//
// Check to see if any of the PS image handling code
// has been downloaded.
//
if (!(pdev->dwFlags & PDEV_UTILSSENT)) {
//
// Download the Adobe PS Utilities Procset.
//
psputs(pdev, "/Adobe_WinNT_Driver_Gfx 175 dict dup begin\n");
if (!bSendPSProcSet(pdev, PSPROC_UTILS))
{
DBGERRMSG("bSendPSProcSet");
return(FALSE);
}
psputs(pdev,
"end def\n[1.000 0 0 1.000 0 0] "
"Adobe_WinNT_Driver_Gfx dup /initialize get exec\n");
pdev->dwFlags |= PDEV_UTILSSENT;
}
if (!(pdev->dwFlags & PDEV_IMAGESENT)) {
//
// Download the Adobe PS Image Procset.
//
psputs(pdev, "Adobe_WinNT_Driver_Gfx begin\n");
if (!bSendPSProcSet(pdev, PSPROC_IMAGE))
{
DBGERRMSG("bSendPSProcSet");
return(FALSE);
}
psputs(pdev, "end reinitialize\n");
pdev->dwFlags |= PDEV_IMAGESENT;
}
//
// Send the source bmp origin, source bmp format, and scanline width.
//
psprintf(pdev, "%l %l %l %l %l %l %l %l %b %b %l beginimage\n",
sizlSrc.cx,
sizlSrc.cy,
ulSrcFormat,
cbSrcWidth,
prclDest->right - prclDest->left,
prclDest->bottom - prclDest->top,
prclDest->left, prclDest->top,
FALSE, // smooth flag
!(BOOL)((pdev->dwFlags & PDEV_DOIMAGEMASK) ||
((bNotSrcCopy) && (ulSrcFormat == 1))),
(LONG)FilterPSBitMapType(pFilter, FALSE));
prgb = (PSRGB *)((pxlo) ? pxlo->pulXlate : NULL);
switch (ulSrcFormat)
{
case 1:
if (pdev->dwFlags & PDEV_DOIMAGEMASK) {
psprintf(pdev, "%d true 1bitmaskimage\n",
(INT)((pdev->dwFlags & PDEV_NOTSRCBLT) ? 255 : 0));
break;
} else {
BOOL bNormalBwImage;
ULONG * pColorMap;
// 5/11/95 -davidx-
// A black and white image is considered normal
// if it does not have a colormap or the first
// entry of the colormap is black and the second
// entry of the colormap is white.
pColorMap = (ULONG*) prgb;
bNormalBwImage =
((pxlo->flXlate & XO_TABLE) == 0) ||
(pxlo->cEntries < 2) ||
(pColorMap == NULL) ||
(pColorMap[0] == RGB(0,0,0) &&
pColorMap[1] == RGB(255,255,255));
if (bNormalBwImage) {
// Normal black and white image is processed
// directly by the PS interpreter without
// having to go through colormap lookup.
psputs(pdev, "doNimage\n");
break;
}
}
// Process a 1-bpp image with a abnormal colormap.
// Fall through!!
case 4 :
case 8 :
if (prgb == NULL)
{
//
// No palette, use the current PS colors.
//
psputs(pdev, "doNimage\n");
}
else
{
//
// There is a palette, send it to the PS interpreter.
// First, compute and send the mono (intensity) palette.
//
psputs(pdev, "<\n");
for (i = 0; i < pxlo->cEntries; prgb++)
{
intensity = INTENSITY(prgb->red,
prgb->green,
prgb->blue);
psputhex(pdev, 1, &intensity);
if (++i % 16)
psputs(pdev," ");
else
psputs(pdev,"\n");
}
//
// If the number of palette entries is less than the
// number of possible colors for ulSrcFormat, pad the
// palette with 0's.
//
for ( ; i < (DWORD)(1 << ulSrcFormat) ; )
{
psputs(pdev,"00");
if (++i % 16)
psputs(pdev," ");
else
psputs(pdev, "\n");
}
psputs(pdev, ">\n");
//
// Send the RGB palette.
//
psputs(pdev, "<\n");
prgb = (PSRGB *)pxlo->pulXlate;
for (i = 0; i < pxlo->cEntries; prgb++)
{
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
psputhex(pdev, 3, (PBYTE) prgb);
if (++i % 8)
psputs(pdev," ");
else
psputs(pdev,"\n");
}
//
// If the number of palette entries is less than the
// number of possible colors for ulSrcFormat, pad the
// palette with 0's.
//
for ( ; i < (DWORD)(1 << ulSrcFormat) ; )
{
psputs(pdev,"000000");
if (++i % 8)
psputs(pdev," ");
else
psputs(pdev, "\n");
}
psputs(pdev, "\n>doclutimage\n");
}
break;
case 24:
//
// 16/24/32 bpp will all translate into a 24bpp destination
// 24BPP images don't need a palette, use the doNimage operator.
//
psputs(pdev, "doNimage\n");
break;
default:
//
// Can't handle bitmaps in formats other than the ones above!
//
return(FALSE);
}
return(TRUE);
}