Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2583 lines
71 KiB

/*++
Copyright (c) 1990-2003 Microsoft Corporation
Module Name:
htblt.c
Abstract:
This module contains all halftone bitblt functions.
Development History:
26-Mar-1992 Thu 23:54:07 updated
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
Major re-write to have DrvStretchBlt(), DrvCopyBits) do the right
things.
15-Nov-1993 Mon 19:28:03 updated
clean up/debugging information
06-Dec-1993 Mon 19:28:03 updated
Made all bitblt go through HandleComplexBitmap.
18-Dec-1993 Sat 08:52:56 updated
Move halftone related stuff to htblt.c
18-Mar-1994 Fri 14:00:14 updated
Adding PLOTF_RTL_NO_DPI_XY, PLOTF_RTLMONO_NO_CID and
PLOTF_RTLMONO_FIXPAL flags
[Environment:]
GDI Device Driver - Plotter.
[Notes:]
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define DBG_PLOTFILENAME DbgHTBlt
#define DBG_HTBLT 0x00000001
#define DBG_ISHTBITS 0x00000002
#define DBG_HTXB 0x00000004
#define DBG_OUTHTBMP 0x00000008
#define DBG_HTBLT_SKIP 0x00000010
#define DBG_TILEBLT 0x00000020
#define DBG_CREATESURFOBJ 0x00000040
#define DBG_BMPDELTA 0x00000080
#define DBG_CLONESURFOBJ 0x00000100
#define DBG_CLONEMASK 0x00000200
#define DBG_HTBLT_CLR 0x00000400
DEFINE_DBGVAR(0);
//
// This is the local structure used in this module only
//
#define SEND_PLOTCMDS(pPDev,pcmd) OutputBytes(pPDev,(pcmd)+1,(LONG)*(pcmd))
#define COPY_PLOTCMDS(cmd,ps,s) if (sizeof(cmd) > cmd[0]+s){CopyMemory(&cmd[cmd[0]+1],ps,s); cmd[0]+=s;}
#define INIT_PLOTCMDS(cmd) cmd[0]=0
#define CHECK_PLOTCMDS(cmd) \
{ \
cmd[cmd[0]+1]=0; PLOTASSERT(1,"Command buffer MUST > %ld bytes", \
cmd[0]<sizeof(cmd),sizeof(cmd)); \
}
#define DELETE_SURFOBJ(pso, phBmp) \
{ \
if (pso) { EngUnlockSurface(pso); pso=NULL; } \
if (*(phBmp)) { EngDeleteSurface((HSURF)*(phBmp)); *(phBmp)=NULL; } \
}
typedef struct _RTLCLRCONFIG {
BYTE ColorModel;
BYTE EncodingMode;
BYTE BitsPerIndex;
BYTE BitsPerR;
BYTE BitsPerG;
BYTE BitsPerB;
} RTLCLRCONFIG, FAR *PRTLCLRCONFIG;
const POINTL ptlZeroOrigin = {0,0};
static const OUTHTBMPFUNC HTBmpFuncTable[] = { Output1bppHTBmp,
Output1bppRotateHTBmp,
Output4bppHTBmp,
Output4bppRotateHTBmp };
#if DBG
static const LPSTR pszHTBmpFunc[] = { "Output1bppHTBmp",
"Output1bppRotateHTBmp",
"Output4bppHTBmp",
"Output4bppRotateHTBmp" };
#endif
#define DEF_MONOPALIDX_0 0xFFFFFF
#define DEF_MONOPALIDX_1 0x000000
#define DEVTODECI(pPdev, x) DIVRNDUP((x) * 720, (pPDev)->lCurResolution)
#define MAX_HP_Y_MOVE 32767
static BYTE StartGraf[] = "\033*r#ds1A";
static BYTE EndGraf[] = "\033*rC";
static BYTE XMoveDECI[] = "\033&a0h#dH";
static BYTE YMoveDECI[] = "\033*b#dY";
static BYTE YMoveDPI[] = "\033*p#pY";
static BYTE XYMoveDPI[] = "\033*p#px#pY";
static BYTE SetRGBCmd[] = "\033*v#da#db#dc#dI";
static DWORD DefWKPal[] = { 0x00FFFFFF, 0x00000000 };
//
// ROP2 used for devices that require BYTE ALIGNMENT of RTL data
//
#define HPBHF_nD_LAST 0x01
#define HPBHF_nS 0x02
#define HPBHF_1_FIRST 0x40
#define HPBHF_PAD_1 0x80
typedef struct _HPBAHACK {
BYTE Rop3RTL;
BYTE Flags;
} HPBAHACK, *PHPBAHACK;
//
// 0x00: 0 [INV] 0xff: 1
// 0x55: ~D [INV] 0xaa: D
// 0x33: ~S [INV] 0xcc: S
// 0x11: ~(D | S) [INV] 0xee: D | S
// 0x22: D & ~S [INV] 0xdd: S | ~D
// 0x44: S & ~D [INV] 0xbb: D | ~S
// 0x66: D ^ S [INV] 0x99: ~(D ^ S)
// 0x77: ~(D & S) [INV] 0x88: D & S
//
//
// 1. HPBHF_PAD_1 - TRUE if we are not doing AND operation
// 2. HPBHF_nS - If we have to manually flip the source
// 3. HPBHF_nD_LAST - If we have to invert the source in HPGL2 afterward
//
//
// Rop2 0x00, 0x05, 0x0A and 0x0F should not come to OutputHTBitmap
//
//
// This table tells us how to simulate certain ROPS by combining rops that
// the target device is known to support. Some times we end up having to
// send the bitmap more than once, but it does end up coming out correctly.
//
static HPBAHACK HPBAHack[] = {
{ 0xAA, 0 }, // 0 0x00
{ 0xEE, HPBHF_PAD_1 | HPBHF_nD_LAST }, // SoD_n 0x01
{ 0x88, HPBHF_nS }, // nS_aD 0x02
{ 0xEE, HPBHF_1_FIRST | HPBHF_PAD_1 | HPBHF_nS }, // nS 0x03
{ 0xEE, HPBHF_PAD_1 | HPBHF_nS | HPBHF_nD_LAST }, // nS_oD_n 0x04
{ 0xAA, HPBHF_nD_LAST }, // nD 0x05
{ 0x66, HPBHF_PAD_1 }, // SxD 0x06
{ 0x88, HPBHF_nD_LAST }, // SaD_n 0x07
{ 0x88, }, // SaD 0x08
{ 0x66, HPBHF_PAD_1 | HPBHF_nD_LAST }, // SxD_n 0x09
{ 0xAA, 0 }, // D 0x0A
{ 0xEE, HPBHF_PAD_1 | HPBHF_nS }, // nS_oD 0x0B
{ 0xEE, HPBHF_1_FIRST | HPBHF_PAD_1 }, // S 0x0C
{ 0x88, HPBHF_nS | HPBHF_nD_LAST }, // nS_aD_n 0x0D
{ 0xEE, HPBHF_PAD_1 }, // SoD 0x0E
{ 0xAA, 0 } // 1 0x0F
};
//
// To make it print correctly in poster mode for the BYTE ALIGNED plotters
// we assume paper is white and do a SRC AND DST
//
#define ROP3_BYTEALIGN_POSTER 0x88
extern PALENTRY HTPal[];
BOOL
IsHTCompatibleSurfObj(
PPDEV pPDev,
SURFOBJ *pso,
XLATEOBJ *pxlo,
DWORD Flags
)
/*++
Routine Description:
This function determines if the surface object is compatible with the
plotter halftone output format.
Arguments:
pPDev - Pointer to the PPDEV 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
Flags - specified ISHTF_xxxx
Return Value:
BOOLEAN true if the pso is compatible with halftone output format, if
return value is true, the pDrvHTInfo->pHTXB is a valid traslation from
indices to 3 planes
Development History:
11-Feb-1993 Thu 18:49:55 created
16-Mar-1994 Wed 14:24:04 updated
Change it so if pxlo is NULL then the xlate will be match the pso
format
Revision History:
--*/
{
LPPALETTEENTRY pPal;
PDRVHTINFO pDrvHTInfo;
PALETTEENTRY SrcPal[18];
PPALENTRY pPalEntry;
HTXB PalNibble[HTPAL_XLATE_COUNT];
ULONG HTPalXor;
UINT i;
HTXB htXB;
BOOL GenHTXB = FALSE;
BOOL RetVal;
BYTE PalXlate[HTPAL_XLATE_COUNT];
UINT AltFmt;
UINT BmpFormat;
UINT cPal;
if (!(pDrvHTInfo = (PDRVHTINFO)(pPDev->pvDrvHTData))) {
PLOTERR(("IsHTCompatibleSurfObj: pDrvHTInfo = NULL?"));
return(FALSE);
}
PLOTDBG(DBG_ISHTBITS, ("IsHTCompatibleSurfObj: Type=%ld, BMF=%ld",
(DWORD)pso->iType, (DWORD)pso->iBitmapFormat));
//
// Make sure these fields' value are valid before the translation is
// created:
//
// 1. pso->iBitmapFormat is one of 1BPP or 4BPP depending on current
// PLOT's surface
// 2. pxlo is non null
// 3. pxlo->fXlate is XO_TABLE
// 4. pxlo->cPal is less than or equal to the halftone palette count
// 5. pxlo->pulXlate is valid
// 6. source color table is within the range of the halftone palette
//
// If your device uses an indexed palette then you must call
// XLATEOBJ_cGetPalette() to get the source palette and make sure that the
// count returned is within your device's range, if we are a 24-bit device
// then you can just get the source palette our from pxlo->pulxlate which
// has the entire source palette for the bitmap
//
RetVal = FALSE;
AltFmt = (UINT)((Flags & ISHTF_ALTFMT) ? pDrvHTInfo->AltBmpFormat : 0xFFFF);
if ((pso->iType == STYPE_BITMAP) &&
(BmpFormat = (UINT)pso->iBitmapFormat) &&
((BmpFormat == (UINT)pDrvHTInfo->HTBmpFormat) ||
(BmpFormat == AltFmt))) {
HTPalXor = pDrvHTInfo->HTPalXor;
pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
if (pxlo) {
if (BmpFormat == BMF_4BPP) {
i = (UINT)((Flags & ISHTF_HTXB) ? 8 : 16);
} else {
i = 2;
}
cPal = XLATEOBJ_cGetPalette(pxlo,
XO_SRCPALETTE,
sizeof(SrcPal) / sizeof(PALETTEENTRY),
(ULONG *)SrcPal);
PLOTDBG(DBG_ISHTBITS, ("pxlo: flXlate=%08lx, SrcType=%ld, DstType=%ld, cPal=%ld",
(DWORD)pxlo->flXlate,
(DWORD)pxlo->iSrcType,
(DWORD)pxlo->iDstType, cPal));
if ((cPal) && (cPal <= i)) {
PLOTDBG(DBG_ISHTBITS,
("IsHTCompatibleSurfObj: HTPalXor=%08lx", HTPalXor));
RetVal = TRUE;
for (i = 0, pPal = SrcPal; i < cPal && i < sizeof(PalXlate); i++, pPal++ ) {
HTXB_R(htXB) = pPal->peRed;
HTXB_G(htXB) = pPal->peGreen;
HTXB_B(htXB) = pPal->peBlue;
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))) {
PLOTDBG(DBG_ISHTBITS,
("SrcPal has NON 0xff/0x00 intensity, NOT HTPalette"));
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;
}
PLOTDBG(DBG_HTXB,
("%d - %02x:%02x:%02x, Idx=%d, PalXlate=%d",
i,
(BYTE)HTXB_R(htXB),
(BYTE)HTXB_G(htXB),
(BYTE)HTXB_B(htXB),
(INT)PalXlate[i],
(INT)pDrvHTInfo->PalXlate[i]));
}
if (BmpFormat == (UINT)BMF_1BPP) {
//
// For 1 BPP, if the DSTPRIM_OK is set and the destination
// is 4BPP then we will deem the surfaces compatible
//
if ((Flags & ISHTF_DSTPRIM_OK) &&
((pDrvHTInfo->HTBmpFormat == BMF_4BPP) ||
(AltFmt == BMF_4BPP))) {
NULL;
} else if (((PalXlate[0] != 0) && (PalXlate[0] != 7)) ||
((PalXlate[1] != 0) && (PalXlate[1] != 7))) {
RetVal = FALSE;
PLOTDBG(DBG_HTXB, ("NON-BLACK/WHITE MONO BITMAP, NOT HTPalette"));
}
}
}
} else {
//
// If the pxlo is NULL and the FORMAT is the same, we assume an
// identity translation. Otherwise we fail.
//
PLOTDBG(DBG_HTXB, ("pxlo=NULL, Xlate to same as BmpFormat=%ld",
(DWORD)BmpFormat));
RetVal = TRUE;
if (BmpFormat == BMF_4BPP) {
cPal = 8;
pPalEntry = HTPal;
} else {
cPal = 2;
pPalEntry = (PPALENTRY)SrcPal;
CopyMemory(pPalEntry + 0, &HTPal[0], sizeof(PALENTRY));
CopyMemory(pPalEntry + 1, &HTPal[7], sizeof(PALENTRY));
}
for (i = 0; i < cPal; i++, pPalEntry++) {
HTXB_R(htXB) = pPalEntry->R;
HTXB_G(htXB) = pPalEntry->G;
HTXB_B(htXB) = pPalEntry->B;
htXB.dw ^= HTPalXor;
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 (!RetVal) {
PLOTDBG(DBG_HTXB, ("**** IsHTCompatibleSurfObj = NO ****"));
return(FALSE);
}
if ((Flags & ISHTF_HTXB) && (GenHTXB)) {
//
// Copy down the pal xlate
//
PLOTDBG(DBG_HTXB, (" --- Copy XLATE TABLE ---"));
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_1BPP) {
pDrvHTInfo->RTLPal[0].Pal = HTPal[PalXlate[0]];
pDrvHTInfo->RTLPal[1].Pal = HTPal[PalXlate[1]];
PLOTDBG(DBG_HTXB, ("IsHTCompatibleSurfObj: MONO 1BPP: 0=%02lx:%02lx:%02lx, 1=%02lx:%02lx:%02lx",
(DWORD)pDrvHTInfo->RTLPal[0].Pal.R,
(DWORD)pDrvHTInfo->RTLPal[0].Pal.G,
(DWORD)pDrvHTInfo->RTLPal[0].Pal.B,
(DWORD)pDrvHTInfo->RTLPal[1].Pal.R,
(DWORD)pDrvHTInfo->RTLPal[1].Pal.G,
(DWORD)pDrvHTInfo->RTLPal[1].Pal.B));
} else if (BmpFormat == (UINT)BMF_4BPP) {
PHTXB pTmpHTXB;
UINT h;
UINT l;
DWORD HighNibble;
PLOTDBG(DBG_HTXB, ("--- Generate 4bpp --> 3 planes xlate ---"));
if (!(pDrvHTInfo->pHTXB)) {
PLOTDBG(DBG_HTXB, ("IsHTCompatibleSurfObj: Allocate pHTXB=%ld",
HTXB_TABLE_SIZE));
if (!(pDrvHTInfo->pHTXB =
(PHTXB)LocalAlloc(LPTR, HTXB_TABLE_SIZE))) {
PLOTERR(("IsHTCompatibleSurfObj: LocalAlloc(HTXB_TABLE_SIZE) failed"));
return(FALSE);
}
}
pDrvHTInfo->RTLPal[0].Pal = HTPal[0];
pDrvHTInfo->RTLPal[1].Pal = HTPal[1];
PLOTDBG(DBG_HTXB, ("IsHTCompatibleSurfObj: COLOR 4BPP: 0=%02lx:%02lx:%02lx, 1=%02lx:%02lx:%02lx",
(DWORD)pDrvHTInfo->RTLPal[0].Pal.R,
(DWORD)pDrvHTInfo->RTLPal[0].Pal.G,
(DWORD)pDrvHTInfo->RTLPal[0].Pal.B,
(DWORD)pDrvHTInfo->RTLPal[1].Pal.R,
(DWORD)pDrvHTInfo->RTLPal[1].Pal.G,
(DWORD)pDrvHTInfo->RTLPal[1].Pal.B));
//
// 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);
}
}
}
PLOTDBG(DBG_HTXB, ("*** IsHTCompatibleSurfObj = %hs ***", (RetVal) ? "TRUE" : "FALSE"));
return(RetVal);
}
DWORD
ExitToHPGL2Mode(
PPDEV pPDev,
LPBYTE pHPGL2ModeCmds,
LPDWORD pOHTFlags,
DWORD OHTFlags
)
/*++
Routine Description:
This function will exit to HPGL2 Mode
Arguments:
pPDev - Pointer to the PDEV
pHTGL2ModeCmds - Pointer to our internal command to switch to HPGL2
OHTFlags - Current OHTFlags
Return Value:
New OHTFlags
Development History:
10-Feb-1994 Thu 12:51:14 created
Revision History:
--*/
{
if (OHTFlags & OHTF_IN_RTLMODE) {
if (OHTFlags & OHTF_SET_TR1) {
//
// Send STM command here
//
OutputString(pPDev, "\033*v1N");
}
SEND_PLOTCMDS(pPDev, pHPGL2ModeCmds);
OHTFlags &= ~OHTF_IN_RTLMODE;
PLOTDBG(DBG_HTBLT, ("*** BackTo HPGL/2: %ld=[%hs]",
(DWORD)*pHPGL2ModeCmds, pHPGL2ModeCmds + 1));
}
//
// If we need to clear clip window do it now
//
if (OHTFlags & OHTF_CLIPWINDOW) {
ClearClipWindow(pPDev);
OHTFlags &= ~OHTF_CLIPWINDOW;
PLOTDBG(DBG_HTBLT, ("OutputHTBitmap: ClearClipWindow"));
}
if (OHTFlags & OHTF_SET_TR1) {
OutputString(pPDev, "TR0;");
}
OHTFlags = 0;
if (pOHTFlags) {
*pOHTFlags = OHTFlags;
}
return(OHTFlags);
}
VOID
MoveRelativeY(
PPDEV pPDev,
LONG Y
)
/*++
Routine Description:
Move relative Y positiion by batch for devices that have y coordinate
move limitations.
Arguments:
pPDev - Pointer to our PDEV
Y - Relative amount to move
Return Value:
VOID
Development History:
13-Apr-1994 Wed 14:38:18 created
Revision History:
--*/
{
LPSTR pMove;
LONG SendY;
BOOL Negative;
pMove = (LPSTR)(RTL_NO_DPI_XY(pPDev) ? YMoveDECI : YMoveDPI);
if (Negative = (Y < 0)) {
Y = -Y;
}
while (Y) {
if ((SendY = Y) > MAX_HP_Y_MOVE) {
SendY = MAX_HP_Y_MOVE;
}
OutputFormatStr(pPDev, pMove, (Negative) ? -SendY : SendY);
Y -= SendY;
}
}
BOOL
OutputHTBitmap(
PPDEV pPDev,
SURFOBJ *psoHT,
CLIPOBJ *pco,
PPOINTL pptlDest,
PRECTL prclSrc,
DWORD Rop3,
LPDWORD pOHTFlags
)
/*++
Routine Description:
This function will handle complex type of region bitmaps
Arguments:
pPDev - Pointer to the PDEV
psoHI - the surface object of the halftone bitmap to be output
pco - a clip object associated with psoHT
pptlDest - pointer to the starting destination point
prclSrc - pointer to the source bitmap rectangle area to be copied
to the destination, if this is NULL then a whole psoHT will
be copied to the destination
Rop3 - a Rop3 to send for the source
pOHTFlags - Pointer to the DWORD containing the current OHTF_xxxx, if this
pointer is NULL then this function will enter RTL mode first
and exit to HPGL2 mode when it returns, if this pointer is
specified then the pOHTFlags will be used and at return the
current OHTFlags will be written to the location pointed to
by pOHTFlags
Return Value:
TRUE if sucessful, FALSE if failure
Development History:
04-Nov-1993 Thu 15:30:13 updated
24-Dec-1993 Fri 05:21:57 updated
Total re-write so that take all the bitmap orientations and enum
rects works correctly. this is the major bitmap function entry point
it will call appropriate bitmap function to redner the final output.
The other things is we need to check if switch between HPGL/2 and RTL
can be more efficient. Make sure we can eaiser to adapate to rotate
the bitmap to the left if necessary.
Correct LogExt.cx useage, we must do SPLTOENGUNITS first
29-Dec-1993 Wed 10:59:41 updated
Change bMore=CLIPOBJ_bEnum sequence,
Change PLOTDBGBLK() macro by adding automatical semi in macro
13-Jan-1994 Thu 14:09:51 updated
add prclSrc
14-Jan-1994 Fri 21:03:26 updated
add Rop3
16-Jan-1994 Thu 14:09:51 updated
Change OutputHTBitmap to take Rop4 to send to plotter.
08-Feb-1994 Tue 15:54:24 updated
Make sure we do nothing if source is not visible
21-Mar-1994 Mon 14:20:18 updated
Allocate extra 2 bytes for the scan/rot buffer in case if we must do
byte aligned. And if we need to do byte aligned thing then always
move the HCAPS to the byte boundary first
13-Apr-1994 Wed 14:59:56 updated
1. Batch the Relative Y move to have 32767 limitation problem solved.
2. GrayScale/gamma correct the input BITMAP color
20-Aug-1994 Sat 21:37:37 updated
Add the bitmap offset location from the FORM imageable area, otherwise
our bitmap will have different offset then the HPGL/2 drawing commands
Revision History:
22-Oct-1999 Fri 12:17:21 updated
Return FALSE right away if a job canceled, since this function can
take very long time to finished.
--*/
{
#define pDrvHTInfo ((PDRVHTINFO)pPDev->pvDrvHTData)
PRECTL prcl;
OUTHTBMPFUNC HTBmpFunc;
HTBMPINFO HTBmpInfo;
HTENUMRCL HTEnumRCL;
RTLCLRCONFIG RTLClrConfig;
RECTL rclSrc;
RECTL rclDest;
POINTL CursorPos;
POINTL BmpOffset;
SIZEL Size;
HPBAHACK CurHPBAHack;
LONG cxLogExt;
LONG TempY;
DWORD OHTFlags;
DWORD PlotFlags;
BOOL More;
BOOL RetVal;
BOOL BmpRotate;
BOOL FirstEnumRCL = TRUE;
UINT i;
BYTE HPGL2ModeCmds[16];
BYTE RTLModeCmds[32];
if (PLOT_CANCEL_JOB(pPDev)) {
return(FALSE);
}
PlotFlags = GET_PLOTFLAGS(pPDev);
OHTFlags = (DWORD)((pOHTFlags) ? (*pOHTFlags & OHTF_MASK) : 0);
//
// Set up exit HPGL/2 and enter RTL mode commands
//
INIT_PLOTCMDS(HPGL2ModeCmds);
if (PF_PUSHPAL(PlotFlags)) {
COPY_PLOTCMDS(HPGL2ModeCmds, "\033*p1P", 5);
}
COPY_PLOTCMDS(HPGL2ModeCmds, "\033%0B", 4);
CHECK_PLOTCMDS(HPGL2ModeCmds);
if (OHTFlags & OHTF_EXIT_TO_HPGL2) {
PLOTDBG(DBG_HTBLT, ("OutputHTBitmap: Force Exit to HPGL2 Mode"));
ExitToHPGL2Mode(pPDev, HPGL2ModeCmds, pOHTFlags, OHTFlags);
return(TRUE);
}
//
// Make sure the caller is right about this,
// so check to see which formats we can handle.
//
PLOTASSERT(1, "OutputHTBitmap: Invalid Bitmap Format %ld passed",
(psoHT->iBitmapFormat ==
pDrvHTInfo->HTBmpFormat) ||
(psoHT->iBitmapFormat ==
pDrvHTInfo->AltBmpFormat),
psoHT->iBitmapFormat);
//
// First set some basic information in HTBmpInfo
//
HTBmpInfo.pPDev = pPDev;
HTBmpInfo.Flags = 0;
HTBmpInfo.Delta = psoHT->lDelta;
//
// We will set color format for the HPGL/2 Plotter to the same one as
// the bitmap format passed, this will allow us to use the 1bpp output
// function for the 4bpp surfaces
//
RTLClrConfig.ColorModel = 0;
RTLClrConfig.EncodingMode = 0;
//
// cxLogExt = the output bitmap function index number
// Size.cx = Count of mono scan lines needed for each pixel line, and
// final count of scan buffer needed
// Size.cy = count of rotation buffer needed (Must be DWORD aligned)
//
if (psoHT->iBitmapFormat == BMF_1BPP) {
cxLogExt = 0;
Size.cx = 1;
RTLClrConfig.BitsPerIndex = 1;
} else {
//
// 4 bits per pel, 3 planes that is
//
cxLogExt = 2;
Size.cx = 3;
RTLClrConfig.BitsPerIndex = 3;
}
RTLClrConfig.BitsPerR =
RTLClrConfig.BitsPerG =
RTLClrConfig.BitsPerB = 8;
//
// We have almost everything setup, now check how to send to the output
// bitmap function, get the full destination size first
//
//
//************************************************************************
// The Following RTL switching, config color command and other related
// commands MUST be sent in this order
//************************************************************************"
//
// 1: Initialize the enter RTL command buffer
//
INIT_PLOTCMDS(RTLModeCmds);
//
// 2. commands to go into RTL mode, and back to HPGL/2 mode, the mode
// switching assumes that the current positions are retained.
//
COPY_PLOTCMDS(RTLModeCmds, "\033%0A", 4);
//
// 3. Push/Pop the HPGL/2 palette commands if this is required (PCD file)
//
if (PF_PUSHPAL(PlotFlags)) {
COPY_PLOTCMDS(RTLModeCmds, "\033*p0P", 5);
}
//
// 4. Color configuration commands and exit back to HPGL/2 command
//
if ((RTLClrConfig.BitsPerIndex != 1) ||
(!PF_RTLMONO_NO_CID(PlotFlags))) {
//
// We only do this if we are COLOR or if we must send CID when mono
// device
//
COPY_PLOTCMDS(RTLModeCmds, "\033*v6W", 5);
COPY_PLOTCMDS(RTLModeCmds, &RTLClrConfig, 6);
}
CHECK_PLOTCMDS(RTLModeCmds);
//
// Now Check the source
//
rclSrc.left =
rclSrc.top = 0;
rclSrc.right = psoHT->sizlBitmap.cx;
rclSrc.bottom = psoHT->sizlBitmap.cy;
if (prclSrc) {
PLOTASSERT(1, "OutputHTBitmap: Invalid prclSrc [%08lx] passed",
((prclSrc->left >= 0) &&
(prclSrc->top >= 0) &&
(prclSrc->right <= psoHT->sizlBitmap.cx) &&
(prclSrc->bottom <= psoHT->sizlBitmap.cy) &&
(prclSrc->left <= prclSrc->right) &&
(prclSrc->top <= prclSrc->bottom)), prclSrc);
if (!IntersectRECTL(&rclSrc, prclSrc)) {
PLOTWARN(("OutputHTBitmap: EMPTY SRC Passed, Done!"));
ExitToHPGL2Mode(pPDev, HPGL2ModeCmds, pOHTFlags, OHTFlags);
return(TRUE);
}
}
if (BmpRotate = (pPDev->PlotForm.BmpRotMode != BMP_ROT_NONE)) {
//
// We must allocate rotation buffer and it must be DWORD aligned.
//
Size.cx *= ((psoHT->sizlBitmap.cy + 23) >> 3);
if (psoHT->iBitmapFormat == BMF_1BPP) {
//
// We also have to take into acount the fact that pixels can start
// anywhere in the first byte, causing us to allocate and extra byte
// for the shift.
//
Size.cy = (LONG)((psoHT->sizlBitmap.cy + 23) >> 3);
Size.cy = (LONG)(DW_ALIGN(Size.cy) << 3);
} else {
Size.cy = (LONG)((psoHT->sizlBitmap.cy + 3) >> 1);
Size.cy = (LONG)(DW_ALIGN(Size.cy) << 1);
}
++cxLogExt;
} else {
//
// For a non-rotated 4BPP bitmap, we need an extra buffer to
// ensure the final 4bpp bitmap is DWORD aligned. This will speed up
// the 4bpp to 3 plane translation.
//
Size.cy = (LONG)((psoHT->sizlBitmap.cx + 23) >> 3);
Size.cx *= Size.cy;
if (psoHT->iBitmapFormat == BMF_4BPP) {
//
// Make sure the we allocate a rotation buffer for alignment
// purposes
//
Size.cy = (LONG)((psoHT->sizlBitmap.cx + 3) << 1);
Size.cy = (LONG)DW_ALIGN(Size.cy);
} else {
//
// BMF_1BPP will be left/right shifted on a per byte basis on
// the fly.
//
Size.cy = 0;
}
}
HTBmpFunc = HTBmpFuncTable[cxLogExt];
//
// Make sure the first buffer is DWORD aligned, otherwise the next
// buffer (pRotBuf) will not start on a DWORD boundary.
//
Size.cx = DW_ALIGN(Size.cx);
PLOTDBGBLK(HTBmpInfo.cScanBuf = Size.cx;
HTBmpInfo.cRotBuf = Size.cy)
PLOTDBG(DBG_OUTHTBMP, ("OutputHTBitmap: [%hs] - ScanBuf=%ld, RotBuf=%ld",
pszHTBmpFunc[cxLogExt], Size.cx, Size.cy));
//
// Allocate scan buffer and rotation temp buffer if needed
//
if (!(HTBmpInfo.pScanBuf = (LPBYTE)LocalAlloc(LPTR, Size.cx + Size.cy))) {
PLOTERR(("OutputHTBmp: LocalAlloc(%ld) Failed, cx=%ld, cy=%ld",
Size.cx + Size.cy, Size.cx, Size.cy));
ExitToHPGL2Mode(pPDev, HPGL2ModeCmds, pOHTFlags, OHTFlags);
return(FALSE);
}
HTBmpInfo.pRotBuf = (Size.cy) ? (HTBmpInfo.pScanBuf + Size.cx) : NULL;
//
// Set up local variables for the command mode and other one time variables
//
cxLogExt = SPLTOENGUNITS(pPDev, pPDev->PlotForm.LogExt.cx);
//
// Now set up the rclDest for the bitmap we will output to. And set More to
// false, which means one RECT.
//
rclDest.left = pptlDest->x;
rclDest.top = pptlDest->y;
rclDest.right = rclDest.left + (rclSrc.right - rclSrc.left);
rclDest.bottom = rclDest.top + (rclSrc.bottom - rclSrc.top);
//
// The following variables are essential for the default assumptions.
//
// 1. RetVal = TRUE if no clip rect we return OK
// 2. More = FALSE default as current HTEnumRCL.c and rectl
// without calling CLIPOBJ_bEnum()
// 3. HTEnumRCL.c = 1 to have only one default HTEnumRCL.rcl
//
RetVal = TRUE;
More = FALSE;
HTEnumRCL.c = 1;
if ((!pco) || (pco->iDComplexity == DC_TRIVIAL)) {
//
// The whole output destination rectangle is visible
//
PLOTDBG(DBG_OUTHTBMP, ("OutputHTBitmap: pco=%hs",
(pco) ? "DC_TRIVIAL" : "NULL"));
HTEnumRCL.rcl[0] = rclDest;
} else if (pco->iDComplexity == DC_RECT) {
//
// The visible area is one rectangle so intersect with the destination
//
PLOTDBG(DBG_OUTHTBMP, ("OutputHTBitmap: pco=DC_RECT"));
HTEnumRCL.rcl[0] = pco->rclBounds;
} else {
//
// We have a complex clipping region to be computed, call engine to start
// enumerating the rectangles and set More = TRUE so we can get the first
// batch of rectangles.
//
PLOTDBG(DBG_OUTHTBMP, ("OutputHTBitmap: pco=DC_COMPLEX, EnumRects now"));
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
More = TRUE;
}
Rop3 &= 0xFF;
PLOTASSERT(1, "OutputHTBitmap: The Rop required PATTERN? [%04lx]",
!ROP3_NEED_PAT(Rop3), Rop3);
if (PF_BYTEALIGN(PlotFlags)) {
if (pPDev->PlotDM.Flags & PDMF_PLOT_ON_THE_FLY) {
PLOTWARN(("OutputHTBitmap: ByteAlign/Poster Mode Rop3 0x%02lx -> 0x%02lx",
Rop3, ROP3_BYTEALIGN_POSTER));
Rop3 = ROP3_BYTEALIGN_POSTER;
}
OHTFlags &= ~OHTF_SET_TR1;
CurHPBAHack = HPBAHack[Rop3 & 0x0F];
if (CurHPBAHack.Flags & HPBHF_nS) {
HTBmpInfo.Flags |= HTBIF_FLIP_MONOBITS;
}
if (CurHPBAHack.Flags & HPBHF_PAD_1) {
HTBmpInfo.Flags |= HTBIF_BA_PAD_1;
}
PLOTDBG(DBG_HTBLT, ("OutpputHTBitmap: BA HACK: Rop3=%02lx -> %02lx, Flags=%04lx",
(DWORD)Rop3,
(DWORD)CurHPBAHack.Rop3RTL,
(DWORD)CurHPBAHack.Flags));
} else {
CurHPBAHack.Rop3RTL = (BYTE)Rop3;
CurHPBAHack.Flags = 0;
}
//
// To have correct image area located for the bitmap, we must offset all
// bitmaps with these amounts
//
BmpOffset.x = SPLTOENGUNITS(pPDev, pPDev->PlotForm.BmpOffset.x);
BmpOffset.y = SPLTOENGUNITS(pPDev, pPDev->PlotForm.BmpOffset.y);
//
// We have 'More' and HTEnumRCL structure set, now go through each clipping
// rectangle and call the halftone output fucntion to do the real work
//
do {
//
// If More is true then we need to get the next batch of rectangles.
//
if (More) {
More = CLIPOBJ_bEnum(pco, sizeof(HTEnumRCL), (ULONG *)&HTEnumRCL);
}
//
// prcl will point to the first enumerated rectangle.
//
prcl = (PRECTL)&HTEnumRCL.rcl[0];
while (HTEnumRCL.c-- && More != DDI_ERROR) {
if (PLOT_CANCEL_JOB(pPDev)) {
RetVal =
More = FALSE;
break;
}
//
// Only do this rectangle area if it is visible
//
HTBmpInfo.rclBmp = *prcl;
if (IntersectRECTL(&(HTBmpInfo.rclBmp), &rclDest)) {
//
// For the very first time, we want to switch to PP1
//
if (FirstEnumRCL) {
SetPixelPlacement(pPDev, SPP_MODE_EDGE);
FirstEnumRCL = FALSE;
}
//
// Now compute useable information to be passed to the output
// halftoned bitmap function
//
HTBmpInfo.OffBmp.x = rclSrc.left +
(HTBmpInfo.rclBmp.left - rclDest.left);
HTBmpInfo.OffBmp.y = rclSrc.top +
(HTBmpInfo.rclBmp.top - rclDest.top);
HTBmpInfo.szlBmp.cx = HTBmpInfo.rclBmp.right -
HTBmpInfo.rclBmp.left;
HTBmpInfo.szlBmp.cy = HTBmpInfo.rclBmp.bottom -
HTBmpInfo.rclBmp.top;
HTBmpInfo.pScan0 = (LPBYTE)psoHT->pvScan0 +
(HTBmpInfo.OffBmp.y * HTBmpInfo.Delta);
PLOTDBG(DBG_HTBLT, ("OutputHTBitmap: rclBmp=(%ld, %ld)-(%ld, %ld) [%ld x %ld] Off=(%ld, %ld)",
HTBmpInfo.rclBmp.left, HTBmpInfo.rclBmp.top,
HTBmpInfo.rclBmp.right, HTBmpInfo.rclBmp.bottom,
HTBmpInfo.szlBmp.cx, HTBmpInfo.szlBmp.cy,
HTBmpInfo.OffBmp.x, HTBmpInfo.OffBmp.y));
//
// Now set the correct cursor position based on the rotation
//
if (BmpRotate) {
Size.cx = HTBmpInfo.szlBmp.cy;
Size.cy = HTBmpInfo.szlBmp.cx;
CursorPos.x = HTBmpInfo.rclBmp.top;
CursorPos.y = cxLogExt - HTBmpInfo.rclBmp.right;
} else {
Size = HTBmpInfo.szlBmp;
CursorPos.x = HTBmpInfo.rclBmp.left;
CursorPos.y = HTBmpInfo.rclBmp.top;
}
//
// Add in the bitmap offset location from the imageable area
//
CursorPos.x += BmpOffset.x;
CursorPos.y += BmpOffset.y;
//
// If we need to BYTE align, then make the X cursor position
// byte aligned first
//
if (PF_BYTEALIGN(PlotFlags)) {
if (i = (UINT)(CursorPos.x & 0x07)) {
//
// We really need to byte aligne x and we also have to
// increase the source width to accomodate the changes
//
PLOTDBG(DBG_HTBLT,
("OutputHTBitmap: NEED BYTE ALIGN X: %ld -> %ld, SRC WIDTH: %ld -> %ld",
CursorPos.x, CursorPos.x - i,
Size.cx, Size.cx + i));
Size.cx += i;
CursorPos.x -= i;
}
Size.cx = (LONG)((Size.cx + 7) & ~(DWORD)7);
}
PLOTDBG(DBG_HTBLT,
("OutputHTBitmap: ABS CAP: (%ld, %ld) --> (%ld, %ld), RELATIVE=(%ld, %ld)",
pPDev->ptlRTLCAP.x, pPDev->ptlRTLCAP.y,
CursorPos.x, CursorPos.y,
CursorPos.x - pPDev->ptlRTLCAP.x,
CursorPos.y - pPDev->ptlRTLCAP.y));
if (!(OHTFlags & OHTF_DONE_ROPTR1)) {
if (OHTFlags & OHTF_IN_RTLMODE) {
SEND_PLOTCMDS(pPDev, HPGL2ModeCmds);
OHTFlags &= ~OHTF_IN_RTLMODE;
PLOTDBG(DBG_HTBLT, ("*** Enter HPGL/2: %ld=[%hs]",
(DWORD)HPGL2ModeCmds[0], &HPGL2ModeCmds[1]));
}
SetRopMode(pPDev,
(CurHPBAHack.Flags & HPBHF_1_FIRST) ?
0x88 : CurHPBAHack.Rop3RTL);
if (OHTFlags & OHTF_SET_TR1) {
OutputString(pPDev, "TR1;");
}
}
//
// Entering RTL mode if not already so
//
if (!(OHTFlags & OHTF_IN_RTLMODE)) {
PLOTDBG(DBG_HTBLT, ("*** Enter RTL: %ld=[%hs]",
(DWORD)RTLModeCmds[0], &RTLModeCmds[1]));
SEND_PLOTCMDS(pPDev, RTLModeCmds);
if (OHTFlags & OHTF_SET_TR1) {
//
// Send STM command here
//
OutputString(pPDev, "\033*v0N");
}
if (CurHPBAHack.Flags & HPBHF_nS) {
HTBmpInfo.Flags |= HTBIF_FLIP_MONOBITS;
} else {
HTBmpInfo.Flags &= ~HTBIF_FLIP_MONOBITS;
}
//
// If bitmap is monochrome then make sure we set the
// palette correctly only if we can set it
//
if ((RTLClrConfig.BitsPerIndex == 1) &&
(!(OHTFlags & OHTF_DONE_ROPTR1))) {
PALDW RTLPal;
BOOL FlipMono = FALSE;
for (i = 0; i < 2; i++) {
RTLPal.dw = pDrvHTInfo->RTLPal[i].dw;
//
// Convert the color through gamma/gray scale
//
GetFinalColor(pPDev, &(RTLPal.Pal));
if (RTLPal.dw != DefWKPal[i]) {
if (PF_RTLMONO_FIXPAL(PlotFlags)) {
FlipMono = TRUE;
} else {
OutputFormatStr(pPDev,
SetRGBCmd,
(DWORD)RTLPal.Pal.R,
(DWORD)RTLPal.Pal.G,
(DWORD)RTLPal.Pal.B,
i);
PLOTDBG(DBG_HTBLT_CLR,
("OutputHTBitmap: Change RTLPal[%ld]=%02lx:%02lx:%02lx",
(DWORD)i,
(DWORD)RTLPal.Pal.R,
(DWORD)RTLPal.Pal.G,
(DWORD)RTLPal.Pal.B));
}
}
}
if (FlipMono) {
HTBmpInfo.Flags ^= HTBIF_FLIP_MONOBITS;
PLOTDBG(DBG_HTBLT_CLR, ("OutputHTBitmap: Flip MONO Bits"));
}
}
}
OHTFlags |= (OHTF_IN_RTLMODE | OHTF_DONE_ROPTR1);
TempY = CursorPos.y - pPDev->ptlRTLCAP.y;
if (PF_RTL_NO_DPI_XY(PlotFlags)) {
//
// We will move X in absolute movements (not relative)
// by always outputing position 0 to flush out the device
// X CAP then move absolute to final X position. We will
// us relative movement for the Y coordinate.
//
OutputFormatStr(pPDev,
XMoveDECI,
DEVTODECI(pPDev, CursorPos.x));
} else {
if ((TempY <= MAX_HP_Y_MOVE) &&
(TempY >= -MAX_HP_Y_MOVE)) {
OutputFormatStr(pPDev,
XYMoveDPI,
CursorPos.x - pPDev->ptlRTLCAP.x,
TempY);
TempY = 0;
} else {
OutputFormatStr(pPDev,
XYMoveDPI,
CursorPos.x - pPDev->ptlRTLCAP.x,
0);
}
}
MoveRelativeY(pPDev, TempY);
//
// Update new cursor position after the RTL commands, the
// CursorPos and pPDev->ptlRTLCAPS always are ABSOLUTE
// coordinates but we will send the RTL RELATIVE
// command to position the bitmap.
//
pPDev->ptlRTLCAP.x = CursorPos.x;
pPDev->ptlRTLCAP.y = CursorPos.y + Size.cy;
//
// Output Start Graphic commands
//
OutputFormatStr(pPDev, StartGraf, Size.cx);
//
// Fill One first if we are simulating rops the device can't
// handle
//
if (CurHPBAHack.Flags & HPBHF_1_FIRST) {
FillRect1bppBmp(&HTBmpInfo, 0xFF, FALSE, BmpRotate);
OutputBytes(HTBmpInfo.pPDev, EndGraf, sizeof(EndGraf));
if (CurHPBAHack.Rop3RTL != 0xAA) {
SEND_PLOTCMDS(pPDev, HPGL2ModeCmds);
SetRopMode(pPDev, CurHPBAHack.Rop3RTL);
SEND_PLOTCMDS(pPDev, RTLModeCmds);
MoveRelativeY(pPDev, -Size.cy);
OutputFormatStr(pPDev, StartGraf, Size.cx);
}
}
//
// Now call the functions to really output the bitmap
//
if (CurHPBAHack.Rop3RTL != 0xAA) {
if (RetVal = HTBmpFunc(&HTBmpInfo)) {
//
// If output is ok then send End Graphic command now
//
OutputBytes(HTBmpInfo.pPDev, EndGraf, sizeof(EndGraf));
} else {
PLOTERR(("OutputHTBitmap: HTBmpFunc = FALSE (failed)"));
More = FALSE;
break;
}
}
if (CurHPBAHack.Flags & HPBHF_nD_LAST) {
SEND_PLOTCMDS(pPDev, HPGL2ModeCmds);
SetRopMode(pPDev, 0x66);
SEND_PLOTCMDS(pPDev, RTLModeCmds);
if ((CurHPBAHack.Flags & HPBHF_1_FIRST) ||
(CurHPBAHack.Rop3RTL != 0xAA)) {
MoveRelativeY(pPDev, -Size.cy);
OutputFormatStr(pPDev, StartGraf, Size.cx);
OHTFlags |= OHTF_IN_RTLMODE;
}
FillRect1bppBmp(&HTBmpInfo, 0x00, TRUE, BmpRotate);
OutputBytes(HTBmpInfo.pPDev, EndGraf, sizeof(EndGraf));
}
if (PF_BYTEALIGN(PlotFlags)) {
OHTFlags &= ~OHTF_DONE_ROPTR1;
}
} else {
PLOTDBG(DBG_HTBLT_SKIP, ("OutputHTBitmap: INVISIBLE rcl=(%ld, %ld)-(%ld, %ld)",
prcl->left, prcl->top, prcl->right, prcl->bottom));
}
prcl++;
}
if (More == DDI_ERROR)
{
More = FALSE;
RetVal = FALSE;
}
} while (More);
//
// Finally return to HPGL/2 mode
//
if ((!RetVal) || (!pOHTFlags)) {
ExitToHPGL2Mode(pPDev, HPGL2ModeCmds, pOHTFlags, OHTFlags);
}
if (pOHTFlags) {
*pOHTFlags = OHTFlags;
}
//
// Get rid of any resources we allocated
//
LocalFree((HLOCAL)HTBmpInfo.pScanBuf);
return(RetVal);
#undef pDrvHTInfo
}
LONG
GetBmpDelta(
DWORD SurfaceFormat,
DWORD cx
)
/*++
Routine Description:
This function calculates the total bytes needed in order to advance a
scan line based on the bitmap format and alignment.
Arguments:
SurfaceFormat - Surface format of the bitmap, this must be one of the
standard formats which are defined as BMF_xxx
cx - Total Pels per scan line in the bitmap.
Return Value:
The return value is the total bytes in one scan line if it is greater than
zero
Development History:
19-Jan-1994 Wed 16:19:39 created
Revision History:
--*/
{
DWORD Delta = cx;
switch (SurfaceFormat) {
case BMF_32BPP:
Delta <<= 5;
break;
case BMF_24BPP:
Delta *= 24;
break;
case BMF_16BPP:
Delta <<= 4;
break;
case BMF_8BPP:
Delta <<= 3;
break;
case BMF_4BPP:
Delta <<= 2;
break;
case BMF_1BPP:
break;
default:
PLOTERR(("GetBmpDelta: Invalid BMF_xxx format = %ld", SurfaceFormat));
break;
}
Delta = (DWORD)DW_ALIGN((Delta + 7) >> 3);
PLOTDBG(DBG_BMPDELTA, ("Format=%ld, cx=%ld, Delta=%ld",
SurfaceFormat, cx, Delta));
return((LONG)Delta);
}
SURFOBJ *
CreateBitmapSURFOBJ(
PPDEV pPDev,
HBITMAP *phBmp,
LONG cxSize,
LONG cySize,
DWORD Format,
LPVOID pvBits
)
/*++
Routine Description:
This function creates a bitmap and locks the bitmap to return a SURFOBJ
Arguments:
pPDev - Pointer to our PDEV
phBmp - Pointer the HBITMAP location to be returned for the bitmap
cxSize - CX size of bitmap to be created
cySize - CY size of bitmap to be created
Format - one of BMF_xxx bitmap format to be created
pvBits - the buffer to be used
Return Value:
SURFOBJ if sucessful, NULL if failed
Development History:
19-Jan-1994 Wed 16:31:50 created
Revision History:
--*/
{
SURFOBJ *pso = NULL;
SIZEL szlBmp;
szlBmp.cx = cxSize;
szlBmp.cy = cySize;
PLOTDBG(DBG_CREATESURFOBJ, ("CreateBitmapSURFOBJ: Format=%ld, Size=%ld x %ld",
Format, cxSize, cySize));
if (*phBmp = EngCreateBitmap(szlBmp,
GetBmpDelta(Format, cxSize),
Format,
BMF_TOPDOWN | BMF_NOZEROINIT,
pvBits)) {
if (EngAssociateSurface((HSURF)*phBmp, (HDEV)pPDev->hpdev, 0)) {
if (pso = EngLockSurface((HSURF)*phBmp)) {
//
// Sucessful lock down, return it
//
return(pso);
} else {
PLOTERR(("CreateBmpSurfObj: EngLockSruface(hBmp) failed!"));
}
} else {
PLOTERR(("CreateBmpSurfObj: EngAssociateSurface() failed!"));
}
} else {
PLOTERR(("CreateBMPSurfObj: FAILED to create Bitmap Format=%ld, %ld x %ld",
Format, cxSize, cySize));
}
DELETE_SURFOBJ(pso, phBmp);
return(NULL);
}
BOOL
HalftoneBlt(
PPDEV pPDev,
SURFOBJ *psoDst,
SURFOBJ *psoHTBlt,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
PRECTL prclDst,
PRECTL prclSrc,
PPOINTL pptlHTOrigin,
BOOL DoStretchBlt
)
/*++
Routine Description:
Arguments:
pPDev - Pointer to our PDEV
psoDst - destination surfobj
psoHTBlt - the final halftoned result will be stored, must be a
4/1 halftoned bitmap format
psoSrc - source surfobj must be BITMAP
pxlo - xlate object from source to the plotter device
prclDest - rectangle area for the destination
prclSrc - rectangle area to be halftoned from the source, if NULL
then full source size is used
pptlHTOrigin - the halftone origin, if NULL then (0,0) is assumed
StretchBlt - if TRUE then a stretch from rclSrc to rclDst otherwise
a tiling is done
Return Value:
BOOL to indicate operation status
Development History:
19-Jan-1994 Wed 15:44:57 created
Revision History:
--*/
{
SIZEL szlSrc;
RECTL rclSrc;
RECTL rclDst;
RECTL rclCur;
RECTL rclHTBlt;
if (PLOT_CANCEL_JOB(pPDev)) {
return(FALSE);
}
PLOTASSERT(1, "HalftoneBlt: psoSrc type [%ld] is not a bitmap",
psoSrc->iType == STYPE_BITMAP, (LONG)psoSrc->iType);
PLOTASSERT(1, "HalftoneBlt: psoHTBlt type [%ld] is not a bitmap",
psoHTBlt->iType == STYPE_BITMAP, (LONG)psoHTBlt->iType);
if (pPDev->psoHTBlt) {
PLOTERR(("HalftoneBlt: EngStretchBlt(HALFTONE) RECURSIVE CALLS NOT ALLOWED!"));
return(FALSE);
}
pPDev->psoHTBlt = psoHTBlt;
if (prclSrc) {
rclSrc = *prclSrc;
} else {
rclSrc.left =
rclSrc.top = 0;
rclSrc.right = psoSrc->sizlBitmap.cx;
rclSrc.bottom = psoSrc->sizlBitmap.cy;
}
if (prclDst) {
rclDst = *prclDst;
} else {
rclDst.left =
rclDst.top = 0;
rclDst.right = psoHTBlt->sizlBitmap.cx;
rclDst.bottom = psoHTBlt->sizlBitmap.cy;
}
if (!pptlHTOrigin) {
pptlHTOrigin = (PPOINTL)&ptlZeroOrigin;
}
if (DoStretchBlt) {
szlSrc.cx = rclDst.right - rclDst.left;
szlSrc.cy = rclDst.bottom - rclDst.top;
} else {
szlSrc.cx = rclSrc.right - rclSrc.left;
szlSrc.cy = rclSrc.bottom - rclSrc.top;
}
PLOTDBG(DBG_HTBLT, ("HalftoneBlt: %hs BLT, (%ld,%ld)-(%ld,%ld), SRC=%ldx%ld",
(DoStretchBlt) ? "STRETCH" : "TILE",
rclDst.left, rclDst.top, rclDst.right,rclDst.bottom,
szlSrc.cx, szlSrc.cy));
//
// Start to tile it, rclCur is current RECTL on the destination
//
rclHTBlt.top = 0;
rclCur.top =
rclCur.bottom = rclDst.top;
while (rclCur.top < rclDst.bottom) {
//
// Check the Current Bottom, clip it if necessary
//
if ((rclCur.bottom += szlSrc.cy) > rclDst.bottom) {
rclCur.bottom = rclDst.bottom;
}
rclHTBlt.bottom = rclHTBlt.top + (rclCur.bottom - rclCur.top);
rclHTBlt.left = 0;
rclCur.left =
rclCur.right = rclDst.left;
while (rclCur.left < rclDst.right) {
//
// Check the Current right, clip it if necessary
//
if ((rclCur.right += szlSrc.cx) > rclDst.right) {
rclCur.right = rclDst.right;
}
//
// Set it for the tiling rectangle in psoHTBlt
//
rclHTBlt.right = rclHTBlt.left + (rclCur.right - rclCur.left);
PLOTDBG(DBG_HTBLT, ("HalftoneBlt: TILE (%ld,%ld)-(%ld,%ld)->(%ld,%ld)-(%ld,%ld)=%ld x %ld",
rclCur.left, rclCur.top, rclCur.right, rclCur.bottom,
rclHTBlt.left, rclHTBlt.top,
rclHTBlt.right, rclHTBlt.bottom,
rclCur.right - rclCur.left,
rclCur.bottom - rclCur.top));
//
// Set it before the call for the DrvCopyBits()
//
pPDev->rclHTBlt = rclHTBlt;
if (!EngStretchBlt(psoDst, // Dest
psoSrc, // SRC
NULL, // MASK
NULL, // CLIPOBJ
pxlo, // XLATEOBJ
NULL, // COLORADJUSTMENT
pptlHTOrigin, // BRUSH ORG
&rclCur, // DEST RECT
&rclSrc, // SRC RECT
NULL, // MASK POINT
HALFTONE)) { // HALFTONE MODE
PLOTERR(("HalftoneeBlt: EngStretchBits(DST=(%ld,%ld)-(%ld,%ld), SRC=(%ld,%ld) FAIELD!",
rclCur.left, rclCur.top,
rclCur.right, rclCur.bottom,
rclSrc.left, rclSrc.top));
pPDev->psoHTBlt = NULL;
return(FALSE);
}
rclHTBlt.left = rclHTBlt.right;
rclCur.left = rclCur.right;
}
rclHTBlt.top = rclHTBlt.bottom;
rclCur.top = rclCur.bottom;
}
pPDev->psoHTBlt = NULL;
return(TRUE);
}
SURFOBJ *
CreateSolidColorSURFOBJ(
PPDEV pPDev,
SURFOBJ *psoDst,
HBITMAP *phBmp,
DWORD SolidColor
)
/*++
Routine Description:
This function creates a SOLID color bitmap surfobj which can be used to
blt around.
Arguments:
pPDev - Pointer to our PDEV
phBmp - Pointer the HBITMAP location to be returned for the bitmap
SolidColor - Solid color
Return Value:
SURFOBJ if sucessful, NULL if failed
Development History:
19-Jan-1994 Wed 16:35:54 created
Revision History:
--*/
{
SURFOBJ *psoHT = NULL;
HBITMAP hBmpSolid = NULL;
SURFOBJ *psoSolid;
//
// First create a 24-bit source color bitmap
//
if (psoSolid = CreateBitmapSURFOBJ(pPDev,
&hBmpSolid,
1,
1,
BMF_24BPP,
NULL)) {
LPBYTE pbgr = (LPBYTE)psoSolid->pvScan0;
PPALENTRY pPal = (PPALENTRY)&SolidColor;
DWORD HTCellSize = (DWORD)HTPATSIZE(pPDev);
*pbgr++ = pPal->R;
*pbgr++ = pPal->G;
*pbgr++ = pPal->B;
//
// Create a compatible halftone surface with size of halftone cell
//
if (psoHT = CreateBitmapSURFOBJ(pPDev,
phBmp,
HTCellSize,
HTCellSize,
(DWORD)HTBMPFORMAT(pPDev),
NULL)) {
//
// Now halftone blt it
//
if (!HalftoneBlt(pPDev, // pPDev
psoDst, // psoDst
psoHT, // psoHTBlt
psoSolid, // psoSrc
NULL, // pxlo,
NULL, // prclDst
NULL, // prclSrc
NULL, // pptlHTOrigin
TRUE)) { // DoStretchBlt
PLOTERR(("CreateSolidColorSURFOBJ: HalftoneBlt(STRETCH) Failed"));
DELETE_SURFOBJ(psoHT, phBmp);
}
} else {
PLOTERR(("CreateSolidColorSURFOBJ: Create 24BPP SOURCE failed"));
}
} else {
PLOTERR(("CreateSolidColorSURFOBJ: Create 24BPP SOURCE failed"));
}
DELETE_SURFOBJ(psoSolid, &hBmpSolid);
return(psoHT);
}
SURFOBJ *
CloneBrushSURFOBJ(
PPDEV pPDev,
SURFOBJ *psoDst,
HBITMAP *phBmp,
BRUSHOBJ *pbo
)
/*++
Routine Description:
This function clones the surface object passed in
Arguments:
pPDev - Points to our PPDEV
psoDst - the surface object for the plotter
phBmp - Pointer to stored hBbitmap created for the cloned surface
pbo - BRUSHOBJ to be cloned
Return Value:
pointer to the cloned surface object, NULL if failure
Development History:
09-Feb-1994 Wed 13:04:46 updated
Make it assert and handle it when things not supposed happened.
04-Jan-1994 Tue 12:11:23 created
Revision History:
--*/
{
//
// Ceate a Solid color brush if so, NOTE: All brush patterns created
// here have brush origin at (0,0) we will align the brush origin
// when we actually do the ROPs
//
if (!IS_RASTER(pPDev)) {
return(FALSE);
}
if (pbo->iSolidColor & 0xFF000000) {
PDEVBRUSH pDevBrush = (PDEVBRUSH)pbo->pvRbrush;
if ((pDevBrush) || (pDevBrush = BRUSHOBJ_pvGetRbrush(pbo))) {
return(CreateBitmapSURFOBJ(pPDev,
phBmp,
pDevBrush->sizlBitmap.cx,
pDevBrush->sizlBitmap.cy,
pDevBrush->BmpFormat,
pDevBrush->BmpBits));
} else {
return(FALSE);
}
} else {
return(CreateSolidColorSURFOBJ(pPDev,
psoDst,
phBmp,
pbo->iSolidColor));
}
}
SURFOBJ *
CloneSURFOBJToHT(
PPDEV pPDev,
SURFOBJ *psoDst,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
HBITMAP *phBmp,
PRECTL prclDst,
PRECTL prclSrc
)
/*++
Routine Description:
This function clones the surface object passed in
Arguments:
pPDev - Pointer to our PPDEV
psoDst - the surface object for the plotter, if psoDst is NULL
then only the bitmapp will be created
psoSrc - The surface object to be cloned
pxlo - XLATE object to be used from source to plotter surfobj
phBmp - Pointer to stored hBbitmap created for the cloned surface
prclDst - rectangle rectangle size/location to be cloned
prclSrc - source rectangle size/location to be cloned
Return Value:
pointer to the cloned surface object, NULL if failed.
if this function is sucessful it will MODIFY the prclSrc to reflect cloned
surface object
Development History:
04-Jan-1994 Tue 12:11:23 created
Revision History:
--*/
{
SURFOBJ *psoHT;
RECTL rclDst;
RECTL rclSrc;
POINTL ptlHTOrigin;
rclSrc.left =
rclSrc.top = 0;
rclSrc.right = psoSrc->sizlBitmap.cx;
rclSrc.bottom = psoSrc->sizlBitmap.cy;
if (prclSrc) {
if (!IntersectRECTL(&rclSrc, prclSrc)) {
PLOTDBG(DBG_CLONESURFOBJ, ("CloneSURFOBJToHT: Source rectangle is empty"));
return(NULL);
}
}
PLOTDBG(DBG_CLONESURFOBJ, ("CloneSURFOBJToHT: rclSrc=(%ld, %ld)-(%ld,%ld) = %ld x %ld",
rclSrc.left, rclSrc.top,
rclSrc.right, rclSrc.bottom,
rclSrc.right - rclSrc.left,
rclSrc.bottom - rclSrc.top));
rclDst.left =
rclDst.top = 0;
rclDst.right = psoDst->sizlBitmap.cx;
rclDst.bottom = psoDst->sizlBitmap.cy;
if (prclDst) {
if (!IntersectRECTL(&rclDst, prclDst)) {
PLOTDBG(DBG_CLONESURFOBJ, ("CloneSURFOBJToHT: Source rectangle is empty"));
return(NULL);
}
}
PLOTDBG(DBG_CLONESURFOBJ, ("CloneSURFOBJToHT: rclDst=(%ld, %ld)-(%ld,%ld) = %ld x %ld",
rclDst.left, rclDst.top,
rclDst.right, rclDst.bottom,
rclDst.right - rclDst.left,
rclDst.bottom - rclDst.top));
if (psoHT = CreateBitmapSURFOBJ(pPDev,
phBmp,
rclDst.right -= rclDst.left,
rclDst.bottom -= rclDst.top,
HTBMPFORMAT(pPDev),
NULL)) {
//
// Halftone and tile the source to the destination
//
ptlHTOrigin.x = rclDst.left;
ptlHTOrigin.y = rclDst.top;
if (prclSrc) {
if ((rclDst.left = prclSrc->left) > 0) {
rclDst.left = 0;
}
if ((rclDst.top = prclSrc->top) > 0) {
rclDst.top = 0;
}
//
// Modify the source to reflect the cloned source
//
*prclSrc = rclDst;
}
if (psoDst) {
if (!HalftoneBlt(pPDev,
psoDst,
psoHT,
psoSrc,
pxlo,
&rclDst,
&rclSrc,
&ptlHTOrigin,
FALSE)) {
PLOTERR(("CloneSURFOBJToHT: HalftoneBlt(TILE) Failed"));
DELETE_SURFOBJ(psoHT, phBmp);
}
}
} else {
PLOTERR(("CreateSolidColorSURFOBJ: Create Halftone SURFOBJ failed"));
}
return(psoHT);
}
SURFOBJ *
CloneMaskSURFOBJ(
PPDEV pPDev,
SURFOBJ *psoMask,
HBITMAP *phBmp,
PRECTL prclMask
)
/*++
Routine Description:
This function clones the mask surface object passed in
Arguments:
pPDev - Pointer to our PPDEV
psoMask - The mask surface object to be cloned
phBmp - Pointer to stored hBbitmap created for the cloned surface
prclMask - Mask source rectangle size/location to be cloned
Return Value:
pointer to the cloned surface object or original passed in psoMask, NULL if
failed.
if this function is sucessful it will MODIFY the prclMask to reflect cloned
surface object
Development History:
04-Jan-1994 Tue 12:11:23 created
Revision History:
--*/
{
SURFOBJ *psoHT;
RECTL rclMask;
DWORD cxMask;
DWORD cyMask;
DWORD xLoop;
if (PLOT_CANCEL_JOB(pPDev)) {
return(FALSE);
}
PLOTASSERT(1, "CloneMaskSURFOBJ: psoMask=%08lx is not 1BPP",
(psoMask) &&
(psoMask->iType == STYPE_BITMAP) &&
(psoMask->iBitmapFormat == BMF_1BPP), psoMask);
PLOTDBG(DBG_CLONEMASK, ("CloneMaskSURFOBJ: prclMask=(%ld, %ld)-(%ld,%ld) = %ld x %ld",
prclMask->left, prclMask->top,
prclMask->right, prclMask->bottom,
prclMask->right - prclMask->left,
prclMask->bottom - prclMask->top));
rclMask.left =
rclMask.top = 0;
rclMask.right = psoMask->sizlBitmap.cx;
rclMask.bottom = psoMask->sizlBitmap.cy;
if (!IntersectRECTL(&rclMask, prclMask)) {
PLOTDBG(DBG_CLONEMASK, ("CloneMaskSURFOBJ: Mask rectangle is empty"));
return(NULL);
}
cxMask = rclMask.right - rclMask.left;
cyMask = rclMask.bottom - rclMask.top;
PLOTDBG(DBG_CLONEMASK, ("CloneMaskSURFOBJ: rclMask=(%ld, %ld)-(%ld,%ld) = %ld x %ld",
rclMask.left, rclMask.top,
rclMask.right, rclMask.bottom,
rclMask.right - rclMask.left,
rclMask.bottom - rclMask.top));
if (psoHT = CreateBitmapSURFOBJ(pPDev,
phBmp,
cxMask,
cyMask,
HTBMPFORMAT(pPDev),
NULL)) {
//
// Update prclMask
//
prclMask->left =
prclMask->top = 0;
prclMask->right = cxMask;
prclMask->bottom = cyMask;
if (psoHT->iBitmapFormat == BMF_1BPP) {
//
// !Remember: Our BMF_1BPP 0=BLACK, 1=WHITE
//
if (!EngBitBlt(psoHT, // psoDst
psoMask, // psoSrc
NULL, // psoMask
NULL, // pco
NULL, // pxlo
prclMask, // prclDst
(PPOINTL)&rclMask, // pptlSrc
NULL, // pptlMask
NULL, // pbo
(PPOINTL)&ptlZeroOrigin, // pptlBrushOrg ZERO
0x3333)) { // NOTSRCCOPY
PLOTERR(("DrvBitBlt: EngBitBlt(Mask 0x3333) FAILED"));
}
} else {
BYTE SrcMaskBeg;
BYTE SrcMask;
BYTE DstMask;
BYTE bSrc;
BYTE bDst;
LPBYTE pbSrcBeg;
LPBYTE pbDstBeg;
LPBYTE pbSrc;
LPBYTE pbDst;
PLOTASSERT(1, "CloneMaskSURFOBJ: Cloned Mask psoHT=%08lx is not 4BPP",
(psoHT->iBitmapFormat == BMF_4BPP), psoHT);
//
// get the starting location of the original 1BPP mask
//
pbSrcBeg = (LPBYTE)psoMask->pvScan0 +
(rclMask.top * psoMask->lDelta) +
(rclMask.left >> 3);
SrcMaskBeg = (BYTE)(0x80 >> (rclMask.left & 0x07));
pbDstBeg = psoHT->pvScan0;
while (cyMask--) {
xLoop = cxMask;
pbSrc = pbSrcBeg;
pbSrcBeg += psoMask->lDelta;
pbDst = pbDstBeg;
pbDstBeg += psoHT->lDelta;
SrcMask = SrcMaskBeg;
DstMask = 0xF0;
bSrc = *pbSrc++;
bDst = 0xFF;
while (xLoop--) {
if (!SrcMask) {
SrcMask = 0x80;
bSrc = *pbSrc++;
}
if (bSrc & SrcMask) {
bDst ^= DstMask;
}
SrcMask >>= 1;
if ((DstMask ^= 0xFF) == 0xF0) {
*pbDst++ = bDst;
bDst = 0xFF;
}
}
}
}
} else {
PLOTERR(("CloneMaskSURFOBJ: Create Mask SURFOBJ failed"));
}
return(psoHT);
}