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.
1753 lines
43 KiB
1753 lines
43 KiB
/*++
|
|
|
|
Copyright (c) 1990-2003 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
enable.c
|
|
|
|
|
|
Abstract:
|
|
|
|
This module contains the Plotter driver's Enable and Disable functions
|
|
and related routines.
|
|
|
|
The functions dealing with driver initialization are as follows:
|
|
|
|
DrvEnableDriver()
|
|
DrvEnablePDEV()
|
|
DrvResetPDEV()
|
|
DrvCompletePDEV()
|
|
DrvEnableSurface()
|
|
DrvDisableSurface()
|
|
DrvDisablePDEV()
|
|
DrvDisableDriver()
|
|
|
|
Author:
|
|
|
|
12-Nov-1993 Fri 10:16:36 updated
|
|
Move all #define related only to this function to here
|
|
|
|
15-Nov-1993 Mon 19:31:34 updated
|
|
clean up / debugging information
|
|
|
|
05-Jan-1994 Wed 22:50:28 updated
|
|
Move ColorMap's RGB pen color to local so that we only need array
|
|
reference, it defined PenRGBColor as DWORD from RGB() macro
|
|
|
|
[Environment:]
|
|
|
|
GDI Device Driver - Plotter.
|
|
|
|
|
|
[Notes:]
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#define DBG_PLOTFILENAME DbgEnable
|
|
|
|
#define DBG_ENABLEDRV 0x00000001
|
|
#define DBG_DISABLEDRV 0x00000002
|
|
#define DBG_ENABLEPDEV 0x00000004
|
|
#define DBG_COMPLETEPDEV 0x00000008
|
|
#define DBG_DISABLEPDEV 0x00000010
|
|
#define DBG_ENABLESURF 0x00000020
|
|
#define DBG_DISABLESURF 0x00000040
|
|
#define DBG_GDICAPS 0x00000080
|
|
#define DBG_DEVCAPS 0x00000100
|
|
#define DBG_PENPAL 0x00000200
|
|
#define DBG_BAND 0x00000400
|
|
#define DBG_DLLINIT 0x00000800
|
|
|
|
|
|
DEFINE_DBGVAR(0);
|
|
|
|
#if DBG
|
|
TCHAR DebugDLLName[] = TEXT("PLOTTER");
|
|
#endif
|
|
|
|
#define FIXUP_PLOTGPC_PDATA(pd,ps,v) \
|
|
if (ps->v) {pd->v=(LPVOID)((LPBYTE)pd+((LPBYTE)(ps->v)-(LPBYTE)ps));}
|
|
|
|
//
|
|
// Local funtion prototypes.
|
|
//
|
|
|
|
BOOL
|
|
CommonStartPDEV(
|
|
PDEV *pPDev,
|
|
DEVMODEW *pPlotDMIn,
|
|
ULONG cPatterns,
|
|
HSURF *phsurfPatterns,
|
|
ULONG cjDevCaps,
|
|
ULONG *pDevCaps,
|
|
ULONG cjDevInfo,
|
|
DEVINFO *pDevInfo
|
|
);
|
|
|
|
|
|
|
|
//
|
|
// Define the table with the hooked function pointers. This table is passed
|
|
// back to the NT graphic engine at DrvEnableDriver time. From then on GDI
|
|
// will call our driver via these supplied hook procs.
|
|
//
|
|
|
|
|
|
static const DRVFN DrvFuncTable[] = {
|
|
|
|
{ INDEX_DrvDisableDriver, (PFN)DrvDisableDriver },
|
|
{ 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_DrvQueryFont, (PFN)DrvQueryFont },
|
|
// { INDEX_DrvQueryFontTree, (PFN)DrvQueryFontTree },
|
|
// { INDEX_DrvQueryFontData, (PFN)DrvQueryFontData },
|
|
|
|
{ INDEX_DrvStrokePath, (PFN)DrvStrokePath },
|
|
{ INDEX_DrvStrokeAndFillPath, (PFN)DrvStrokeAndFillPath },
|
|
{ INDEX_DrvFillPath, (PFN)DrvFillPath },
|
|
{ INDEX_DrvRealizeBrush, (PFN)DrvRealizeBrush },
|
|
{ INDEX_DrvBitBlt, (PFN)DrvBitBlt },
|
|
{ INDEX_DrvStretchBlt, (PFN)DrvStretchBlt },
|
|
{ INDEX_DrvCopyBits, (PFN)DrvCopyBits },
|
|
|
|
{ INDEX_DrvPaint, (PFN)DrvPaint },
|
|
{ INDEX_DrvGetGlyphMode, (PFN)DrvGetGlyphMode },
|
|
{ INDEX_DrvTextOut, (PFN)DrvTextOut },
|
|
{ INDEX_DrvSendPage, (PFN)DrvSendPage },
|
|
{ INDEX_DrvStartPage, (PFN)DrvStartPage },
|
|
{ INDEX_DrvStartDoc, (PFN)DrvStartDoc },
|
|
{ INDEX_DrvEndDoc, (PFN)DrvEndDoc },
|
|
|
|
{ INDEX_DrvEscape, (PFN)DrvEscape },
|
|
};
|
|
|
|
#define TOTAL_DRVFUNC (sizeof(DrvFuncTable)/sizeof(DrvFuncTable[0]))
|
|
|
|
#ifdef USERMODE_DRIVER
|
|
|
|
|
|
HINSTANCE ghInstance;
|
|
|
|
BOOL
|
|
DllMain(
|
|
HANDLE hModule,
|
|
ULONG ulReason,
|
|
PCONTEXT pContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DLL initialization procedure.
|
|
|
|
Arguments:
|
|
|
|
hModule - DLL instance handle
|
|
ulReason - Reason for the call
|
|
pContext - Pointer to context (not used by us)
|
|
|
|
Return Value:
|
|
|
|
TRUE if DLL is initialized successfully, FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (ulReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
ghInstance = hModule;
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
DrvQueryDriverInfo(
|
|
DWORD dwMode,
|
|
PVOID pBuffer,
|
|
DWORD cbBuf,
|
|
PDWORD pcbNeeded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Query driver information
|
|
|
|
Arguments:
|
|
|
|
dwMode - Specify the information being queried
|
|
pBuffer - Points to output buffer
|
|
cbBuf - Size of output buffer in bytes
|
|
pcbNeeded - Return the expected size of output buffer
|
|
|
|
Return Value:
|
|
|
|
TRUE if successful, FALSE if there is an error
|
|
|
|
--*/
|
|
|
|
{
|
|
switch (dwMode)
|
|
{
|
|
case DRVQUERY_USERMODE:
|
|
|
|
PLOTASSERT(1, "DrvQueryDriverInfo: pcbNeeded [%08lx] is NULL", pcbNeeded != NULL, pcbNeeded);
|
|
*pcbNeeded = sizeof(DWORD);
|
|
|
|
if (pBuffer == NULL || cbBuf < sizeof(DWORD))
|
|
{
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return FALSE;
|
|
}
|
|
|
|
*((PDWORD) pBuffer) = TRUE;
|
|
return TRUE;
|
|
|
|
default:
|
|
|
|
PLOTERR(("Unknown dwMode in DrvQueryDriverInfo: %d\n", dwMode));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#endif // USERMODE_DRIVER
|
|
|
|
|
|
|
|
BOOL
|
|
DrvEnableDriver(
|
|
ULONG iEngineVersion,
|
|
ULONG cb,
|
|
DRVENABLEDATA *pded
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Requests the driver to fill in a structure containing recognized functions
|
|
and other control information. One time initialization, such as semaphore
|
|
allocation may be performed, but no device activity should happen. That
|
|
is done when DrvEnablePDEV is called. This function is the only way the
|
|
engine can determine what functions we supply to it.
|
|
|
|
Arguments:
|
|
|
|
iEngineVersion - The engine version which we run under
|
|
|
|
cb - total bytes in pded
|
|
|
|
pded - Pointer to the DRVENABLEDATA data structure
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if sucssfully FALSE otherwise
|
|
|
|
|
|
Author:
|
|
|
|
01-Dec-1993 Wed 02:03:20 created
|
|
|
|
03-Mar-1994 Thu 10:04:30 updated
|
|
Adding EngineVersion check to make sure ourself can run correctly.
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PLOTDBG(DBG_ENABLEDRV, ("DrvEnableDriver: EngineVersion=%08lx, Request=%08lx",
|
|
iEngineVersion, DDI_DRIVER_VERSION_NT4));
|
|
|
|
//
|
|
// Verify the Engine version is at least what we know we can work with.
|
|
// If its older, error out now, as we don't know what may happen.
|
|
//
|
|
|
|
if (iEngineVersion < DDI_DRIVER_VERSION_NT4) {
|
|
|
|
PLOTRIP(("DrvEnableDriver: EARLIER VERSION: EngineVersion(%08lx) < Request(%08lx)",
|
|
iEngineVersion, DDI_DRIVER_VERSION_NT4));
|
|
|
|
SetLastError(ERROR_BAD_DRIVER_LEVEL);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// cb is a count of the number of bytes available in pded. It is not
|
|
// clear that there is any significant use of the engine version number.
|
|
// Returns TRUE if successfully enabled, otherwise FALSE.
|
|
//
|
|
// iEngineVersion is the engine version while DDI_DRIVER_VERSION is the
|
|
// driver version. So, unless we re-compile the driver and get a new
|
|
// version of driver, we can only stick with our version.
|
|
//
|
|
|
|
if (cb < sizeof(DRVENABLEDATA)) {
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
PLOTRIP(("DrvEnableDriver: cb=%ld, should be %ld\n",
|
|
cb, sizeof(DRVENABLEDATA)));
|
|
return(FALSE);
|
|
}
|
|
|
|
pded->iDriverVersion = DDI_DRIVER_VERSION_NT4;
|
|
|
|
//
|
|
// Fill in the driver table returned to the engine. This table is used
|
|
// by GDI to call the rest of our functinos.
|
|
//
|
|
|
|
pded->c = TOTAL_DRVFUNC;
|
|
pded->pdrvfn = (DRVFN *)DrvFuncTable;
|
|
|
|
//
|
|
// Initialize the GPC cache
|
|
//
|
|
|
|
InitCachedData();
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
DrvDisableDriver(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called just before the engine unloads the driver. Main purpose is
|
|
to allow freeing of any resources obtained during the DrvEnableDriver()
|
|
call.
|
|
|
|
Arguments:
|
|
|
|
NONE
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
Author:
|
|
|
|
01-Dec-1993 Wed 02:02:18 created
|
|
|
|
01-Feb-1994 Tue 22:03:03 updated
|
|
Make sure we unload the cache.
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DestroyCachedData();
|
|
|
|
PLOTDBG(DBG_DISABLEDRV, ("DrvDisableDriver: Done!!"));
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
FreeAllocMem(
|
|
PPDEV pPDev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function frees all the memory allocated during the lifetime of the
|
|
PDEV.
|
|
|
|
|
|
Arguments:
|
|
|
|
pPDev - Our instance data
|
|
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
|
|
Author:
|
|
|
|
24-Oct-1995 Tue 16:28:35 created
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Free any memory allocated during PDEV initialization.
|
|
//
|
|
|
|
if (pPDev) {
|
|
|
|
PDRVHTINFO pDrvHTInfo;
|
|
|
|
if (pPDev->hPalDefault) {
|
|
|
|
EngDeletePalette(pPDev->hPalDefault);
|
|
pPDev->hPalDefault = NULL;
|
|
}
|
|
|
|
if (pDrvHTInfo = (PDRVHTINFO)(pPDev->pvDrvHTData)) {
|
|
|
|
if (pDrvHTInfo->pHTXB) {
|
|
|
|
LocalFree((HLOCAL)pDrvHTInfo->pHTXB);
|
|
pDrvHTInfo->pHTXB = NULL;
|
|
}
|
|
|
|
pPDev->pvDrvHTData = NULL;
|
|
}
|
|
|
|
if (pPDev->pPenCache) {
|
|
|
|
LocalFree((HLOCAL)pPDev->pPenCache);
|
|
pPDev->pPenCache = NULL;
|
|
}
|
|
|
|
if (pPDev->pTransPosTable) {
|
|
|
|
LocalFree((HLOCAL)pPDev->pTransPosTable);
|
|
pPDev->pTransPosTable = NULL;
|
|
}
|
|
|
|
FreeOutBuffer(pPDev);
|
|
|
|
LocalFree((HLOCAL)pPDev);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DHPDEV
|
|
DrvEnablePDEV(
|
|
DEVMODEW *pPlotDMIn,
|
|
PWSTR pwszLogAddr,
|
|
ULONG cPatterns,
|
|
HSURF *phsurfPatterns,
|
|
ULONG cjDevCaps,
|
|
ULONG *pDevCaps,
|
|
ULONG cjDevInfo,
|
|
DEVINFO *pDevInfo,
|
|
HDEV hdev,
|
|
PWSTR pwszDeviceName,
|
|
HANDLE hDriver
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Function called to let the driver create the data structures
|
|
needed to support the device, and also to tell the engine
|
|
about its capabilities. This is the stage where we find out
|
|
exactly which device we are dealing with, and so we need to
|
|
find out its capabilities.
|
|
|
|
Arguments:
|
|
|
|
pPlotDMIn - Pointer to the DEVMODE data structure
|
|
|
|
pwszLogAddr - pointer to the output location, (ie. LPT1
|
|
|
|
cPatterns - Count of pattern to be set in phsurfPatterns
|
|
|
|
phsurfPatterns - pointer to the standard pattern HSURF array
|
|
|
|
cjDevCaps - total size of pDevCaps pointed to.
|
|
|
|
pDevCaps - pointer to the device cap DWORDs
|
|
|
|
cjDevInfo - total size of pDevInfo pointed to
|
|
|
|
pDevInfo - pointer to the DEVINFO data structure
|
|
|
|
hdev - Handle to the logical device from the engine
|
|
|
|
pwszDeviceName - pointer to the plotter device name
|
|
|
|
hDriver - handle to this driver
|
|
|
|
|
|
Return Value:
|
|
|
|
DHPDEV if sucessful, NULL if failed
|
|
|
|
|
|
Author:
|
|
|
|
15-Dec-1993 Wed 21:04:40 updated
|
|
Add cached mechanism for the PLOTGPC
|
|
|
|
14-Dec-1993 Tue 20:22:26 updated
|
|
Update how the pen plotter data should work
|
|
|
|
23-Nov-1993 Tue 19:48:08 updated
|
|
Clean up and using new devmode.c in ..\lib directory
|
|
|
|
17:30 on Mon 1 Apr 1991
|
|
Took skeletal code from RASDD printer driver
|
|
|
|
16-Jul-1996 Tue 13:59:15 updated
|
|
Fix up the pData in the PLOTGPC/GPCVARSIZE structure, since the
|
|
pointer is based on the cached GPC not the clone copy of it
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PPDEV pPDev = NULL;
|
|
PPLOTGPC pPlotGPC;
|
|
LPWSTR pwszDataFile = NULL;
|
|
|
|
#ifdef USERMODE_DRIVER
|
|
|
|
PDRIVER_INFO_2 pDriverInfo = NULL;
|
|
DWORD dwBytesNeeded;
|
|
|
|
#endif
|
|
|
|
|
|
UNREFERENCED_PARAMETER(pwszLogAddr);
|
|
|
|
#ifndef USERMODE_DRIVER
|
|
|
|
pwszDataFile = EngGetPrinterDataFileName(hdev);
|
|
|
|
#else
|
|
|
|
if (!GetPrinterDriver(hDriver, NULL, 2, NULL, 0, &dwBytesNeeded) &&
|
|
GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
|
|
(pDriverInfo = (PDRIVER_INFO_2)LocalAlloc(LPTR, dwBytesNeeded)) &&
|
|
GetPrinterDriver(hDriver, NULL, 2, (LPBYTE)pDriverInfo, dwBytesNeeded, &dwBytesNeeded))
|
|
{
|
|
pwszDataFile = pDriverInfo->pDataFile;
|
|
}
|
|
|
|
#endif // !USERMODE_DRIVER
|
|
|
|
if (!pwszDataFile) {
|
|
|
|
PLOTRIP(("DrvEnablePDEV: pwszDataFile is NULL"));
|
|
|
|
} else if (!(pPlotGPC = GetCachedPlotGPC(pwszDataFile))) {
|
|
|
|
PLOTRIP(("DrvEnablePDEV: GetCachedPlotGPC(%ws) failed", pwszDataFile));
|
|
|
|
} else if (!(pPDev = (PPDEV)LocalAlloc(LPTR,
|
|
sizeof(PDEV) + sizeof(DRVHTINFO) +
|
|
pPlotGPC->cjThis +
|
|
pPlotGPC->SizeExtra))) {
|
|
|
|
//
|
|
// Free the cached pPlotGPC before we leave
|
|
//
|
|
|
|
UnGetCachedPlotGPC(pPlotGPC);
|
|
|
|
PLOTRIP(("DrvEnablePDEV: LocalAlloc(PDEV + DRVHTINFO + pPlotGPC) failed."));
|
|
|
|
} else {
|
|
|
|
PLOTDBG(DBG_ENABLEPDEV,("EnablePDEV: PlotGPC data file=%ws",
|
|
pwszDataFile));
|
|
|
|
//
|
|
// If we got the PDEV set the ID for later checking, also set the
|
|
// hPrinter so we can use it later
|
|
//
|
|
|
|
pPDev->pvDrvHTData = (LPVOID)((LPBYTE)pPDev + sizeof(PDEV));
|
|
pPDev->hPrinter = hDriver;
|
|
pPDev->SizePDEV = sizeof(PDEV);
|
|
pPDev->PDEVBegID = PDEV_BEG_ID;
|
|
pPDev->PDEVEndID = PDEV_END_ID;
|
|
|
|
//
|
|
// We will get the PLOTGPC from the cach, the pPlotGPC is
|
|
// allocated by the ReadPlotGPCFromFile() using LocalAlloc().
|
|
//
|
|
// *** NOW we will Clone the cached pPlotGPC then un-cached it
|
|
//
|
|
|
|
pPDev->pPlotGPC = (PPLOTGPC)((LPBYTE)pPDev + sizeof (PDEV) +
|
|
sizeof(DRVHTINFO));
|
|
|
|
CopyMemory(pPDev->pPlotGPC,
|
|
pPlotGPC,
|
|
pPlotGPC->cjThis + pPlotGPC->SizeExtra);
|
|
|
|
//
|
|
// 16-Jul-1996 Tue 13:59:15 updated
|
|
// Fix up the pData in the PLOTGPC/GPCVARSIZE structure, since the
|
|
// pointer is based on the cached GPC not the clone copy of it
|
|
//
|
|
|
|
FIXUP_PLOTGPC_PDATA(pPDev->pPlotGPC, pPlotGPC, InitString.pData);
|
|
FIXUP_PLOTGPC_PDATA(pPDev->pPlotGPC, pPlotGPC, Forms.pData);
|
|
FIXUP_PLOTGPC_PDATA(pPDev->pPlotGPC, pPlotGPC, Pens.pData);
|
|
|
|
UnGetCachedPlotGPC(pPlotGPC);
|
|
|
|
//
|
|
// Now, depending on if its a pen/raster device, we will update
|
|
// the pen data.
|
|
//
|
|
|
|
PLOTASSERT(1, "Raster Plotter should not have PEN data [%08lx]",
|
|
((pPDev->pPlotGPC->Flags & PLOTF_RASTER) &&
|
|
(pPDev->pPlotGPC->Pens.pData == NULL)) ||
|
|
((!(pPDev->pPlotGPC->Flags & PLOTF_RASTER)) &&
|
|
(pPDev->pPlotGPC->Pens.pData != NULL)),
|
|
pPDev->pPlotGPC->Pens.pData);
|
|
|
|
//
|
|
// Read the data from the registry which defines device settings.
|
|
// The user may have modified the paper type loaded etc.
|
|
//
|
|
|
|
GetDefaultPlotterForm(pPDev->pPlotGPC, &(pPDev->CurPaper));
|
|
|
|
//
|
|
// Set the default Flags in case we did not update from the registry
|
|
//
|
|
|
|
pPDev->PPData.Flags = PPF_AUTO_ROTATE |
|
|
PPF_SMALLER_FORM |
|
|
PPF_MANUAL_FEED_CX;
|
|
|
|
if (IS_RASTER(pPDev)) {
|
|
|
|
//
|
|
// Raster devices do not need pen data
|
|
//
|
|
|
|
UpdateFromRegistry(hDriver,
|
|
&(pPDev->pPlotGPC->ci),
|
|
&(pPDev->pPlotGPC->DevicePelsDPI),
|
|
&(pPDev->pPlotGPC->HTPatternSize),
|
|
&(pPDev->CurPaper),
|
|
&(pPDev->PPData),
|
|
NULL,
|
|
0,
|
|
NULL);
|
|
|
|
} else {
|
|
|
|
//
|
|
// The Pen plotter does not need ColorInfo, DevicePelsDPI and
|
|
// HTPatternSize
|
|
//
|
|
|
|
UpdateFromRegistry(hDriver,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&(pPDev->CurPaper),
|
|
&(pPDev->PPData),
|
|
NULL,
|
|
MAKELONG(0xFFFF, pPDev->pPlotGPC->MaxPens),
|
|
(PPENDATA)pPDev->pPlotGPC->Pens.pData);
|
|
}
|
|
|
|
//
|
|
// common code for DrvEnablePDEV and DrvResetPDEV
|
|
// we must first copy the device name to the pPDev->PlotDM
|
|
// then call the common code.
|
|
//
|
|
|
|
WCPYFIELDNAME(pPDev->PlotDM.dm.dmDeviceName, pwszDeviceName);
|
|
|
|
if (!CommonStartPDEV(pPDev,
|
|
pPlotDMIn,
|
|
cPatterns,
|
|
phsurfPatterns,
|
|
cjDevCaps,
|
|
pDevCaps,
|
|
cjDevInfo,
|
|
pDevInfo)) {
|
|
|
|
FreeAllocMem(pPDev);
|
|
pPDev = NULL;
|
|
|
|
}
|
|
}
|
|
|
|
#ifdef USERMODE_DRIVER
|
|
|
|
if (pDriverInfo) {
|
|
|
|
LocalFree((HLOCAL)pDriverInfo);
|
|
}
|
|
|
|
#endif // USERMODE_DRIVER
|
|
|
|
return((DHPDEV)pPDev);
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
DrvResetPDEV(
|
|
DHPDEV dhpdevOld,
|
|
DHPDEV dhpdevNew
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when an application wishes to change the output style in the
|
|
midst of a job. Typically this would be to change from portrait to
|
|
landscape or vice versa. Any other sensible change is permitted.
|
|
|
|
Arguments:
|
|
|
|
dhpdevOld - the OLD pPDev which we returned in DrvEnablePDEV
|
|
|
|
dhpdevNew - the NEW pPDev which we returned in DrvEnablePDEV
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
BOOLEAN
|
|
|
|
|
|
Author:
|
|
|
|
23-Nov-1993 Tue 20:07:45 updated
|
|
totaly re-write
|
|
|
|
17:30 on Mon 1 Apr 1991
|
|
Took skeletal code from RASDD printer driver
|
|
|
|
|
|
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#define pPDevOld ((PDEV *) dhpdevOld)
|
|
#define pPDevNew ((PDEV *) dhpdevNew)
|
|
|
|
//
|
|
// Make sure we got the correct pPlotDMin for this pPDev
|
|
//
|
|
|
|
if ((pPDevOld->PlotDM.dm.dmDriverVersion !=
|
|
pPDevNew->PlotDM.dm.dmDriverVersion) ||
|
|
(wcscmp((LPWSTR)pPDevOld->PlotDM.dm.dmDeviceName,
|
|
(LPWSTR)pPDevNew->PlotDM.dm.dmDeviceName))) {
|
|
|
|
PLOTERR(("DrvResetPDEV: Incompatible PLOTDEVMODE"));
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// We have nothing to carry over from old to new
|
|
//
|
|
|
|
return(TRUE);
|
|
|
|
|
|
#undef pPDevNew
|
|
#undef pPDevOld
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DrvCompletePDEV(
|
|
DHPDEV dhpdev,
|
|
HDEV hpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when the engine has completed installation of the physical
|
|
device. Basically it provides the connection between the
|
|
engine's hpdev and ours. Some functions require us to pass in
|
|
the engines's hpdev, so we save it now in our pdev so that we
|
|
can get to it later.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - Returned from dhpdevCreatePDEV
|
|
|
|
hpdev - Engine's corresponding handle
|
|
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
|
|
Author:
|
|
|
|
01-Dec-1993 Wed 01:56:58 created
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Simply record the value in the PDEV we have allocated.
|
|
//
|
|
|
|
((PPDEV)dhpdev)->hpdev = hpdev;
|
|
|
|
PLOTDBG(DBG_COMPLETEPDEV, ("CompletePDEV: Done!"));
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DrvDisablePDEV(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called when the engine has finished with this PDEV. Basically we throw
|
|
away all connections etc. then free the memory.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - OUR handle to the pdev
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
|
|
Author:
|
|
|
|
01-Dec-1993 Wed 01:55:43 created
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#define pPDev ((PDEV *) dhpdev)
|
|
|
|
//
|
|
// Undo all that has been done with the PDEV. Basically this means
|
|
// freeing the memory we consumed.
|
|
//
|
|
|
|
FreeAllocMem(pPDev);
|
|
|
|
PLOTDBG(DBG_DISABLEPDEV, ("DrvDisablePDEV: FreeAllocMem() completes"));
|
|
|
|
#undef pPDev
|
|
}
|
|
|
|
|
|
|
|
|
|
HSURF
|
|
DrvEnableSurface(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Function to create the physical drawing surface for the pdev
|
|
that was created earlier. Since we don't really have a bitmap surface,
|
|
all we do here is allocate the output buffer. This is typical for a
|
|
Device Managed Surface. After this call completes succesfully, GDI can
|
|
start drawing on our surface.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
dhpdev - OUR handle to the pdev
|
|
|
|
Return Value:
|
|
|
|
HSURF for the surface we created
|
|
|
|
|
|
Author:
|
|
|
|
01-Dec-1993 Wed 01:47:36 created
|
|
|
|
10-Dec-1993 Fri 16:36:37 updated
|
|
Move PlotCreatePalette() to here to prevent GP
|
|
|
|
16-Dec-1993 Thu 12:16:11 updated
|
|
Move PlotCreatePalette() out to SendPageHeader() in output.c so that
|
|
we do not sending some PC commands which has no effects.
|
|
|
|
06-Jan-1994 Thu 04:12:37 updated
|
|
Re-arrange the code sequence.
|
|
Adding Error codes so it will failed the call if engine said so.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#define pPDev ((PPDEV)dhpdev)
|
|
|
|
PDRVHTINFO pDrvHTInfo;
|
|
SIZEL SurfSize;
|
|
|
|
|
|
pDrvHTInfo = (PDRVHTINFO)(pPDev->pvDrvHTData);
|
|
|
|
//
|
|
// Make sure we delete this xlate table before we process the new
|
|
// surface
|
|
//
|
|
|
|
if (pDrvHTInfo->pHTXB) {
|
|
|
|
LocalFree((HLOCAL)pDrvHTInfo->pHTXB);
|
|
pDrvHTInfo->pHTXB = NULL;
|
|
}
|
|
|
|
pDrvHTInfo->Flags = 0;
|
|
pDrvHTInfo->PalXlate[0] = 0xff;
|
|
pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
|
|
|
|
//
|
|
// Since output is expected to follow this call, allocate storage for the
|
|
// output buffer. This used to be statically allocated within the PDEV but
|
|
// now we can save that space for INFO type DCs, since CreateIC won't
|
|
// actually end up calling DrvEnableSurface.
|
|
//
|
|
|
|
if (!AllocOutBuffer(pPDev)) {
|
|
|
|
PLOTERR(("DrvEnableSurface: AllocOutBuffer() failed"));
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// For now pass in my PDev pointer as the dhsurf value. If we actually
|
|
// need to pass back an hsurf to the engine later, We can use this value
|
|
// as a pointer to the hsurf value stored in our PDev.
|
|
//
|
|
|
|
SurfSize.cx = pPDev->HorzRes;
|
|
SurfSize.cy = pPDev->VertRes;
|
|
|
|
if (!(pPDev->hsurf = EngCreateDeviceSurface((DHSURF)pPDev, SurfSize,
|
|
IS_RASTER(pPDev) ? BMF_24BPP : BMF_4BPP))) {
|
|
PLOTERR(("DrvEnableSurface: EngCreateDeviceSurface() failed"));
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
//
|
|
// Now we need to associate the newly created surface with the already
|
|
// created PDEV. In this function, we inform the NT graphics engine,
|
|
// which functions our driver supports.
|
|
//
|
|
|
|
if (!EngAssociateSurface(pPDev->hsurf,
|
|
(HDEV)pPDev->hpdev,
|
|
HOOK_BITBLT |
|
|
HOOK_STRETCHBLT |
|
|
HOOK_COPYBITS |
|
|
HOOK_STROKEPATH |
|
|
HOOK_FILLPATH |
|
|
HOOK_STROKEANDFILLPATH |
|
|
HOOK_PAINT |
|
|
HOOK_TEXTOUT)) {
|
|
|
|
PLOTERR(("DrvEnableSurface: EngAssociateSurface() failed"));
|
|
|
|
DrvDisableSurface((DHPDEV)pPDev->hpdev);
|
|
EngDeleteSurface(pPDev->hsurf);
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
return(pPDev->hsurf);
|
|
|
|
#undef pPDev
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DrvDisableSurface(
|
|
DHPDEV dhpdev
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The drawing surface is no longer required, so we can delete any
|
|
memory we allocated in conjunction with it.
|
|
|
|
Arguments:
|
|
|
|
dhpdev - our pPDev
|
|
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
|
|
Author:
|
|
|
|
01-Dec-1993 Wed 01:45:39 created
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
#define pPDev ((PPDEV)dhpdev)
|
|
|
|
if (pPDev->hsurf) {
|
|
|
|
EngDeleteSurface(pPDev->hsurf);
|
|
}
|
|
|
|
#undef pPDev
|
|
}
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
hypot(
|
|
DWORD x,
|
|
DWORD y
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the length of the hypotenous of a xRight triangle whose sides
|
|
are passed in as the parameters.
|
|
|
|
Arguments:
|
|
|
|
x - x side of the triangle
|
|
|
|
y - y size of the triangle
|
|
|
|
Return Value:
|
|
|
|
hypotenous
|
|
|
|
|
|
Author:
|
|
|
|
13:54 on Tue 02 Feb 1993
|
|
Re-instated from Win 3.1, for compatability.
|
|
|
|
01-Dec-1993 Wed 01:10:55 updated
|
|
update to DWORD
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD hypo;
|
|
DWORD Delta;
|
|
DWORD Target;
|
|
|
|
//
|
|
// Finds the hypoteneous of a xRight triangle with legs equal to x and y.
|
|
// Assumes x, y, hypo are integers. Use sq(x) + sq(y) = sq(hypo);
|
|
// Start with MAX(x, y), use sq(x + 1) = sq(x) + 2x + 1 to incrementally
|
|
// get to the target hypotenouse.
|
|
//
|
|
|
|
hypo = max(x, y);
|
|
Target = min(x, y);
|
|
Target *= Target;
|
|
|
|
for (Delta = 0; Delta < Target; hypo++) {
|
|
|
|
Delta += (DWORD)((hypo << 1) + 1);
|
|
}
|
|
|
|
return(hypo);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
FillDeviceCaps(
|
|
PPDEV pPDev,
|
|
GDIINFO *pGDIInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set up the device caps for this particular plotter. Some fields require
|
|
calculations based on device resolution, etc.
|
|
|
|
We simply fill the GDIINFO structure passed to us. The calling
|
|
function will take care of copying the information into the
|
|
Graphics Engine's buffer.
|
|
|
|
|
|
Arguments:
|
|
|
|
pPDev - Pointer to the PDEV data structure
|
|
|
|
pGDIInfo - Pointer to the GDIINFO data structure to be filled in
|
|
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
|
|
Author:
|
|
|
|
24-Nov-1993 Wed 22:38:10 updated
|
|
Re-write, and using CurForm to replace the pform and PAPER_DIM
|
|
|
|
23-Dec-1993 Thu 21:56:20 updated
|
|
Make halftone bitmap surface also look at dmColor which set by the
|
|
user if it want to print grey scale or device is not color
|
|
|
|
07-Feb-1994 Mon 20:37:13 updated
|
|
When is DMCOLOR_COLOR the ulNumColors return to the engine will be
|
|
MaxPens which specified in the PCD file not 8
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
PDRVHTINFO pDrvHTInfo;
|
|
LONG Scale;
|
|
|
|
|
|
//
|
|
// we will always start from clean state
|
|
//
|
|
|
|
ZeroMemory(pGDIInfo, sizeof(GDIINFO));
|
|
|
|
//
|
|
// Get pDrvHTInfo data pointer and set the basic version information
|
|
//
|
|
|
|
pDrvHTInfo = (PDRVHTINFO)pPDev->pvDrvHTData;
|
|
pGDIInfo->ulVersion = DRIVER_VERSION;
|
|
pGDIInfo->ulTechnology = (IS_RASTER(pPDev) ? DT_RASPRINTER : DT_PLOTTER);
|
|
|
|
//
|
|
// We have pPDev->PlotForm updated during the ValidateSetPLOTDM() call, so
|
|
// use it, we need to look into the dmScale to see if we need to scale
|
|
// all of the values.
|
|
//
|
|
|
|
Scale = (LONG)pPDev->PlotDM.dm.dmScale;
|
|
pGDIInfo->ulHorzSize = pPDev->PlotForm.LogExt.cx / (Scale * 10);
|
|
pGDIInfo->ulVertSize = pPDev->PlotForm.LogExt.cy / (Scale * 10);
|
|
pPDev->HorzRes =
|
|
pGDIInfo->ulHorzRes = SPLTOENGUNITS(pPDev, pPDev->PlotForm.LogExt.cx);
|
|
pPDev->VertRes =
|
|
pGDIInfo->ulVertRes = SPLTOENGUNITS(pPDev, pPDev->PlotForm.LogExt.cy);
|
|
|
|
PLOTDBG(DBG_GDICAPS, ("GDICAPS: H/V Size=%d x %d, H/V Res=%ld x %ld",
|
|
pGDIInfo->ulHorzSize, pGDIInfo->ulVertSize,
|
|
pGDIInfo->ulHorzRes, pGDIInfo->ulVertRes));
|
|
|
|
pGDIInfo->szlPhysSize.cx = SPLTOENGUNITS(pPDev,pPDev->PlotForm.LogSize.cx);
|
|
pGDIInfo->szlPhysSize.cy = SPLTOENGUNITS(pPDev,pPDev->PlotForm.LogSize.cy);
|
|
pGDIInfo->ptlPhysOffset.x = SPLTOENGUNITS(pPDev,pPDev->PlotForm.PhyOrg.x);
|
|
pGDIInfo->ptlPhysOffset.y = SPLTOENGUNITS(pPDev,pPDev->PlotForm.PhyOrg.y);
|
|
|
|
PLOTDBG(DBG_GDICAPS, ("GDICAPS: PhySize= %d x %d, PhyOff=(%ld, %ld)",
|
|
pGDIInfo->szlPhysSize.cx, pGDIInfo->szlPhysSize.cy,
|
|
pGDIInfo->ptlPhysOffset.x, pGDIInfo->ptlPhysOffset.y));
|
|
|
|
//
|
|
// Assume the device has a 1:1 aspect ratio
|
|
//
|
|
|
|
pGDIInfo->ulLogPixelsX =
|
|
pGDIInfo->ulLogPixelsY = (pPDev->lCurResolution * Scale / 100);
|
|
|
|
PLOTDBG(DBG_GDICAPS, ("GDICAPS: LogPixelsX/Y = %d x %d",
|
|
pGDIInfo->ulLogPixelsX, pGDIInfo->ulLogPixelsY));
|
|
|
|
pGDIInfo->ulAspectX =
|
|
pGDIInfo->ulAspectY = pPDev->lCurResolution;
|
|
pGDIInfo->ulAspectXY = hypot(pGDIInfo->ulAspectX, pGDIInfo->ulAspectY);
|
|
|
|
|
|
pGDIInfo->ciDevice = pPDev->pPlotGPC->ci;
|
|
pGDIInfo->ulDevicePelsDPI = (DWORD)pPDev->pPlotGPC->DevicePelsDPI *
|
|
(DWORD)Scale / (DWORD)100;
|
|
pGDIInfo->ulHTPatternSize = pPDev->pPlotGPC->HTPatternSize;
|
|
pGDIInfo->flHTFlags = HT_FLAG_HAS_BLACK_DYE;
|
|
pGDIInfo->ulPrimaryOrder = PRIMARY_ORDER_CBA;
|
|
|
|
PLOTDBG(DBG_GDICAPS, ("GDICAPS: HTPatSize=%ld, DevPelsDPI=%ld, PrimaryOrder=%ld",
|
|
pGDIInfo->ulHTPatternSize, pGDIInfo->ulDevicePelsDPI,
|
|
pGDIInfo->ulPrimaryOrder));
|
|
|
|
//
|
|
// If the device is a color device, then set up the Halftoning info now.
|
|
//
|
|
|
|
if (pPDev->PlotDM.dm.dmColor == DMCOLOR_COLOR) {
|
|
|
|
//
|
|
// Do this only if we really want to do color in R/G/B not C/M/Y
|
|
//
|
|
|
|
PLOTDBG(DBG_DEVCAPS, ("FillDeviceCaps: Doing Color Output"));
|
|
|
|
pDrvHTInfo->HTPalCount = 8;
|
|
pDrvHTInfo->HTBmpFormat = (BYTE)BMF_4BPP;
|
|
pDrvHTInfo->AltBmpFormat = (BYTE)BMF_1BPP;
|
|
pGDIInfo->ulHTOutputFormat = HT_FORMAT_4BPP;
|
|
|
|
} else {
|
|
|
|
pDrvHTInfo->HTPalCount = 2;
|
|
pDrvHTInfo->HTBmpFormat = (BYTE)BMF_1BPP;
|
|
pDrvHTInfo->AltBmpFormat = (BYTE)0xff;
|
|
pGDIInfo->ulHTOutputFormat = HT_FORMAT_1BPP;
|
|
|
|
//
|
|
// Using this flag will give us a good benefit, the flag notifies gdi
|
|
// and halftone eng. that the output from halftone will be
|
|
// 0=white and 1=black
|
|
// as opposed to the typical 0=black, 1=white, so that at 99% of time
|
|
// we do not have to flip the B/W buffer except if CopyBits is from the
|
|
// calling app.
|
|
//
|
|
// pGDIInfo->flHTFlags |= HT_FLAG_OUTPUT_CMY;
|
|
//
|
|
|
|
PLOTDBG(DBG_DEVCAPS, ("FillDeviceCaps: Doing GREY SCALE (%hs) Output",
|
|
(pGDIInfo->flHTFlags & HT_FLAG_OUTPUT_CMY) ? "CMY: 0=W, 1=K" :
|
|
"RGB: 0=K, 1=W"));
|
|
}
|
|
|
|
pGDIInfo->ulNumColors = pPDev->pPlotGPC->MaxPens;
|
|
pDrvHTInfo->Flags = 0;
|
|
pDrvHTInfo->PalXlate[0] = 0xff;
|
|
pDrvHTInfo->HTPalXor = HTPALXOR_SRCCOPY;
|
|
|
|
pGDIInfo->cBitsPixel = 24;
|
|
pGDIInfo->cPlanes = 1;
|
|
|
|
//
|
|
// Some other information the Engine expects us to fill in.
|
|
//
|
|
|
|
pGDIInfo->ulDACRed = 0;
|
|
pGDIInfo->ulDACGreen = 0;
|
|
pGDIInfo->ulDACBlue = 0;
|
|
pGDIInfo->flRaster = 0;
|
|
pGDIInfo->flTextCaps = 0;
|
|
pGDIInfo->xStyleStep = 1;
|
|
pGDIInfo->yStyleStep = 1;
|
|
pGDIInfo->denStyleStep = PLOT_STYLE_STEP(pPDev);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
FillDevInfo(
|
|
PPDEV pPDev,
|
|
DEVINFO *pDevInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Set up the device info for this particular plotter. Some fields
|
|
require calculations based on device resolution, etc.
|
|
|
|
We simply fill the DevInfo structure passed to us. The calling
|
|
function will take care of copying the information into the
|
|
Graphics Engine's buffer.
|
|
|
|
|
|
Arguments:
|
|
|
|
pPDev - pointer to the PDEV data structure
|
|
|
|
pDevInfo - pointer to the DEVINFO to be filled
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if sucessful FALSE otherwise
|
|
|
|
|
|
Author:
|
|
|
|
01-Dec-1993 Wed 00:46:00 created
|
|
|
|
10-Dec-1993 Fri 16:37:06 updated
|
|
Temp. disable and move the PlotCreatePalette to EnableSurf call
|
|
|
|
17-Dec-1993 Fri 16:37:06 updated
|
|
Move PlotCreatePalette to StartDoc time
|
|
|
|
05-Jan-1994 Wed 22:54:21 updated
|
|
Move PenColor Reference to this file and reference that directly as
|
|
DWORD generate by RGB() marco
|
|
|
|
14-Jan-1994 Fri 15:35:02 updated
|
|
Remove HTPatternSize param
|
|
|
|
23-Feb-1994 Wed 13:02:09 updated
|
|
Make sure we return GCAPS_HALFTONE so that we will get DrvStretchBlt()
|
|
callback
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Start with a clean slate.
|
|
//
|
|
|
|
ZeroMemory(pDevInfo, sizeof(DEVINFO));
|
|
|
|
//
|
|
// fill in the graphics capabilities flags we know we can handle at
|
|
// the very least.
|
|
//
|
|
|
|
pDevInfo->flGraphicsCaps = GCAPS_ALTERNATEFILL |
|
|
GCAPS_HORIZSTRIKE |
|
|
GCAPS_VERTSTRIKE |
|
|
GCAPS_VECTORFONT;
|
|
|
|
//
|
|
// If RGB mode is on for color handling then text can be opaque
|
|
//
|
|
|
|
if (IS_RASTER(pPDev)) {
|
|
|
|
pDevInfo->flGraphicsCaps |= GCAPS_HALFTONE;
|
|
|
|
if (IS_COLOR(pPDev)) {
|
|
|
|
pDevInfo->flGraphicsCaps |= GCAPS_OPAQUERECT;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check and set the BEZIER capability of the device....
|
|
//
|
|
|
|
if (IS_BEZIER(pPDev)) {
|
|
|
|
pDevInfo->flGraphicsCaps |= GCAPS_BEZIERS;
|
|
}
|
|
|
|
if (IS_WINDINGFILL(pPDev)) {
|
|
|
|
pDevInfo->flGraphicsCaps |= GCAPS_WINDINGFILL;
|
|
}
|
|
|
|
//
|
|
// We don't process DrvDitherColor (perhaps later?), so set the size of
|
|
// the Dither Brush to 0 to indicate this to the engine. THIS IS IN THE
|
|
// SPEC FOR DrvDitherBrush () function.
|
|
//
|
|
|
|
pDevInfo->cxDither = 0;
|
|
pDevInfo->cyDither = 0;
|
|
|
|
//
|
|
// the following line is set by PH. According to PH, we need
|
|
// to have 16 colors. We cannot only have 9 colors (for pen plotter).
|
|
//
|
|
//
|
|
// 01-Dec-1993 Wed 01:31:16 updated
|
|
// The reason that engine need 16 colors is it optimized by using bit 3
|
|
// as duplicate bit (used only bit 0/1/2) and bit 3 always mask off, so
|
|
// that engine can do faster comparsion
|
|
//
|
|
|
|
//
|
|
// If its a raster device, tell the engine that we are a 24 bit color
|
|
// device. This way we get the max resolution for bitmaps and brushes
|
|
// and can reducedown as required.
|
|
//
|
|
|
|
if (IS_RASTER(pPDev)) {
|
|
|
|
pDevInfo->iDitherFormat = BMF_24BPP;
|
|
|
|
} else {
|
|
|
|
pDevInfo->iDitherFormat = BMF_4BPP;
|
|
}
|
|
|
|
if (pPDev->hPalDefault) {
|
|
|
|
EngDeletePalette(pPDev->hPalDefault);
|
|
pPDev->hPalDefault = NULL;
|
|
}
|
|
|
|
//
|
|
// Create the Pen palette based only on the total number of pens the
|
|
// device can handle.
|
|
//
|
|
|
|
if (IS_RASTER(pPDev)) {
|
|
|
|
//
|
|
// This is a raster device, we will always make it a 24-bit device so
|
|
// the engine will pass back max color info and we can dither/halftone
|
|
// as we see fit. If we don't do this, the Engine will reduce bitmaps
|
|
// to our color space before passing the bitmaps onto us.
|
|
//
|
|
|
|
if (!(pDevInfo->hpalDefault =
|
|
EngCreatePalette(PAL_BGR, 0, 0, 0, 0, 0))) {
|
|
|
|
//
|
|
// The create failed so raise an error
|
|
//
|
|
|
|
PLOTERR(("FillDevInfo: EngCreatePalette(PAL_BGR) failed."));
|
|
return(FALSE);
|
|
}
|
|
|
|
} else {
|
|
|
|
DWORD DevColor[MAX_PENPLOTTER_PENS + 2];
|
|
PDWORD pdwCur;
|
|
PPENDATA pPenData;
|
|
PALENTRY PalEntry;
|
|
UINT cPens;
|
|
|
|
extern PALENTRY PlotPenPal[];
|
|
|
|
|
|
PLOTASSERT(1, "Too many pens defined for pen plotter (%ld)",
|
|
(pPDev->pPlotGPC->Pens.Count <= MAX_PENPLOTTER_PENS),
|
|
pPDev->pPlotGPC->Pens.Count);
|
|
|
|
if (pPDev->pPlotGPC->Pens.Count > MAX_PENPLOTTER_PENS)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Get the start of where to fill colors
|
|
//
|
|
|
|
pdwCur = &DevColor[0];
|
|
|
|
//
|
|
// 1st Entry is always WHITE
|
|
//
|
|
|
|
*pdwCur++ = RGB(255, 255, 255);
|
|
|
|
//
|
|
// Now go into a loop loading up the rest of the colors
|
|
//
|
|
|
|
PLOTDBG(DBG_PENPAL, ("Pen Palette #%02ld = 255:255:255", 0));
|
|
|
|
for (cPens = 1, pPenData = (PPENDATA)pPDev->pPlotGPC->Pens.pData;
|
|
cPens <= (UINT)pPDev->pPlotGPC->Pens.Count;
|
|
pPenData++) {
|
|
|
|
//
|
|
// Place the RGB value into the palette
|
|
//
|
|
|
|
PalEntry = PlotPenPal[pPenData->ColorIdx];
|
|
*pdwCur++ = RGB(PalEntry.R, PalEntry.G, PalEntry.B);
|
|
|
|
PLOTDBG(DBG_PENPAL, ("Pen Palette #%02ld = %03ld:%03ld:%03ld",
|
|
cPens,
|
|
(LONG)PalEntry.R, (LONG)PalEntry.G, (LONG)PalEntry.B));
|
|
|
|
//
|
|
// Track total number of pens defined
|
|
//
|
|
|
|
++cPens;
|
|
}
|
|
|
|
//
|
|
// Last Pen is BRIGHT YELLOW WHITE, this is done so that a non-white
|
|
// will map to this pen, in order to effect painting on the device.
|
|
// Otherwise, if a non-white pen, gets mapped to white, nothing
|
|
// would get rendered on the surface.
|
|
//
|
|
|
|
*pdwCur++ = RGB(255, 255, 254);
|
|
cPens++;
|
|
|
|
PLOTDBG(DBG_PENPAL, ("Pen Palette #%02ld = 255:255:254", cPens - 1));
|
|
|
|
//
|
|
// Now create the engine palette
|
|
//
|
|
|
|
if (!(pDevInfo->hpalDefault = EngCreatePalette(PAL_INDEXED,
|
|
cPens,
|
|
DevColor,
|
|
0,
|
|
0,
|
|
0))) {
|
|
//
|
|
// The create failed so raise an error
|
|
//
|
|
|
|
PLOTERR(("FillDevInfo: EngCreatePalette(PAL_INDEXED=%ld) failed.",
|
|
cPens));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save the created palette / later we need to destroy it.
|
|
//
|
|
|
|
pPDev->hPalDefault = pDevInfo->hpalDefault;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
CommonStartPDEV(
|
|
PDEV *pPDev,
|
|
DEVMODEW *pPlotDMIn,
|
|
ULONG cPatterns,
|
|
HSURF *phsurfPatterns,
|
|
ULONG cjDevCaps,
|
|
ULONG *pDevCaps,
|
|
ULONG cjDevInfo,
|
|
DEVINFO *pDevInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Function to perform the PDEV initialization. This is common to
|
|
DrvEnablePDEV and DrvResetPDEV. The individual functions
|
|
do whatever is required before calling into here.
|
|
|
|
Arguments:
|
|
|
|
pPDev - the pPDev which we returned in DrvEnablePDEV
|
|
|
|
pPlotDMIn - Pointer to the DEVMODE data structure
|
|
|
|
cPatterns - Count of patterns to be set in phsurfPatterns
|
|
|
|
phsurfPatterns - pointer to the standard pattern HSURF array
|
|
|
|
cjDevCaps - total size of pDevCaps pointed to.
|
|
|
|
pDevCaps - pointer to the device cap DWORDs
|
|
|
|
cjDevInfo - total size of pDevInfo pointed to
|
|
|
|
pDevInfo - pointer to the DEVINFO data structure
|
|
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN
|
|
|
|
|
|
Author:
|
|
|
|
23-Nov-1993 Tue 20:13:10 created
|
|
Re-write
|
|
|
|
05-Jan-1994 Wed 23:34:18 updated
|
|
Make PlotXDPI for the Pen Plotter rather than PLOTTER_UNITS_DPI
|
|
|
|
06-Jan-1994 Thu 13:10:11 updated
|
|
Change RasterDPI always be the resoluton reports back to the engine
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
GDIINFO GdiInfo;
|
|
DEVINFO DevInfo;
|
|
DWORD dmErrBits;
|
|
|
|
|
|
//
|
|
// Validate the DEVMODE structure passed in by the user, If OK, set the
|
|
// appropriate fields in the PDEV, the validateSetPlotDM() will always
|
|
// return a valid PLOTDEVMODE so we just use it. Any valid DM info will
|
|
// merged into the final DEVMODE
|
|
//
|
|
|
|
if (dmErrBits = ValidateSetPLOTDM(pPDev->hPrinter,
|
|
pPDev->pPlotGPC,
|
|
pPDev->PlotDM.dm.dmDeviceName,
|
|
(PPLOTDEVMODE)pPlotDMIn,
|
|
&(pPDev->PlotDM),
|
|
&(pPDev->CurForm))) {
|
|
|
|
PLOTWARN(("CommonStartPDEV: ValidateSetPLOTDM() ErrBits=%08lx",
|
|
dmErrBits));
|
|
}
|
|
|
|
//
|
|
// fill in our PDEV structure...
|
|
//
|
|
// The RasterDPI will be used for raster printer resolution, for pen
|
|
// plotters this is the GPC's ideal resolution.
|
|
//
|
|
|
|
pPDev->lCurResolution = (LONG)pPDev->pPlotGPC->RasterXDPI;
|
|
|
|
PLOTDBG(DBG_GDICAPS, ("CURRENT Resolution = %ld", pPDev->lCurResolution));
|
|
|
|
SetPlotForm(&(pPDev->PlotForm),
|
|
pPDev->pPlotGPC,
|
|
&(pPDev->CurPaper),
|
|
&(pPDev->CurForm),
|
|
&(pPDev->PlotDM),
|
|
&(pPDev->PPData));
|
|
|
|
//
|
|
// fill in the device capabilities in GDIINFO data structure for the engine
|
|
//
|
|
|
|
if ((cjDevCaps) && (pDevCaps)) {
|
|
|
|
FillDeviceCaps(pPDev, &GdiInfo);
|
|
CopyMemory(pDevCaps, &GdiInfo, min(cjDevCaps, sizeof(GDIINFO)));
|
|
}
|
|
|
|
//
|
|
// Fill in DevInfo data structrue
|
|
//
|
|
|
|
if ((cjDevInfo) && (pDevInfo)) {
|
|
|
|
if (!FillDevInfo(pPDev, &DevInfo)) {
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
CopyMemory(pDevInfo, &DevInfo, min(cjDevInfo, sizeof(DEVINFO)));
|
|
}
|
|
|
|
//
|
|
// Set it to NULL so that the engine can create halftone one for us
|
|
//
|
|
|
|
if ((cPatterns) && (phsurfPatterns)) {
|
|
|
|
ZeroMemory(phsurfPatterns, sizeof(HSURF) * cPatterns);
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
}
|