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.
 
 
 
 
 
 

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;
}