Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1511 lines
37 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
enable.c
Abstract:
Implementation of PostScript driver entry points:
DrvEnableDriver
DrvDisableDriver
DrvEnablePDEV
DrvResetPDEV
DrvCompletePDEV
DrvDisablePDEV
DrvEnableSurface
DrvDisableSurface
[Environment:]
Win32 subsystem, PostScript driver, kernel mode
Revision History:
10/16/90 -kentse-
Created it.
08/22/95 -kentse-
Implement soft font support in kernel mode.
Clean up.
mm/dd/yy -author-
description
--*/
#define _HTUI_APIS_
#include "pscript.h"
#include "halftone.h"
HSEMAPHORE hSoftListSemaphore;
HSEMAPHORE hPpdSemaphore;
VOID FreePdevMemory(PDEVDATA);
BOOL FillPsDevData(PDEVDATA, PDEVMODE, PWSTR);
BOOL FillPsDevInfo(PDEVDATA, ULONG, PDEVINFO);
VOID FillPsDevCaps(PDEVDATA, ULONG, ULONG *);
BOOL SetFormMetrics(PDEVDATA);
BOOL SameDevmodeFormTray(PDEVMODE, PDEVMODE);
BOOL ComputePsGlyphSet(VOID);
VOID FreePsGlyphSet(VOID);
DWORD PickDefaultHTPatSize(DWORD, DWORD, BOOL);
// Our DRVFN table which tells the engine where to find the
// routines we support.
static DRVFN gadrvfn[] =
{
{INDEX_DrvEnablePDEV, (PFN)DrvEnablePDEV },
{INDEX_DrvResetPDEV, (PFN)DrvResetPDEV },
{INDEX_DrvCompletePDEV, (PFN)DrvCompletePDEV },
{INDEX_DrvDisablePDEV, (PFN)DrvDisablePDEV },
{INDEX_DrvEnableSurface, (PFN)DrvEnableSurface },
{INDEX_DrvDisableSurface, (PFN)DrvDisableSurface },
{INDEX_DrvBitBlt, (PFN)DrvBitBlt },
{INDEX_DrvStretchBlt, (PFN)DrvStretchBlt },
{INDEX_DrvCopyBits, (PFN)DrvCopyBits },
{INDEX_DrvTextOut, (PFN)DrvTextOut },
{INDEX_DrvQueryFont, (PFN)DrvQueryFont },
{INDEX_DrvQueryFontTree, (PFN)DrvQueryFontTree },
{INDEX_DrvQueryFontData, (PFN)DrvQueryFontData },
{INDEX_DrvSendPage, (PFN)DrvSendPage },
{INDEX_DrvStrokePath, (PFN)DrvStrokePath },
{INDEX_DrvFillPath, (PFN)DrvFillPath },
{INDEX_DrvStrokeAndFillPath,(PFN)DrvStrokeAndFillPath},
{INDEX_DrvRealizeBrush, (PFN)DrvRealizeBrush },
{INDEX_DrvStartPage, (PFN)DrvStartPage },
{INDEX_DrvStartDoc, (PFN)DrvStartDoc },
{INDEX_DrvEscape, (PFN)DrvEscape },
{INDEX_DrvDrawEscape, (PFN)DrvDrawEscape },
{INDEX_DrvEndDoc, (PFN)DrvEndDoc },
{INDEX_DrvGetGlyphMode, (PFN)DrvGetGlyphMode },
{INDEX_DrvFontManagement, (PFN)DrvFontManagement },
{INDEX_DrvQueryAdvanceWidths, (PFN)DrvQueryAdvanceWidths}
};
BOOL
DrvEnableDriver(
ULONG iEngineVersion,
ULONG cb,
PDRVENABLEDATA pded
)
/*++
Routine Description:
Implementation of DDI entry point DrvEnableDriver.
Please refer to DDK documentation for more details.
--*/
{
TRACEDDIENTRY("DrvEnableDriver");
// Make sure we have a valid engine version and
// we're given enough room for the DRVENABLEDATA.
if (iEngineVersion < DDI_DRIVER_VERSION ||
cb < sizeof(DRVENABLEDATA))
{
DBGMSG(DBG_LEVEL_ERROR, "Invalid parameters.\n");
SETLASTERROR(ERROR_BAD_DRIVER_LEVEL);
return FALSE;
}
// Fill in the DRVENABLEDATA structure for the engine.
pded->iDriverVersion = DDI_DRIVER_VERSION;
pded->c = sizeof(gadrvfn) / sizeof(DRVFN);
pded->pdrvfn = gadrvfn;
// One-time initialization, such as the creation of semaphores,
// may be performed at this time. The actual enabling of hardware
// should wait until DrvEnablePDEV is called.
hPpdSemaphore = CREATESEMAPHORE();
hSoftListSemaphore = CREATESEMAPHORE();
// Compute glyph set supported by PostScript driver
return ComputePsGlyphSet();
}
DHPDEV
DrvEnablePDEV(
PDEVMODE pdriv,
PWSTR pwstrLogAddress,
ULONG cPatterns,
HSURF *ahsurfPatterns,
ULONG cjGdiInfo,
ULONG *pGdiInfo,
ULONG cb,
PDEVINFO pdevinfo,
HDEV hdev,
PWSTR pwstrDeviceName,
HANDLE hPrinter
)
/*++
Routine Description:
Implementation of DDI entry point DrvEnablePDEV.
Please refer to DDK documentation for more details.
--*/
{
DWORD count;
PDEVDATA pdev;
HHEAP hheap;
TRACEDDIENTRY("DrvEnablePDEV");
UNREFERENCED_PARAMETER(pwstrLogAddress);
// Create a heap and allocate memory for our DEVDATA block.
if ((hheap = HEAPCREATE()) == NULL) {
DBGERRMSG("HEAPCREATE");
return NULL;
}
// Allocate the pdev and store the heap handle in there.
if ((pdev = HEAPALLOC(hheap, sizeof(DEVDATA))) == NULL) {
DBGERRMSG("HEAPALLOC");
HEAPDESTROY(hheap);
return NULL;
}
memset(pdev, 0, sizeof(DEVDATA));
pdev->hheap = hheap;
pdev->hPrinter = hPrinter;
pdev->pwstrDocName = (PWSTR) NULL;
// Get a handle to the driver DLL module from DDI.
pdev->hModule = EngLoadModule(EngGetDriverName(hdev));
if (pdev->hModule == NULL) {
DBGERRMSG("EngLoadModule");
FreePdevMemory(pdev);
return NULL;
}
// Load the printer description file
ACQUIRESEMAPHORE(hPpdSemaphore);
pdev->hppd = PpdCreate(EngGetPrinterDataFileName(hdev));
RELEASESEMAPHORE(hPpdSemaphore);
if (pdev->hppd == NULL) {
DBGERRMSG("PpdCreate");
FreePdevMemory(pdev);
return NULL;
}
// Initialize the PostScript output buffer
psinitbuf(pdev);
// Allocate memory for default user's color adjustment
if ((pdev->pvDrvHTData = HEAPALLOC(hheap, sizeof(DRVHTINFO))) == NULL)
{
DBGERRMSG("HEAPALLOC");
FreePdevMemory(pdev);
return NULL;
}
memset(pdev->pvDrvHTData, 0, sizeof(DRVHTINFO));
// Fill in DEVDATA structure and DEVMODE information
if (! FillPsDevData(pdev, pdriv, pwstrDeviceName)) {
DBGERRMSG("FillPsDevData");
FreePdevMemory(pdev);
return NULL;
}
// Fill in the device capabilities for the engine.
FillPsDevCaps(pdev, cjGdiInfo, pGdiInfo);
// Get the count of device fonts for the current printer.
// Do not enumerate device fonts unless told to do so.
pdev->cDeviceFonts =
(pdev->pPrinterData->dwFlags & PSDEV_IGNORE_DEVFONT) ?
0 : LISTOBJ_Count((PLISTOBJ) pdev->hppd->pFontList);
// Now add in any installed soft fonts.
EnumSoftFonts(pdev, hdev);
// Fill in DEVINFO structure. Must be called after EnumSoftFonts.
if (! FillPsDevInfo(pdev, cb, pdevinfo)) {
DBGERRMSG("FillPsDevInfo");
FreePdevMemory(pdev);
return NULL;
}
// Create bit arrays for keeping track of PS fonts.
// Use one bit for each device and soft fonts.
// If the bit for a device font is set, that means the
// device font has been used before. If the bit for a
// soft font is set, that means the soft font has been
// downloaded to the printer.
//
// The bit array in DEVDATA contains accumulated info.
// It's used to generate %%DocumentNeededFonts and
// %%DocumentSuppliedFonts DSC comments.
count = pdevinfo->cFonts;
pdev->pFontFlags = BitArrayCreate(pdev->hheap, count);
pdev->cgs.pFontFlags = BitArrayCreate(pdev->hheap, count);
if (! pdev->pFontFlags || ! pdev->cgs.pFontFlags) {
DBGERRMSG("BitArrayCreate");
FreePdevMemory(pdev);
return NULL;
}
// Get a pointer to NTFM structure for each of the device
// or soft font.
count = sizeof(PNTFM) * pdevinfo->cFonts;
if (count > 0) {
PNTFM *ppntfm;
if ((ppntfm = HEAPALLOC(pdev->hheap, count)) == NULL) {
DBGERRMSG("HEAPALLOC");
FreePdevMemory(pdev);
return NULL;
}
pdev->pDeviceNtfms = ppntfm;
memset(ppntfm, 0, count);
for (count = 1; count <= pdevinfo->cFonts; count++) {
*ppntfm = GetFont(pdev, count);
if (*ppntfm++ == NULL) {
DBGERRMSG("GetFont");
FreePdevMemory(pdev);
return NULL;
}
}
}
// We will zero out all the hSurface for the pattern so that engine can
// automatically simulate the staandard pattern for us
memset(ahsurfPatterns, 0, sizeof(HSURF) * cPatterns);
// Return a pointer to our DEVDATA structure. It is supposed to
// be a handle, but we know it is a pointer.
return (DHPDEV) pdev;
}
BOOL
DrvResetPDEV(
DHPDEV dhpdevOld,
DHPDEV dhpdevNew
)
/*++
Routine Description:
Implementation of DDI entry point DrvResetPDEV.
Please refer to DDK documentation for more details.
--*/
{
PDEVDATA pdevOld, pdevNew;
TRACEDDIENTRY("DrvResetPDEV");
// Since this call changes the device mode of an existing PDEV,
// make sure we have an existing, valid PDEV.
pdevOld = (PDEVDATA) dhpdevOld;
pdevNew = (PDEVDATA) dhpdevNew;
if (! bValidatePDEV(pdevOld) || ! bValidatePDEV(pdevNew)) {
DBGERRMSG("bValidatePDEV");
SETLASTERROR(ERROR_INVALID_PARAMETER);
return(FALSE);
}
if (pdevOld->dwFlags & PDEV_STARTDOC) {
if (pdevOld->iPageNumber > 0 &&
!bPageIndependence(pdevOld) && !bNoFirstSave(pdevOld))
{
ps_restore(pdevOld, FALSE, FALSE);
}
pdevNew->iPageNumber = pdevOld->iPageNumber;
pdevNew->dwFlags |= PDEV_RESETPDEV;
pdevNew->dwFlags |= pdevOld->dwFlags &
(PDEV_STARTDOC | PDEV_MANUALFEED | PDEV_INSIDE_PATHESCAPE |
PDEV_PROCSET | PDEV_RAWBEFOREPROCSET |
PDEV_EPSPRINTING_ESCAPE);
//
// Check if the new and the old PDEV have the same form/tray selection
//
if (SameDevmodeFormTray(&pdevNew->dm.dmPublic, &pdevOld->dm.dmPublic))
pdevNew->dwFlags |= PDEV_SAME_FORMTRAY;
// Carry over the accumulated PS font info
if (pdevOld->cDeviceFonts == pdevNew->cDeviceFonts &&
pdevOld->cSoftFonts == pdevNew->cSoftFonts)
{
if (pdevNew->pFontFlags) {
HEAPFREE(pdevNew->hheap, pdevNew->pFontFlags);
pdevNew->pFontFlags = NULL;
}
if (pdevOld->pFontFlags)
pdevNew->pFontFlags = BitArrayDuplicate(pdevNew->hheap, pdevOld->pFontFlags);
} else {
DBGMSG(DBG_LEVEL_WARNING, "Incorrect number of PS fonts.\n");
}
ASSERT(pdevNew->pSuppliedFonts == NULL);
pdevNew->pSuppliedFonts = pdevOld->pSuppliedFonts;
pdevOld->pSuppliedFonts = NULL;
}
// Flush any data left in the old output buffer
psflush(pdevOld);
}
VOID
DrvCompletePDEV(
DHPDEV dhpdev,
HDEV hdev
)
/*++
Routine Description:
Implementation of DDI entry point DrvCompletePDEV.
Please refer to DDK documentation for more details.
--*/
{
TRACEDDIENTRY("DrvCompletePDEV");
if (! bValidatePDEV((PDEVDATA)dhpdev)) {
DBGERRMSG("bValidatePDEV");
SETLASTERROR(ERROR_INVALID_PARAMETER);
return;
}
// Store the engine's handle to the physical device in our DEVDATA.
((PDEVDATA) dhpdev)->hdev = hdev;
}
HSURF
DrvEnableSurface(
DHPDEV dhpdev
)
/*++
Routine Description:
Implementation of DDI entry point DrvEnableSurface.
Please refer to DDK documentation for more details.
--*/
{
PDEVDATA pdev;
PDRVHTINFO pDrvHTInfo;
SIZEL sizlDev;
TRACEDDIENTRY("DrvEnableSurface");
// Get the pointer to our DEVDATA structure and make sure it's valid.
pdev = (PDEVDATA)dhpdev;
if (! bValidatePDEV(pdev)) {
DBGERRMSG("bValidatePDEV");
SETLASTERROR(ERROR_INVALID_PARAMETER);
return(0L);
}
pDrvHTInfo = (PDRVHTINFO)(pdev->pvDrvHTData);
if (pDrvHTInfo->HTBmpFormat == BMF_4BPP) {
if (pDrvHTInfo->pHTXB == NULL &&
(pDrvHTInfo->pHTXB =
HEAPALLOC(pdev->hheap, HTXB_TABLE_SIZE)) == NULL)
{
DBGERRMSG("HEAPALLOC");
return NULL;
}
} else {
if (pDrvHTInfo->pHTXB != NULL) {
HEAPFREE(pdev->hheap, pDrvHTInfo->pHTXB);
pDrvHTInfo->pHTXB = NULL;
}
}
// Invalidate the PALXlate table, and initial any flags
pDrvHTInfo->Flags = 0;
pDrvHTInfo->PalXlate[0] = 0xff;
pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
// Convert the imageable area from PostScript USER space into
// device space.
sizlDev.cx = PSRealToPixel(
pdev->CurForm.ImageArea.right - pdev->CurForm.ImageArea.left,
pdev->dm.dmPublic.dmPrintQuality);
sizlDev.cy = PSRealToPixel(
pdev->CurForm.ImageArea.top - pdev->CurForm.ImageArea.bottom,
pdev->dm.dmPublic.dmPrintQuality);
// Call the engine to create a surface handle for us.
pdev->hsurf = EngCreateDeviceSurface((DHSURF)pdev, sizlDev, BMF_24BPP);
if (pdev->hsurf == NULL) {
DBGERRMSG("EngCreateDeviceSurface");
return NULL;
}
EngAssociateSurface(pdev->hsurf, (HDEV)pdev->hdev,
(HOOK_BITBLT | HOOK_STRETCHBLT | HOOK_TEXTOUT |
HOOK_STROKEPATH | HOOK_FILLPATH | HOOK_COPYBITS |
HOOK_STROKEANDFILLPATH));
// Return the handle to the caller.
return(pdev->hsurf);
}
VOID
DrvDisableSurface(
DHPDEV dhpdev
)
/*++
Routine Description:
Implementation of DDI entry point DrvDisableSurface.
Please refer to DDK documentation for more details.
--*/
{
PDEVDATA pdev;
PDRVHTINFO pDrvHTInfo;
TRACEDDIENTRY("DrvDisableSurface");
// Get the pointer to our DEVDATA structure and make sure it is ours.
pdev = (PDEVDATA)dhpdev;
if (! bValidatePDEV(pdev))
return;
// Free up xlate table
pDrvHTInfo = (PDRVHTINFO)(pdev->pvDrvHTData);
if (pDrvHTInfo->pHTXB != NULL) {
HEAPFREE(pdev->hheap, pDrvHTInfo->pHTXB);
pDrvHTInfo->pHTXB = NULL;
}
// Delete our surface.
if (pdev->hsurf != NULL) {
// Call the engine to delete the surface handle.
EngDeleteSurface(pdev->hsurf);
// Zero out our the copy of the handle in our DEVDATA.
pdev->hsurf = NULL;
}
}
VOID
DrvDisablePDEV(
DHPDEV dhpdev
)
/*++
Routine Description:
Implementation of DDI entry point DrvDisablePDEV.
Please refer to DDK documentation for more details.
--*/
{
PDEVDATA pdev;
DWORD i;
TRACEDDIENTRY("DrvDisablePDEV");
pdev = (PDEVDATA)dhpdev;
if (! bValidatePDEV(pdev)) {
DBGERRMSG("bValidatePDEV");
SETLASTERROR(ERROR_INVALID_PARAMETER);
return;
}
// Free up our default device palette.
if (pdev->hpal)
EngDeletePalette(pdev->hpal);
// Initialize the PostScript output buffer
psinitbuf(pdev);
// Free up all memory allocated for the current PDEV
FreePdevMemory(pdev);
}
VOID
DrvDisableDriver(
VOID
)
/*++
Routine Description:
Implementation of DDI entry point DrvDisableDriver.
Please refer to DDK documentation for more details.
--*/
{
TRACEDDIENTRY("DrvDisableDriver");
// Free up memory used to store the set of supported glyph handles
FreePsGlyphSet();
// Free up memory used by the cached the soft font nodes
FlushSoftFontCache();
// Delete semaphore objects
DELETESEMAPHORE(hPpdSemaphore);
DELETESEMAPHORE(hSoftListSemaphore);
return;
}
VOID
FreePdevMemory(
PDEVDATA pdev
)
/*++
Routine Description:
Free up all memory associated with the specified PDEV
Arguments:
pdev Pointer to our DEVDATA structure
Return Value:
NONE
--*/
{
ASSERT(pdev != NULL);
// Unmap PSCRIPT.DLL module from memory
if (pdev->hModule != NULL) {
FREEMODULE(pdev->hModule);
}
// Free up memory occupied by the soft font information
FreeSoftFontInfo(pdev);
// Free up memory occupied by TrueType substitution table
if (pdev->pTTSubstTable) {
MEMFREE(pdev->pTTSubstTable);
}
// Free up memory occupied by the list of supplied fonts
ClearSuppliedGdiFonts(pdev);
// Free up memory occupied by printer property data
if (pdev->pPrinterData) {
MEMFREE(pdev->pPrinterData);
}
// Delete the PPD object
if (pdev->hppd != NULL) {
PpdDelete(pdev->hppd);
}
// Destroy the heap associated with the specified PDEV
// and all memory allocated from the heap.
HEAPDESTROY(pdev->hheap);
}
BOOL
bValidatePDEV(
PDEVDATA pdev
)
/*++
Routine Description:
Validate input DEVDATA structure
Arguments:
pdev Pointer to DEVDATA structure
Return Value:
TRUE if DEVDATA structure is valid. FALSE otherwise.
--*/
{
return (pdev != NULL &&
pdev->dwID == DRIVER_SIGNATURE &&
pdev->dwEndPDEV == DRIVER_SIGNATURE);
}
BOOL
FillPsDevData(
PDEVDATA pdev,
PDEVMODE pdm,
PWSTR pwstrDeviceName
)
/*++
Routine Description:
Fill out DEVDATA structure and DEVMODE information
Arguments:
pdev Pointer to DEVDATA structure to fill in
pdm Pointer to input devmode information
pwstrDeviceName Pointer to device name string
Return Value:
TRUE if successful. FALSE otherwise.
--*/
{
// Mark the DEVDATA structure as ours.
pdev->dwID = pdev->dwEndPDEV = DRIVER_SIGNATURE;
// Now, initialize the flags.
pdev->dwFlags = 0L;
// Get printer property data from registry
// use default if it's not yet in the registry
pdev->pPrinterData = GetPrinterProperties(pdev->hPrinter, pdev->hppd);
if (pdev->pPrinterData == NULL) {
DBGERRMSG("GetPrinterProperties");
return FALSE;
}
// Initialize our DEVMODE structure for the current printer.
SetDefaultDevMode(
(PDEVMODE) &pdev->dm, pwstrDeviceName, pdev->hppd,
(pdev->pPrinterData->dwFlags & PSDEV_METRIC) != 0);
// Validate the devmode structure passed in by the user, if everything
// is OK, set the fields selected by the user.
if (! ValidateSetDevMode((PDEVMODE) &pdev->dm, pdm, pdev->hppd)) {
DBGERRMSG("ValidateSetDevMode");
}
if (! SetFormMetrics(pdev))
return FALSE;
// calculate maximum number of fonts we can download
pdev->maxDLFonts = pdev->pPrinterData->dwFreeVm / AVERAGE_FONT_SIZE;
if (pdev->maxDLFonts < 1)
pdev->maxDLFonts = 1;
// no page has been printed
pdev->iPageNumber = 0;
// set number of copies, this may get overwritten by SETCOPYCOUNT escape.
pdev->cCopies = pdev->dm.dmPublic.dmCopies;
// Read TrueType font substitution table from registry
pdev->pTTSubstTable = CurrentTrueTypeSubstTable(pdev->hPrinter);
if (pdev->pTTSubstTable == NULL) {
// Unable to read table from registry, use default
pdev->pTTSubstTable = DefaultTrueTypeSubstTable(pdev->hModule);
if (pdev->pTTSubstTable == NULL) {
DBGMSG(DBG_LEVEL_ERROR,
"Failed to initialze font substitution table.\n");
return FALSE;
}
}
// initialize the current graphics state.
pdev->pcgsSave = NULL;
memset(&pdev->cgs, 0, sizeof(CGS));
init_cgs(pdev);
// allocate memory for the DLFONT structures.
pdev->pDLFonts = HEAPALLOC(pdev->hheap, sizeof(DLFONT)*pdev->maxDLFonts);
if (!pdev->pDLFonts) {
DBGERRMSG("HEAPALLOC");
return(FALSE);
}
memset(pdev->pDLFonts, 0, sizeof(DLFONT) * pdev->maxDLFonts);
// set the scaling factor from the DEVMODE.
pdev->psfxScale = LTOPSFX(pdev->dm.dmPublic.dmScale) / 100;
pdev->ScaledDPI = ((pdev->dm.dmPublic.dmPrintQuality *
pdev->dm.dmPublic.dmScale) / 100);
// initialize the CharString buffer for Type 1 fonts.
pdev->pCSBuf = NULL;
pdev->pCSPos = NULL;
pdev->pCSEnd = NULL;
return(TRUE);
}
BOOL
FillPsDevInfo(
PDEVDATA pdev,
ULONG cb,
PDEVINFO pdevinfo
)
/*++
Routine Description:
Fill in the DEVINFO structure pointed to by pdevinfo.
Arguments:
pdev Pointer to our DEVDATA structure
cb Size of structure pointed to by pdevinfo
pdevinfo Pointer to DEVINFO structure
[Notes:]
Since we have to worry about not writing out more than cb bytes to
pdevinfo, we will fill in a local buffer, then copy cb bytes to
pdevinfo.
Return Value:
TRUE if successful. FALSE otherwise.
--*/
#define DEFAULT_POSTSCRIPT_POINT_SIZE 10
{
DEVINFO mydevinfo;
// fill in the graphics capabilities flags.
memset(&mydevinfo, 0, sizeof(mydevinfo));
mydevinfo.flGraphicsCaps = GCAPS_BEZIERS | GCAPS_GEOMETRICWIDE |
GCAPS_ALTERNATEFILL | GCAPS_WINDINGFILL |
GCAPS_OPAQUERECT | GCAPS_HALFTONE;
//
// Disable metafile spooling if necessary
//
if ((pdev->dm.dmPrivate.dwFlags & PSDEVMODE_METAFILE_SPOOL) == 0)
mydevinfo.flGraphicsCaps |= GCAPS_DONTJOURNAL;
if (pdev->cDeviceFonts > 0) {
/* Set DDI default font to Courier, 100 pixels tall */
wcscpy((PWSTR)mydevinfo.lfDefaultFont.lfFaceName, L"Courier");
mydevinfo.lfDefaultFont.lfEscapement = 0;
mydevinfo.lfDefaultFont.lfOrientation = 0;
mydevinfo.lfDefaultFont.lfHeight =
- ((pdev->dm.dmPublic.dmPrintQuality *
DEFAULT_POSTSCRIPT_POINT_SIZE) + 36) / 72;
mydevinfo.lfDefaultFont.lfWidth = 0;
mydevinfo.lfDefaultFont.lfWeight = 400;
mydevinfo.lfDefaultFont.lfItalic = 0;
mydevinfo.lfDefaultFont.lfUnderline = 0;
mydevinfo.lfDefaultFont.lfStrikeOut = 0;
mydevinfo.lfDefaultFont.lfPitchAndFamily = FF_MODERN | FIXED_PITCH;
// Copy default info ANSI_FIXED and ANSI_VARIABLE log fonts
memcpy(&mydevinfo.lfAnsiVarFont, &mydevinfo.lfDefaultFont, sizeof(LOGFONT));
memcpy(&mydevinfo.lfAnsiFixFont, &mydevinfo.lfDefaultFont, sizeof(LOGFONT));
// Now insert ANSI_FIXED and ANSI_VAR facenames
wcscpy((PWSTR)mydevinfo.lfAnsiVarFont.lfFaceName, L"Helvetica");
mydevinfo.lfAnsiVarFont.lfPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
wcscpy((PWSTR)mydevinfo.lfAnsiFixFont.lfFaceName, L"Courier");
mydevinfo.lfAnsiFixFont.lfPitchAndFamily = FF_MODERN | FIXED_PITCH;
}
// we do not reinitialize number of fonts at this time;
// just use whatever we computed previously. [bodind]
mydevinfo.cFonts = pdev->cDeviceFonts + pdev->cSoftFonts;
// since this can get called from DrvRestartPDEV, delete a palette if one
// exists, then create a new one.
if (pdev->hpal)
EngDeletePalette(pdev->hpal);
// create the default device palette. let the engine know we are an
// RGB device.
// we don't want the engine doing any dithering for us, we are
// a 24BPP device, let the printer do the work.
mydevinfo.cxDither = 0;
mydevinfo.cyDither = 0;
mydevinfo.iDitherFormat = BMF_24BPP;
if (!(mydevinfo.hpalDefault = EngCreatePalette(PAL_RGB, 0, 0, 0, 0, 0)))
{
DBGERRMSG("EngCreatePalette");
return(FALSE);
}
// store the palette handle in our PDEV.
pdev->hpal = mydevinfo.hpalDefault;
// now copy the DEVINFO structure.
memcpy((LPVOID)pdevinfo, (LPVOID)&mydevinfo, cb);
return(TRUE);
}
VOID
FillPsDevCaps(
PDEVDATA pdev,
ULONG cjGdiInfo,
ULONG *pGdiInfo
)
/*++
Routine Description:
Fill in the device capabilities information for the engine.
Arguments:
pdev Pointer to DEVDATA structure
cjGdiInfo Size of buffer pointed to by pGdiInfo
pGdiInfo Pointer to a GDIINFO buffer
Return Value:
NONE
--*/
{
DEVHTINFO CurDevHTInfo;
PDRVHTINFO pDrvHTInfo;
GDIINFO gdiinfo;
DWORD cbNeeded;
LONG lSize;
pDrvHTInfo = (PDRVHTINFO)pdev->pvDrvHTData;
// Make sure we don't overrun anything..
cjGdiInfo = min(cjGdiInfo, sizeof(GDIINFO));
// Since we have to worry about the size of the buffer, and
// we will most always be asked for full structure of information,
// fill in the entire structure locally, then copy the appropriate
// number of entries into the aulCaps buffer.
//!!! Need to check on the version number and what it means.
// fill in the version number.
gdiinfo.ulVersion = GDI_VERSION;
// Fill in the device classification index.
gdiinfo.ulTechnology = DT_RASPRINTER;
// Fill in the printable area in millimeters. The printable areas
// are provided in the PPD files in points. A point is 1/72 of an
// inch. There are 25.4 mm per inch. So, if X is the width in
// points, (X * 25.4) / 72 gives the number of millimeters.
// We then take into account the scaling factor of 100% Things to
// note: 2540 / 4 = 635. 72 / 4 = 18.
//
// Make the number negative, and it is now micrometers.
// this will make transforms just a bit more accurate.
//
// !!! PS unit is now represented in 24.8 fixed-point format.
lSize = PSRealToMicron(
pdev->CurForm.ImageArea.right - pdev->CurForm.ImageArea.left);
gdiinfo.ulHorzSize = (ULONG) (-lSize * 100 / pdev->dm.dmPublic.dmScale);
lSize = PSRealToMicron(
pdev->CurForm.ImageArea.top - pdev->CurForm.ImageArea.bottom);
gdiinfo.ulVertSize = (ULONG) (-lSize * 100 / pdev->dm.dmPublic.dmScale);
// Fill in the printable area in device units. The printable areas
// are provided in the PPD files in points. A point is 1/72 of an
// inch. The device resolution is given in device units per inch.
// So if X is the width in points, (X * resolution) / 72 gives the
// width in device units.
//
// !!! PS unit is now represented in 24.8 fixed-point format.
gdiinfo.ulHorzRes = PSRealToPixel(
pdev->CurForm.ImageArea.right - pdev->CurForm.ImageArea.left,
pdev->dm.dmPublic.dmPrintQuality);
gdiinfo.ulVertRes = PSRealToPixel(
pdev->CurForm.ImageArea.top - pdev->CurForm.ImageArea.bottom,
pdev->dm.dmPublic.dmPrintQuality);
// Fill in the default bitmap format information fields.
gdiinfo.cBitsPixel = 1;
gdiinfo.cPlanes = 1;
gdiinfo.ulDACRed = 0;
gdiinfo.ulDACGreen = 0;
gdiinfo.ulDACBlue = 0;
// Fill in number of physical, non-dithered colors printer can print.
gdiinfo.ulNumColors =
pdev->hppd->bColorDevice ? NUM_PURE_COLORS : NUM_PURE_GRAYS;
gdiinfo.flRaster = 0;
// It is assumed all postscript printers have 1:1 aspect ratio.
// fill in the pixels per inch.
gdiinfo.ulLogPixelsX = pdev->ScaledDPI;
gdiinfo.ulLogPixelsY = pdev->ScaledDPI;
// !!! [GilmanW] 16-Apr-1992 hack-attack
// !!! Return the new flTextCaps flags. I think these are alright, but
// !!! you better check them over, KentSe.
gdiinfo.flTextCaps =
TC_OP_CHARACTER // Can do OutputPrecision CHARACTER
| TC_OP_STROKE // Can do OutputPrecision STROKE
| TC_CP_STROKE // Can do ClipPrecision STROKE
| TC_CR_ANY // Can do CharRotAbility ANY
| TC_SF_X_YINDEP // Can do ScaleFreedom X_YINDEPENDENT
| TC_SA_DOUBLE // Can do ScaleAbility DOUBLE
| TC_SA_INTEGER // Can do ScaleAbility INTEGER
| TC_SA_CONTIN // Can do ScaleAbility CONTINUOUS
| TC_UA_ABLE // Can do UnderlineAbility ABLE
| TC_SO_ABLE; // Can do StrikeOutAbility ABLE
gdiinfo.xStyleStep = 1L;
gdiinfo.yStyleStep = 1L;
gdiinfo.ulAspectX = pdev->dm.dmPublic.dmPrintQuality;
gdiinfo.ulAspectY = gdiinfo.ulAspectX;
gdiinfo.ulAspectXY = (gdiinfo.ulAspectX * 1414) / 1000; // ~sqrt(2).
// Interesting value. It makes a dotted line have 25 dots per inch,
// and it matches RASDD.
gdiinfo.denStyleStep = pdev->dm.dmPublic.dmPrintQuality / 25;
// Let the world know of our margins
gdiinfo.ptlPhysOffset.x =
PSRealToPixel(
pdev->CurForm.ImageArea.left,
pdev->dm.dmPublic.dmPrintQuality);
gdiinfo.ptlPhysOffset.y =
PSRealToPixel(
pdev->CurForm.PaperSize.height - pdev->CurForm.ImageArea.top,
pdev->dm.dmPublic.dmPrintQuality);
// Let 'em know how big our piece of paper is.
gdiinfo.szlPhysSize.cx =
PSRealToPixel(
pdev->CurForm.PaperSize.width,
pdev->dm.dmPublic.dmPrintQuality);
gdiinfo.szlPhysSize.cy =
PSRealToPixel(
pdev->CurForm.PaperSize.height,
pdev->dm.dmPublic.dmPrintQuality);
// Retrieve halftone information
//
// We will do in following sequence, and exit the sequence if sucessful
//
// 1. Read from registry if one present (USER ADJUSTMENT)
// 2. Read from mini driver's default if one present (DEVICE DEFAULT)
// 3. Set standard halftone default (HALFTONE DEFAULT)
// Try to read halftone information from registry
if (GetDeviceHalftoneSetup(pdev->hPrinter, &CurDevHTInfo)) {
gdiinfo.ciDevice = CurDevHTInfo.ColorInfo;
gdiinfo.ulDevicePelsDPI = (ULONG)CurDevHTInfo.DevPelsDPI;
gdiinfo.ulHTPatternSize = (ULONG)CurDevHTInfo.HTPatternSize;
} else {
// Check if PPD file has any halftone information
// Use default halftone information
gdiinfo.ciDevice = DefDevHTInfo.ColorInfo;
gdiinfo.ulDevicePelsDPI = (ULONG)DefDevHTInfo.DevPelsDPI;
// 22-Nov-1994 Tue 16:08:23 updated -by- Daniel Chou (danielc)
// We must use the real printer resolution to pick the halftone
// pattern size
gdiinfo.ulHTPatternSize =
PickDefaultHTPatSize(pdev->dm.dmPublic.dmPrintQuality,
pdev->dm.dmPublic.dmPrintQuality,
FALSE);
}
// 17-Nov-1994 Thu 17:04:43 updated -by- Daniel Chou (danielc)
//
// We must also scaled the DevicePelsDPI because ulLogPixelX/Y are scaled
// and passed to the GDI, and later ulLogPixelX/Y will passed to the
// GDI halftone as Device Resolutions so relatively the DevicePelsDPI also
// will be scaled.
gdiinfo.ulDevicePelsDPI = (ULONG)((gdiinfo.ulDevicePelsDPI *
pdev->dm.dmPublic.dmScale) / 100);
// Validate this data, we do not want to have gdi go crazy.
if (gdiinfo.ulHTPatternSize > HT_PATSIZE_16x16_M) {
gdiinfo.ulHTPatternSize = (ULONG)DefDevHTInfo.HTPatternSize;
}
// Get halftone color adjustment information
pDrvHTInfo->ca = pdev->dm.dmPrivate.coloradj;
// PrimaryOrder ABC = RGB, which B=Plane1, G=Plane2, R=Plane3
gdiinfo.flHTFlags = HT_FLAG_HAS_BLACK_DYE;
gdiinfo.ulPrimaryOrder = (ULONG)PRIMARY_ORDER_ABC;
if (pdev->hppd->bColorDevice &&
(pdev->dm.dmPublic.dmColor == DMCOLOR_COLOR))
{
pDrvHTInfo->HTPalCount = 8;
pDrvHTInfo->HTBmpFormat = (BYTE)BMF_4BPP;
pDrvHTInfo->AltBmpFormat = (BYTE)BMF_1BPP;
gdiinfo.ulHTOutputFormat = HT_FORMAT_4BPP;
} else {
pDrvHTInfo->HTPalCount = 2;
pDrvHTInfo->HTBmpFormat = (BYTE)BMF_1BPP;
pDrvHTInfo->AltBmpFormat = (BYTE)0xff;
gdiinfo.ulHTOutputFormat = HT_FORMAT_1BPP;
}
pDrvHTInfo->Flags = 0;
pDrvHTInfo->PalXlate[0] = 0xff;
pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
// Copy cjGdiInfo elements of gdiinfo to aulCaps.
memcpy(pGdiInfo, &gdiinfo, cjGdiInfo);
}
BOOL
SetDefaultPrinterForm(
PDEVDATA pdev
)
/*++
Routine Description:
Save default printer form information in DEVDATA structure
Arguments:
pdev Pointer to DEVDATA structure
Return Value:
TRUE if successful. FALSE otherwise.
--*/
{
CHAR DefaultFormA[CCHFORMNAME];
WORD featureIndex;
HPPD hppd = pdev->hppd;
PMEDIAOPTION pMediaOption;
DBGMSG(DBG_LEVEL_WARNING, "Selecting the default printer form.\n");
// Sanity check
if (hppd->pPageSizes == NULL)
return FALSE;
// Get the default form name and convert it to ASCII
CopyUnicode2Str(
DefaultFormA,
GetDefaultFormName(pdev->pPrinterData->dwFlags & PSDEV_METRIC),
CCHFORMNAME);
// Check if the form is supported on the printer
pMediaOption = (PMEDIAOPTION)
PpdFindUiOptionWithXlation(
hppd->pPageSizes->pUiOptions, DefaultFormA, &featureIndex);
if (pMediaOption == NULL) {
// If the form is not supported on the device,
// use the default printer form.
featureIndex = (WORD) hppd->pPageSizes->dwDefault;
pMediaOption = (PMEDIAOPTION)
LISTOBJ_FindIndexed(
(PLISTOBJ) hppd->pPageSizes->pUiOptions, featureIndex);
}
if (pMediaOption == NULL)
return FALSE;
// Save default printer form information in DEVDATA structure
CopyStr2Unicode(pdev->CurForm.FormName, pMediaOption->pName, CCHFORMNAME);
CopyStringA(pdev->CurForm.PaperName, pMediaOption->pName, CCHFORMNAME);
pdev->CurForm.ImageArea = pMediaOption->imageableArea;
pdev->CurForm.PaperSize = pMediaOption->dimension;
pdev->CurForm.featureIndex = featureIndex;
return TRUE;
}
VOID
AdjustForLandscape(
PDEVDATA pdev
)
/*++
Routine Description:
Adjust paper size and imageable area for landscape orientation
Arguments:
pdev Pointer to DEVDATA structure
Return Value:
NONE
--*/
{
// We only have to do this when devmode specifies landscape mode
if ((pdev->dm.dmPublic.dmFields & DM_ORIENTATION) &&
(pdev->dm.dmPublic.dmOrientation == DMORIENT_LANDSCAPE))
{
PSRECT imagearea;
PSREAL psrealTmp;
// Swap width and height dimensions
psrealTmp = pdev->CurForm.PaperSize.width;
pdev->CurForm.PaperSize.width = pdev->CurForm.PaperSize.height;
pdev->CurForm.PaperSize.height = psrealTmp;
// Recalculate imageable area
if (! (pdev->dm.dmPrivate.dwFlags & PSDEVMODE_LSROTATE)) {
// Normal landscape (+90 degree rotation)
imagearea.left = pdev->CurForm.ImageArea.bottom;
imagearea.top = pdev->CurForm.PaperSize.height - pdev->CurForm.ImageArea.left;
imagearea.right = pdev->CurForm.ImageArea.top;
imagearea.bottom = pdev->CurForm.PaperSize.height - pdev->CurForm.ImageArea.right;
} else {
// Rotated landscape (-90 degree rotation)
imagearea.left = pdev->CurForm.PaperSize.width - pdev->CurForm.ImageArea.top;
imagearea.top = pdev->CurForm.ImageArea.right;
imagearea.right = pdev->CurForm.PaperSize.width - pdev->CurForm.ImageArea.bottom;
imagearea.bottom = pdev->CurForm.ImageArea.left;
}
pdev->CurForm.ImageArea = imagearea;
// Indicate we selected landscape mode
pdev->CurForm.bLandscape = TRUE;
}
}
BOOL
SetFormMetrics(
PDEVDATA pdev
)
/*++
Routine Description:
Fill in the printer form information in DEVDATA structure.
Arguments:
pdev Pointer to DEVDATA structure
Return Value:
TRUE if successful. FALSE otherwise.
--*/
{
LOGFORM logForm;
PDEVMODE pdm = (PDEVMODE) &pdev->dm;
// Find the form specified in the devmode. Then try to match that
// form to a printer form. Fall back to default printer form if
// that fails.
if (ValidateDevModeForm(pdev->hPrinter, pdm, &logForm) == FORM_ERROR ||
! FormSupportedOnPrinter(
pdev->hppd, (PFORM_INFO_1) &logForm, &pdev->CurForm, FALSE))
{
if (! SetDefaultPrinterForm(pdev)) {
DBGERRMSG("SetDefaultPrinterForm");
return FALSE;
}
}
// Adjust size and imageable area for landscape orientation
AdjustForLandscape(pdev);
return TRUE;
}
BOOL
SameDevmodeFormTray(
PDEVMODE pdmNew,
PDEVMODE pdmOld
)
/*++
Routine Description:
Check if the form/tray selection specified in the new and the old devmode is identical
Arguments:
pdmNew - Specifies the new devmode
pdmOld - Specifies the old devmode
Return Value:
TRUE if the form/tray selection is identical in the new and old devmode
FALSE otherwise
--*/
{
BOOL sameForm, sameTray;
//
// Check if the tray selection is the same
//
sameTray = (pdmNew->dmDefaultSource == pdmOld->dmDefaultSource);
//
// Check if the form selection is the same
//
if (IsCustomForm(pdmNew)) {
sameForm = IsCustomForm(pdmOld) &&
pdmNew->dmPaperWidth == pdmOld->dmPaperWidth &&
pdmNew->dmPaperLength == pdmOld->dmPaperLength;
} else if (pdmNew->dmFields & DM_PAPERSIZE) {
sameForm = (pdmOld->dmFields & DM_PAPERSIZE) &&
pdmNew->dmPaperSize == pdmOld->dmPaperSize;
} else if (pdmNew->dmFields & DM_FORMNAME) {
sameForm = (pdmOld->dmFields & DM_FORMNAME) &&
wcscmp(pdmNew->dmFormName, pdmOld->dmFormName) == EQUAL_STRING;
} else
sameForm = FALSE;
return sameForm & sameTray;
}