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.
1141 lines
23 KiB
1141 lines
23 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
winddi.c
|
|
|
|
Abstract:
|
|
|
|
Implementation of device and surface related DDI entry points:
|
|
|
|
DrvEnableDriver
|
|
DrvDisableDriver
|
|
DrvEnablePDEV
|
|
DrvResetPDEV
|
|
DrvCompletePDEV
|
|
DrvDisablePDEV
|
|
DrvEnableSurface
|
|
DrvDisableSurface
|
|
|
|
Environment:
|
|
|
|
PCL-XL driver, kernel mode
|
|
|
|
Revision History:
|
|
|
|
11/04/95 -davidx-
|
|
Created it.
|
|
|
|
mm/dd/yy -author-
|
|
description
|
|
|
|
--*/
|
|
|
|
#include "xldrv.h"
|
|
|
|
//
|
|
// Forward declaration of local functions
|
|
//
|
|
|
|
static VOID FreeDevData(PDEVDATA);
|
|
static VOID SetPrinterForm(PDEVDATA);
|
|
static VOID SetDefaultForm(PDEVDATA);
|
|
static VOID AdjustLandscapeForm(PPRINTERFORM, INT);
|
|
static BOOL FillDevData(PDEVDATA, PDEVMODE, PWSTR);
|
|
static BOOL FillDevInfo(PDEVDATA, ULONG, PVOID);
|
|
static BOOL FillGdiInfo(PDEVDATA, ULONG, PVOID);
|
|
|
|
|
|
//
|
|
// Our DRVFN table which tells the engine where to find the routines we support.
|
|
//
|
|
|
|
static DRVFN XlDriverFuncs[] =
|
|
{
|
|
{ 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_DrvStartDoc, (PFN) DrvStartDoc },
|
|
{ INDEX_DrvEndDoc, (PFN) DrvEndDoc },
|
|
{ INDEX_DrvStartPage, (PFN) DrvStartPage },
|
|
{ INDEX_DrvSendPage, (PFN) DrvSendPage },
|
|
|
|
{ INDEX_DrvRealizeBrush, (PFN) DrvRealizeBrush },
|
|
{ INDEX_DrvCopyBits, (PFN) DrvCopyBits },
|
|
{ INDEX_DrvBitBlt, (PFN) DrvBitBlt },
|
|
{ INDEX_DrvStretchBlt, (PFN) DrvStretchBlt },
|
|
{ INDEX_DrvPaint, (PFN) DrvPaint },
|
|
{ INDEX_DrvStrokePath, (PFN) DrvStrokePath },
|
|
{ INDEX_DrvFillPath, (PFN) DrvFillPath },
|
|
{ INDEX_DrvStrokeAndFillPath, (PFN) DrvStrokeAndFillPath },
|
|
{ INDEX_DrvTextOut, (PFN) DrvTextOut },
|
|
|
|
{ INDEX_DrvEscape, (PFN) DrvEscape },
|
|
|
|
{ INDEX_DrvQueryFont, (PFN) DrvQueryFont },
|
|
{ INDEX_DrvQueryFontTree, (PFN) DrvQueryFontTree },
|
|
{ INDEX_DrvQueryFontData, (PFN) DrvQueryFontData },
|
|
{ INDEX_DrvGetGlyphMode, (PFN) DrvGetGlyphMode },
|
|
{ INDEX_DrvFontManagement, (PFN) DrvFontManagement },
|
|
{ INDEX_DrvQueryAdvanceWidths, (PFN) DrvQueryAdvanceWidths },
|
|
};
|
|
|
|
//
|
|
// Definition of global variables
|
|
//
|
|
|
|
INT _debugLevel; // control the amount of debug messages generated
|
|
|
|
|
|
BOOL
|
|
DrvEnableDriver(
|
|
ULONG iEngineVersion,
|
|
ULONG cb,
|
|
PDRVENABLEDATA pDrvEnableData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvEnableDriver.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
iEngineVersion - Specifies the DDI version number that GDI is written for
|
|
cb - Size of the buffer pointed to by pDrvEnableData
|
|
pDrvEnableData - Points to an DRVENABLEDATA structure
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
_debugLevel = 1;
|
|
Verbose(("Entering DrvEnableDriver...\n"));
|
|
|
|
//
|
|
// 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)) {
|
|
|
|
Error(("DrvEnableDriver failed\n"));
|
|
SetLastError(ERROR_BAD_DRIVER_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Fill in the DRVENABLEDATA structure for the engine.
|
|
//
|
|
|
|
pDrvEnableData->iDriverVersion = DDI_DRIVER_VERSION;
|
|
pDrvEnableData->c = sizeof(XlDriverFuncs) / sizeof(DRVFN);
|
|
pDrvEnableData->pdrvfn = XlDriverFuncs;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
DHPDEV
|
|
DrvEnablePDEV(
|
|
PDEVMODE pdm,
|
|
PWSTR pLogAddress,
|
|
ULONG cPatterns,
|
|
HSURF *phsurfPatterns,
|
|
ULONG cjGdiInfo,
|
|
ULONG *pGdiInfo,
|
|
ULONG cjDevInfo,
|
|
DEVINFO *pDevInfo,
|
|
HDEV hdev,
|
|
PWSTR pDeviceName,
|
|
HANDLE hPrinter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvEnablePDEV.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
pdm - Points to a DEVMODEW structure that contains driver data
|
|
pLogAddress - Points to the logical address string
|
|
cPatterns - Specifies the number of standard patterns
|
|
phsurfPatterns - Buffer to hold surface handles to standard patterns
|
|
cjGdiInfo - Size of GDIINFO buffer
|
|
pGdiInfo - Points to a GDIINFO structure
|
|
cjDevInfo - Size of DEVINFO buffer
|
|
pDevInfo - Points to a DEVINFO structure
|
|
hdev - GDI device handle
|
|
pDeviceName - Points to device name string
|
|
hPrinter - Spooler printer handle
|
|
|
|
Return Value:
|
|
|
|
Driver device handle, NULL if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVDATA pdev;
|
|
|
|
Verbose(("Entering DrvEnablePDEV...\n"));
|
|
|
|
//
|
|
// Allocate memory for our DEVDATA structure and initialize it
|
|
//
|
|
|
|
if (! (pdev = MemAlloc(sizeof(DEVDATA)))) {
|
|
|
|
Error(("MemAlloc failed\n"));
|
|
return NULL;
|
|
}
|
|
|
|
memset(pdev, 0, sizeof(DEVDATA));
|
|
pdev->hPrinter = hPrinter;
|
|
|
|
//
|
|
// Get a handle to the driver DLL module from DDI.
|
|
//
|
|
|
|
if (! (pdev->hInst = EngLoadModule(EngGetDriverName(hdev)))) {
|
|
|
|
Error(("EngLoadModule failed\n"));
|
|
MemFree(pdev);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Fill out DEVDATA, GDIINFO, and DEVINFO structures
|
|
//
|
|
|
|
if (! FillDevData(pdev, pdm, EngGetPrinterDataFileName(hdev)) ||
|
|
! FillGdiInfo(pdev, cjGdiInfo, pGdiInfo) ||
|
|
! FillDevInfo(pdev, cjDevInfo, pDevInfo))
|
|
{
|
|
Error(("Couldn't get device data\n"));
|
|
FreeDevData(pdev);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Zero out the array of HSURF's so that the engine will
|
|
// automatically simulate the standard patterns for us
|
|
//
|
|
|
|
memset(phsurfPatterns, 0, sizeof(HSURF) * cPatterns);
|
|
|
|
//
|
|
// Return a pointer to our DEVDATA structure
|
|
//
|
|
|
|
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.
|
|
|
|
Arguments:
|
|
|
|
phpdevOld - Driver handle to the old device
|
|
phpdevNew - Driver handle to the new device
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVDATA pdevOld, pdevNew;
|
|
|
|
Verbose(("Entering DrvResetPDEV...\n"));
|
|
|
|
//
|
|
// 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 (! ValidDevData(pdevOld) || ! ValidDevData(pdevNew)) {
|
|
|
|
Error(("ValidDevData failed\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Transfer information from old DEVDATA to new DEVDATA
|
|
//
|
|
|
|
if (pdevOld->pageCount != 0) {
|
|
|
|
pdevNew->pageCount = pdevOld->pageCount;
|
|
pdevNew->flags |= PDEV_RESETPDEV;
|
|
|
|
//
|
|
// Carry over information about downloaded fonts
|
|
//
|
|
|
|
pdevNew->pdlFonts = pdevOld->pdlFonts;
|
|
pdevOld->pdlFonts = NULL;
|
|
}
|
|
|
|
//
|
|
// Carry over relevant flag bits
|
|
//
|
|
|
|
pdevNew->flags |= pdevOld->flags & (PDEV_CANCELLED);
|
|
|
|
//
|
|
// Flush out any buffered data for the original device
|
|
//
|
|
|
|
return splflush(pdevOld);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DrvCompletePDEV(
|
|
DHPDEV dhpdev,
|
|
HDEV hdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvCompletePDEV.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Driver device handle
|
|
hdev - GDI device handle
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVDATA pdev = (PDEVDATA) dhpdev;
|
|
|
|
Verbose(("Entering DrvCompletePDEV...\n"));
|
|
|
|
if (! ValidDevData(pdev)) {
|
|
|
|
Assert(FALSE);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Remember the engine's handle to the physical device
|
|
//
|
|
|
|
pdev->hdev = hdev;
|
|
}
|
|
|
|
|
|
|
|
HSURF
|
|
DrvEnableSurface(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvEnableSurface.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Driver device handle
|
|
|
|
Return Value:
|
|
|
|
Handle to newly created surface, NULL if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVDATA pdev = (PDEVDATA) dhpdev;
|
|
SIZEL size;
|
|
|
|
Verbose(("Entering DrvEnableSurface...\n"));
|
|
|
|
//
|
|
// Validate the pointer to our DEVDATA structure
|
|
//
|
|
|
|
if (! ValidDevData(pdev)) {
|
|
|
|
Error(("ValidDevData\n"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Calculate the size of the device imageable area. Remeber to
|
|
// convert from our internal units (micron) to device pixels.
|
|
//
|
|
|
|
size.cx = MicronToPixel(
|
|
RectWidth(&pdev->paper.imageableArea),
|
|
pdev->dm.dmPublic.dmPrintQuality);
|
|
|
|
size.cy = MicronToPixel(
|
|
RectHeight(&pdev->paper.imageableArea),
|
|
pdev->dm.dmPublic.dmPrintQuality);
|
|
|
|
//
|
|
// Call the engine to create a device surface for us
|
|
//
|
|
|
|
pdev->hsurf = EngCreateDeviceSurface((DHSURF) pdev, size, BMF_24BPP);
|
|
|
|
if (pdev->hsurf == NULL) {
|
|
|
|
Error(("EngCreateDeviceSurface\n"));
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Associate the surface with the device and inform the
|
|
// engine which functions we have hooked out
|
|
//
|
|
|
|
EngAssociateSurface(pdev->hsurf, pdev->hdev,
|
|
HOOK_TEXTOUT |
|
|
HOOK_COPYBITS |
|
|
HOOK_BITBLT |
|
|
HOOK_STRETCHBLT |
|
|
HOOK_PAINT |
|
|
HOOK_STROKEPATH |
|
|
HOOK_FILLPATH |
|
|
HOOK_STROKEANDFILLPATH);
|
|
|
|
//
|
|
// Return the surface handle to the engine
|
|
//
|
|
|
|
return pdev->hsurf;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DrvDisableSurface(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvDisableSurface.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Driver device handle
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVDATA pdev = (PDEVDATA) dhpdev;
|
|
|
|
Verbose(("Entering DrvDisableSurface...\n"));
|
|
|
|
if (! ValidDevData(pdev)) {
|
|
|
|
Assert(FALSE);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Call the engine to delete the surface handle
|
|
//
|
|
|
|
if (pdev->hsurf != NULL) {
|
|
|
|
EngDeleteSurface(pdev->hsurf);
|
|
pdev->hsurf = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DrvDisablePDEV(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvDisablePDEV.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Driver device handle
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
PDEVDATA pdev = (PDEVDATA) dhpdev;
|
|
|
|
Verbose(("Entering DrvDisablePDEV...\n"));
|
|
|
|
if (! ValidDevData(pdev)) {
|
|
|
|
Assert(FALSE);
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Free up memory allocated for the current PDEV
|
|
//
|
|
|
|
FreeDevData(pdev);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DrvDisableDriver(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Implementation of DDI entry point DrvDisableDriver.
|
|
Please refer to DDK documentation for more details.
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
Verbose(("Entering DrvDisableDriver...\n"));
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
FreeDevData(
|
|
PDEVDATA pdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free up all memory associated with the specified PDEV
|
|
|
|
Arguments:
|
|
|
|
pdev Pointer to our DEVDATA structure
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
PDLFONT pdlFont, pdlFree;
|
|
|
|
Assert(ValidDevData(pdev));
|
|
Assert(pdev->hInst && pdev->pmpd);
|
|
|
|
//
|
|
// Free up memory occupied by downloaded font data structures
|
|
//
|
|
|
|
pdlFont = pdev->pdlFonts;
|
|
|
|
while (pdlFont != NULL) {
|
|
|
|
pdlFree = pdlFont;
|
|
pdlFont = pdlFont->pNext;
|
|
FreeDownloadedFont(pdlFree);
|
|
}
|
|
|
|
//
|
|
// Memory used for downloaded character indices
|
|
//
|
|
|
|
MemFree(pdev->pCharIndexBuffer);
|
|
MemFree(pdev->pCharIndexFlags);
|
|
|
|
//
|
|
// Memory used for holding dashed line attributes
|
|
//
|
|
|
|
MemFree(pdev->cgs.pDashs);
|
|
|
|
//
|
|
// Free up our default device palette, if we had one.
|
|
//
|
|
|
|
if (pdev->hpal)
|
|
EngDeletePalette(pdev->hpal);
|
|
|
|
MpdDelete(pdev->pmpd);
|
|
EngFreeModule(pdev->hInst);
|
|
MemFree(pdev);
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
FillDevData(
|
|
PDEVDATA pdev,
|
|
PDEVMODE pdm,
|
|
PWSTR pwstrDataFile
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fill out DEVDATA structure and DEVMODE information
|
|
|
|
Arguments:
|
|
|
|
pdev - Pointer to DEVDATA structure to fill in
|
|
pdm - Pointer to input devmode information
|
|
pwstrDataFile - Pointer to the name of driver data file
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful. FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Mark the DEVDATA structure as ours
|
|
//
|
|
|
|
Assert(pdev != NULL);
|
|
pdev->signature = DRIVER_SIGNATURE;
|
|
|
|
//
|
|
// Load PCL-XL printer description data
|
|
//
|
|
// Get printer property data from registry
|
|
// use default if it's not yet in the registry
|
|
//
|
|
// Combine DEVMODE information:
|
|
// start with the driver default
|
|
// then merge with the system default
|
|
// finally merge with the input devmode
|
|
//
|
|
|
|
if (!(pdev->pmpd = MpdCreate(pwstrDataFile)) ||
|
|
!GetPrinterProperties(&pdev->prnprop, pdev->hPrinter, pdev->pmpd) ||
|
|
!GetCombinedDevmode(&pdev->dm, pdm, pdev->hPrinter, pdev->pmpd))
|
|
{
|
|
Error(("FillDevData failed\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Set printer paper size information
|
|
//
|
|
|
|
SetPrinterForm(pdev);
|
|
|
|
//
|
|
// Check if a device supports color
|
|
//
|
|
|
|
pdev->colorFlag =
|
|
ColorDevice(pdev->pmpd) &&
|
|
(pdev->dm.dmPublic.dmFields & DM_COLOR) && pdev->dm.dmPublic.dmColor == DMCOLOR_COLOR;
|
|
|
|
//
|
|
// Calculate number of device fonts
|
|
//
|
|
|
|
pdev->deviceFonts = pdev->pmpd->cFonts;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
FillDevInfo(
|
|
PDEVDATA pdev,
|
|
ULONG cb,
|
|
PVOID 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 first fill in a local buffer, then copy cb bytes
|
|
to pdevinfo.
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful. FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
DEVINFO devinfo;
|
|
|
|
memset(&devinfo, 0, sizeof(devinfo));
|
|
|
|
//
|
|
// Fill in the graphics capabilities flags
|
|
//
|
|
|
|
devinfo.flGraphicsCaps =
|
|
GCAPS_BEZIERS |
|
|
GCAPS_GEOMETRICWIDE |
|
|
GCAPS_ALTERNATEFILL |
|
|
GCAPS_WINDINGFILL |
|
|
GCAPS_OPAQUERECT |
|
|
GCAPS_ARBRUSHOPAQUE |
|
|
GCAPS_HALFTONE;
|
|
|
|
//
|
|
// Get information about the default device font. Default size 10 point.
|
|
//
|
|
|
|
if ((devinfo.cFonts = pdev->deviceFonts) > 0) {
|
|
|
|
PDEVFONT pFont;
|
|
PIFIMETRICS pifi;
|
|
|
|
pFont = pdev->pmpd->pFonts;
|
|
Assert(pFont != NULL);
|
|
|
|
if (pFont->pMetrics != NULL) {
|
|
|
|
pifi = OffsetToPointer(pFont->pMetrics, pFont->pMetrics->loIfiMetrics);
|
|
CopyStringW(devinfo.lfDefaultFont.lfFaceName,
|
|
OffsetToPointer(pifi, pifi->dpwszFaceName),
|
|
LF_FACESIZE);
|
|
|
|
devinfo.lfDefaultFont.lfPitchAndFamily = pifi->jWinPitchAndFamily;
|
|
devinfo.lfDefaultFont.lfWeight = pifi->usWinWeight;
|
|
devinfo.lfDefaultFont.lfHeight =
|
|
- (pdev->dm.dmPublic.dmPrintQuality * 10L + 36) / 72;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We don't want the engine to any dithering for us.
|
|
// Let the printer do the work instead.
|
|
//
|
|
|
|
devinfo.cxDither = devinfo.cyDither = 0;
|
|
devinfo.iDitherFormat = BMF_24BPP;
|
|
|
|
if (! (pdev->hpal = EngCreatePalette(PAL_RGB, 0, 0, 0, 0, 0))) {
|
|
|
|
Error(("EngCreatePalette\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
devinfo.hpalDefault = pdev->hpal;
|
|
|
|
//
|
|
// Now copy the DEVINFO structure into the caller-provided buffer
|
|
//
|
|
|
|
ErrorIf(cb != sizeof(devinfo),
|
|
("Incorrect devinfo buffer size: %d != %d\n", cb, sizeof(devinfo)));
|
|
|
|
memcpy(pdevinfo, &devinfo, min(cb, sizeof(devinfo)));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
FillGdiInfo(
|
|
PDEVDATA pdev,
|
|
ULONG cb,
|
|
PVOID pgdiinfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fill in the device capabilities information for the engine.
|
|
|
|
Arguments:
|
|
|
|
pdev - Pointer to DEVDATA structure
|
|
cb - Size of buffer pointed to by pgdiinfo
|
|
pgdiinfo - Pointer to a GDIINFO buffer
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
GDIINFO gdiinfo;
|
|
INT scale, resolution;
|
|
|
|
memset(&gdiinfo, 0, sizeof(gdiinfo));
|
|
scale = pdev->dm.dmPublic.dmScale;
|
|
resolution = pdev->dm.dmPublic.dmPrintQuality;
|
|
|
|
//
|
|
// This field doesn't seem to have any effect for printer drivers.
|
|
// Put our driver version number in there anyway.
|
|
//
|
|
|
|
gdiinfo.ulVersion = DRIVER_VERSION;
|
|
|
|
//
|
|
// We're raster printers
|
|
//
|
|
|
|
gdiinfo.ulTechnology = DT_RASPRINTER;
|
|
|
|
//
|
|
// Width and height of physical surface measured in microns.
|
|
// Remember to turn on the sign bit and also take scaling into account.
|
|
//
|
|
|
|
gdiinfo.ulHorzSize = -MulDiv(RectWidth(&pdev->paper.imageableArea), 100, scale);
|
|
gdiinfo.ulVertSize = -MulDiv(RectHeight(&pdev->paper.imageableArea), 100, scale);
|
|
|
|
//
|
|
// Width and height of physical surface measured in device pixels
|
|
//
|
|
|
|
gdiinfo.ulHorzRes =
|
|
MicronToPixel(RectWidth(&pdev->paper.imageableArea), resolution);
|
|
|
|
gdiinfo.ulVertRes =
|
|
MicronToPixel(RectHeight(&pdev->paper.imageableArea), resolution);
|
|
|
|
//
|
|
// Color depth information:
|
|
// If the device only has one color plane, then it's a monochrome
|
|
// or grayscale device. Otherwise, it's a color device.
|
|
//
|
|
|
|
gdiinfo.cBitsPixel = pdev->pmpd->bitsPerPlane;
|
|
gdiinfo.cPlanes = pdev->pmpd->numPlanes;
|
|
gdiinfo.ulNumColors =
|
|
1 << (((gdiinfo.cPlanes == 1) ? 1 : 3) * gdiinfo.cBitsPixel);
|
|
|
|
//
|
|
// Resolution information
|
|
//
|
|
|
|
gdiinfo.ulLogPixelsX =
|
|
gdiinfo.ulLogPixelsY = resolution * scale / 100;
|
|
|
|
//
|
|
// Win31 compatible text capability flags. Are they still used by anyone?
|
|
//
|
|
|
|
gdiinfo.flTextCaps =
|
|
TC_OP_CHARACTER |
|
|
TC_OP_STROKE |
|
|
TC_CP_STROKE |
|
|
TC_CR_ANY |
|
|
TC_SF_X_YINDEP |
|
|
TC_SA_CONTIN |
|
|
TC_IA_ABLE |
|
|
TC_UA_ABLE |
|
|
TC_SO_ABLE |
|
|
TC_RA_ABLE |
|
|
TC_VA_ABLE;
|
|
|
|
//
|
|
// Since PCL-XL is device resolution independent, the driver
|
|
// can assume device pixels always have 1:1 aspect ratio.
|
|
//
|
|
|
|
gdiinfo.ulAspectX =
|
|
gdiinfo.ulAspectY = 1000;
|
|
gdiinfo.ulAspectXY = 1414;
|
|
|
|
//
|
|
// Dotted line appears to be approximately 25dpi
|
|
//
|
|
|
|
gdiinfo.xStyleStep =
|
|
gdiinfo.yStyleStep = 1;
|
|
gdiinfo.denStyleStep = resolution / 25;
|
|
|
|
//
|
|
// Size and margins of physical surface measured in device pixels
|
|
//
|
|
|
|
gdiinfo.szlPhysSize.cx = MicronToPixel(pdev->paper.size.cx, resolution);
|
|
gdiinfo.szlPhysSize.cy = MicronToPixel(pdev->paper.size.cy, resolution);
|
|
|
|
gdiinfo.ptlPhysOffset.x =
|
|
MicronToPixel(pdev->paper.imageableArea.left, resolution);
|
|
gdiinfo.ptlPhysOffset.y =
|
|
MicronToPixel(pdev->paper.imageableArea.top, resolution);
|
|
|
|
//
|
|
// Use default halftone information
|
|
//
|
|
|
|
gdiinfo.ciDevice = DefDevHTInfo.ColorInfo;
|
|
gdiinfo.ulDevicePelsDPI = resolution;
|
|
gdiinfo.ulPrimaryOrder = PRIMARY_ORDER_ABC;
|
|
gdiinfo.ulHTPatternSize = HT_PATSIZE_8x8_M;
|
|
gdiinfo.ulHTOutputFormat =
|
|
pdev->colorFlag ? HT_FORMAT_4BPP : HT_FORMAT_1BPP;
|
|
gdiinfo.flHTFlags = HT_FLAG_HAS_BLACK_DYE;
|
|
|
|
//
|
|
// Copy cjGdiInfo elements of gdiinfo to aulCaps.
|
|
//
|
|
|
|
ErrorIf(cb != sizeof(gdiinfo),
|
|
("Incorrect gdiinfo buffer size: %d != %d\n", cb, sizeof(gdiinfo)));
|
|
|
|
memcpy(pgdiinfo, &gdiinfo, min(cb, sizeof(gdiinfo)));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
SetPrinterForm(
|
|
PDEVDATA pdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Store printer paper size information in our DEVDATA structure
|
|
|
|
Arguments:
|
|
|
|
pdev - Pointer to our DEVDATA structure
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
FORM_INFO_1 formInfo;
|
|
WCHAR formName[CCHFORMNAME];
|
|
PDEVMODE pdm;
|
|
|
|
//
|
|
// Find the form specified in the devmode and match it to a printer
|
|
// paper size. If that fails, fallback to default printer paper size.
|
|
//
|
|
|
|
pdm = (PDEVMODE) &pdev->dm;
|
|
|
|
if (! ValidDevmodeForm(pdev->hPrinter, pdm, &formInfo, formName) ||
|
|
! MapToPrinterForm(pdev->pmpd, &formInfo, &pdev->paper, FALSE))
|
|
{
|
|
SetDefaultForm(pdev);
|
|
}
|
|
|
|
//
|
|
// Adjust size and imageable area for landscape orientation
|
|
//
|
|
|
|
if ((pdm->dmFields & DM_ORIENTATION) && pdm->dmOrientation == DMORIENT_LANDSCAPE) {
|
|
|
|
AdjustLandscapeForm(&pdev->paper, LandscapeRotation(&pdev->dm));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
SetDefaultForm(
|
|
PDEVDATA pdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Store default printer paper size information in DEVDATA structure
|
|
|
|
Arguments:
|
|
|
|
pdev - Pointer to our DEVDATA structure
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
PFEATURE pFeature;
|
|
PPAPERSIZE pPaperSize;
|
|
WORD index;
|
|
|
|
pFeature = MpdPaperSizes(pdev->pmpd);
|
|
Assert(pFeature != NULL);
|
|
|
|
pPaperSize = FindNamedSelection(pFeature,
|
|
DefaultFormName(pdev->dm.dmPrivate.flags & XLDM_METRIC),
|
|
&index);
|
|
|
|
if (pPaperSize == NULL)
|
|
pPaperSize = DefaultSelection(pFeature, &index);
|
|
|
|
Assert(pPaperSize != NULL);
|
|
|
|
pdev->paper.imageableArea = pPaperSize->imageableArea;
|
|
pdev->paper.size = pPaperSize->size;
|
|
pdev->paper.selection = index;
|
|
CopyStringW(pdev->paper.name, pPaperSize->pName, CCHFORMNAME);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
AdjustLandscapeForm(
|
|
PPRINTERFORM pPaper,
|
|
INT rotation
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adjust printer paper size information if we're in
|
|
one of the landscape orientations.
|
|
|
|
Arguments:
|
|
|
|
pPaper - Pointer to a PRINTERFORM structure
|
|
rotation - Landscape rotation: 90 or 270
|
|
|
|
Return Value:
|
|
|
|
NONE
|
|
|
|
--*/
|
|
|
|
{
|
|
LONG width, height;
|
|
RECTL imagearea;
|
|
|
|
width = pPaper->size.cx;
|
|
height = pPaper->size.cy;
|
|
imagearea = pPaper->imageableArea;
|
|
|
|
//
|
|
// Swap width and height
|
|
//
|
|
|
|
pPaper->size.cx = height;
|
|
pPaper->size.cy = width;
|
|
|
|
//
|
|
// Adjust margins
|
|
//
|
|
|
|
if (rotation == 90) {
|
|
|
|
//
|
|
// Rotate 90 degrees counterclockwise
|
|
//
|
|
|
|
pPaper->imageableArea.left = height - imagearea.bottom;
|
|
pPaper->imageableArea.top = imagearea.left;
|
|
pPaper->imageableArea.right = height - imagearea.top;
|
|
pPaper->imageableArea.bottom = imagearea.right;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Rotate 90 degrees clockwise
|
|
//
|
|
|
|
pPaper->imageableArea.left = imagearea.top;
|
|
pPaper->imageableArea.top = width - imagearea.right;
|
|
pPaper->imageableArea.right = imagearea.bottom;
|
|
pPaper->imageableArea.bottom = width - imagearea.left;
|
|
}
|
|
}
|
|
|
|
|