mirror of https://github.com/lianthony/NT4.0
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
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;
|
|
}
|
|
|