/*************************** Module Header ******************************** * enablpdv.c * Functions associated with EnablePDEV/RestartPDEV/CompletePDEV/ * DisablePDEV. * EnablePDEV is called after EnableDriver, and is the call when * the driver sets up any storage or other requirements, except * any storage associated with the drawing surface. RestartPDEV is * called when the device configuration is being changed in a * major way, for example changing from Portraint to Landscape mode. * DisablePDEV is called when the engine has finished with the * physical device. * * 13:43 on Mon 19 Nov 1990 -by- Lindsay Harris [lindsayh] * * Copyright (C) 1990 - 1993 Microsoft Corporation * *************************************************************************/ #include #include #include #include "pdev.h" #include #include "fnenabl.h" #include #include #include "win30def.h" #include "udmindrv.h" #include "udpfm.h" #include "uddevice.h" #include "stretch.h" #include "udrender.h" #include #include "rasdd.h" //sandram #include "udresrc.h" #include "udfnprot.h" #include "oem.h" BYTE cxHTPatSize[] = { 2,2,4,4,6,6,8,8,10,10,12,12,14,14,16,16 }; BYTE cyHTPatSize[] = { 2,2,4,4,6,6,8,8,10,10,12,12,14,14,16,16 }; #if DBG DWORD gdwEnablPdevCount = 0; DWORD gdwDisablPdevCount = 0; extern HSEMAPHORE hsem ; #endif /* * Set heap sizes. The minimum is the amount allocated at the start * of operations, while the maximum is set to zero, meaning that the * limit is set by the amount of memory the process can have. */ #define HEAP_MIN_SIZE ( 16 * 1024) /* Min bytes allocated for heap */ #define HEAP_MAX_SIZE (1024 * 1024) /* Max bytes allocated for heap */ /* * Private local function prototypes. */ BOOL bGetDevInfo( PDEV *, DEVINFO *, GDIINFO *); BOOL bInitPDEV( PDEV *, DEVMODEW *, PWSTR, ULONG, HSURF *, ULONG, ULONG *, ULONG, DEVINFO *, HDEV, PWSTR, HANDLE ); void vLogFont( LOGFONT *, FONTMAP * ); /******************************Public*Routine******************************\ * vFreePdev * * free any memory allocated for this pdev * * * History: * 01-Mar-1995 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/ VOID vFreePdev( PDEV *ppdev) { if (ppdev->pstrDataFile) DRVFREE(ppdev->pstrDataFile); if (ppdev->pstrModel) DRVFREE(ppdev->pstrModel); ASSERTRASDD(!(ppdev->pvRenderData),"RASDD!vFreePdev:pvRenderData should be NULL\n"); ASSERTRASDD(!(ppdev->pFileList),"RASDD!vFreePdev:ppdev->pFileList should be NULL\n"); #if NEED_TO_FREERES if (ppdev->pNTRes) DRVFREE( ppdev->pNTRes ); if (ppdev->pGPCData) DRVFREE( ppdev->pGPCData ); #endif if (ppdev->pUDPDev) DRVFREE(ppdev->pUDPDev); DRVFREE(ppdev); } /************************* Function Header ******************************* * DrvEnablePDEV * Function called to let the driver create the data structures * needed to support the device, and also to tell the engine * about its capabilities. This is the stage where we find out * exactly which device we are dealing with, and so we need to * find out its capabilities. * * HISTORY: * 17:03 on Thu 20 Aug 1992 -by- Lindsay Harris [lindsayh] * Converted to UNICODE with wide structures. * * 28-May-1991 Tue 12:56:16 updated -by- Daniel Chou (danielc) * clear the PDEV to all zeros after get it from heap * * 17:41 on Thu 14 Feb 1991 -by- Lindsay Harris [lindsayh] * Updated to new DDI spec. * * 13:47 on Mon 19 Nov 1990 -by- Lindsay Harris [lindsayh] * Created it. * *************************************************************************/ DHPDEV DrvEnablePDEV( pdevmode, pwstrPrtName, cPatterns, phsurfPatterns, cjGdiInfo, pulGdiInfo, cjDevInfo, pdevinfo, hdev, pwstrDeviceName, hDriver ) DEVMODEW *pdevmode; /* Driver data */ PWSTR pwstrPrtName; /* Printer's name in CreateDC() */ ULONG cPatterns; /* Count of standard patterns */ HSURF *phsurfPatterns; /* Buffer for standard patterns */ ULONG cjGdiInfo; /* Size of buffer for GdiInfo */ ULONG *pulGdiInfo; /* Buffer for GDIINFO */ ULONG cjDevInfo; /* Number of bytes in devinfo */ DEVINFO *pdevinfo; /* Device info */ HDEV hdev; // HDEV, used for callbacks PWSTR pwstrDeviceName; /* Device Name - "LaserJet II" */ HANDLE hDriver; /* Printer handle for spooler access */ { /* * The engine requires a new physical device from us. Thus, * we need to allocate the storage and initialise it for the * particular device. * Function returns a handle to the pdev, which is returned to us * in RestartPDEV and CompletePDEV, and also EnableSurface. */ PDEV *pPDev = NULL; /* Ditto */ #if DBG EngAcquireSemaphore(hsem); gdwEnablPdevCount++; EngReleaseSemaphore(hsem); //SetAllocCounters(); #endif /* * We need to get the full path of the driver to load the module from. * We used to just use "rasdd.dll" but if there were multiple drivers * lying around, one in the '0' directory and one in the '1' directory, * it is undefined which driver you get so you can get the resources for * the wrong driver (erick 4/6/94). */ if( (pPDev = (PDEV *)DRVALLOC( sizeof( PDEV ) )) ) { /* * make sure start with clean state */ ZeroMemory( pPDev, sizeof( PDEV ) ); pPDev->hheap = 0; /* For future reference */ pPDev->ulID = PDEV_ID; /* Just for checking! */ pPDev->hPrinter = hDriver; /* Convert logical address to path name to info about this device. */ if( !(pPDev->pstrDataFile = WstrToHeap( pPDev->hheap, EngGetPrinterDataFileName(hdev) )) || !(pPDev->pstrModel = WstrToHeap( pPDev->hheap, pwstrDeviceName )) ) { vFreePdev(pPDev); pPDev = NULL; } else { pPDev->pstrPrtName = NULL; // Get a handle to the driver DLL module from DDI. if ( !(pPDev->hModDrv = EngLoadModule(EngGetDriverName(hdev))) ) { RIP("Rasdd!DrvEnablePDEV:EngLoadModule on Rasdd Failed"); vFreePdev(pPDev); pPDev = NULL; #if DO_LATER //Get a handle for loading minidrivers for callbacks. if (!( pPDev->hImageMod = EngLoadImage(pPDev->pstrDataFile)) ) { RIP("Rasdd!DrvEnablePDEV:EngLoadImage Failed\n"); vFreePdev(pPDev); pPDev = NULL; } #endif } /* * Now that we know where everything is located, we can determine * our specific characteristics.This requires us to read the Windows * mini-driver resources so that we can set our own capabilities. */ else if ( !bInitPDEV( pPDev, pdevmode, pwstrPrtName, cPatterns, phsurfPatterns, cjGdiInfo, pulGdiInfo, cjDevInfo, pdevinfo, hdev, pwstrDeviceName, hDriver ) ) { /* Initialisation failed, so free the heap and return. */ RASDERRMSG("bInitPDEV"); vFreePdev(pPDev); pPDev = NULL; } } } return (DHPDEV)pPDev; } /****************************** Function Header **************************** * IsPaperSizeAndSourceSameAndOrientDifferent * Checks the PaperSize of Old and new PDEV. It takes care of Orientation. * Also checks if the orientation is different. * RETURNS: * TRUE - if PaperSize and Source are same * FALSE - other wise. * * HISTORY: * 15:54 on SAT 06 Jan 1995 -by- Ganesh Pandey [ganeshp] * Initial version - probably not complete. * ***************************************************************************/ BOOL IsPaperSizeAndSourceSameAndOrientDifferent( UD_PDEV *pUDPDevNew, UD_PDEV *pUDPDevOld ) { POINT ptPhysNew,ptPhysOld; /* physical paper size */ if (pUDPDevNew->iOrient == pUDPDevOld->iOrient) return FALSE; //Get the Size for New PDEV if ( pUDPDevNew->iOrient == DMORIENT_LANDSCAPE ) { ptPhysNew.x = pUDPDevNew->pfPaper.ptPhys.y; ptPhysNew.y = pUDPDevNew->pfPaper.ptPhys.x; } else { ptPhysNew.x = pUDPDevNew->pfPaper.ptPhys.x; ptPhysNew.y = pUDPDevNew->pfPaper.ptPhys.y; } //Get the Size from Old PDEV. if ( pUDPDevOld->iOrient == DMORIENT_LANDSCAPE ) { ptPhysOld.x = pUDPDevOld->pfPaper.ptPhys.y; ptPhysOld.y = pUDPDevOld->pfPaper.ptPhys.x; } else { ptPhysOld.x = pUDPDevOld->pfPaper.ptPhys.x; ptPhysOld.y = pUDPDevOld->pfPaper.ptPhys.y; } return ( (ptPhysNew.x == ptPhysOld.x) && (ptPhysNew.y == ptPhysOld.y) && (pUDPDevNew->sPaperSource == pUDPDevOld->sPaperSource) ); } /****************************** Function Header **************************** * DrvResetPDEV * 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. * * RETURNS: * TRUE - device successfully reorganised * FALSE - unable to change - e.g. change of device name. * * HISTORY: * 15:54 on Fri 05 Jan 1995 -by- Ganesh Pandey [ganeshp] * Initial version - probably not complete. * ***************************************************************************/ BOOL DrvResetPDEV ( DHPDEV dhpdevOld, /* Original PDEV */ DHPDEV dhpdevNew /* New PDEV */ ) { UD_PDEV *pUDPDevOld, *pUDPDevNew; PDEV *pPDEVOld, *pPDEVNew; BOOL bOK = FALSE; pPDEVOld = (PDEV *)dhpdevOld; pPDEVNew = (PDEV *)dhpdevNew; pUDPDevNew = (UD_PDEV *)(pPDEVNew->pUDPDev); pUDPDevOld = (UD_PDEV *)(pPDEVOld->pUDPDev) ; /* Validate the PDEVs */ if( (pPDEVOld->ulID != PDEV_ID) || (pPDEVNew->ulID != PDEV_ID) ) { RIP( "INCORRECT PDEV ID in DrvResetPDEV (RasDD)" ); return(bOK); } /* Notify OEM */ bOK = bOEMResetPDEV(pPDEVOld, pPDEVNew); /* * Set this flag only when initialization is not needed, because it will * eject the page. Check if DrvStartDoc was called for the old PDEVICE * because DrvRestPDev can be called between documents also. We are only * interested in the case where the document has started printing. * */ if( (pUDPDevOld->fMode & PF_DOCSTARTED) && (pUDPDevNew->fMDGeneral & MD_DUPLEX) && (pUDPDevNew->sDuplex != DMDUP_SIMPLEX) && (pUDPDevNew->sDuplex == pUDPDevOld->sDuplex) && (IsPaperSizeAndSourceSameAndOrientDifferent(pUDPDevNew,pUDPDevOld)) ) { pUDPDevNew->fMode |= PF_RESET_NOINIT_PG; } return(bOK); } /****************************** Function Header **************************** * bInitPDEV * Function to perform the PDEV initialisation. This is common to * DrvEnablePDEV and DrvRestartPDEV. These individual functions * do whatever is required before calling in here. * * RETURNS: * TRUE - successful initialisation * FALSE - unable to do the job (error code logged) * * HISTORY: * 29-May-1991 Wed 21:39:40 updated -by- Daniel Chou (danielc) * Calling EnableHalftone() * * 15:46 on Fri 01 Mar 1991 -by- Lindsay Harris [lindsayh] * Split out from DrvEnablPDEV * * 27-Jan-1993 Wed 07:34:04 updated -by- Daniel Chou (danielc) * clean up, have engine do the work * ****************************************************************************/ BOOL bInitPDEV( pPDev, pdevmode, pwstrPrtName, cPatterns, phsurfPatterns, cjGdiInfo, pulGdiInfo, cjDevInfo, pdevinfo, hdev, pwstrDeviceName, hdriver ) PDEV *pPDev; /* The device of interest */ PWSTR pwstrPrtName; /* Printer name */ DEVMODEW *pdevmode; /* User's devmode */ ULONG cPatterns; /* Count for standard patterns */ HSURF *phsurfPatterns; /* Handles to standard patterns */ ULONG cjGdiInfo; /* Bytes in the devcaps following */ ULONG *pulGdiInfo; /* Place for the devcaps data */ ULONG cjDevInfo; /* Bytes in the device info following */ DEVINFO *pdevinfo; /* Place for the DEVINFO data */ HDEV hdev; /* HDEV, for callbacks */ PWSTR pwstrDeviceName; /* Model name */ HANDLE hdriver; /* Printer handle for spooler access */ { /* * Printer characterisation is determined from the devmode and * minidriver resources. First step is to obtain the minidriver * data. */ GDIINFO GdiInfo; /* UniDrv code fills it in for us */ DEVINFO DevInfo; /* Device caps */ OEMENABLEPDEVPARAM OEMParam = {0}; /* * Initialise the LOCAL structures to 0 before passing off to the * functions that (selectively) fill them in. */ ZeroMemory( &GdiInfo, sizeof( GdiInfo ) ); ZeroMemory( &DevInfo, sizeof( DevInfo ) ); // // We first NULL out all HSURF which engine asked for, this will cause // engine to automatically generate best standard patterns for this // particular device // ZeroMemory( phsurfPatterns, sizeof(HSURF) * cPatterns); /* Fill out what we know of OEMENABLEPDEVPARAM. */ OEMParam.cbSize = sizeof(OEMENABLEPDEVPARAM); OEMParam.pdm = pdevmode; OEMParam.pwszLogAddress = pwstrPrtName; OEMParam.cPat = cPatterns; OEMParam.phsurfPatterns = phsurfPatterns; OEMParam.cjCaps = cjGdiInfo; OEMParam.pdevcaps = pulGdiInfo; OEMParam.cjDevInfo = cjDevInfo; OEMParam.pdi = pdevinfo; OEMParam.hdev = hdev; OEMParam.pwszDeviceName = pwstrDeviceName; OEMParam.hDriver = hdriver; if( !udInit( pPDev, &GdiInfo, pdevmode, &OEMParam ) ) return FALSE; /* * Initialise the DEVINFO structure and also initialise the pattern * information requested by the engine. First step is to try * initialising the halftone info & dll. */ GdiInfo.flHTFlags = HT_FLAG_HAS_BLACK_DYE; if (!bGetDevInfo( pPDev, &DevInfo, &GdiInfo )) { return(FALSE); } DevInfo.cxDither = cxHTPatSize[GdiInfo.ulHTPatternSize]; DevInfo.cyDither = cyHTPatSize[GdiInfo.ulHTPatternSize]; /* * Everything completed OK, so we can overwrite the data areas * passed in to us. */ cjGdiInfo = min( cjGdiInfo, sizeof( GDIINFO ) ); CopyMemory( pulGdiInfo, &GdiInfo, cjGdiInfo ); cjDevInfo = min( cjDevInfo, sizeof( DEVINFO ) ); CopyMemory( pdevinfo, &DevInfo, cjDevInfo ); return TRUE; } /***************************** Function Header ************************** * DrvCompletePDEV * Called when the engine has completed installation of the physical * device. Basically it provides the connection between the * engine's hdev and ours. Some functions require us to pass in * the engines's hdev, so we save it now in our pdev so that we * can get to it later. * * HISTORY: * 17:41 on Thu 14 Feb 1991 -by- Lindsay Harris [lindsayh] * Updated to new DDI spec. * * 16:46 on Mon 19 Nov 1990 -by- Lindsay Harris [lindsayh] * Created it. * ************************************************************************/ void DrvCompletePDEV( dhpdev, hdev ) DHPDEV dhpdev; /* Returned from dhpdevCreatePDEV */ HDEV hdev; /* Engine's corresponding handle */ { /* * Simply record the value in the PDEV we have allocated. * ALWAYS returns TRUE. */ ((PDEV *)dhpdev)->hdev = hdev; return; } /***************************** Function Header ************************** * DrvDisablePDEV * Called when the engine has finished with this PDEV. Basically * we throw away all connections etc. then free the heap. * * HISTORY: * 10:04 on Thu 23 May 1991 -by- Lindsay Harris [lindsayh] * Freed halftone module, if used. * * 17:42 on Thu 14 Feb 1991 -by- Lindsay Harris [lindsayh] * Updated to new DDI spec * * 16:22 on Mon 19 Nov 1990 -by- Lindsay Harris [lindsayh] * Created it. * * 29-May-1991 Wed 21:39:40 updated -by- Daniel Chou (danielc) * Calling DiableHalftone() * ************************************************************************/ VOID DrvDisablePDEV( dhpdev ) DHPDEV dhpdev; { /* * Undo all that has been done with the PDEV. Basically this means * freeing the memory we consumed. */ /* Notify OEM. */ vOEMDisablePDEV((PDEV*) dhpdev); /* * Free any font memory that may have been allocated. */ #define pPDEV ((PDEV *)dhpdev) #if DBG EngAcquireSemaphore(hsem); gdwDisablPdevCount++; EngReleaseSemaphore(hsem); #endif vFontFreeMem( pPDEV ); /* * Free the resource data - NT or WIN 3.1 */ if( pPDEV->pvWinResData ) { WinResClose( pPDEV->pvWinResData ); /* Free the Resource data */ if (pPDEV->pvWinResData) DRVFREE(pPDEV->pvWinResData); pPDEV->pvWinResData = 0; } /* * And any palette data. */ if( pPDEV->hpal ) EngDeletePalette( pPDEV->hpal ); /* Delete the Pallete Data */ if( pPDEV->pPalData ) DRVFREE(pPDEV->pPalData); /* Unload the Image if loaded for callbacks */ if( pPDEV->hImageMod ) EngUnloadImage( pPDEV->hImageMod ); /* Unload Rasdd Module Handle, loaded for rasdd resources */ if (pPDEV->hModDrv) EngFreeModule(pPDEV->hModDrv); //derryd Free The mini PDEV if( ((UD_PDEV*)(pPDEV->pUDPDev))->pMDev ) { DRVFREE(((UD_PDEV*)(pPDEV->pUDPDev))->pMDev); ((UD_PDEV*)(pPDEV->pUDPDev))->pMDev = NULL; } vFreePdev(pPDEV); return; } /************************** FUNCTION HEADER ********************************** * bGetDevInfo * Set up the device caps for this particular printer. Some fields * require calculations based on device resolution, etc. * * RETURNS: * True for success, False for error. * * HISTORY: * 18:16 on Wed 03 Jul 1991 -by- Lindsay Harris [lindsayh] * Returns number of colours in palette * * 29-May-1991 Wed 21:40:02 updated -by- Daniel Chou (danielc) * Add in halftone codes and re-order the color table/palette * * 14:54 on Thu 21 Feb 1991 -by- Lindsay Harris [lindsayh] * Filled it in, now that engine looks at data. * * 11-Oct-1991 Fri 19:08:28 updated -by- Daniel Chou (danielc) * Addin the HTDataFlags so that we remember if this device is monochrome * or not, previously the color output (DitherBrush) was always monochrome * even if output device is color, which cause strong blue appear in the * color output for the grey color test * * 27-Jan-1993 Wed 07:35:37 updated -by- Daniel Chou (danielc) * add in pGDIInfo parameter so we can setup more halftone parameters * in GDIINFO to have engine work for us * ****************************************************************************/ BOOL bGetDevInfo( pPDev, pdevinfo, pGDIInfo ) PDEV *pPDev; DEVINFO *pdevinfo; /* Where to put the data */ GDIINFO *pGDIInfo; { /* * For now, we simply set it all to zero. This means we have no * capabilities, but this is true for now. Later we may be able * to include a default font. */ PAL_DATA *pPD; UD_PDEV *ptUDPDev = pPDev->pUDPDev; /* !!!Lindsayh: Still uses old format data !!! WILL NEED FIXING LATER */ #define pUDPDev ((UD_PDEV *)pPDev->pUDPDev) /* * We may need to change this graphic capabilities as we go along. */ pdevinfo->flGraphicsCaps = 0; /* Can't do a damn thing */ if( !(pPD = (PAL_DATA *)DRVALLOC( sizeof( PAL_DATA ) )) ) { return(FALSE); } pPDev->pPalData = pPD; /* For all the others! */ if( pdevinfo->cFonts = pUDPDev->cFonts ) { /* Device fonts are available, so set the default font data */ if( pUDPDev->pFMDefault ) vLogFont( &pdevinfo->lfDefaultFont, pUDPDev->pFMDefault ); } ZeroMemory( &pdevinfo->lfAnsiVarFont, sizeof( LOGFONT ) ); ZeroMemory( &pdevinfo->lfAnsiFixFont, sizeof( LOGFONT ) ); /* * We don't process DrvDitherColor (perhaps later?), so set the * size of the Dither Brush to 0 to indicate this to the engine. * THIS IS IN THE SPEC FOR DrvDitherBrush() function. HOWEVER, * if halftoning is available, then we can do it! */ pdevinfo->flGraphicsCaps |= (GCAPS_ARBRUSHOPAQUE | GCAPS_HALFTONE | GCAPS_MONO_DITHER | GCAPS_COLOR_DITHER); if( pUDPDev->fMode & PF_NOEMFSPOOL ) pdevinfo->flGraphicsCaps |= GCAPS_DONTJOURNAL; if( pUDPDev->fMode & PF_SEIKO ) { /* !!! HACK for Seiko printer */ long lRet; int _iI; PALETTEENTRY pe[ 256 ]; /* 8 bits per pel - all the way */ lRet = HT_Get8BPPFormatPalette(pe, (USHORT)pGDIInfo->ciDevice.RedGamma, (USHORT)pGDIInfo->ciDevice.GreenGamma, (USHORT)pGDIInfo->ciDevice.BlueGamma ); if( lRet < 1 ) { #if DBG DbgPrint( "Rasdd!GetPalette8BPP returns %ld\n", lRet ); #endif return(FALSE); } /* * Convert the HT derived palette to the engine's desired format. */ for( _iI = 0; _iI < lRet; _iI++ ) { pPD->ulPalCol[ _iI ] = RGB( pe[ _iI ].peRed, pe[ _iI ].peGreen, pe[ _iI ].peBlue ); } pPD->iWhiteIndex = lRet; pPD->cPal = lRet; pdevinfo->iDitherFormat = BMF_8BPP; pGDIInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA; pGDIInfo->ulHTOutputFormat = HT_FORMAT_8BPP; } //sandram - added another else for Color LaserJet else if (pUDPDev->fMode & PF_8BPP) { long lRet; lRet = lSetup8BitPalette (pUDPDev, pPD, pdevinfo, pGDIInfo); if( lRet < 1 ) { #if DBG DbgPrint( "Rasdd!GetPalette8BPP returns %ld\n", lRet ); #endif return(FALSE); } } else if (pUDPDev->fMode & PF_24BPP) { long lRet; lRet = lSetup24BitPalette (pPD, pdevinfo, pGDIInfo); if( lRet < 1 ) { #if DBG DbgPrint( "Rasdd!GetPalette8BPP returns %ld\n", lRet ); #endif return(FALSE); } } else { if( pUDPDev->Resolution.fDump & RES_DM_COLOR ) { /* * We appear to GDI as an RGB surface, regardless of what * the printer is. CMY(K) printers have their pallete * reversed at rendering time. This is required for Win 3.1 * compatability and many things assume an RGB palette, and * break if this is not the case. * * DC_PRIMARY_RGB * ------------------------------------------ * Index 0 = Black * Index 1 = Red * Index 2 = Green * Index 3 = Yellow * Index 4 = Blue * Index 5 = Magenta * Index 6 = Cyan * Index 7 = White *-------------------------------------------- * Bit 0 = Red * Bit 1 = Green * Bit 2 = Blue * * If a separate black dye is available, this can be arranged * to fall out at transpose time - we have a slightly different * transpose table to do the work. */ /* * Many apps and the engine presume an RGB colour model, so * we pretend to be one! We invert the bits at render time. */ pPD->iWhiteIndex = 7; /* * Set the palette colours. Remember we are only RGB format. * NOTE that gdisrv requires us to fill in all 16 entries, * even though we have only 8. So the second 8 are a duplicate * of the first 8. */ pPD->ulPalCol[ 0 ] = pPD->ulPalCol[ 8 ] = RGB( 0x00, 0x00, 0x00 ); pPD->ulPalCol[ 1 ] = pPD->ulPalCol[ 9 ] = RGB( 0xff, 0x00, 0x00 ); pPD->ulPalCol[ 2 ] = pPD->ulPalCol[ 10 ] = RGB( 0x00, 0xff, 0x00 ); pPD->ulPalCol[ 3 ] = pPD->ulPalCol[ 11 ] = RGB( 0xff, 0xff, 0x00 ); pPD->ulPalCol[ 4 ] = pPD->ulPalCol[ 12 ] = RGB( 0x00, 0x00, 0xff ); pPD->ulPalCol[ 5 ] = pPD->ulPalCol[ 13 ] = RGB( 0xff, 0x00, 0xff ); pPD->ulPalCol[ 6 ] = pPD->ulPalCol[ 14 ] = RGB( 0x00, 0xff, 0xff ); pPD->ulPalCol[ 7 ] = pPD->ulPalCol[ 15 ] = RGB( 0xff, 0xff, 0xff ); pPD->cPal = 16; pdevinfo->iDitherFormat = BMF_4BPP; pdevinfo->flGraphicsCaps |= GCAPS_FORCEDITHER; pGDIInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA; pGDIInfo->ulHTOutputFormat = HT_FORMAT_4BPP; /* * !ganeshp:Temp Fix for fixing the mapping light gray color to * white on color Printers.This will be removed once we have * text dithering capability in GDI and support for getting * back the original color. Map a Off white Color to black on * color printers. */ pPD->ulPalCol[ 8 ] = RGB( 0xf0, 0xf0, 0xf0 ); } else { /* * Monochrome printer, so there are only 2 colours, black * and white. It would be nice if the bitmap was set with * black as 1 and white as 0. HOWEVER, there are presumptions * all over the place that 0 is black. SO, we set them to * the preferred way, then invert before rendering. */ pPD->cPal = 2; pPD->ulPalCol[ 0 ] = RGB(0x00, 0x00, 0x00); pPD->ulPalCol[ 1 ] = RGB(0xff, 0xff, 0xff); pPD->iWhiteIndex = 1; pdevinfo->iDitherFormat = BMF_1BPP; /* Monochrome format */ pGDIInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA; pGDIInfo->ulHTOutputFormat = HT_FORMAT_1BPP; } } if (pUDPDev->sBitsPixel == 24 && pUDPDev->sDevPlanes == 1) pPDev->hpal = pdevinfo->hpalDefault = EngCreatePalette( PAL_RGB, 0, 0, 0, 0, 0 ); else pPDev->hpal = pdevinfo->hpalDefault = EngCreatePalette( PAL_INDEXED, pPD->cPal, pPD->ulPalCol, 0, 0, 0 ); if (pPDev->hpal == (HPALETTE) NULL) { return(FALSE); } pGDIInfo->ulNumPalReg = pPD->cPal; return(TRUE); #undef pUDPDev } /****************************** Function Header ***************************** * vLogFont * Turn an IFIMETRICS structure into a LOGFONT structure, for whatever * reason this is needed. * * RETURNS: * Nothing, as this function cannot fail! * * HISTORY: * 16:46 on Sat 20 Mar 1993 -by- Lindsay Harris [lindsayh] * Formalise it, handle scalable fonts. * * Initial version was written in the early days. * ****************************************************************************/ void vLogFont( pLF, pFM ) LOGFONT *pLF; /* Output is a LOGFONT */ FONTMAP *pFM; /* Input is a FONTMAP */ { /* * Convert from IFIMETRICS to LOGFONT type structure. */ int iLen; /* Loop variable */ IFIMETRICS *pIFI; WCHAR *pwch; /* Address of face name */ pIFI = pFM->pIFIMet; /* The BIG metrics */ pLF->lfHeight = pIFI->fwdWinAscender + pIFI->fwdWinDescender; pLF->lfWidth = pIFI->fwdAveCharWidth; /* * Note that this may be a scalable font, in which case we pick a * reasonable number! */ if( pIFI->flInfo & (FM_INFO_ISOTROPIC_SCALING_ONLY|FM_INFO_ANISOTROPIC_SCALING_ONLY|FM_INFO_ARB_XFORMS)) { /* * Invent an arbitrary size. We choose an approximately 10 point * font. The height is achieved easily, as we simply set the * height based on the device resolution! For the width, adjust * it using the same factor as we used on the height. This * assumes that the resolution is the same in both directions, * but this is reasonable given laser printers are the most * common with scalable fonts. */ pLF->lfHeight = pFM->wYRes / 7; /* This is about 10 points */ pLF->lfWidth = (2 * pLF->lfHeight * pFM->wXRes) / (3 * pFM->wYRes); } pLF->lfEscapement = 0; pLF->lfOrientation = 0; pLF->lfWeight = pIFI->usWinWeight; pLF->lfItalic = (BYTE)((pIFI->fsSelection & FM_SEL_ITALIC) ? 1 : 0); pLF->lfUnderline = (BYTE)((pIFI->fsSelection & FM_SEL_UNDERSCORE) ? 1 : 0); pLF->lfStrikeOut = (BYTE)((pIFI->fsSelection & FM_SEL_STRIKEOUT) ? 1 : 0); pLF->lfCharSet = pIFI->jWinCharSet; pLF->lfOutPrecision = OUT_DEFAULT_PRECIS; pLF->lfClipPrecision = CLIP_DEFAULT_PRECIS; pLF->lfQuality = DEFAULT_QUALITY; pLF->lfPitchAndFamily = pIFI->jWinPitchAndFamily; /* * Copy the face name, after figuring out it's address! */ pwch = (WCHAR *)((BYTE *)pIFI + pIFI->dpwszFaceName); iLen = min( wcslen( pwch ), LF_FACESIZE - 1 ); wcsncpy( pLF->lfFaceName, pwch, iLen ); pLF->lfFaceName[ iLen ] = (WCHAR)0; return; }