/*++ 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 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; }