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.
2315 lines
65 KiB
2315 lines
65 KiB
/*++
|
|
|
|
Copyright (c) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
raster.c
|
|
|
|
Abstract:
|
|
|
|
Implementation of the interface between Control module and Raster module
|
|
|
|
Environment:
|
|
|
|
Windows NT Unidrv driver
|
|
|
|
Revision History:
|
|
|
|
12/15/96 -alvins-
|
|
Created
|
|
|
|
--*/
|
|
|
|
#include "raster.h"
|
|
#include "rastproc.h"
|
|
#include "rmrender.h"
|
|
#include "unirc.h"
|
|
#include "xlraster.h"
|
|
|
|
// internal function declarations
|
|
void vSetHTData(PDEV *, GDIINFO *);
|
|
BOOL bInitColorOrder(PDEV *);
|
|
DWORD PickDefaultHTPatSize(DWORD,DWORD);
|
|
VOID v8BPPLoadPal(PDEV *);
|
|
BOOL bEnoughDRCMemory(PDEV *);
|
|
|
|
#ifdef TIMING
|
|
#include <stdio.h>
|
|
void DrvDbgPrint(
|
|
char *,
|
|
...);
|
|
#endif
|
|
|
|
// parameter definitions
|
|
static RMPROCS RasterProcs =
|
|
{
|
|
RMStartDoc,
|
|
RMStartPage,
|
|
RMSendPage,
|
|
RMEndDoc,
|
|
RMNextBand,
|
|
RMStartBanding,
|
|
RMResetPDEV,
|
|
RMEnableSurface,
|
|
RMDisableSurface,
|
|
RMDisablePDEV,
|
|
RMCopyBits,
|
|
RMBitBlt,
|
|
RMStretchBlt,
|
|
RMDitherColor,
|
|
RMStretchBltROP,
|
|
RMPaint,
|
|
RMPlgBlt
|
|
};
|
|
|
|
CONST BYTE cxcyHTPatSize[HT_PATSIZE_MAX_INDEX+1] = {
|
|
|
|
2,2,4,4,6,6,8,8,10,10,12,12,14,14,16,16
|
|
#ifndef WINNT_40
|
|
,84,91
|
|
#endif
|
|
};
|
|
|
|
|
|
#define VALID_YC 0xFFFE
|
|
#define GAMMA_LINEAR 10000
|
|
#define GAMMA_DEVICE_HT 8000
|
|
#define GAMMA_SUPERCELL GAMMA_LINEAR
|
|
#define GAMMA_DITHER 9250
|
|
#define GAMMA_GEN_PROFILE 0xFFFF
|
|
|
|
|
|
CONST COLORINFO DefColorInfoLinear =
|
|
{
|
|
{ 6400, 3300, 0 }, // xr, yr, Yr
|
|
{ 3000, 6000, 0 }, // xg, yg, Yg
|
|
{ 1500, 600, 0 }, // xb, yb, Yb
|
|
{ 0, 0,VALID_YC }, // xc, yc, Yc Y=0=HT default
|
|
{ 0, 0, 0 }, // xm, ym, Ym
|
|
{ 0, 0, 0 }, // xy, yy, Yy
|
|
{ 3127, 3290, 10000 }, // xw, yw, Yw
|
|
|
|
10000, // R gamma
|
|
10000, // G gamma
|
|
10000, // B gamma
|
|
|
|
712, 121, // M/C, Y/C
|
|
86, 468, // C/M, Y/M
|
|
21, 35 // C/Y, M/Y
|
|
};
|
|
|
|
|
|
//*******************************************************
|
|
BOOL
|
|
RMInit (
|
|
PDEV *pPDev,
|
|
DEVINFO *pDevInfo,
|
|
GDIINFO *pGDIInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to initialize raster related information in
|
|
pPDev, pDevInfo and pGDIInfo
|
|
|
|
Arguments:
|
|
|
|
pPDev Pointer to PDEV structure
|
|
pDevInfo Pointer to DEVINFO structure
|
|
pGDIInfo Pointer to GDIINFO structure
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
BOOL bRet = FALSE;
|
|
PRASTERPDEV pRPDev;
|
|
|
|
// Validate Input Parameters and ASSERT.
|
|
ASSERT(pPDev);
|
|
ASSERT(pDevInfo);
|
|
ASSERT(pGDIInfo);
|
|
|
|
// initialize the hook flag
|
|
pPDev->fHooks |= HOOK_BITBLT | HOOK_STRETCHBLT | HOOK_COPYBITS;
|
|
|
|
// initialize Proc jump table
|
|
pPDev->pRasterProcs = &RasterProcs;
|
|
|
|
// initialize Raster Pdev
|
|
if (!bInitRasterPDev(pPDev))
|
|
return FALSE;
|
|
|
|
pRPDev = (PRASTERPDEV)pPDev->pRasterPDEV;
|
|
|
|
//
|
|
// Set up the default HALFTONE and colour calibration data.
|
|
//
|
|
vSetHTData( pPDev, pGDIInfo );
|
|
|
|
//
|
|
// initialize graphic capabilities
|
|
//
|
|
pDevInfo->flGraphicsCaps |= (GCAPS_ARBRUSHOPAQUE | GCAPS_HALFTONE | GCAPS_MONO_DITHER | GCAPS_COLOR_DITHER);
|
|
|
|
// initialize DevInfo parameters for rendering
|
|
// test whether standard dither or custom pattern
|
|
#ifndef WINNT_40
|
|
if (pGDIInfo->ulHTPatternSize == HT_PATSIZE_USER) {
|
|
pDevInfo->cxDither = (USHORT)pPDev->pHalftone->HalftonePatternSize.x;
|
|
pDevInfo->cyDither = (USHORT)pPDev->pHalftone->HalftonePatternSize.y;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
pDevInfo->cxDither =
|
|
pDevInfo->cyDither = cxcyHTPatSize[pGDIInfo->ulHTPatternSize];
|
|
}
|
|
pPDev->dwHTPatSize = pDevInfo->cyDither;
|
|
// if no quality macro setting, overwrite with halftone type
|
|
//
|
|
if ((pPDev->pdmPrivate->dwFlags & DXF_CUSTOM_QUALITY) ||
|
|
(pPDev->pdmPrivate->iQuality != QS_BEST &&
|
|
pPDev->pdmPrivate->iQuality != QS_BETTER &&
|
|
pPDev->pdmPrivate->iQuality != QS_DRAFT))
|
|
pPDev->pdm->dmDitherType = pGDIInfo->ulHTPatternSize;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//*******************************************************
|
|
BOOL
|
|
bInitRasterPDev(
|
|
PDEV *pPDev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine allocates the RASTERPDEV and initializes various fields.
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to PDEV.
|
|
|
|
Return Value:
|
|
|
|
TRUE - for success
|
|
FALSE - for failure
|
|
|
|
--*/
|
|
|
|
{
|
|
PRASTERPDEV pRPDev;
|
|
GLOBALS *pGlobals = pPDev->pGlobals;
|
|
PLISTNODE pListNode;
|
|
|
|
if ( !(pRPDev = MemAllocZ(sizeof(RASTERPDEV))) )
|
|
{
|
|
ERR(("Unidrv!RMInit: Can't Allocate RASTERPDEV\n"));
|
|
return FALSE;
|
|
}
|
|
pPDev->pRasterPDEV = pRPDev;
|
|
|
|
// map all callback functions
|
|
//
|
|
|
|
if (pPDev->pOemHookInfo)
|
|
{
|
|
pRPDev->pfnOEMCompression =
|
|
(PFN_OEMCompression)pPDev->pOemHookInfo[EP_OEMCompression].pfnHook;
|
|
pRPDev->pfnOEMHalftonePattern =
|
|
(PFN_OEMHalftonePattern)pPDev->pOemHookInfo[EP_OEMHalftonePattern].pfnHook;
|
|
if (pPDev->pColorModeEx && pPDev->pColorModeEx->dwIPCallbackID > 0)
|
|
{
|
|
pRPDev->pfnOEMImageProcessing = (PFN_OEMImageProcessing)
|
|
pPDev->pOemHookInfo[EP_OEMImageProcessing].pfnHook;
|
|
}
|
|
pRPDev->pfnOEMFilterGraphics =
|
|
(PFN_OEMFilterGraphics)pPDev->pOemHookInfo[EP_OEMFilterGraphics].pfnHook;
|
|
}
|
|
// Determine the pixel depth, # planes and color order
|
|
//
|
|
if (!(bInitColorOrder(pPDev)))
|
|
{
|
|
ERR(("Invalid Color Order"));
|
|
pPDev->pRasterPDEV = NULL;
|
|
MemFree(pRPDev);
|
|
return FALSE;
|
|
}
|
|
|
|
//* Determine whether to set DC_EXPLICIT_COLOR flag
|
|
if (pGlobals->bUseCmdSendBlockDataForColor)
|
|
pRPDev->fColorFormat |= DC_EXPLICIT_COLOR;
|
|
|
|
//* Determine DC_CF_SEND_CR flag
|
|
if (pGlobals->bMoveToX0BeforeColor)
|
|
pRPDev->fColorFormat |= DC_CF_SEND_CR;
|
|
|
|
//* Determine DC_SEND_ALL_PLANES flag
|
|
if (pGlobals->bRasterSendAllData)
|
|
pRPDev->fColorFormat |= DC_SEND_ALL_PLANES;
|
|
|
|
|
|
/*TBD: if there is a filter callback, set BLOCK_IS_BAND
|
|
//
|
|
if (I've got a filter callback?)
|
|
pRPDev->fRMode |= PFR_BLOCK_IS_BAND;
|
|
*/
|
|
|
|
// Initialize whether there are SRCBMPWIDTH / SRCBMPHEIGHT commands
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_SETSRCBMPWIDTH))
|
|
pRPDev->fRMode |= PFR_SENDSRCWIDTH;
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_SETSRCBMPHEIGHT))
|
|
pRPDev->fRMode |= PFR_SENDSRCHEIGHT;
|
|
|
|
// Initialize whether there is a BEGINRASTER command
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_BEGINRASTER))
|
|
pRPDev->fRMode |= PFR_SENDBEGINRASTER;
|
|
|
|
// Initialize rules testing
|
|
// If Rectangle width and height commands exist assume we have black or
|
|
// gray rectangles unless only white rect command exist. This is because
|
|
// some devices have no explicit rectangle commands while others only have
|
|
// white rectangles.
|
|
//
|
|
if (pPDev->fMode & PF_RECT_FILL)
|
|
{
|
|
pRPDev->fRMode |= PFR_RECT_FILL | PFR_RECT_HORIZFILL;
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_RECTBLACKFILL))
|
|
pRPDev->dwRectFillCommand = CMD_RECTBLACKFILL;
|
|
else if (COMMANDPTR(pPDev->pDriverInfo,CMD_RECTGRAYFILL))
|
|
pRPDev->dwRectFillCommand = CMD_RECTGRAYFILL;
|
|
else if (COMMANDPTR(pPDev->pDriverInfo,CMD_RECTWHITEFILL))
|
|
pRPDev->fRMode &= ~(PFR_RECT_FILL | PFR_RECT_HORIZFILL);
|
|
}
|
|
// Initialize whether to send ENDBLOCK commands
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_ENDBLOCKDATA))
|
|
pRPDev->fRMode |= PFR_ENDBLOCK;
|
|
|
|
//* Initialize resolution fields
|
|
//
|
|
pRPDev->sMinBlankSkip = (short)pPDev->pResolutionEx->dwMinStripBlankPixels;
|
|
pRPDev->sNPins = (WORD)pPDev->pResolutionEx->dwPinsPerLogPass;
|
|
pRPDev->sPinsPerPass = (WORD)pPDev->pResolutionEx->dwPinsPerPhysPass;
|
|
|
|
//* initialize fDump flags
|
|
//
|
|
if (pGlobals->bOptimizeLeftBound)
|
|
pRPDev->fDump |= RES_DM_LEFT_BOUND;
|
|
if (pGlobals->outputdataformat == ODF_H_BYTE)
|
|
pRPDev->fDump |= RES_DM_GDI;
|
|
|
|
//* initialize fBlockOut flags
|
|
//
|
|
//* first map the GPD blanks parameters to GPC
|
|
pListNode = LISTNODEPTR(pPDev->pDriverInfo,pPDev->pGlobals->liStripBlanks);
|
|
while (pListNode)
|
|
{
|
|
if (pListNode->dwData == SB_LEADING)
|
|
pRPDev->fBlockOut |= RES_BO_LEADING_BLNKS;
|
|
else if (pListNode->dwData == SB_ENCLOSED)
|
|
pRPDev->fBlockOut |= RES_BO_ENCLOSED_BLNKS;
|
|
else if (pListNode->dwData == SB_TRAILING)
|
|
pRPDev->fBlockOut |= RES_BO_TRAILING_BLNKS;
|
|
pListNode = LISTNODEPTR(pPDev->pDriverInfo,pListNode->dwNextItem);
|
|
}
|
|
// Do we need to set to uni directional printing?
|
|
//
|
|
if (pPDev->pResolutionEx->bRequireUniDir)
|
|
pRPDev->fBlockOut |= RES_BO_UNIDIR;
|
|
|
|
// Can we output multiple rows at a time?
|
|
//
|
|
if (pPDev->pGlobals->bSendMultipleRows)
|
|
pRPDev->fBlockOut |= RES_BO_MULTIPLE_ROWS;
|
|
|
|
// Set flag if we need to mirror the individual raster bytes
|
|
//
|
|
if (pPDev->pGlobals->bMirrorRasterByte)
|
|
pRPDev->fBlockOut |= RES_BO_MIRROR;
|
|
|
|
// initialize fCursor flags
|
|
//
|
|
pRPDev->fCursor = 0;
|
|
if (pGlobals->cyafterblock == CYSBD_AUTO_INCREMENT)
|
|
pRPDev->fCursor |= RES_CUR_Y_POS_AUTO;
|
|
|
|
if (pGlobals->cxafterblock == CXSBD_AT_GRXDATA_ORIGIN)
|
|
pRPDev->fCursor |= RES_CUR_X_POS_ORG;
|
|
|
|
else if (pGlobals->cxafterblock == CXSBD_AT_CURSOR_X_ORIGIN)
|
|
pRPDev->fCursor |= RES_CUR_X_POS_AT_0;
|
|
|
|
//
|
|
// check for compression modes
|
|
//
|
|
if (!pRPDev->pfnOEMFilterGraphics)
|
|
{
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_ENABLETIFF4))
|
|
{
|
|
pRPDev->fRMode |= PFR_COMP_TIFF;
|
|
}
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_ENABLEFERLE))
|
|
{
|
|
pRPDev->fRMode |= PFR_COMP_FERLE;
|
|
}
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_ENABLEDRC) &&
|
|
!pPDev->pGlobals->bSendMultipleRows &&
|
|
pRPDev->sDevPlanes == 1 && bEnoughDRCMemory(pPDev))
|
|
{
|
|
// For DRC we disable moving the left boundary
|
|
//
|
|
pRPDev->fBlockOut &= ~RES_BO_LEADING_BLNKS;
|
|
pRPDev->fDump &= ~RES_DM_LEFT_BOUND;
|
|
//
|
|
// If there is a source width command we also disable
|
|
// TRAILING blanks
|
|
//
|
|
if (pRPDev->fRMode & PFR_SENDSRCWIDTH)
|
|
pRPDev->fBlockOut &= ~RES_BO_TRAILING_BLNKS;
|
|
//
|
|
// For DRC we disable all rules
|
|
pRPDev->fRMode &= ~PFR_RECT_FILL;
|
|
|
|
pRPDev->fRMode |= PFR_COMP_DRC;
|
|
}
|
|
if (COMMANDPTR(pPDev->pDriverInfo,CMD_ENABLEOEMCOMP))
|
|
{
|
|
if (pRPDev->pfnOEMCompression)
|
|
pRPDev->fRMode |= PFR_COMP_OEM;
|
|
}
|
|
// for these compression modes it is more efficient to
|
|
// disable horizontal rules code and enclosed blanks
|
|
//
|
|
if (pRPDev->fRMode & (PFR_COMP_TIFF | PFR_COMP_DRC | PFR_COMP_FERLE))
|
|
{
|
|
pRPDev->fRMode &= ~PFR_RECT_HORIZFILL;
|
|
pRPDev->fBlockOut &= ~RES_BO_ENCLOSED_BLNKS;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//**************************************************************
|
|
BOOL
|
|
bInitColorOrder(
|
|
PDEV *pPDev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine initializes the order to print the color planes
|
|
for those devices that specify multiple plane output. It also
|
|
maps the appropriate color command for each color.
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to PDEV.
|
|
|
|
Return Value:
|
|
|
|
TRUE - for success
|
|
FALSE - for failure
|
|
|
|
--*/
|
|
|
|
{
|
|
PCOLORMODEEX pColorModeEx;
|
|
PLISTNODE pListNode;
|
|
DWORD dwIndex;
|
|
DWORD dwColorCmd;
|
|
BYTE ColorIndex;
|
|
INT dwPlanes = 0;
|
|
INT iDevNumPlanes;
|
|
PRASTERPDEV pRPDev = (PRASTERPDEV)pPDev->pRasterPDEV;
|
|
|
|
// check if structure exists
|
|
if (pPDev->pColorModeEx)
|
|
{
|
|
short sDrvBPP;
|
|
sDrvBPP = (short)pPDev->pColorModeEx->dwDrvBPP;
|
|
pRPDev->sDevBPP = (short)pPDev->pColorModeEx->dwPrinterBPP;
|
|
pRPDev->sDevPlanes = (short)pPDev->pColorModeEx->dwPrinterNumOfPlanes;
|
|
pRPDev->dwIPCallbackID = pPDev->pColorModeEx->dwIPCallbackID;
|
|
//
|
|
// calculate equivalent output pixel depth and
|
|
// test for valid formats
|
|
//
|
|
if (pRPDev->sDevPlanes == 1)
|
|
{
|
|
if (pRPDev->sDevBPP != 1 &&
|
|
pRPDev->sDevBPP != 8 &&
|
|
pRPDev->sDevBPP != 24)
|
|
{
|
|
ERR (("Unidrv: Invalid DevBPP\n"));
|
|
return FALSE;
|
|
}
|
|
pRPDev->sDrvBPP = pRPDev->sDevBPP;
|
|
}
|
|
else if ((pRPDev->sDevBPP == 1) &&
|
|
(pRPDev->sDevPlanes == 3 || pRPDev->sDevPlanes == 4))
|
|
{
|
|
pRPDev->sDrvBPP = 4;
|
|
}
|
|
#ifdef MULTIPLANE
|
|
else if ((pRPDev->sDevBPP == 2) &&
|
|
(pRPDev->sDevPlanes == 3 || pRPDev->sDevPlanes == 4))
|
|
{
|
|
pRPDev->CyanLevels = 2;
|
|
pRPDev->MagentaLevels = 2;
|
|
pRPDev->YellowLevels = 2;
|
|
pRPDev->BlackLevels = 1;
|
|
pRPDev->sDevBitsPerPlane = 2;
|
|
pRPDev->sDrvBPP = 8;
|
|
}
|
|
else if (pRPDev->sDevPlanes > 4 && pRPDev->sDevPlanes <= 8)
|
|
{
|
|
pRPDev->CyanLevels = 3;
|
|
pRPDev->MagentaLevels = 3;
|
|
pRPDev->YellowLevels = 3;
|
|
pRPDev->BlackLevels = 3;
|
|
pRPDev->sDevBitsPerPlane = 1;
|
|
pRPDev->sDrvBPP = 8;
|
|
}
|
|
#endif
|
|
else
|
|
pRPDev->sDrvBPP = 0;
|
|
|
|
// test for valid input, input must match render depth
|
|
// or there must be a callback function
|
|
//
|
|
if (pRPDev->sDrvBPP != sDrvBPP &&
|
|
(pRPDev->dwIPCallbackID == 0 ||
|
|
pRPDev->pfnOEMImageProcessing == NULL) &&
|
|
pPDev->ePersonality != kPCLXL &&
|
|
pPDev->ePersonality != kPCLXL_RASTER)
|
|
{
|
|
ERR (("Unidrv: OEMImageProcessing callback required\n"))
|
|
return FALSE;
|
|
}
|
|
//
|
|
// if color mode we need to determine the color order to
|
|
// send the different color planes
|
|
//
|
|
if (pPDev->pColorModeEx->bColor && pRPDev->sDrvBPP > 1)
|
|
{
|
|
//* Initialize 8BPP and 24BPP flags
|
|
pRPDev->sDevPlanes = (short)pPDev->pColorModeEx->dwPrinterNumOfPlanes;
|
|
if (pRPDev->sDevPlanes > 1)
|
|
{
|
|
iDevNumPlanes = pRPDev->sDevPlanes;
|
|
|
|
pListNode = LISTNODEPTR(pPDev->pDriverInfo,pPDev->pColorModeEx->liColorPlaneOrder);
|
|
while (pListNode && dwPlanes < iDevNumPlanes)
|
|
{
|
|
switch (pListNode->dwData)
|
|
{
|
|
case COLOR_CYAN:
|
|
ColorIndex = DC_PLANE_CYAN;
|
|
dwColorCmd = CMD_SENDCYANDATA;
|
|
break;
|
|
case COLOR_MAGENTA:
|
|
ColorIndex = DC_PLANE_MAGENTA;
|
|
dwColorCmd = CMD_SENDMAGENTADATA;
|
|
break;
|
|
case COLOR_YELLOW:
|
|
ColorIndex = DC_PLANE_YELLOW;
|
|
dwColorCmd = CMD_SENDYELLOWDATA;
|
|
break;
|
|
case COLOR_RED:
|
|
ColorIndex = DC_PLANE_RED;
|
|
dwColorCmd = CMD_SENDREDDATA;
|
|
pRPDev->fColorFormat |= DC_PRIMARY_RGB;
|
|
break;
|
|
case COLOR_GREEN:
|
|
ColorIndex = DC_PLANE_GREEN;
|
|
dwColorCmd = CMD_SENDGREENDATA;
|
|
pRPDev->fColorFormat |= DC_PRIMARY_RGB;
|
|
break;
|
|
case COLOR_BLUE:
|
|
ColorIndex = DC_PLANE_BLUE;
|
|
dwColorCmd = CMD_SENDBLUEDATA;
|
|
pRPDev->fColorFormat |= DC_PRIMARY_RGB;
|
|
break;
|
|
case COLOR_BLACK:
|
|
ColorIndex = DC_PLANE_BLACK;
|
|
dwColorCmd = CMD_SENDBLACKDATA;
|
|
break;
|
|
#ifdef MULTIPLANE
|
|
// TBD
|
|
#endif
|
|
default:
|
|
ERR (("Invalid ColorPlaneOrder value"));
|
|
return FALSE;
|
|
break;
|
|
}
|
|
// verify the command exists
|
|
if (COMMANDPTR(pPDev->pDriverInfo,dwColorCmd) == NULL)
|
|
return FALSE;
|
|
|
|
#ifdef MULTIPLANE
|
|
if (iDevNumPlanes >= 6)
|
|
{
|
|
pRPDev->rgbOrder[dwPlanes] = ColorIndex+4;
|
|
pRPDev->rgbCmdOrder[dwPlanes] = CMD_SENDBLACKDATA;
|
|
dwPlanes++;
|
|
}
|
|
#endif
|
|
pRPDev->rgbOrder[dwPlanes] = ColorIndex;
|
|
pRPDev->rgbCmdOrder[dwPlanes] = dwColorCmd;
|
|
dwPlanes++;
|
|
pListNode = LISTNODEPTR(pPDev->pDriverInfo,pListNode->dwNextItem);
|
|
}
|
|
// GPD must define all planes
|
|
if (dwPlanes < iDevNumPlanes)
|
|
return FALSE;
|
|
|
|
//* Determine DC_EXTRACT_BLK flag
|
|
if (iDevNumPlanes == 4)
|
|
pRPDev->fColorFormat |= DC_EXTRACT_BLK;
|
|
}
|
|
else if (pRPDev->sDevPlanes != 1)
|
|
return FALSE;
|
|
|
|
// if we have an OEM callback then it is
|
|
// responsible for black generation and data inversion
|
|
//
|
|
if (pRPDev->pfnOEMImageProcessing)
|
|
pRPDev->fColorFormat |= DC_OEM_BLACK;
|
|
|
|
pRPDev->fDump |= RES_DM_COLOR;
|
|
}
|
|
// monochrome but could have pixel depth
|
|
else {
|
|
pRPDev->sDevPlanes = 1;
|
|
pRPDev->rgbOrder[0] = DC_PLANE_BLACK;
|
|
pRPDev->rgbCmdOrder[0] = CMD_SENDBLOCKDATA;
|
|
}
|
|
}
|
|
// no ColorMode so use default: monochrome mode
|
|
else {
|
|
pRPDev->sDrvBPP = 1;
|
|
pRPDev->sDevBPP = 1;
|
|
pRPDev->sDevPlanes = 1;
|
|
pRPDev->rgbOrder[0] = DC_PLANE_BLACK;
|
|
pRPDev->rgbCmdOrder[0] = CMD_SENDBLOCKDATA;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//*************************************************
|
|
void
|
|
vSetHTData(
|
|
PDEV *pPDev,
|
|
GDIINFO *pGDIInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Fill in the halftone information required by GDI. These are filled
|
|
in from the GPD data or from default values.
|
|
|
|
Arguments:
|
|
pPDev Pointer to PDEV structure
|
|
pGDIInfo Pointer to GDIINFO structure
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
INT iPatID;
|
|
PRASTERPDEV pRPDev = pPDev->pRasterPDEV;
|
|
PHALFTONING pHalftone = pPDev->pHalftone;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD ul;
|
|
int iGenProfile;
|
|
|
|
|
|
// set to spotdiameter, if zero, GDI calculates its own value
|
|
// Set MS bit designating a percentage value * 10.
|
|
//
|
|
if (pPDev->pResolutionEx->dwSpotDiameter >= 10000)
|
|
{
|
|
pPDev->fMode |= PF_SINGLEDOT_FILTER;
|
|
pGDIInfo->ulDevicePelsDPI = ((pPDev->pResolutionEx->dwSpotDiameter - 10000) * 10) | 0x8000;
|
|
}
|
|
else
|
|
pGDIInfo->ulDevicePelsDPI = (pPDev->pResolutionEx->dwSpotDiameter * 10) | 0x8000;
|
|
|
|
// RASDD always sets this to BLACK_DYE only
|
|
// HT_FLAG_: SQUARE_DEVICE_PEL/HAS_BLACK_DYE/ADDITIVE_PRIMS/OUTPUT_CMY
|
|
//
|
|
pGDIInfo->flHTFlags = HT_FLAG_HAS_BLACK_DYE;
|
|
|
|
#ifdef MULTIPLANE
|
|
if (pRPDev->sDevBitsPerPlane)
|
|
{
|
|
pGDIInfo->flHTFlags |= MAKE_CMY332_MASK(pRPDev->CyanLevels,
|
|
pRPDev->MagentaLevels,
|
|
pRPDev->YellowLevels);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// For 16 and 24bpp devices GDI will not do device color
|
|
// mapping unless this flag is set in the GPD
|
|
//
|
|
#ifndef WINNT_40
|
|
if (pPDev->pGlobals->bEnableGDIColorMapping)
|
|
pGDIInfo->flHTFlags |= HT_FLAG_DO_DEVCLR_XFORM;
|
|
if (pPDev->pdmPrivate->iQuality != QS_BEST &&
|
|
!(pPDev->pdmPrivate->dwFlags & DXF_TEXTASGRAPHICS))
|
|
{
|
|
pGDIInfo->flHTFlags |= HT_FLAG_PRINT_DRAFT_MODE;
|
|
}
|
|
#endif
|
|
// At this point we need to determine the halftoning pattern
|
|
// to be utilized depending on whether this is a standard halftone
|
|
// custom halftone or oem supplied dither method
|
|
//
|
|
|
|
// if standard halftone ID map to standard pattern size values
|
|
//
|
|
#ifndef WINNT_40
|
|
if (!pHalftone || pHalftone->dwHTID == HT_PATSIZE_AUTO)
|
|
{
|
|
if (pPDev->sBitsPixel == 1)
|
|
iPatID = PickDefaultHTPatSize((DWORD)pGDIInfo->ulLogPixelsX,
|
|
(DWORD)pGDIInfo->ulLogPixelsY);
|
|
else if (pPDev->sBitsPixel == 8)
|
|
iPatID = HT_PATSIZE_4x4_M;
|
|
|
|
else if (pPDev->sBitsPixel >= 24)
|
|
iPatID = HT_PATSIZE_8x8_M;
|
|
|
|
else
|
|
iPatID = HT_PATSIZE_SUPERCELL_M;
|
|
}
|
|
else if (pHalftone->dwHTID <= HT_PATSIZE_MAX_INDEX)
|
|
{
|
|
iPatID = pHalftone->dwHTID;
|
|
}
|
|
else
|
|
{
|
|
iPatID = HT_PATSIZE_USER;
|
|
}
|
|
#else
|
|
if (!pHalftone || pHalftone->dwHTID == HT_PATSIZE_AUTO || pHalftone->dwHTID > HT_PATSIZE_MAX_INDEX)
|
|
{
|
|
if (pPDev->sBitsPixel == 8)
|
|
iPatID = HT_PATSIZE_4x4_M;
|
|
|
|
else if (pPDev->sBitsPixel == 4 && pGDIInfo->ulLogPixelsX < 400)
|
|
iPatID = HT_PATSIZE_6x6_M;
|
|
|
|
else
|
|
iPatID = PickDefaultHTPatSize((DWORD)pGDIInfo->ulLogPixelsX,
|
|
(DWORD)pGDIInfo->ulLogPixelsY);
|
|
}
|
|
else
|
|
iPatID = pHalftone->dwHTID;
|
|
#endif
|
|
//
|
|
// setup ciDevice to point to default color space based
|
|
// on halftone method and render depth
|
|
//
|
|
// 22-Jan-1998 Thu 01:17:54 updated -by- Daniel Chou (danielc)
|
|
// for saving the data, we will assume gamma 1.0 and has dye correction to
|
|
// start with then modify as necessary
|
|
//
|
|
|
|
pGDIInfo->ciDevice = DefColorInfoLinear;
|
|
|
|
if (pPDev->sBitsPixel >= 24 && pRPDev->pfnOEMImageProcessing)
|
|
{
|
|
|
|
//
|
|
// No dye correction and the gamma is linear 1.0
|
|
//
|
|
|
|
ZeroMemory(&(pGDIInfo->ciDevice.MagentaInCyanDye),
|
|
sizeof(LDECI4) * 6);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
LDECI4 Gamma;
|
|
|
|
|
|
if (pPDev->sBitsPixel >= 8) {
|
|
|
|
Gamma = GAMMA_DEVICE_HT;
|
|
|
|
}
|
|
#ifndef WINNT_40
|
|
else if ((iPatID == HT_PATSIZE_SUPERCELL) ||
|
|
(iPatID == HT_PATSIZE_SUPERCELL_M))
|
|
{
|
|
Gamma = GAMMA_SUPERCELL;
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
Gamma = GAMMA_DITHER;
|
|
}
|
|
|
|
pGDIInfo->ciDevice.RedGamma =
|
|
pGDIInfo->ciDevice.GreenGamma =
|
|
pGDIInfo->ciDevice.BlueGamma = Gamma;
|
|
}
|
|
|
|
//
|
|
// If this flag is set in the registry we inform GDI halftoning
|
|
// to ignore all color settings and pass data through raw
|
|
// for calibration purposes
|
|
//
|
|
if( !EngGetPrinterData( pPDev->devobj.hPrinter, L"ICMGenProfile", &dwType,
|
|
(BYTE *)&iGenProfile, sizeof(iGenProfile), &ul ) &&
|
|
ul == sizeof(iGenProfile) && iGenProfile == 1 )
|
|
{
|
|
pGDIInfo->ciDevice.RedGamma =
|
|
pGDIInfo->ciDevice.GreenGamma =
|
|
pGDIInfo->ciDevice.BlueGamma = GAMMA_GEN_PROFILE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// now modify with any GPD parameters
|
|
//
|
|
if ((int)pPDev->pResolutionEx->dwRedDeviceGamma >= 0)
|
|
pGDIInfo->ciDevice.RedGamma = pPDev->pResolutionEx->dwRedDeviceGamma;
|
|
if ((int)pPDev->pResolutionEx->dwGreenDeviceGamma >= 0)
|
|
pGDIInfo->ciDevice.GreenGamma = pPDev->pResolutionEx->dwGreenDeviceGamma;
|
|
if ((int)pPDev->pResolutionEx->dwBlueDeviceGamma >= 0)
|
|
pGDIInfo->ciDevice.BlueGamma = pPDev->pResolutionEx->dwBlueDeviceGamma;
|
|
if ((int)pPDev->pGlobals->dwMagentaInCyanDye >= 0)
|
|
pGDIInfo->ciDevice.MagentaInCyanDye = pPDev->pGlobals->dwMagentaInCyanDye;
|
|
if ((int)pPDev->pGlobals->dwYellowInCyanDye >= 0)
|
|
pGDIInfo->ciDevice.YellowInCyanDye = pPDev->pGlobals->dwYellowInCyanDye;
|
|
if ((int)pPDev->pGlobals->dwCyanInMagentaDye >= 0)
|
|
pGDIInfo->ciDevice.CyanInMagentaDye = pPDev->pGlobals->dwCyanInMagentaDye;
|
|
if ((int)pPDev->pGlobals->dwYellowInMagentaDye >= 0)
|
|
pGDIInfo->ciDevice.YellowInMagentaDye = pPDev->pGlobals->dwYellowInMagentaDye;
|
|
if ((int)pPDev->pGlobals->dwCyanInYellowDye >= 0)
|
|
pGDIInfo->ciDevice.CyanInYellowDye = pPDev->pGlobals->dwCyanInYellowDye;
|
|
if ((int)pPDev->pGlobals->dwMagentaInYellowDye >= 0)
|
|
pGDIInfo->ciDevice.MagentaInYellowDye = pPDev->pGlobals->dwMagentaInYellowDye;
|
|
}
|
|
//
|
|
// test for a custom pattern
|
|
//
|
|
#ifndef WINNT_40
|
|
if (iPatID == HT_PATSIZE_USER)
|
|
{
|
|
DWORD dwX,dwY,dwPats,dwRC,dwCallbackID,dwPatSize,dwOnePatSize;
|
|
int iSize = 0;
|
|
PBYTE pRes = NULL;
|
|
|
|
dwX = pHalftone->HalftonePatternSize.x;
|
|
dwY = pHalftone->HalftonePatternSize.y;
|
|
dwRC = pHalftone->dwRCpatternID;
|
|
|
|
pGDIInfo->ulHTPatternSize = HT_PATSIZE_DEFAULT;
|
|
|
|
if (dwX < HT_USERPAT_CX_MIN || dwX > HT_USERPAT_CX_MAX ||
|
|
dwY < HT_USERPAT_CY_MIN || dwY > HT_USERPAT_CY_MAX)
|
|
{
|
|
ERR (("Unidrv!RMInit: Missing or invalid custom HT size\n"));
|
|
return;
|
|
}
|
|
dwPats = pHalftone->dwHTNumPatterns;
|
|
dwCallbackID = pHalftone->dwHTCallbackID;
|
|
|
|
// calculate the size of the halftone pattern
|
|
//
|
|
dwOnePatSize = ((dwX * dwY) + 3) & ~3;
|
|
dwPatSize = dwOnePatSize * dwPats;
|
|
|
|
// test for resource ID which means the pattern is
|
|
// in the resource dll.
|
|
//
|
|
if (dwRC > 0)
|
|
{
|
|
RES_ELEM ResInfo;
|
|
if (!BGetWinRes(&pPDev->WinResData,(PQUALNAMEEX)&dwRC,RC_HTPATTERN,&ResInfo))
|
|
{
|
|
ERR (("Unidrv!RMInit: Can't find halftone resource\n"));
|
|
return;
|
|
}
|
|
else if ((DWORD)ResInfo.iResLen < dwPatSize && dwCallbackID <= 0)
|
|
{
|
|
ERR (("Unidrv!RMInit: Invalid resource size\n"));
|
|
return;
|
|
}
|
|
pRes = ResInfo.pvResData;
|
|
iSize = ResInfo.iResLen;
|
|
}
|
|
else if (dwCallbackID <= 0)
|
|
{
|
|
ERR (("Unidrv!RMInit: no OEMHalftonePattern callback ID\n"));
|
|
return;
|
|
}
|
|
//
|
|
// test whether we need to make the OEMHalftonePattern callback
|
|
// this will either unencrypt the resource pattern or it will
|
|
// generate a halftone pattern on the fly.
|
|
//
|
|
if (dwCallbackID > 0)
|
|
{
|
|
PBYTE pPattern;
|
|
// allocate memory for the callback
|
|
//
|
|
if ((pPattern = MemAllocZ(dwPatSize)) != NULL)
|
|
{
|
|
BOOL bStatus = FALSE;
|
|
|
|
FIX_DEVOBJ(pPDev,EP_OEMHalftonePattern);
|
|
|
|
|
|
if (pRPDev->pfnOEMHalftonePattern)
|
|
{
|
|
if(pPDev->pOemEntry)
|
|
{
|
|
if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
|
|
{
|
|
HRESULT hr ;
|
|
hr = HComHalftonePattern((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
|
|
(PDEVOBJ)pPDev,pPattern,dwX,dwY,dwPats,dwCallbackID,pRes,iSize) ;
|
|
if(SUCCEEDED(hr))
|
|
bStatus = TRUE ; // cool !
|
|
}
|
|
else
|
|
{
|
|
bStatus = pRPDev->pfnOEMHalftonePattern((PDEVOBJ)pPDev,pPattern,dwX,dwY,dwPats,dwCallbackID,pRes,iSize) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if(!bStatus)
|
|
{
|
|
MemFree (pPattern);
|
|
ERR (("\nUnidrv!RMInit: Failed OEMHalftonePattern call\n"));
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
pRes = pPattern;
|
|
pRPDev->pHalftonePattern = pPattern;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERR (("\nUnidrv!RMInit: Failed Custom Halftone MemAlloc\n"));
|
|
return;
|
|
}
|
|
}
|
|
//
|
|
// if we still have a valid custom pattern we will now
|
|
// update the GDIINFO structure
|
|
//
|
|
pGDIInfo->cxHTPat = dwX;
|
|
pGDIInfo->cyHTPat = dwY;
|
|
pGDIInfo->pHTPatA = pRes;
|
|
if (dwPats == 3)
|
|
{
|
|
pGDIInfo->pHTPatB = &pRes[dwOnePatSize];
|
|
pGDIInfo->pHTPatC = &pRes[dwOnePatSize*2];
|
|
}
|
|
else {
|
|
pGDIInfo->pHTPatB = pRes;
|
|
pGDIInfo->pHTPatC = pRes;
|
|
}
|
|
}
|
|
#endif
|
|
pGDIInfo->ulHTPatternSize = iPatID;
|
|
return;
|
|
}
|
|
//*************************************************************
|
|
DWORD
|
|
PickDefaultHTPatSize(
|
|
DWORD xDPI,
|
|
DWORD yDPI
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function return default halftone pattern size used for
|
|
a particular device resolution
|
|
|
|
Arguments:
|
|
|
|
xDPI - Device LOGPIXELS X
|
|
|
|
yDPI - Device LOGPIXELS Y
|
|
|
|
Return Value:
|
|
|
|
DWORD HT_PATSIZE_xxxx
|
|
|
|
--*/
|
|
{
|
|
DWORD HTPatSize;
|
|
|
|
//
|
|
// use the smaller resolution as the pattern guide
|
|
//
|
|
|
|
if (xDPI > yDPI)
|
|
xDPI = yDPI;
|
|
|
|
if (xDPI >= 2400)
|
|
HTPatSize = HT_PATSIZE_16x16_M;
|
|
|
|
else if (xDPI >= 1800)
|
|
HTPatSize = HT_PATSIZE_14x14_M;
|
|
|
|
else if (xDPI >= 1200)
|
|
HTPatSize = HT_PATSIZE_12x12_M;
|
|
|
|
else if (xDPI >= 800)
|
|
HTPatSize = HT_PATSIZE_10x10_M;
|
|
|
|
else if (xDPI >= 300)
|
|
HTPatSize = HT_PATSIZE_8x8_M;
|
|
|
|
else
|
|
HTPatSize = HT_PATSIZE_6x6_M;
|
|
|
|
return(HTPatSize);
|
|
}
|
|
//*************************************************************
|
|
BOOL
|
|
bEnoughDRCMemory(
|
|
PDEV *pPDev
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function determines whether the device has sufficient
|
|
memory to enable DRC compression.
|
|
|
|
Arguments:
|
|
|
|
pPDev - pointer to PDEV structure
|
|
|
|
Return Value:
|
|
|
|
TRUE if sufficient memory, else FALSE
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// if this is a page printer then we will require that there be enough
|
|
// free memory to store the entire raster page at 1bpp
|
|
//
|
|
if (pPDev->pGlobals->printertype != PT_PAGE ||
|
|
!(COMMANDPTR(pPDev->pDriverInfo,CMD_DISABLECOMPRESSION)) ||
|
|
(pPDev->pMemOption && (int)pPDev->pMemOption->dwInstalledMem >
|
|
(pPDev->sf.szImageAreaG.cx * pPDev->sf.szImageAreaG.cy >> 3)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
VERBOSE (("Unidrv: Insufficient memory for DRC\n"));
|
|
return FALSE;
|
|
}
|
|
#ifndef DISABLE_NEWRULES
|
|
//*************************************************************
|
|
VOID
|
|
OutputRules(
|
|
PDEV *pPDev
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function outputs any rules that still remain after rendering
|
|
the current band or page.
|
|
|
|
Arguments:
|
|
|
|
pPDev - pointer to PDEV structure
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
if (pPDev->pbRulesArray && pPDev->dwRulesCount)
|
|
{
|
|
PRECTL pRect;
|
|
DWORD i;
|
|
DRAWPATRECT PatRect;
|
|
PatRect.wStyle = 0; // black rectangle
|
|
PatRect.wPattern = 0; // pattern not used
|
|
|
|
// DbgPrint("Black rules = %u\n",pPDev->dwRulesCount);
|
|
|
|
for (i = 0;i < pPDev->dwRulesCount;i++)
|
|
{
|
|
pRect = &pPDev->pbRulesArray[i];
|
|
PatRect.ptPosition.x = pRect->left;
|
|
PatRect.ptPosition.y = pRect->top;
|
|
PatRect.ptSize.x = pRect->right - pRect->left;
|
|
PatRect.ptSize.y = pRect->bottom - pRect->top;
|
|
if (pPDev->fMode & PF_SINGLEDOT_FILTER)
|
|
{
|
|
if (PatRect.ptSize.y < 2)
|
|
PatRect.ptSize.y = 2;
|
|
if (PatRect.ptSize.x < 2)
|
|
PatRect.ptSize.x = 2;
|
|
}
|
|
DrawPatternRect(pPDev,&PatRect);
|
|
}
|
|
pPDev->dwRulesCount = 0;
|
|
}
|
|
}
|
|
#endif
|
|
//*************************************************************
|
|
VOID
|
|
EnableMirroring(
|
|
PDEV *pPDev,
|
|
SURFOBJ *pso
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function mirrors the data in the current band or page.
|
|
|
|
Arguments:
|
|
|
|
pPDev - pointer to PDEV structure
|
|
pso - pointer to SURFOBJ structure containing the bitmap
|
|
|
|
Return Value:
|
|
|
|
none
|
|
|
|
--*/
|
|
{
|
|
INT iScanLine;
|
|
INT iLastY;
|
|
INT i;
|
|
|
|
// if the surface hasn't been used then no point in mirroring it
|
|
//
|
|
if (!(pPDev->fMode & PF_SURFACE_USED))
|
|
return;
|
|
|
|
// precalculate necessary shared loop parameters
|
|
//
|
|
iScanLine = (((pso->sizlBitmap.cx * pPDev->sBitsPixel) + 31) & ~31) / BBITS;
|
|
iLastY = pPDev->rcClipRgn.bottom - pPDev->rcClipRgn.top;
|
|
|
|
// First test whether we need to do landscape mirroring
|
|
// If so we will mirror the data top to bottom by swapping scan lines
|
|
//
|
|
if (pPDev->pOrientation && pPDev->pOrientation->dwRotationAngle != ROTATE_NONE)
|
|
{
|
|
BYTE ubWhite;
|
|
INT iTmpLastY = iLastY;
|
|
|
|
// determined erase byte
|
|
//
|
|
if (pPDev->sBitsPixel == 4)
|
|
ubWhite = 0x77;
|
|
else if (pPDev->sBitsPixel == 8)
|
|
ubWhite = (BYTE)((PAL_DATA*)(pPDev->pPalData))->iWhiteIndex;
|
|
else
|
|
ubWhite = 0xff;
|
|
|
|
// loop once per scan line swapping the rows
|
|
//
|
|
iLastY--;
|
|
for (i = 0;i < iLastY;i++,iLastY--)
|
|
{
|
|
BYTE *pBits1,*pBits2;
|
|
|
|
pBits1 = (PBYTE)pso->pvBits + (iScanLine * i);
|
|
pBits2 = (PBYTE)pso->pvBits + (iScanLine * iLastY);
|
|
|
|
// test if bottom line has data
|
|
//
|
|
if (pPDev->pbRasterScanBuf[iLastY / LINESPERBLOCK] & 1)
|
|
{
|
|
// test if top line has data, if so swap data
|
|
//
|
|
if (pPDev->pbRasterScanBuf[i / LINESPERBLOCK] & 1)
|
|
{
|
|
INT j = iScanLine >> 2;
|
|
do {
|
|
DWORD dwTmp = ((DWORD *)pBits1)[j];
|
|
((DWORD *)pBits1)[j] = ((DWORD *)pBits2)[j];
|
|
((DWORD *)pBits2)[j] = dwTmp;
|
|
} while (--j > 0);
|
|
}
|
|
else
|
|
{
|
|
CopyMemory(pBits1,pBits2,iScanLine);
|
|
FillMemory(pBits2,iScanLine,ubWhite);
|
|
}
|
|
}
|
|
// test if top line has data
|
|
//
|
|
else if (pPDev->pbRasterScanBuf[i / LINESPERBLOCK] & 1)
|
|
{
|
|
CopyMemory(pBits2,pBits1,iScanLine);
|
|
FillMemory(pBits1,iScanLine,ubWhite);
|
|
}
|
|
// neither scan line has data but we need to erase both anyway
|
|
//
|
|
else
|
|
{
|
|
FillMemory(pBits1,iScanLine,ubWhite);
|
|
FillMemory(pBits2,iScanLine,ubWhite);
|
|
}
|
|
|
|
}
|
|
// set all bits since everything has been erased
|
|
for (i = 0;i < iTmpLastY;i += LINESPERBLOCK)
|
|
{
|
|
pPDev->pbRasterScanBuf[i / LINESPERBLOCK] = 1;
|
|
}
|
|
}
|
|
//
|
|
// We are doing portrait mirroring, test for 1bpp
|
|
//
|
|
else if (pPDev->sBitsPixel == 1)
|
|
{
|
|
BYTE ubMirror[256];
|
|
INT iLastX;
|
|
INT iShift;
|
|
|
|
// create byte mirroring table
|
|
//
|
|
for (i = 0;i < 256;i++)
|
|
{
|
|
BYTE bOut = 0;
|
|
if (i & 0x01) bOut |= 0x80;
|
|
if (i & 0x02) bOut |= 0x40;
|
|
if (i & 0x04) bOut |= 0x20;
|
|
if (i & 0x08) bOut |= 0x10;
|
|
if (i & 0x10) bOut |= 0x08;
|
|
if (i & 0x20) bOut |= 0x04;
|
|
if (i & 0x40) bOut |= 0x02;
|
|
if (i & 0x80) bOut |= 0x01;
|
|
ubMirror[i] = bOut;
|
|
}
|
|
// create shift value to re-align data
|
|
//
|
|
iShift = (8 - (pso->sizlBitmap.cx & 0x7)) & 0x7;
|
|
|
|
// loop once per scan line and mirror left to right
|
|
//
|
|
for (i = 0;i < iLastY;i++)
|
|
{
|
|
BYTE *pBits = (PBYTE)pso->pvBits + (iScanLine * i);
|
|
if (pPDev->pbRasterScanBuf[i / LINESPERBLOCK])
|
|
{
|
|
INT j;
|
|
INT iLastX;
|
|
|
|
// test whether we need to pre-shift the data
|
|
//
|
|
if (iShift)
|
|
{
|
|
iLastX = (pso->sizlBitmap.cx + 7) / 8;
|
|
iLastX--;
|
|
while (iLastX > 0)
|
|
{
|
|
pBits[iLastX] = (pBits[iLastX-1] << (8-iShift)) | (pBits[iLastX] >> iShift);
|
|
iLastX--;
|
|
}
|
|
pBits[0] = (BYTE)(pBits[0] >> iShift);
|
|
}
|
|
// Now we are ready to mirror the bytes
|
|
//
|
|
j = 0;
|
|
iLastX = (pso->sizlBitmap.cx + 7) / 8;
|
|
while (j < iLastX)
|
|
{
|
|
BYTE ubTmp;
|
|
iLastX--;
|
|
ubTmp = ubMirror[pBits[iLastX]];
|
|
pBits[iLastX] = ubMirror[pBits[j]];
|
|
pBits[j] = ubTmp;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// We are doing portrait mirroring, test for 4bpp
|
|
//
|
|
else if (pPDev->sBitsPixel == 4)
|
|
{
|
|
BYTE ubMirror[256];
|
|
|
|
// create byte mirroring table
|
|
//
|
|
for (i = 0;i < 256;i++)
|
|
{
|
|
ubMirror[i] = ((BYTE)i << 4) | ((BYTE)i >> 4);
|
|
}
|
|
// loop once per scan line and mirror left to right
|
|
//
|
|
for (i = 0;i < iLastY;i++)
|
|
{
|
|
BYTE *pBits = (PBYTE)pso->pvBits + (iScanLine * i);
|
|
if (pPDev->pbRasterScanBuf[i / LINESPERBLOCK])
|
|
{
|
|
INT j = 0;
|
|
INT iLastX = (pso->sizlBitmap.cx + 1) / 2;
|
|
while (j < iLastX)
|
|
{
|
|
BYTE ubTmp;
|
|
iLastX--;
|
|
ubTmp = ubMirror[pBits[iLastX]];
|
|
pBits[iLastX] = ubMirror[pBits[j]];
|
|
pBits[j] = ubTmp;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// We are doing portrait mirroring, test for 8bpp
|
|
//
|
|
else if (pPDev->sBitsPixel == 8)
|
|
{
|
|
// loop once per scan line and mirror left to right
|
|
//
|
|
for (i = 0;i < iLastY;i++)
|
|
{
|
|
BYTE *pBits = (PBYTE)pso->pvBits + (iScanLine * i);
|
|
if (pPDev->pbRasterScanBuf[i / LINESPERBLOCK])
|
|
{
|
|
INT j = 0;
|
|
INT iLastX = pso->sizlBitmap.cx - 1;
|
|
while (j < iLastX)
|
|
{
|
|
BYTE ubTmp = pBits[iLastX];
|
|
pBits[iLastX] = pBits[j];
|
|
pBits[j] = ubTmp;
|
|
iLastX--;
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// We are doing portrait mirroring, 24bpp
|
|
//
|
|
else
|
|
{
|
|
// loop once per scan line and mirror left to right
|
|
//
|
|
for (i = 0;i < iLastY;i++)
|
|
{
|
|
BYTE *pBits = (PBYTE)pso->pvBits + (iScanLine * i);
|
|
if (pPDev->pbRasterScanBuf[i / LINESPERBLOCK])
|
|
{
|
|
INT j = 0;
|
|
INT iLastX = (pso->sizlBitmap.cx * 3) - 3;
|
|
while (j < iLastX)
|
|
{
|
|
BYTE ubTmp[3];
|
|
memcpy(&ubTmp[0],&pBits[iLastX],3);
|
|
memcpy(&pBits[iLastX],&pBits[j],3);
|
|
memcpy(&pBits[j],&ubTmp,3);
|
|
iLastX -= 3;
|
|
j += 3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//*************************************************************
|
|
PDWORD
|
|
pSetupOEMImageProcessing(
|
|
PDEV *pPDev,
|
|
SURFOBJ *pso
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes all the relevant parameters and then
|
|
calls the OEMImageProcessing function.
|
|
|
|
Arguments:
|
|
|
|
pPDev - pointer to PDEV structure
|
|
pso - pointer to SURFOBJ structure
|
|
pptl - pointer to current position of band
|
|
|
|
Return Value:
|
|
|
|
Pointer to modified bitmap if any
|
|
|
|
--*/
|
|
{
|
|
#ifndef DISABLE_SUBBANDS
|
|
BITMAPINFOHEADER bmi;
|
|
IPPARAMS State;
|
|
RASTERPDEV *pRPDev;
|
|
PBYTE pbResult = NULL ;
|
|
INT iStart, iEnd ,iScanLine, iLastY;
|
|
|
|
pRPDev = pPDev->pRasterPDEV;
|
|
|
|
//
|
|
// initialize the state structure
|
|
//
|
|
State.dwSize = sizeof (IPPARAMS);
|
|
State.bBanding = pPDev->bBanding;
|
|
//
|
|
// Determine the pointer to the halftone option name
|
|
//
|
|
if (pPDev->pHalftone)
|
|
{
|
|
State.pHalftoneOption =
|
|
OFFSET_TO_POINTER(pPDev->pDriverInfo->pubResourceData,
|
|
pPDev->pHalftone->GenericOption.loKeywordName);
|
|
}
|
|
else
|
|
State.pHalftoneOption = NULL;
|
|
|
|
//
|
|
// Set blank band flag if this band hasn't been erased or
|
|
// drawn on.
|
|
if ((pPDev->fMode & PF_SURFACE_USED) &&
|
|
((pPDev->fMode & PF_ROTATE) ||
|
|
(pRPDev->sDrvBPP != 0) ||
|
|
((LINESPERBLOCK % pRPDev->sNPins) != 0)))
|
|
{
|
|
CheckBitmapSurface(pso, NULL);
|
|
}
|
|
|
|
//
|
|
// loop once per strip
|
|
//
|
|
iScanLine = (((pso->sizlBitmap.cx * pPDev->sBitsPixel) + 31) & ~31) / BBITS;
|
|
iLastY = pPDev->rcClipRgn.bottom - pPDev->rcClipRgn.top;
|
|
|
|
if(pPDev->iBandDirection == SW_UP)
|
|
{
|
|
iStart = iLastY;
|
|
do
|
|
{
|
|
// search for contiguous sub-bands of white or non-white
|
|
//
|
|
PBYTE pBits;
|
|
BYTE Mode;
|
|
|
|
iEnd = iStart ;
|
|
iStart = ((iEnd - 1)/ LINESPERBLOCK) * LINESPERBLOCK ;
|
|
|
|
// first band (end of bitmap) may be partial.
|
|
|
|
Mode = pPDev->pbRasterScanBuf[iStart / LINESPERBLOCK];
|
|
while (iStart) // not yet at start of bitmap
|
|
{
|
|
int iPreview = iStart - LINESPERBLOCK;
|
|
|
|
if (Mode != pPDev->pbRasterScanBuf[iPreview / LINESPERBLOCK])
|
|
break;
|
|
iStart = iPreview ;
|
|
}
|
|
|
|
// initialize starting position of the sub-band
|
|
//
|
|
State.ptOffset.x = pPDev->rcClipRgn.left;
|
|
State.ptOffset.y = pPDev->rcClipRgn.top + iStart;
|
|
|
|
// test whether to set blank flag
|
|
//
|
|
if (Mode)
|
|
State.bBlankBand = FALSE;
|
|
else
|
|
State.bBlankBand = TRUE;
|
|
|
|
//
|
|
// initialize the bitmapinfo structure
|
|
//
|
|
bmi.biSize = sizeof (BITMAPINFOHEADER);
|
|
bmi.biWidth = pso->sizlBitmap.cx;
|
|
bmi.biHeight = iEnd - iStart;
|
|
bmi.biPlanes = 1;
|
|
bmi.biBitCount = pPDev->sBitsPixel;
|
|
bmi.biSizeImage = iScanLine * bmi.biHeight;
|
|
bmi.biCompression = BI_RGB;
|
|
bmi.biXPelsPerMeter = pPDev->ptGrxRes.x;
|
|
bmi.biYPelsPerMeter = pPDev->ptGrxRes.y;
|
|
bmi.biClrUsed = 0;
|
|
bmi.biClrImportant = 0;
|
|
|
|
// update the bitmap pointer
|
|
//
|
|
pBits = (PBYTE)pso->pvBits + (iScanLine * iStart);
|
|
|
|
// update the pPDev pointer for this callback
|
|
//
|
|
FIX_DEVOBJ(pPDev,EP_OEMImageProcessing);
|
|
|
|
if(pPDev->pOemEntry)
|
|
{
|
|
if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
|
|
{
|
|
HRESULT hr ;
|
|
hr = HComImageProcessing((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
|
|
(PDEVOBJ)pPDev,
|
|
pBits,
|
|
&bmi,
|
|
(PBYTE)&((PAL_DATA *)(pPDev->pPalData))->ulPalCol[0],
|
|
pRPDev->dwIPCallbackID,
|
|
&State, &pbResult);
|
|
if(SUCCEEDED(hr))
|
|
; // cool !
|
|
}
|
|
else
|
|
{
|
|
pbResult = pRPDev->pfnOEMImageProcessing(
|
|
(PDEVOBJ)pPDev,
|
|
pBits,
|
|
&bmi,
|
|
(PBYTE)&((PAL_DATA *)(pPDev->pPalData))->ulPalCol[0],
|
|
pRPDev->dwIPCallbackID,
|
|
&State);
|
|
}
|
|
if (pbResult == NULL)
|
|
{
|
|
#if DBG
|
|
DbgPrint ("unidrv!ImageProcessing: OEMImageProcessing returned error\n");
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
} while (iStart /* iEnd < iLastY */);
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
iEnd = 0;
|
|
do
|
|
{
|
|
// search for contiguous sub-bands of white or non-white
|
|
//
|
|
PBYTE pBits;
|
|
BYTE Mode;
|
|
iStart = iEnd;
|
|
Mode = pPDev->pbRasterScanBuf[iEnd / LINESPERBLOCK];
|
|
while (1)
|
|
{
|
|
iEnd += LINESPERBLOCK;
|
|
if (iEnd >= iLastY)
|
|
break;
|
|
if (Mode != pPDev->pbRasterScanBuf[iEnd / LINESPERBLOCK])
|
|
break;
|
|
}
|
|
//
|
|
// limit this section to the end of the band
|
|
//
|
|
if (iEnd > iLastY)
|
|
iEnd = iLastY;
|
|
|
|
// initialize starting position of the sub-band
|
|
//
|
|
State.ptOffset.x = pPDev->rcClipRgn.left;
|
|
State.ptOffset.y = pPDev->rcClipRgn.top + iStart;
|
|
|
|
// test whether to set blank flag
|
|
//
|
|
if (Mode)
|
|
State.bBlankBand = FALSE;
|
|
else
|
|
State.bBlankBand = TRUE;
|
|
|
|
//
|
|
// initialize the bitmapinfo structure
|
|
//
|
|
bmi.biSize = sizeof (BITMAPINFOHEADER);
|
|
bmi.biWidth = pso->sizlBitmap.cx;
|
|
bmi.biHeight = iEnd - iStart;
|
|
bmi.biPlanes = 1;
|
|
bmi.biBitCount = pPDev->sBitsPixel;
|
|
bmi.biSizeImage = iScanLine * bmi.biHeight;
|
|
bmi.biCompression = BI_RGB;
|
|
bmi.biXPelsPerMeter = pPDev->ptGrxRes.x;
|
|
bmi.biYPelsPerMeter = pPDev->ptGrxRes.y;
|
|
bmi.biClrUsed = 0;
|
|
bmi.biClrImportant = 0;
|
|
|
|
// update the bitmap pointer
|
|
//
|
|
pBits = (PBYTE)pso->pvBits + (iScanLine * iStart);
|
|
|
|
// update the pPDev pointer for this callback
|
|
//
|
|
FIX_DEVOBJ(pPDev,EP_OEMImageProcessing);
|
|
|
|
if(pPDev->pOemEntry)
|
|
{
|
|
if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
|
|
{
|
|
HRESULT hr ;
|
|
hr = HComImageProcessing((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
|
|
(PDEVOBJ)pPDev,
|
|
pBits,
|
|
&bmi,
|
|
(PBYTE)&((PAL_DATA *)(pPDev->pPalData))->ulPalCol[0],
|
|
pRPDev->dwIPCallbackID,
|
|
&State, &pbResult);
|
|
if(SUCCEEDED(hr))
|
|
; // cool !
|
|
}
|
|
else
|
|
{
|
|
pbResult = pRPDev->pfnOEMImageProcessing(
|
|
(PDEVOBJ)pPDev,
|
|
pBits,
|
|
&bmi,
|
|
(PBYTE)&((PAL_DATA *)(pPDev->pPalData))->ulPalCol[0],
|
|
pRPDev->dwIPCallbackID,
|
|
&State);
|
|
}
|
|
if (pbResult == NULL)
|
|
{
|
|
#if DBG
|
|
DbgPrint ("unidrv!ImageProcessing: OEMImageProcessing returned error\n");
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
} while (iEnd < iLastY);
|
|
}
|
|
#else
|
|
BITMAPINFOHEADER bmi;
|
|
IPPARAMS State;
|
|
RASTERPDEV *pRPDev;
|
|
PBYTE pbResult = NULL ;
|
|
|
|
pRPDev = pPDev->pRasterPDEV;
|
|
|
|
//
|
|
// initialize the state structure
|
|
//
|
|
State.dwSize = sizeof (IPPARAMS);
|
|
State.bBanding = pPDev->bBanding;
|
|
//
|
|
// Determine the pointer to the halftone option name
|
|
//
|
|
if (pPDev->pHalftone)
|
|
{
|
|
State.pHalftoneOption =
|
|
OFFSET_TO_POINTER(pPDev->pDriverInfo->pubResourceData,
|
|
pPDev->pHalftone->GenericOption.loKeywordName);
|
|
}
|
|
else
|
|
State.pHalftoneOption = NULL;
|
|
|
|
//
|
|
// Set blank band flag if this band hasn't been erased or
|
|
// drawn on.
|
|
if (pPDev->fMode & PF_SURFACE_USED)
|
|
{
|
|
CheckBitmapSurface(pso, NULL);
|
|
State.bBlankBand = FALSE;
|
|
}
|
|
else
|
|
State.bBlankBand = TRUE;
|
|
|
|
// initialize starting position of the band
|
|
//
|
|
State.ptOffset.x = pPDev->rcClipRgn.left;
|
|
State.ptOffset.y = pPDev->rcClipRgn.top;
|
|
//
|
|
// initialize the bitmapinfo structure
|
|
//
|
|
bmi.biSize = sizeof (BITMAPINFOHEADER);
|
|
bmi.biWidth = pso->sizlBitmap.cx;
|
|
bmi.biHeight = pso->sizlBitmap.cy;
|
|
bmi.biPlanes = 1;
|
|
bmi.biBitCount = pPDev->sBitsPixel;
|
|
bmi.biCompression = BI_RGB;
|
|
bmi.biSizeImage = (((bmi.biWidth * bmi.biBitCount) + 31) & ~31) *
|
|
bmi.biHeight;
|
|
bmi.biXPelsPerMeter = pPDev->ptGrxRes.x;
|
|
bmi.biYPelsPerMeter = pPDev->ptGrxRes.y;
|
|
bmi.biClrUsed = 0;
|
|
bmi.biClrImportant = 0;
|
|
|
|
// update the pPDev pointer for this callback
|
|
//
|
|
FIX_DEVOBJ(pPDev,EP_OEMImageProcessing);
|
|
|
|
if(pPDev->pOemEntry)
|
|
{
|
|
if(((POEM_PLUGIN_ENTRY)pPDev->pOemEntry)->pIntfOem ) // OEM plug in uses COM and function is implemented.
|
|
{
|
|
HRESULT hr ;
|
|
hr = HComImageProcessing((POEM_PLUGIN_ENTRY)pPDev->pOemEntry,
|
|
(PDEVOBJ)pPDev,
|
|
pso->pvBits,
|
|
&bmi,
|
|
(PBYTE)&((PAL_DATA *)(pPDev->pPalData))->ulPalCol[0],
|
|
pRPDev->dwIPCallbackID,
|
|
&State, &pbResult);
|
|
if(SUCCEEDED(hr))
|
|
; // cool !
|
|
}
|
|
else
|
|
{
|
|
pbResult = pRPDev->pfnOEMImageProcessing(
|
|
(PDEVOBJ)pPDev,
|
|
pso->pvBits,
|
|
&bmi,
|
|
(PBYTE)&((PAL_DATA *)(pPDev->pPalData))->ulPalCol[0],
|
|
pRPDev->dwIPCallbackID,
|
|
&State);
|
|
}
|
|
}
|
|
#endif
|
|
return (PDWORD)pbResult ;
|
|
}
|
|
//******************************************************************
|
|
BOOL
|
|
RMStartDoc(
|
|
SURFOBJ *pso,
|
|
PWSTR pDocName,
|
|
DWORD jobId
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to allow any raster module initialization
|
|
at DrvStartDoc time.
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
pDocName Pointer to document name
|
|
jobId Job ID
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
#ifdef TIMING
|
|
ENG_TIME_FIELDS TimeTab;
|
|
PDEV *pPDev = (PDEV *) pso->dhpdev;
|
|
RASTERPDEV *pRPDev = pPDev->pRasterPDEV;
|
|
EngQueryLocalTime(&TimeTab);
|
|
pRPDev->dwDocTiming = (((TimeTab.usMinute*60)+TimeTab.usSecond)*1000)+
|
|
TimeTab.usMilliseconds;
|
|
DrvDbgPrint("Unidrv!StartDoc\n");
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
//************************ Function Header ***********************************
|
|
BOOL
|
|
RMEndDoc (
|
|
SURFOBJ *pso,
|
|
FLONG flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called at DrvEndDoc to allow the raster module
|
|
to clean up any raster related initializations
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
FLONG flags
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
#ifdef TIMING
|
|
DWORD eTime;
|
|
char buf[80];
|
|
ENG_TIME_FIELDS TimeTab;
|
|
PDEV *pPDev = (PDEV *) pso->dhpdev;
|
|
RASTERPDEV *pRPDev = pPDev->pRasterPDEV;
|
|
EngQueryLocalTime(&TimeTab);
|
|
eTime = (((TimeTab.usMinute*60)+TimeTab.usSecond)*1000)+
|
|
TimeTab.usMilliseconds;
|
|
sprintf (buf,"Unidrv!EndDoc: %ld\n",eTime - pRPDev->dwDocTiming);
|
|
DrvDbgPrint(buf);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
|
|
//******************************************************************
|
|
BOOL
|
|
RMStartPage (
|
|
SURFOBJ *pso
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called to allow any raster module initialization
|
|
at DrvStartPage time.
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
//************************ Function Header ***********************************
|
|
BOOL
|
|
RMSendPage (
|
|
SURFOBJ *pso
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called at DrvSendPage to allow the raster module
|
|
to output any raster data to the printer.
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
PDEV *pPDev; /* Access to all that is important */
|
|
RENDER RenderData; /* Rendering data passed to bRender() */
|
|
PRASTERPDEV pRPDev; /* raster module PDEV */
|
|
|
|
// all we need to do now is render the bitmap (output it to the printer)
|
|
// we must be careful however since the control module also calls this
|
|
// function after the last band has been output in banding mode. In this
|
|
// case we don't want to output any data
|
|
//
|
|
pPDev = (PDEV *) pso->dhpdev;
|
|
pRPDev = pPDev->pRasterPDEV;
|
|
|
|
//
|
|
// Reset palette data
|
|
//
|
|
if (pPDev->ePersonality == kPCLXL_RASTER && pPDev->pVectorPDEV)
|
|
{
|
|
PCLXLResetPalette((PDEVOBJ)pPDev);
|
|
}
|
|
|
|
if (pso->iType == STYPE_BITMAP)
|
|
{
|
|
PDWORD pBits;
|
|
//
|
|
// test whether mirroring should be enabled
|
|
//
|
|
if (pPDev->fMode2 & PF2_MIRRORING_ENABLED)
|
|
EnableMirroring(pPDev,pso);
|
|
//
|
|
// Decide whether to make OEM callback function
|
|
//
|
|
if (pRPDev->pfnOEMImageProcessing && !pPDev->bBanding)
|
|
{
|
|
if ((pBits = pSetupOEMImageProcessing(pPDev,pso)) == NULL)
|
|
return FALSE;
|
|
}
|
|
else
|
|
pBits = pso->pvBits;
|
|
|
|
//
|
|
// test whether unidrv is doing the dump
|
|
//
|
|
if (pRPDev->sDrvBPP)
|
|
{
|
|
if( pRPDev->pvRenderData != NULL )
|
|
{
|
|
// if we are not in banding mode we need to
|
|
// render the data for the entire page.
|
|
//
|
|
if (!pPDev->bBanding)
|
|
{
|
|
RenderData = *(RENDER *)(pRPDev->pvRenderData);
|
|
|
|
if( bRenderStartPage( pPDev ) )
|
|
{
|
|
#ifndef DISABLE_NEWRULES
|
|
OutputRules(pPDev);
|
|
#endif
|
|
bRender( pso, pPDev, &RenderData, pso->sizlBitmap, pBits );
|
|
((RENDER *)(pRPDev->pvRenderData))->plrWhite = RenderData.plrWhite;
|
|
}
|
|
}
|
|
// now we clean up our structures in
|
|
// both banding and non-banding cases
|
|
//
|
|
bRenderPageEnd( pPDev );
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//************************ Function Header ***********************************
|
|
BOOL
|
|
RMNextBand (
|
|
SURFOBJ *pso,
|
|
POINTL *pptl
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called at DrvSendPage to allow the raster module
|
|
to output any raster data to the printer.
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
RASTERPDEV *pRPDev;
|
|
PDEV *pPDev; /* Access to all that is important */
|
|
|
|
pPDev = (PDEV *) pso->dhpdev;
|
|
pRPDev = pPDev->pRasterPDEV;
|
|
|
|
// only output if raster band or surface is dirty
|
|
// if not just return true
|
|
if (pPDev->fMode & PF_ENUM_GRXTXT)
|
|
{
|
|
PDWORD pBits;
|
|
//
|
|
// test whether mirroring should be enabled
|
|
//
|
|
if (pPDev->fMode2 & PF2_MIRRORING_ENABLED)
|
|
EnableMirroring(pPDev,pso);
|
|
//
|
|
// Decide whether to make OEM callback function
|
|
//
|
|
if (pRPDev->pfnOEMImageProcessing)
|
|
{
|
|
if ((pBits = pSetupOEMImageProcessing(pPDev,pso)) == NULL)
|
|
return FALSE;
|
|
}
|
|
else
|
|
pBits = pso->pvBits;
|
|
|
|
//
|
|
// test whether unidrv is doing the dump
|
|
//
|
|
if (pRPDev->sDrvBPP)
|
|
{
|
|
if( pRPDev->pvRenderData == NULL )
|
|
return FALSE;
|
|
|
|
//
|
|
// Reset palette data
|
|
//
|
|
if (pPDev->ePersonality == kPCLXL_RASTER && pPDev->pVectorPDEV)
|
|
{
|
|
PCLXLResetPalette((PDEVOBJ)pPDev);
|
|
}
|
|
|
|
#ifndef DISABLE_NEWRULES
|
|
OutputRules(pPDev);
|
|
#endif
|
|
if( !bRender( pso, pPDev, pRPDev->pvRenderDataTmp, pso->sizlBitmap, pBits ) )
|
|
{
|
|
if ( ((RENDER *)(pRPDev->pvRenderDataTmp))->plrWhite )
|
|
MemFree(((RENDER *)(pRPDev->pvRenderDataTmp))->plrWhite);
|
|
|
|
((RENDER *)(pRPDev->pvRenderData))->plrWhite =
|
|
((RENDER *)(pRPDev->pvRenderDataTmp))->plrWhite = NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
if ( ((RENDER *)(pRPDev->pvRenderDataTmp))->plrWhite )
|
|
MemFree(((RENDER *)(pRPDev->pvRenderDataTmp))->plrWhite);
|
|
|
|
((RENDER *)(pRPDev->pvRenderData))->plrWhite =
|
|
((RENDER *)(pRPDev->pvRenderDataTmp))->plrWhite = NULL;
|
|
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
//************************ Function Header ***********************************
|
|
BOOL
|
|
RMStartBanding (
|
|
SURFOBJ *pso,
|
|
POINTL *pptl
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called to tell the driver to prepare for banding and return the
|
|
origin of the first band.
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
PDEV *pPDev; /* Access to all that is important */
|
|
RASTERPDEV *pRPDev; /* raster module PDEV */
|
|
|
|
pPDev = (PDEV *) pso->dhpdev;
|
|
|
|
pRPDev = pPDev->pRasterPDEV; /* For our convenience */
|
|
|
|
//
|
|
if (pRPDev->sDrvBPP)
|
|
{
|
|
|
|
if( pRPDev->pvRenderData == NULL )
|
|
return FALSE; /* Should not happen, nasty if it does */
|
|
|
|
if( !bRenderStartPage( pPDev ) )
|
|
return FALSE;
|
|
|
|
/* reset the render data for this band */
|
|
|
|
*(RENDER *)(pRPDev->pvRenderDataTmp) = *(RENDER *)(pRPDev->pvRenderData);
|
|
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
//************************ Function Header ***********************************
|
|
BOOL
|
|
RMResetPDEV (
|
|
PDEV *pPDevOld,
|
|
PDEV *pPDevNew
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Called when an application wishes to change the output style in the
|
|
midst of a job. Typically this would be to change from portrait to
|
|
landscape or vice versa. Any other sensible change is permitted.
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
|
|
Return Value:
|
|
TRUE - device successfully reorganised
|
|
FALSE - unable to change - e.g. change of device name.
|
|
|
|
Note:
|
|
|
|
--*/
|
|
{
|
|
// as near as I can tell I don't need to do anything
|
|
// for the raster module.
|
|
return TRUE;
|
|
}
|
|
|
|
//************************ Function Header ***********************************
|
|
BOOL
|
|
RMEnableSurface (
|
|
PDEV *pPDev
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
Note:
|
|
|
|
--*/
|
|
{
|
|
RASTERPDEV *pRPDev = pPDev->pRasterPDEV;
|
|
|
|
if (DRIVER_DEVICEMANAGED (pPDev)) // device surface
|
|
return TRUE;
|
|
|
|
//Initialize the RPDev Paldata.
|
|
ASSERT(pPDev->pPalData);
|
|
pRPDev->pPalData = pPDev->pPalData; /* For all the others! */
|
|
|
|
//
|
|
// initialize render parameters if we are doing
|
|
// the dump function
|
|
//
|
|
if (pRPDev->sDrvBPP)
|
|
{
|
|
ULONG iFormat;
|
|
// determine the bitmap format
|
|
switch (pRPDev->sDrvBPP)
|
|
{
|
|
case 1:
|
|
iFormat = BMF_1BPP;
|
|
break;
|
|
case 4:
|
|
iFormat = BMF_4BPP;
|
|
break;
|
|
case 8:
|
|
iFormat = BMF_8BPP;
|
|
break;
|
|
case 24:
|
|
iFormat = BMF_24BPP;
|
|
break;
|
|
default:
|
|
ERR(("Unknown sBitsPixel in RMEnableSurface"));
|
|
return FALSE;
|
|
}
|
|
|
|
// if these calls fail, control will call RMDisableSurface
|
|
//
|
|
if( !bSkipInit( pPDev ) || !bInitTrans( pPDev ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* Also initialise the rendering structures.
|
|
*/
|
|
|
|
if( !bRenderInit( pPDev, pPDev->szBand, iFormat ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//************************ Function Header ***********************************
|
|
VOID
|
|
RMDisableSurface (
|
|
PDEV *pPDev
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called at DrvDisableSurface to allow the raster module
|
|
to cleanup any required stuff usually generated at EnableSurface time.
|
|
|
|
Arguments:
|
|
|
|
pso Pointer to SURFOBJ
|
|
|
|
Return Value:
|
|
|
|
void
|
|
|
|
--*/
|
|
{
|
|
RASTERPDEV *pRPDev; /* Unidrive stuff */
|
|
|
|
|
|
pRPDev = pPDev->pRasterPDEV;
|
|
|
|
/*
|
|
* Free the rendering storage.
|
|
*/
|
|
if (pRPDev->sDrvBPP)
|
|
{
|
|
vRenderFree( pPDev );
|
|
|
|
if( pRPDev->pdwTrans )
|
|
{
|
|
MemFree( pRPDev->pdwTrans );
|
|
pRPDev->pdwTrans = NULL;
|
|
}
|
|
|
|
if( pRPDev->pdwColrSep )
|
|
{
|
|
MemFree( pRPDev->pdwColrSep );
|
|
pRPDev->pdwColrSep = NULL;
|
|
}
|
|
|
|
if( pRPDev->pdwBitMask )
|
|
{
|
|
MemFree( pRPDev->pdwBitMask );
|
|
pRPDev->pdwBitMask = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
//************************ Function Header ***********************************
|
|
VOID
|
|
RMDisablePDEV (
|
|
PDEV *pPDev
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when the engine has finished with this PDEV. Basically
|
|
we throw away all connections etc. then free the heap.
|
|
|
|
Arguments:
|
|
|
|
pPDev Pointer to PDEV
|
|
|
|
Return Value:
|
|
|
|
TRUE for success and FALSE for failure
|
|
|
|
--*/
|
|
{
|
|
RASTERPDEV *pRPDev = pPDev->pRasterPDEV;
|
|
|
|
/*
|
|
* Undo all that has been done with the PDEV. Basically this means
|
|
* freeing the memory we consumed.
|
|
*/
|
|
|
|
// test for valid raster PDEV
|
|
if (pRPDev)
|
|
{
|
|
// Delete custom halftone pattern
|
|
if (pRPDev->pHalftonePattern)
|
|
MemFree(pRPDev->pHalftonePattern);
|
|
|
|
// Delete the raster module PDEV
|
|
MemFree(pRPDev);
|
|
}
|
|
|
|
//
|
|
// PCLXL raster mode
|
|
// Free XLRASTER
|
|
//
|
|
if (pPDev->ePersonality == kPCLXL_RASTER && pPDev->pVectorPDEV)
|
|
{
|
|
PCLXLFreeRaster((PDEVOBJ)pPDev);
|
|
}
|
|
return;
|
|
}
|
|
|
|
BOOL
|
|
RMInitDevicePal(
|
|
PDEV *pPDev,
|
|
PAL_DATA *pPal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function calculates a device palette to be download
|
|
to the printer for planar mode devices
|
|
|
|
Arguments:
|
|
|
|
pPDev - pointer to PDEV structure
|
|
pPal - pointer to PAL_DATA structure
|
|
Return Value:
|
|
|
|
--*/
|
|
{
|
|
int i,j;
|
|
int RMask,GMask,BMask;
|
|
ULONG *pPalette;
|
|
RASTERPDEV *pRPDev;
|
|
|
|
pRPDev = pPDev->pRasterPDEV;
|
|
|
|
if (pPal == NULL || pRPDev == NULL || pRPDev->sDevPlanes != 3
|
|
|| pPal->wPalDev < 8 || (!(pPalette = pPal->pulDevPalCol)) )
|
|
{
|
|
ERR (("Unidrv!RMInitDevicePal: Invalid Parameters, pPal = %p, \
|
|
pRPDev = %p, pRPDev->sDevPlanes = %d,pPal->wPalDev = %d,\
|
|
pPalette = %p\n",pPal,pRPDev,pRPDev->sDevPlanes,pPal->wPalDev,\
|
|
pPalette));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Determine which bits map to which color
|
|
//
|
|
for (i = 0;i < 3;i++)
|
|
{
|
|
switch (pRPDev->rgbOrder[i])
|
|
{
|
|
case DC_PLANE_CYAN:
|
|
case DC_PLANE_RED:
|
|
RMask = 1 << i;
|
|
break;
|
|
case DC_PLANE_MAGENTA:
|
|
case DC_PLANE_GREEN:
|
|
GMask = 1 << i;
|
|
break;
|
|
case DC_PLANE_YELLOW:
|
|
case DC_PLANE_BLUE:
|
|
BMask = 1 << i;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// create the palette entries
|
|
//
|
|
|
|
for (i = 0;i < 8;i++)
|
|
{
|
|
//
|
|
// if CMY mode complement index
|
|
//
|
|
if (pRPDev->fColorFormat & DC_PRIMARY_RGB)
|
|
j = i;
|
|
else
|
|
j = ~i;
|
|
|
|
pPalette[i] = RGB((j & RMask) ? 255 : 0,
|
|
(j & GMask) ? 255 : 0,
|
|
(j & BMask) ? 255 : 0);
|
|
}
|
|
return TRUE;
|
|
}
|