|
|
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993
//--------------------------------------------------------------------------
//
// 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)
// 1) add the prclBound parameter to the bDoClipObj()
// 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.
//
// Copyright (c) 1990-1992 Microsoft Corporation
//
// This module contains DrvBitBlt, DrvStretchBlt and related routines.
//--------------------------------------------------------------------------
#include "stdlib.h"
#include "pscript.h"
#include "enable.h"
#include "halftone.h"
extern VOID vHexOut(PDEVDATA, PBYTE, LONG);
extern BOOL bDoClipObj(PDEVDATA, CLIPOBJ *, RECTL *, RECTL *, BOOL *, BOOL *, DWORD);
extern SHORT PSBitMapType(PDEVDATA pdev, BOOL BinaryClearChannel);
#ifdef INDEX_PAL
extern ULONG PSMonoPalette[];
extern ULONG PSColorPalette[];
#endif
#if DBG
BOOL DbgPSBitBlt = 0;
#endif
#define PRINT_TOPDOWN 0x02
#define PRINT_SRCAND 0x04
#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)
//
// declarations of routines residing within this module.
//
VOID
BeginImage(
PDEVDATA pdev,
BOOL Mono,
int x,
int y,
int cx,
int cy,
int cxBytes
);
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);
BOOL DoSourceCopy(
PDEVDATA pdev,
SURFOBJ *psoSrc,
PRECTL prclSrc,
PRECTL prclDest,
XLATEOBJ *pxlo,
RECTL *prclClipBound,
BOOL bNotSrcCopy);
//
//********** 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))) {
DbgPrint("\nPSCRIPT!HalftoneBlt: pDrvHTInfo = NULL ???\n");
return(FALSE);
}
if (pDrvHTInfo->Flags & DHIF_IN_STRETCHBLT) {
#if DBG
DbgPrint("\nPSCRIPT!HalftoneBlt: EngStretchBlt() RECURSIVE CALLS NOT ALLOWED!!!\n");
#endif
return(FALSE);
}
//
// Setup these data before calling EngStretchBlt(), these are used at later
// DrvCopyBits() call
//
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("\nPSCRIPT!HalftoneBlt: CLIP: Complex=%ld",
(DWORD)pco->iDComplexity);
DbgPrint("\nClip rclBounds = (%ld, %ld) - (%ld, %ld)",
pco->rclBounds.left,
pco->rclBounds.top,
pco->rclBounds.right,
pco->rclBounds.bottom);
} else {
DbgPrint("\nPSCRIPT!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
#if DBG
DbgPrint("\nPSCRIPT!HalftoneBlt: EngStretchBlt(HALFTONE) Failed\n");
#endif
}
//
// 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:
--*/
{
#ifdef INDEX_PAL
PALETTEENTRY *prgb;
PALETTEENTRY *ppalette;
ULONG *pulColors;
#else
BGR_PAL_ENTRY *pbgr;
#endif
PDRVHTINFO pDrvHTInfo;
UINT BmpFormat;
UINT cPal;
if (!(pDrvHTInfo = (PDRVHTINFO)(pdev->pvDrvHTData))) {
DbgPrint("\nPSCRIPT!IsHTCompatibleSurfObj: pDrvHTInfo = NULL ???\n");
return(FALSE);
}
#if DBG
if (DbgPSBitBlt) {
DbgPrint("\n** IsHTCompatibleSurfObj **");
DbgPrint("\niType=%ld, BmpFormat=%ld",
(DWORD)pso->iType,
(DWORD)pso->iBitmapFormat);
if (pxlo) {
DbgPrint("\npxlo: flXlate=%08lx, cPal=%ld, pulXlate=%08lx",
(DWORD)pxlo->flXlate,
(DWORD)pxlo->cEntries,
(DWORD)pxlo->pulXlate);
} else {
DbgPrint("\npxlo = NULL");
}
}
#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("\npso->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) &&
#ifdef INDEX_PAL
((pxlo->flXlate & XO_TRIVIAL) ||
((pxlo->flXlate & XO_TABLE) &&
#else
(pxlo->flXlate & XO_TABLE) &&
#endif
((cPal = (UINT)pxlo->cEntries) <= (UINT)pDrvHTInfo->HTPalCount) &&
#ifdef INDEX_PAL
(ppalette = (PALETTEENTRY *)pxlo->pulXlate)))) {
#else
(pbgr = (BGR_PAL_ENTRY *)pxlo->pulXlate)) {
#endif
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("\nHTPalXor=%08lx", HTPalXor);
}
#endif
#ifdef INDEX_PAL
// if the TRIVIAL color translation flag is set, then fill in
// halftoning palette from our hardcoded palettes.
if (BmpFormat == (UINT)BMF_1BPP) {
pulColors = PSMonoPalette;
} else {
pulColors = PSColorPalette;
}
if (pxlo->flXlate & XO_TRIVIAL) {
if (BmpFormat == (UINT)BMF_1BPP) {
cPal = 2;
ppalette = (PALETTEENTRY *)PSMonoPalette;
} else {
cPal = 8;
ppalette = (PALETTEENTRY *)PSColorPalette;
}
}
for (i = 0; i < cPal; i++, ppalette++) {
if (pxlo->flXlate & XO_TRIVIAL) {
prgb = ppalette;
}
else if (pxlo->flXlate & XO_TABLE) {
if (BmpFormat == BMF_24BPP) {
prgb = ppalette;
} else {
prgb = (PALETTEENTRY *)(pulColors +
XLATEOBJ_iXlate(pxlo, *(ULONG *)ppalette));
}
}
HTXB_R(htXB) = prgb->peRed;
HTXB_G(htXB) = prgb->peGreen;
HTXB_B(htXB) = prgb->peBlue;
#else
for (i = 0; i < cPal; i++, pbgr++) {
HTXB_R(htXB) = pbgr->bgrRed;
HTXB_G(htXB) = pbgr->bgrGreen;
HTXB_B(htXB) = pbgr->bgrBlue;
#endif
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("\nSrcPal has NON 0xff/0x00 intensity, NOT HTPalette");
}
#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("\n%d - %02x:%02x:%02x -> %02x:%02x:%02x, Idx=%d, PalXlate=%d",
i,
#ifdef INDEX_PAL
(BYTE)prgb->peRed,
(BYTE)prgb->peGreen,
(BYTE)prgb->peBlue,
#else
(BYTE)pbgr->bgrRed,
(BYTE)pbgr->bgrGreen,
(BYTE)pbgr->bgrBlue,
#endif
(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("\nNON-BLACK/WHITE MONO BITMAP, NOT HTPalette");
}
#endif
return(FALSE);
}
}
if (GenHTXB) {
//
// Copy down the pal xlate
//
#if DBG
if (DbgPSBitBlt) {
DbgPrint("\n --- Copy XLATE TABLE ---");
}
#endif
CopyMemory(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("\n --- Generate 4bpp --> 3 planes xlate ---");
}
#endif
if (!(pDrvHTInfo->pHTXB)) {
RIP("PSCRIPT!IsHTCompatibleSurfObj: NULL pDrvHTInfo->pHTXB\n");
if (!(pDrvHTInfo->pHTXB = (PHTXB)
HeapAlloc(pdev->hheap, 0, HTXB_TABLE_SIZE))) {
RIP("PSCRIPT!IsHTCompatibleSurfObj: HeapAlloc(HTXB_TABLE_SIZE) failed\n");
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
//
CopyMemory(pTmpHTXB,
pTmpHTXB - HTXB_L_NIBBLE_MAX,
sizeof(HTXB) * HTXB_L_NIBBLE_DUP);
}
//
// Copy high nibble duplication, 128 of them
//
CopyMemory(pTmpHTXB,
pDrvHTInfo->pHTXB,
sizeof(HTXB) * HTXB_H_NIBBLE_DUP);
}
}
#if DBG
if (DbgPSBitBlt) {
DbgPrint("\n******* IsHTCompatibleSurfObj = YES *******");
}
#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:
--*/
{
PDRVHTINFO pDrvHTInfo;
LPBYTE pbHTBits;
LPBYTE pbOutput;
SIZEL SizeBlt;
RECTL rclBounds;
LONG cbToNextScan;
DWORD AllocSize;
DWORD cxDestBytes;
DWORD cxDestDW;
DWORD xLoop;
DWORD yLoop;
BOOL Mono;
BOOL bMoreClipping;
BOOL bFirstClipPass;
DWORD dwBlack = RGB_BLACK;
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
//
if (pDrvHTInfo->PalXlate[0]) {
cxDestDW = (DWORD)((cxDestBytes + 3) >> 2);
AllocSize = cxDestDW * sizeof(DWORD);
#if DBG
if (DbgPSBitBlt) {
DbgPrint("\nOutputHTCompatibleBits: MONO -- INVERT");
}
#endif
} else {
#if DBG
if (DbgPSBitBlt) {
DbgPrint("\nOutputHTCompatibleBits: MONO");
}
#endif
AllocSize = 0;
}
} else {
#if DBG
if (DbgPSBitBlt) {
DbgPrint("\nOutputHTCompatibleBits: 4 BIT --> 3 PLANES");
}
#endif
AllocSize = (DWORD)(cxDestBytes * 3);
}
if (AllocSize) {
if (!(pbOutput = (LPBYTE)HeapAlloc(pdev->hheap, 0, AllocSize))) {
#if DBG
DbgPrint("\nOutputHTCompatibleBits: HeapAlloc(HT CopyBits Buffer) Failed\n");
#endif
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("\nOutputHTCompatibleBits: pco = %08lx", (DWORD)pco);
}
#endif
bMoreClipping = TRUE;
bFirstClipPass = TRUE;
while (bMoreClipping)
{
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
pbHTBits = (LPBYTE)psoHT->pvScan0;
if ((bDoClipObj(pdev, pco, &rclBounds, NULL, &bMoreClipping,
&bFirstClipPass, MAX_CLIP_RECTS)) && (pco)) {
//
// If clipping is send to the printer then ps_save() already done
// at bDoClipObj()
//
#if DBG
if (DbgPSBitBlt) {
DbgPrint("\nOutputHTCompatibleBits: PS_CLIP: Complex=%ld",
(DWORD)pco->iDComplexity);
DbgPrint("\nClip rclBounds = (%ld, %ld) - (%ld, %ld)",
rclBounds.left,
rclBounds.top,
rclBounds.right,
rclBounds.bottom);
}
#endif
ps_clip(pdev, TRUE);
} else {
ps_save(pdev, TRUE);
}
//
// 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
// if we are doing the SourceOr hack, then we need to output the
// foreground color now.
if (pdev->dwFlags & PDEV_SOURCEORHACK)
#ifdef INDEX_PAL
ps_setrgbcolor(pdev, (PALETTEENTRY *)&dwBlack);
#else
ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&dwBlack);
#endif
BeginImage(pdev, Mono, xDest, yDest, SizeBlt.cx, SizeBlt.cy,
cxDestBytes);
// clear the flag now.
pdev->dwFlags &= ~PDEV_SOURCEORHACK;
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;
vHexOut(pdev, (PBYTE)pbOutput, cxDestBytes);
PrintString(pdev, "\n");
}
} else {
while (yLoop--) {
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
vHexOut(pdev, pbHTBits, cxDestBytes);
PrintString(pdev, "\n");
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);
}
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
vHexOut(pdev, pbScanR0, cxDestBytes);
PrintString(pdev, "\n");
vHexOut(pdev, pbScanG0, cxDestBytes);
PrintString(pdev, "\n");
vHexOut(pdev, pbScanB0, cxDestBytes);
PrintString(pdev, "\n");
}
}
//
// After ps_save() we better have ps_restore() to match it
//
ps_restore(pdev, TRUE);
}
//
// Release scan line buffers if we did allocate one
//
if (pbOutput) {
HeapFree(pdev->hheap, 0, (PVOID)pbOutput);
}
return(TRUE);
}
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;
PRECTL prclClip;
BOOL bClipping;
BOOL bMoreClipping;
BOOL bFirstClipPass;
//
// 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
//
#if DBG
DbgPrint("\nPSCRIPT!DrvCopyBits: Cannot copy to NON-DEVICE destination\n");
#endif
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
pdev = (PDEVDATA)psoDest->dhpdev;
if (!bValidatePDEV(pdev)) {
#if DBG
DbgPrint("\nPSCRIPT!DrvCopyBits: Invalid PDEV for destination passed.\n");
#endif
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (pdev->dwFlags & PDEV_PSHALFTONE)
{
//
// Let the Postscript interpreter do the halftoning.
//
rclSrc.left = pptlSrc->x;
rclSrc.top = pptlSrc->y;
rclSrc.right = pptlSrc->x + psoSrc->sizlBitmap.cx;
rclSrc.bottom = pptlSrc->y + psoSrc->sizlBitmap.cy;
prclClip = &rclClip;
bMoreClipping = TRUE;
bFirstClipPass = TRUE;
while (bMoreClipping)
{
if (!(bClipping = bDoClipObj(pdev, pco, &rclClip, prclDest,
&bMoreClipping, &bFirstClipPass,
MAX_CLIP_RECTS)))
prclClip = NULL;
else
ps_clip(pdev, TRUE);
// DoSourceCopy does not know how to use prclClip, so don't give it one.
// if (!DoSourceCopy(pdev, psoSrc, &rclSrc, prclDest, pxlo, prclClip,
if (!DoSourceCopy(pdev, psoSrc, &rclSrc, prclDest, pxlo, NULL,
FALSE))
return(FALSE);
if (bClipping)
ps_restore(pdev, TRUE);
}
}
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)) {
#if DBG
DbgPrint("\nWARNING: PSCRIPT!DrvCopyBits: Engine passed SOURCE != DEST size, CLIP IT");
#endif
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
//
// get the pointer to our DEVDATA structure and make sure it is ours.
//
pdev = (PDEVDATA)psoDest->dhpdev;
if (!bValidatePDEV(pdev)) {
RIP("PSCRIPT!DrvStretchBlt: invalid pdev.\n");
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
// clear the source OR hack bit.
pdev->dwFlags &= ~PDEV_SOURCEORHACK;
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 does not return a value.
//
// History:
// 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;
BOOL NotSrcCopy;
PRECTL prclClip;
RECTL rclClip;
RECTL rclTmp;
BOOL bMoreClipping;
BOOL bFirstClipPass;
// make sure none of the high bits are set.
ASSERTPS((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)) {
RIP("PSCRIPT!DrvBitBlt: invalid pdev.\n");
SetLastError(ERROR_INVALID_PARAMETER);
return(FALSE);
}
//
// 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))) {
DbgPrint("\nPSCRIPT!DrvBitBlt: pDrvHTInfo = NULL ???\n");
return(FALSE);
}
NotSrcCopy = FALSE;
//
// Following are the one involve with source and destination. each rop4
// will have two version, one for rop3/rop3 other for rop3/mask
//
// clear the source OR hack bit.
pdev->dwFlags &= ~PDEV_SOURCEORHACK;
switch (rop4) {
//----------------------------------------------------------------------
// Rop4 Request Op. SrcMASK Pscript Result Op.
//----------------------------------------------------------------------
case 0xB8B8: // ugly raster op that apps seem to use to blt text
case 0xB8AA: // to our surface, when they treat us as a raster device.
if (psoSrc->iBitmapFormat == BMF_1BPP)
pdev->dwFlags |= PDEV_SOURCEORHACK;
case 0x1111: // ~( S | D) ~S
case 0x11AA: // ~( 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
NotSrcCopy = TRUE;
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->dwFlags & PDEV_PSHALFTONE)
{
//
// Let the Postscript interpreter do the halftoning.
//
rclSrc.left = pptlSrc->x;
rclSrc.top = pptlSrc->y;
rclSrc.right = pptlSrc->x + psoSrc->sizlBitmap.cx;
rclSrc.bottom = pptlSrc->y + psoSrc->sizlBitmap.cy;
prclClip = &rclClip;
bMoreClipping = TRUE;
bFirstClipPass = TRUE;
while (bMoreClipping)
{
if (!(bClipping = bDoClipObj(pdev, pco, &rclClip, prclTrg,
&bMoreClipping, &bFirstClipPass,
MAX_CLIP_RECTS)))
prclClip = NULL;
else
ps_clip(pdev, TRUE);
// DoSourceCopy does not know how to use prclClip, so don't give it one.
// if (!DoSourceCopy(pdev, psoSrc, &rclSrc, prclTrg, pxlo, prclClip,
if (!DoSourceCopy(pdev, psoSrc, &rclSrc, prclTrg, pxlo, NULL,
NotSrcCopy))
return(FALSE);
if (bClipping)
ps_restore(pdev, TRUE);
}
break;
}
else
{
//
// 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,
NotSrcCopy));
}
}
//
// 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))
{
RIP("PSCRIPT: vBitBlt - 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.
bMoreClipping = TRUE;
bFirstClipPass = TRUE;
while (bMoreClipping)
{
bClipping = bDoClipObj(pdev, pco, NULL, prclTrg, &bMoreClipping,
&bFirstClipPass, MAX_CLIP_RECTS);
if (bClipping) {
ps_clip(pdev, TRUE);
}
#ifdef INDEX_PAL
ps_setrgbcolor(pdev, (PALETTEENTRY *)&ulColor);
#else
ps_setrgbcolor(pdev, (BGR_PAL_ENTRY *)&ulColor);
#endif
// 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.left = prclTrg->left;
rclTmp.top = prclTrg->top;
rclTmp.right = prclTrg->right;
rclTmp.bottom = prclTrg->bottom;
if ((prclTrg->right - prclTrg->left) > 1)
rclTmp.right -= 1;
if ((prclTrg->bottom - prclTrg->top) > 1)
rclTmp.bottom -= 1;
ps_box(pdev, &rclTmp);
PrintString(pdev, "f\n");
if (bClipping) {
ps_restore(pdev, TRUE);
}
}
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.
// handle the clip object passed in.
bMoreClipping = TRUE;
bFirstClipPass = TRUE;
while (bMoreClipping)
{
bClipping = bDoClipObj(pdev, pco, NULL, prclTrg, &bMoreClipping,
&bFirstClipPass, MAX_CLIP_RECTS);
if (bClipping) {
ps_clip(pdev, TRUE);
}
if (!DoPatCopy(pdev, psoTrg, prclTrg, pbo, pptlBrush, rop4, bInvertPat)) {
return(FALSE);
}
if (bClipping) {
ps_restore(pdev, TRUE);
}
}
break;
default:
return (EngBitBlt(
psoTrg,
psoSrc,
psoMask,
pco,
pxlo,
prclTrg,
pptlSrc,
pptlMask,
pbo,
pptlBrush,
rop4));
}
//
// bDoClipObj does a save around the clip region.
//
return(TRUE);
}
VOID
BeginImage(
PDEVDATA pdev,
BOOL Mono,
int x,
int y,
int cx,
int cy,
int cxBytes
)
/*++
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:
--*/
{
POINTPSFX ptpsfx;
//
// create the necessary string(s) on the printer's stack to read
// in the bitmap data.
//
if (Mono) {
PrintString(pdev, "/mstr ");
PrintDecimal(pdev, 1, cxBytes);
PrintString(pdev, " string def\n");
} else {
PrintString(pdev, "/rstr ");
PrintDecimal(pdev, 1, cxBytes);
PrintString(pdev, " string def\n");
PrintString(pdev, "/gstr ");
PrintDecimal(pdev, 1, cxBytes);
PrintString(pdev, " string def\n");
PrintString(pdev, "/bstr ");
PrintDecimal(pdev, 1, cxBytes);
PrintString(pdev, " string def\n");
}
//
// 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
//
ptpsfx.x = X72DPI(x);
ptpsfx.y = Y72DPI(y);
PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y);
PrintString(pdev, " _snap translate\n");
//
// scale the image.
//
ptpsfx.x = ((cx * PS_FIX_RESOLUTION) + (pdev->psdm.dm.dmPrintQuality / 2)) /
pdev->psdm.dm.dmPrintQuality;
ptpsfx.y = ((cy * PS_FIX_RESOLUTION) + (pdev->psdm.dm.dmPrintQuality / 2)) /
pdev->psdm.dm.dmPrintQuality;
PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y);
PrintString(pdev, " scale\n");
//
// Output the image operator and the scan data.
//
PrintDecimal(pdev, 2, cx, cy);
PrintString(pdev, " ");
if (pdev->dwFlags & PDEV_SOURCEORHACK)
PrintString(pdev, "true [");
else
PrintString(pdev, "1 [");
PrintDecimal(pdev, 1, cx);
PrintString(pdev, " 0 0 ");
//
// We will always send in as TOPDOWN when we calling this function
//
PrintDecimal(pdev, 1, -cy);
PrintString(pdev, " 0 0] ");
if (Mono) {
PrintString(pdev, "{currentfile mstr readhexstring pop}");
if (pdev->dwFlags & PDEV_SOURCEORHACK)
PrintString(pdev, " im\n");
else
PrintString(pdev, " image\n");
} else {
PrintString(pdev, "\n{currentfile rstr readhexstring pop}\n");
PrintString(pdev, "{currentfile gstr readhexstring pop}\n");
PrintString(pdev, "{currentfile bstr readhexstring pop}\n");
PrintString(pdev, "true 3 colorimage\n");
}
}
//--------------------------------------------------------------------
// 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;
if ((prclTrg->right - prclTrg->left) > 1)
rclTmp.right -= 1;
if ((prclTrg->bottom - prclTrg->top) > 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_API_MAX))
bUserPat = TRUE;
}
}
if (!bUserPat)
ps_box(pdev, & rclTmp);
// now fill the target rectangle with the given pattern.
return(ps_patfill(pdev, pso, (FLONG)FP_WINDINGMODE, pbo, pptlBrush, (MIX)rop4,
&rclTmp, bInvertPat, FALSE));
}
//--------------------------------------------------------------------
// BOOL DoSourceCopy(pdev, psoSrc, prclSrc, prclDest, pxlo, prclClipBound,
// bNotSrcCopy)
// PDEVDATA pdev;
// SURFOBJ *psoSrc;
// PRECTL prclSrc;
// PRECTL prclDest;
// XLATEOBJ *pxlo;
// RECTL *prclClipBound;
// BOOL bNotSrcCopy;
//
// This routine projects an image of a rectangle on
// the source DC's bitmap onto the printer.
//
// 06-Jun-1991 -by- Kent Settle (kentse)
// Wrote it.
// 17-Mar-1993 -by- Rob Kiesler
// Resurrected and rewritten to allow the PS Interpreter to do Halftoning.
//--------------------------------------------------------------------
BOOL DoSourceCopy(pdev, psoSrc, prclSrc, prclDest, pxlo, prclClipBound,
bNotSrcCopy)
PDEVDATA pdev;
SURFOBJ *psoSrc;
PRECTL prclSrc;
PRECTL prclDest;
XLATEOBJ *pxlo;
RECTL *prclClipBound;
BOOL bNotSrcCopy;
{
RECTL rclBand, rclDest, rclClip;
LONG Temp;
DWORD cbSrcScanLine;
DWORD cbDstScanLine;
POINTL ZeroPointl={0,0};
PBYTE pbSrc;
ULONG ulbpp;
DWORD cScanlines;
//
// If we know the destination clipping region bounding rectangle then we
// can allocate smaller bitmap and use that bounding rectangle as our
// banding rectangle for halftone, if prclClipBound is NULL then the whole
// destinaiton rectangle is our bounding (banding) rectangle area
//
// make sure the destination rectangle is well ordered.
rclDest = *prclDest;
if (rclDest.left > rclDest.right)
{
Temp = rclDest.left;
rclDest.left = rclDest.right;
rclDest.right = Temp;
}
if (rclDest.top > rclDest.bottom)
{
Temp = rclDest.top;
rclDest.top = rclDest.bottom;
rclDest.bottom = Temp;
}
// if there is a clipping rectangle, intersect it with the destination
// rectangle to come up with a banding rectangle.
if (prclClipBound)
{
rclClip = *prclClipBound;
// Make sure the clip rectangle is well ordered
if (rclClip.left > rclClip.right)
{
Temp = rclClip.left;
rclClip.left = rclClip.right;
rclClip.right = Temp;
}
if (rclClip.top > rclClip.bottom)
{
Temp = rclClip.top;
rclClip.top = rclClip.bottom;
rclClip.bottom = Temp;
}
// now intersect the destination and clip rectangles.
if ((rclDest.left >= rclClip.right) ||
(rclClip.left >= rclDest.right) ||
(rclDest.top >= rclClip.bottom) ||
(rclClip.top >= rclDest.bottom))
{
#if DBG
DbgPrint("PSCRIPT!DoSourceCopy: NULL rectangle, returning FALSE.\n");
#endif
return(FALSE);
}
// we know we have a non-NULL intersection.
rclBand.left = max(rclClip.left, rclDest.left);
rclBand.right = min(rclClip.right, rclDest.right);
rclBand.bottom = min(rclClip.bottom, rclDest.bottom);
rclBand.top = max(rclClip.top, rclDest.top);
}
else
rclBand = rclDest;
//
// Now check if the banding area is bigger than our page size, if so clip
// to the page limit
//
if (rclBand.left < 0)
rclBand.left = 0;
if (rclBand.top < 0)
rclBand.top = 0;
//
// send out the bitmap data one scanline at a time.
// and compute DWORD aligned scanline width in bytes
//
//
// Number of pels/scanline.
//
cbSrcScanLine = psoSrc->sizlBitmap.cx;
//
// times how many bits per pel.
//
switch (psoSrc->iBitmapFormat)
{
case BMF_1BPP:
ulbpp = 1;
break;
case BMF_4BPP:
ulbpp = 4;
break;
case BMF_8BPP:
ulbpp = 8;
break;
case BMF_16BPP:
ulbpp = 16;
break;
case BMF_24BPP:
ulbpp = 24;
break;
case BMF_32BPP:
ulbpp = 32;
break;
}
cbSrcScanLine *= ulbpp;
//
// cbSrcScanLine now equals the number of bits per scanline.
// 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.
//
cbDstScanLine = (cbSrcScanLine + 7) >> 3;
//
// Now convert cbSrcScanLine to the number of bytes per scanline,
// taking into account that scanlines are padded out to 32 bit
// boundaries.
//
cbSrcScanLine = ((cbDstScanLine + 3) >> 2) * 4;
//
// Output the PostScript beginimage operator.
//
BeginImageEx(pdev,
psoSrc->sizlBitmap,
ulbpp,
cbDstScanLine,
&rclBand,
FALSE,
pxlo);
//
// Set up pbSrc -> start of the source bitmap.
//
pbSrc = psoSrc->pvBits;
cScanlines = (DWORD)psoSrc->sizlBitmap.cy;
while (cScanlines--)
{
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
//
// Output each scanline to the printer
//
vHexOut(pdev, pbSrc, cbDstScanLine);
PrintString(pdev, "\n");
pbSrc += cbSrcScanLine;
}
PrintString(pdev, "\nendimage\n");
return(TRUE);
}
//--------------------------------------------------------------------
// 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)
PDEVDATA pdev;
SIZEL sizlSrc;
ULONG ulSrcFormat;
DWORD cbSrcWidth;
PRECTL prclDest;
BOOL bNotSrcCopy;
XLATEOBJ *pxlo;
{
#ifdef INDEX_PAL
PALETTEENTRY *prgb;
DWORD i;
POINTPSFX ptpsfx;
CHAR bmpTypeStr[2];
BYTE intensity;
PALETTEENTRY *prgbFore;
PALETTEENTRY *prgbBack;
PALETTEENTRY *ppalette;
PALETTEENTRY *ppalSave;
ULONG *pulColors;
DWORD cColors;
//
// 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.
//
PrintString(pdev, "/Adobe_WinNT_Driver_Gfx 175 dict dup begin\n");
if (!bSendPSProcSet(pdev, UTILS))
{
RIP("PSCRIPT!BeginImageEx: Couldn't download Utils Procset.\n");
return(FALSE);
}
PrintString(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.
//
PrintString(pdev, "Adobe_WinNT_Driver_Gfx begin\n");
if (!bSendPSProcSet(pdev, IMAGE))
{
RIP("PSCRIPT!BeginImageEx: Couldn't download Image Procset.\n");
return(FALSE);
}
PrintString(pdev, "end reinitialize\n");
pdev->dwFlags |= PDEV_IMAGESENT;
}
//
// Send the source bmp origin, source bmp format, and scanline width.
//
PrintDecimal(pdev, 4, sizlSrc.cx, sizlSrc.cy, ulSrcFormat, cbSrcWidth);
// PrintDecimal(pdev, 4, sizlSrc.cx, (prclDest->bottom - prclDest->top),
// ulSrcFormat, cbSrcWidth);
PrintString(pdev, " ");
//
// Compute the destination rectangle extents, and convert to fixed point.
//
#if 0
ptpsfx.x = ((prclDest->right - prclDest->left) * PS_FIX_RESOLUTION) /
pdev->psdm.dm.dmPrintQuality;
ptpsfx.y = ((prclDest->bottom - prclDest->top) * PS_FIX_RESOLUTION) /
pdev->psdm.dm.dmPrintQuality;
PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y);
PrintString(pdev, " "); // PrintPSFIX doesn't generate a " " after
// the last # printed!
#endif
ptpsfx.x = ((prclDest->right - prclDest->left) * PS_FIX_RESOLUTION) /
pdev->psdm.dm.dmPrintQuality;
ptpsfx.y = ((prclDest->bottom - prclDest->top) * PS_FIX_RESOLUTION) /
pdev->psdm.dm.dmPrintQuality;
PrintDecimal(pdev, 1, (prclDest->right - prclDest->left));
PrintString(pdev, " 72 mul DPI div ");
PrintDecimal(pdev, 1, (prclDest->bottom - prclDest->top));
PrintString(pdev, " 72 mul DPI div ");
//
// Convert Destination Rect Origin to fixed point.
//
#if 0
ptpsfx.x = X72DPI(prclDest->left);
ptpsfx.y = Y72DPI(prclDest->top);
PrintPSFIX(pdev, 2, ptpsfx.x, ptpsfx.y);
#endif
PrintDecimal(pdev, 1, prclDest->left);
PrintString(pdev, " 72 mul DPI div ");
PrintDecimal(pdev, 1, pdev->CurForm.imagearea.left);
PrintString(pdev, " add\n");
PrintDecimal(pdev, 1, pdev->CurForm.imagearea.top);
PrintString(pdev, " ");
PrintDecimal(pdev, 1, prclDest->top);
PrintString(pdev, " 72 mul DPI div sub\n");
PrintString(pdev, " false "); // Smoothflag = FALSE for now.
PrintString(pdev, bNotSrcCopy && (ulSrcFormat == 1) ? "false " : "true ");
//
// Determine the type of data (binary RLE, ASCII85 RLE, etc) which
// the output channel supports, and pass it to the "beginimage"
// operator.
//
itoa(PSBitMapType(pdev, FALSE), bmpTypeStr, 10);
PrintString(pdev, bmpTypeStr);
PrintString(pdev, " ");
PrintString(pdev, "beginimage\n");
if (pxlo)
{
// get pointer to our device palettes.
if (ulSrcFormat == 1)
pulColors = PSMonoPalette;
else
pulColors = PSColorPalette;
if (pxlo->flXlate & XO_TRIVIAL)
{
// if the TRIVIAL color translation flag is set, then fill in
// halftoning palette from our hardcoded palettes.
if (ulSrcFormat == 1)
ppalette = (PALETTEENTRY *)PSMonoPalette;
else
ppalette = (PALETTEENTRY *)PSColorPalette;
}
else if (pxlo->flXlate & XO_TABLE)
{
ppalette = (PALETTEENTRY *)pxlo->pulXlate;
}
else
ppalette = (PALETTEENTRY *)NULL;
}
else
ppalette = (PALETTEENTRY *)NULL;
// ppalette now points to our palette. the format of this palette can
// vary depending on pxlo->flXlate.
switch (ulSrcFormat)
{
case 1:
#if 0
if (ppalette == NULL)
{
//
// No palette, so assume fgcolor = black, bgcolor = white.
//
PrintString(pdev, "1bitbwcopyimage\n");
}
else
{
//
// There is a palette, check the fg and bg colors.
//
if (pxlo->flXlate & XO_TRIVIAL)
{
prgbBack = ppalette;
prgbFore = ppalette + 1;
}
else
{
prgbBack = (PALETTEENTRY *)(pulColors +
XLATEOBJ_iXlate(pxlo, *(ULONG *)ppalette));
prgbFore = (PALETTEENTRY *)(pulColors +
XLATEOBJ_iXlate(pxlo, *(ULONG *)(ppalette + 1)));
}
if ((prgbBack->peRed == 0xFF) &&
(prgbBack->peGreen == 0xFF) &&
(prgbBack->peBlue == 0xFF) &&
(prgbFore->peRed == 0x00) &&
(prgbFore->peGreen == 0x00) &&
(prgbFore->peBlue == 0x00))
{
//
// fgcolor = black, bgcolor = white. The default case.
//
PrintString(pdev, "1bitbwcopyimage\n");
}
else
{
//
// Either fg != black, or bg != white, must send
// fg and bg colors.
//
PrintPSFIX(pdev, 3, LTOPSFX((ULONG)prgbFore->peRed) / 255,
LTOPSFX((ULONG)prgbFore->peGreen) / 255,
LTOPSFX((ULONG)prgbFore->peBlue) / 255);
PrintString(pdev, " false ");
PrintPSFIX(pdev, 3, LTOPSFX((ULONG)prgbBack->peRed) / 255,
LTOPSFX((ULONG)prgbBack->peGreen) / 255,
LTOPSFX((ULONG)prgbBack->peBlue) / 255);
PrintString(pdev, " false ");
PrintString(pdev, "1bitcopyimage\n");
}
}
#endif
PrintString(pdev, " doNimage\n");
break;
case 4 :
case 8 :
if (ppalette == NULL)
{
//
// No palette, use the current PS colors.
//
PrintString(pdev, "doNimage\n");
}
else
{
//
// There is a palette, send it to the PS interpreter.
// First, compute and send the mono (intensity) palette.
//
PrintString(pdev, "<\n");
if (pxlo->flXlate & XO_TRIVIAL)
{
if (ulSrcFormat == 4)
cColors = 16;
#if DBG
else
RIP("PSCRIPT!BeginImageEx: invalid pxlo format.\n");
#endif
}
else
cColors = pxlo->cEntries;
ppalSave = ppalette;
for (i = 0; i < cColors; ppalette++)
{
if (pxlo->flXlate & XO_TRIVIAL)
prgb = ppalette;
else
prgb = (PALETTEENTRY *)(pulColors +
XLATEOBJ_iXlate(pxlo, *(ULONG *)ppalette));
intensity = INTENSITY(prgb->peRed,
prgb->peGreen,
prgb->peBlue);
vHexOut(pdev, &intensity, 1);
if (++i % 16)
PrintString(pdev," ");
else
PrintString(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) ; )
{
PrintString(pdev,"00");
if (++i % 16)
PrintString(pdev," ");
else
PrintString(pdev, "\n");
}
PrintString(pdev, ">\n");
//
// Send the RGB palette.
//
PrintString(pdev, "<\n");
ppalette = ppalSave;
for (i = 0; i < cColors; ppalette++)
{
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
if (pxlo->flXlate & XO_TRIVIAL)
prgb = ppalette;
else
prgb = (PALETTEENTRY *)(pulColors +
XLATEOBJ_iXlate(pxlo, *(ULONG *)ppalette));
if (pxlo->iSrcType & PAL_BGR)
{
vHexOut(pdev, &(prgb->peBlue), 1);
vHexOut(pdev, &(prgb->peGreen), 1);
vHexOut(pdev, &(prgb->peRed), 1);
}
else
{
vHexOut(pdev, (PBYTE)prgb, 3);
}
if (++i % 8)
PrintString(pdev," ");
else
PrintString(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) ; )
{
PrintString(pdev,"000000");
if (++i % 8)
PrintString(pdev," ");
else
PrintString(pdev, "\n");
}
PrintString(pdev, "\n>\n");
PrintString(pdev, "doclutimage\n");
}
break;
#else // 24BPP case.
BGR_PAL_ENTRY *pbgr;
DWORD i;
POINTPSFX ptpsfx;
CHAR bmpTypeStr[2];
BYTE intensity;
BGR_PAL_ENTRY *pbgrFore;
BGR_PAL_ENTRY *pbgrBack;
//
// 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.
//
PrintString(pdev, "/Adobe_WinNT_Driver_Gfx 175 dict dup begin\n");
if (!bSendPSProcSet(pdev, UTILS))
{
RIP("PSCRIPT!BeginImageEx: Couldn't download Utils Procset.\n");
return(FALSE);
}
PrintString(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.
//
PrintString(pdev, "Adobe_WinNT_Driver_Gfx begin\n");
if (!bSendPSProcSet(pdev, IMAGE))
{
RIP("PSCRIPT!BeginImageEx: Couldn't download Image Procset.\n");
return(FALSE);
}
PrintString(pdev, "end reinitialize\n");
pdev->dwFlags |= PDEV_IMAGESENT;
}
//
// Send the source bmp origin, source bmp format, and scanline width.
//
PrintDecimal(pdev, 4, sizlSrc.cx, sizlSrc.cy, ulSrcFormat, cbSrcWidth);
PrintString(pdev, " ");
//
// Compute the destination rectangle extents, and convert to fixed point.
//
ptpsfx.x = ((prclDest->right - prclDest->left) * PS_FIX_RESOLUTION) /
pdev->psdm.dm.dmPrintQuality;
ptpsfx.y = ((prclDest->bottom - prclDest->top) * PS_FIX_RESOLUTION) /
pdev->psdm.dm.dmPrintQuality;
PrintDecimal(pdev, 1, (prclDest->right - prclDest->left));
PrintString(pdev, " 72 mul DPI div ");
PrintDecimal(pdev, 1, (prclDest->bottom - prclDest->top));
PrintString(pdev, " 72 mul DPI div ");
//
// Convert Destination Rect Origin to fixed point.
//
PrintDecimal(pdev, 1, prclDest->left);
PrintString(pdev, " 72 mul DPI div ");
PrintDecimal(pdev, 1, pdev->CurForm.imagearea.left);
PrintString(pdev, " add\n");
PrintDecimal(pdev, 1, pdev->CurForm.imagearea.top);
PrintString(pdev, " ");
PrintDecimal(pdev, 1, prclDest->top);
PrintString(pdev, " 72 mul DPI div sub");
PrintString(pdev, " false "); // Smoothflag = FALSE for now.
PrintString(pdev, bNotSrcCopy && (ulSrcFormat == 1) ? "false " : "true ");
//
// Determine the type of data (binary RLE, ASCII85 RLE, etc) which
// the output channel supports, and pass it to the "beginimage"
// operator.
//
itoa(PSBitMapType(pdev, FALSE), bmpTypeStr, 10);
PrintString(pdev, bmpTypeStr);
PrintString(pdev, " ");
PrintString(pdev, "beginimage\n");
if (pxlo)
pbgr = (BGR_PAL_ENTRY *)pxlo->pulXlate;
else
pbgr = (BGR_PAL_ENTRY *)NULL;
switch (ulSrcFormat)
{
case 1:
#if 0
if (pbgr == NULL)
{
//
// No palette, so assume fgcolor = black, bgcolor = white.
//
PrintString(pdev, "1bitbwcopyimage\n");
}
else
{
pbgrBack = pbgr;
pbgrFore = pbgr + 1;
if ((pbgrBack->bgrRed == 0xFF) &&
(pbgrBack->bgrGreen == 0xFF) &&
(pbgrBack->bgrBlue == 0xFF) &&
(pbgrFore->bgrRed == 0x00) &&
(pbgrFore->bgrGreen == 0x00) &&
(pbgrFore->bgrBlue == 0x00))
{
//
// fgcolor = black, bgcolor = white. The default case.
//
PrintString(pdev, "1bitbwcopyimage\n");
}
else
{
//
// Either fg != black, or bg != white, must send
// fg and bg colors.
//
PrintPSFIX(pdev, 3, LTOPSFX((ULONG)pbgrFore->bgrRed) / 255,
LTOPSFX((ULONG)pbgrFore->bgrGreen) / 255,
LTOPSFX((ULONG)pbgrFore->bgrBlue) / 255);
PrintString(pdev, " false ");
PrintPSFIX(pdev, 3, LTOPSFX((ULONG)pbgrBack->bgrRed) / 255,
LTOPSFX((ULONG)pbgrBack->bgrGreen) / 255,
LTOPSFX((ULONG)pbgrBack->bgrBlue) / 255);
PrintString(pdev, " false ");
PrintString(pdev, "1bitcopyimage\n");
}
}
#endif
PrintString(pdev, "doNimage\n");
break;
case 4 :
case 8 :
if (pbgr == NULL)
{
//
// No palette, use the current PS colors.
//
PrintString(pdev, "doNimage\n");
}
else
{
//
// There is a palette, send it to the PS interpreter.
// First, compute and send the mono (intensity) palette.
//
PrintString(pdev, "<\n");
for (i = 0; i < pxlo->cEntries; pbgr++)
{
intensity = INTENSITY(pbgr->bgrRed,
pbgr->bgrGreen,
pbgr->bgrBlue);
vHexOut(pdev, &intensity, 1);
if (++i % 16)
PrintString(pdev," ");
else
PrintString(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) ; )
{
PrintString(pdev,"00");
if (++i % 16)
PrintString(pdev," ");
else
PrintString(pdev, "\n");
}
PrintString(pdev, ">\n");
//
// Send the RGB palette.
//
PrintString(pdev, "<\n");
pbgr = (BGR_PAL_ENTRY *)pxlo->pulXlate;
for (i = 0; i < pxlo->cEntries; pbgr++)
{
if (pdev->dwFlags & PDEV_CANCELDOC)
break;
if (pxlo->iSrcType & PAL_BGR)
{
vHexOut(pdev, (PBYTE)pbgr, 3);
}
else
{
vHexOut(pdev, &(pbgr->bgrRed), 1);
vHexOut(pdev, &(pbgr->bgrGreen), 1);
vHexOut(pdev, &(pbgr->bgrBlue), 1);
}
if (++i % 8)
PrintString(pdev," ");
else
PrintString(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) ; )
{
PrintString(pdev,"000000");
if (++i % 8)
PrintString(pdev," ");
else
PrintString(pdev, "\n");
}
PrintString(pdev, "\n>\n");
PrintString(pdev, "doclutimage\n");
}
break;
#endif
case 24 :
//
// 24BPP images don't need a palette, use the doNimage operator.
//
PrintString(pdev, "doNimage\n");
break;
default:
//
// Can't handle bitmaps in formats other than the ones above!
//
return(FALSE);
}
return(TRUE);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.