|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
enable.c
Abstract:
Implementation of device and surface related DDI entry points:
DrvEnableDriver DrvDisableDriver DrvEnablePDEV DrvResetPDEV DrvCompletePDEV DrvDisablePDEV DrvEnableSurface DrvDisableSurface DrvBitBlt DrvStretchBlt DrvDitherColor DrvEscape
Environment:
Fax driver, kernel mode
Revision History:
01/09/96 -davidx- Created it.
mm/dd/yy -author- description
--*/
#include "faxdrv.h"
#include "forms.h"
#define CLOSE_HANDLE(h) if (!CloseHandle(h)) Error(("CloseHandle failed: %d.\n", GetLastError()))
//
// Our DRVFN table which tells the engine where to find the routines we support.
//
static DRVFN FaxDriverFuncs[] = { { 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_DrvBitBlt, (PFN) DrvBitBlt }, { INDEX_DrvStretchBlt, (PFN) DrvStretchBlt }, { INDEX_DrvCopyBits, (PFN) DrvCopyBits }, { INDEX_DrvDitherColor, (PFN) DrvDitherColor }, { INDEX_DrvEscape, (PFN) DrvEscape }, };
//
// Forward declaration of local functions
//
VOID SelectPrinterForm(PDEVDATA); BOOL FillDevInfo(PDEVDATA, ULONG, PVOID); BOOL FillGdiInfo(PDEVDATA, ULONG, PVOID); VOID FreeDevData(PDEVDATA);
HINSTANCE ghInstance;
BOOL DllEntryPoint( 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:
Assert(pcbNeeded != NULL); *pcbNeeded = sizeof(DWORD);
if (pBuffer == NULL || cbBuf < sizeof(DWORD)) { SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; }
*((PDWORD) pBuffer) = TRUE; return TRUE;
default:
Error(("Unknown dwMode in DrvQueryDriverInfo: %d\n", dwMode)); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } }
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
--*/
{ 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_NT4 || 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_NT4; pDrvEnableData->c = sizeof(FaxDriverFuncs) / sizeof(DRVFN); pDrvEnableData->pdrvfn = FaxDriverFuncs;
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 DEVMODE 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; #ifndef USERMODE_DRIVER
ULONG ul; #endif
Verbose(("Entering DrvEnablePDEV...\n"));
//
// Allocate memory for our DEVDATA structure and initialize it
//
if (! (pdev = MemAllocZ(sizeof(DEVDATA)))) {
Error(("Memory allocation failed\n")); return NULL; }
pdev->hPrinter = hPrinter; pdev->bPrintPreview = FALSE; pdev->hPreviewMapping = NULL;
#ifdef USERMODE_DRIVER
pdev->hPreviewFile = INVALID_HANDLE_VALUE; #endif
pdev->pTiffPageHeader = NULL; pdev->pbTiffPageFP = NULL; pdev->startDevData = pdev; pdev->endDevData = pdev;
//
// Save and validate DEVMODE information
// start with the driver default
// then merge with the system default
// finally merge with the input devmode
//
if (CurrentVersionDevmode(pdm)) {
memcpy(&pdev->dm, pdm, sizeof(DRVDEVMODE));
//
// NOTE: We now use dmPrintQuality and dmYResolution fields
// to store the resolution measured in dots-per-inch. Add
// the following check as a safety precaution in case older
// DEVMODE is passed to us.
//
if (pdev->dm.dmPublic.dmPrintQuality <= 0 || pdev->dm.dmPublic.dmYResolution <= 0) { pdev->dm.dmPublic.dmPrintQuality = FAXRES_HORIZONTAL; pdev->dm.dmPublic.dmYResolution = FAXRES_VERTICAL; }
//
// Check if we were given a mapping file
//
if (pdev->dm.dmPrivate.szMappingFile[0] != TEXT('\0')) { //
// Load the preview file image:
//
// In user mode this is done by - CreateFile(), CreateFileMapping() and MapViewOfFile().
// In kernel mode this is done by - EngLoadModuleForWrite() and EngMapModule().
//
#ifdef USERMODE_DRIVER
//
// First, open the file
//
if ( INVALID_HANDLE_VALUE == (pdev->hPreviewFile = SafeCreateFile( pdev->dm.dmPrivate.szMappingFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL)) ) { Error(("Failed opening mapping file.\n")); } else { //
// Then create a mapping object
//
pdev->hPreviewMapping = CreateFileMapping( pdev->hPreviewFile, // handle to file
NULL, // security
PAGE_READWRITE, // protection
0, // high-order DWORD of size
MAX_TIFF_PAGE_SIZE, // low-order DWORD of size
NULL // object name
); #else
//
// First, load the file image
//
pdev->hPreviewMapping = EngLoadModuleForWrite(pdev->dm.dmPrivate.szMappingFile, 0); #endif
if (pdev->hPreviewMapping) { //
// Now, open a view to the image in our address space
//
#ifdef USERMODE_DRIVER
pdev->pTiffPageHeader = (PMAP_TIFF_PAGE_HEADER) MapViewOfFile( pdev->hPreviewMapping, // handle to file-mapping object
FILE_MAP_WRITE, // access mode
0, // high-order DWORD of offset
0, // low-order DWORD of offset
0 // number of bytes to map
); if ( (NULL != pdev->pTiffPageHeader) && (sizeof(MAP_TIFF_PAGE_HEADER) == pdev->pTiffPageHeader->cb) ) #else
pdev->pTiffPageHeader = (PMAP_TIFF_PAGE_HEADER) EngMapModule(pdev->hPreviewMapping, &ul); if ( (NULL != pdev->pTiffPageHeader) && (MAX_TIFF_PAGE_SIZE == ul) && (sizeof(MAP_TIFF_PAGE_HEADER) == pdev->pTiffPageHeader->cb) ) #endif
{ //
// Sucess
//
pdev->bPrintPreview = pdev->pTiffPageHeader->bPreview; pdev->pbTiffPageFP = (LPBYTE) (pdev->pTiffPageHeader + 1); } else { Error(("Failed opening view.\n"));
#ifdef USERMODE_DRIVER
if (pdev->pTiffPageHeader) { UnmapViewOfFile(pdev->pTiffPageHeader); } CLOSE_HANDLE(pdev->hPreviewMapping); CLOSE_HANDLE(pdev->hPreviewFile); pdev->hPreviewFile = NULL; #else
EngFreeModule(pdev->hPreviewMapping); #endif
pdev->hPreviewMapping = NULL; pdev->pTiffPageHeader = NULL; } } else { Error(("Failed mapping file: %s.\n", pdev->dm.dmPrivate.szMappingFile));
#ifdef USERMODE_DRIVER
// Close the file handle
CLOSE_HANDLE(pdev->hPreviewFile); pdev->hPreviewFile = NULL; #endif
}
#ifdef USERMODE_DRIVER
} #endif
} else { Warning(("No mapping file specified.\n")); } } else {
Error(("Bad DEVMODE passed to DrvEnablePDEV\n")); DriverDefaultDevmode(&pdev->dm, NULL, hPrinter); }
//
// Calculate the paper size information
//
SelectPrinterForm(pdev);
//
// Fill out GDIINFO and DEVINFO structure
//
if (! FillGdiInfo(pdev, cjGdiInfo, pGdiInfo) || ! FillDevInfo(pdev, cjDevInfo, pDevInfo)) { 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"));
//
// Validate both old and new device
//
pdevOld = (PDEVDATA) dhpdevOld; pdevNew = (PDEVDATA) dhpdevNew;
if (! ValidDevData(pdevOld) || ! ValidDevData(pdevNew)) {
Error(("ValidDevData failed\n")); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
Verbose(("Entering DrvResetPDEV...\n"));
//
// Transfer information from old device to new device
//
if (pdevOld->pageCount != 0) {
pdevNew->pageCount = pdevOld->pageCount; pdevNew->flags |= PDEV_RESETPDEV; pdevNew->fileOffset = pdevOld->fileOffset;
if (pdevOld->pFaxIFD) {
pdevNew->pFaxIFD = pdevOld->pFaxIFD; pdevOld->pFaxIFD = NULL; } }
//
// Carry over relevant flag bits
//
pdevNew->flags |= pdevOld->flags & PDEV_CANCELLED; return TRUE; }
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; FLONG flHooks;
Verbose(("Entering DrvEnableSurface...\n"));
//
// Validate the pointer to our DEVDATA structure
//
if (! ValidDevData(pdev)) {
Error(("ValidDevData failed\n")); SetLastError(ERROR_INVALID_PARAMETER); return NULL; }
//
// Adjust the bitmap size so that we always end up with 1728 pixels per scanline
//
Assert(MAX_WIDTH_PIXELS % DWORDBITS == 0);
if (IsLandscapeMode(pdev)) {
Assert(pdev->imageSize.cy <= MAX_WIDTH_PIXELS); pdev->imageSize.cy = MAX_WIDTH_PIXELS; pdev->imageSize.cx = ((pdev->imageSize.cx + (BYTEBITS - 1)) / BYTEBITS) * BYTEBITS;
} else {
Assert(pdev->imageSize.cx <= MAX_WIDTH_PIXELS); pdev->imageSize.cx = MAX_WIDTH_PIXELS; }
pdev->lineOffset = PadBitsToBytes(pdev->imageSize.cx, sizeof(DWORD));
//
// Call the engine to create a standard bitmap surface for us
//
pdev->hbitmap = (HSURF) EngCreateBitmap(pdev->imageSize, pdev->lineOffset, BMF_1BPP, BMF_TOPDOWN | BMF_NOZEROINIT | BMF_USERMEM, NULL);
if (pdev->hbitmap == NULL) {
Error(("EngCreateBitmap failed\n")); return NULL; }
//
// Associate the surface with the device and inform the
// engine which functions we have hooked out
//
if (pdev->dm.dmPrivate.flags & FAXDM_NO_HALFTONE) flHooks = 0; else flHooks = (HOOK_STRETCHBLT | HOOK_BITBLT | HOOK_COPYBITS);
EngAssociateSurface(pdev->hbitmap, pdev->hdev, flHooks);
//
// Return the surface handle to the engine
//
return pdev->hbitmap; }
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->hbitmap != NULL) {
EngDeleteSurface(pdev->hbitmap); pdev->hbitmap = 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")); }
BOOL IsCompatibleSurface( SURFOBJ *psoDst, SURFOBJ *psoSrc, XLATEOBJ *pxlo )
/*++
Routine Description:
Check if the source surface is compatible with the destination surface i.e. we can bitblt without halftonig
Arguments:
psoDst - Specifies the destination surface psoSrc - Specifies the source surface pxlo - How to transform colors between the source surface and the destination surface
Return Value:
TRUE if the source surface is compatible with the destination surface FALSE otherwise
--*/
{ BOOL result;
//
// We know our destination surface is always 1bpp
//
Assert(psoDst->iBitmapFormat == BMF_1BPP);
//
// Check whether the transformation is trivial
//
if (!pxlo || (pxlo->flXlate & XO_TRIVIAL)) {
result = (psoSrc->iBitmapFormat == psoDst->iBitmapFormat);
} else if ((pxlo->flXlate & XO_TABLE) && pxlo->cEntries <= 2) { ULONG srcPalette[2];
srcPalette[0] = srcPalette[1] = RGB_BLACK; XLATEOBJ_cGetPalette(pxlo, XO_SRCPALETTE, pxlo->cEntries, srcPalette);
result = (srcPalette[0] == RGB_BLACK || srcPalette[0] == RGB_WHITE) && (srcPalette[1] == RGB_BLACK || srcPalette[1] == RGB_WHITE);
} else result = FALSE;
return result; }
BOOL DrvCopyBits( SURFOBJ *psoTrg, SURFOBJ *psoSrc, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclDst, POINTL *pptlSrc )
/*++
Routine Description:
Implementation of DDI entry point DrvCopyBits. We need to hook out this function. Otherwise bitmaps won't be halftoned.
Arguments:
Please refer to DDK documentation for more details.
Return Value:
TRUE if successful, FALSE otherwise
--*/
{ Verbose(("Entering DrvCopyBits ...\n")); //
// Check if halftoning is necessary
// If not, let the engine handle it
//
if ((psoSrc->iType != STYPE_BITMAP) || (psoTrg->iType != STYPE_BITMAP) || IsCompatibleSurface(psoTrg, psoSrc, pxlo)) { return EngCopyBits(psoTrg, psoSrc, pco, pxlo, prclDst, pptlSrc); } else { POINTL ptlBrushOrg; RECTL rclDst, rclSrc;
ptlBrushOrg.x = ptlBrushOrg.y = 0;
rclDst = *prclDst; rclSrc.left = pptlSrc->x; rclSrc.top = pptlSrc->y; rclSrc.right = rclSrc.left + (rclDst.right - rclDst.left); rclSrc.bottom = rclSrc.top + (rclDst.bottom - rclDst.top);
if ((rclSrc.right > psoSrc->sizlBitmap.cx) || (rclSrc.bottom > psoSrc->sizlBitmap.cy)) { rclSrc.right = psoSrc->sizlBitmap.cx; rclSrc.bottom = psoSrc->sizlBitmap.cy; rclDst.right = rclDst.left + (rclSrc.right - rclSrc.left); rclDst.bottom = rclDst.top + (rclSrc.bottom - rclSrc.top); }
return EngStretchBlt(psoTrg, psoSrc, NULL, pco, pxlo, &DefHTClrAdj, &ptlBrushOrg, &rclDst, &rclSrc, NULL, HALFTONE); } }
BOOL DrvBitBlt( SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush, ROP4 rop4 )
/*++
Routine Description:
Implementation of DDI entry point DrvBitBlt. We need to hook out this function. Otherwise bitmaps won't be halftoned.
Arguments:
Please refer to DDK documentation for more details.
Return Value:
TRUE if successful, FALSE otherwise
--*/
{ COLORADJUSTMENT *pca; PDEVDATA pdev; DWORD rop3Foreground, rop3Background; SURFOBJ *psoNewSrc; HBITMAP hbmpNewSrc; POINTL brushOrg; BOOL result;
Verbose(("Entering DrvBitBlt...\n")); //
// Validate input parameters
//
Assert(psoTrg != NULL); pdev = (PDEVDATA) psoTrg->dhpdev;
if (! ValidDevData(pdev)) {
Error(("ValidDevData failed\n")); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
//
// Use the system default color adjustment information
//
pca = &DefHTClrAdj;
//
// Figure out the foreground and background ROP3
//
psoNewSrc = NULL; hbmpNewSrc = NULL; rop3Foreground = GetForegroundRop3(rop4); rop3Background = GetBackgroundRop3(rop4);
if ((Rop3NeedPattern(rop3Foreground) || Rop3NeedPattern(rop3Background)) && pptlBrush) {
brushOrg = *pptlBrush;
} else {
brushOrg.x = brushOrg.y = 0; }
//
// If a source bitmap is involved in the raster operation and
// the source is not compatible with the destination surface,
// then we'll halftone the source bitmap into a new bitmap and
// bitblt the new bitmap onto the destination surface.
//
if ((Rop3NeedSource(rop3Foreground) || Rop3NeedSource(rop3Background)) && !IsCompatibleSurface(psoTrg, psoSrc, pxlo)) { RECTL rclNewSrc, rclOldSrc; SIZEL bmpSize; LONG lDelta;
rclNewSrc.left = rclNewSrc.top = 0; rclNewSrc.right = prclTrg->right - prclTrg->left; rclNewSrc.bottom = prclTrg->bottom - prclTrg->top;
rclOldSrc.left = pptlSrc->x; rclOldSrc.top = pptlSrc->y; rclOldSrc.right = rclOldSrc.left + rclNewSrc.right; rclOldSrc.bottom = rclOldSrc.top + rclNewSrc.bottom;
//
// Express path for the most common case: SRCCOPY
//
if (rop4 == 0xcccc) {
return EngStretchBlt(psoTrg, psoSrc, psoMask, pco, pxlo, pca, &brushOrg, prclTrg, &rclOldSrc, pptlMask, HALFTONE); }
//
// Modify the brush origin, because when we blt to the clipped bitmap
// the origin is at bitmap's (0, 0) minus the original location
//
brushOrg.x -= prclTrg->left; brushOrg.y -= prclTrg->top;
//
// Create a temporary bitmap surface
// Halftone the source bitmap into the temporary bitmap
//
Assert(psoTrg->iBitmapFormat == BMF_1BPP);
bmpSize.cx = rclNewSrc.right; bmpSize.cy = rclNewSrc.bottom; lDelta = PadBitsToBytes(bmpSize.cx, sizeof(DWORD));
if (! (hbmpNewSrc = EngCreateBitmap(bmpSize, lDelta, BMF_1BPP, BMF_TOPDOWN | BMF_NOZEROINIT, NULL)) || ! EngAssociateSurface((HSURF) hbmpNewSrc, pdev->hdev, 0) || ! (psoNewSrc = EngLockSurface((HSURF) hbmpNewSrc)) || ! EngStretchBlt(psoNewSrc, psoSrc, NULL, NULL, pxlo, pca, &brushOrg, &rclNewSrc, &rclOldSrc, NULL, HALFTONE)) { if (psoNewSrc) EngUnlockSurface(psoNewSrc); if (hbmpNewSrc) EngDeleteSurface((HSURF) hbmpNewSrc);
return FALSE; }
//
// Proceed to bitblt from the temporary bitmap to the destination
//
psoSrc = psoNewSrc; pptlSrc = (PPOINTL) &rclNewSrc.left; pxlo = NULL; brushOrg.x = brushOrg.y = 0; }
//
// Let engine do the work
//
result = EngBitBlt(psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg, pptlSrc, pptlMask, pbo, &brushOrg, rop4);
//
// Clean up properly before returning
//
if (psoNewSrc) EngUnlockSurface(psoNewSrc);
if (hbmpNewSrc) EngDeleteSurface((HSURF) hbmpNewSrc);
return result; }
BOOL DrvStretchBlt( SURFOBJ *psoDest, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo, COLORADJUSTMENT *pca, POINTL *pptlBrushOrg, RECTL *prclDest, RECTL *prclSrc, POINTL *pptlMask, ULONG iMode )
/*++
Routine Description:
Implementation of DDI entry point DrvDisableDriver. We need to hook out this function. Otherwise bitmaps won't be halftoned.
Arguments:
Please refer to DDK documentation for more details.
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{ Verbose(("Entering DrvStretchBlt...\n"));
//
// If no color adjustment information is provided, use the system default
//
if (pca == NULL) pca = &DefHTClrAdj;
//
// Let engine do the work; make sure halftone is enabled
//
return EngStretchBlt(psoDest, psoSrc, psoMask, pco, pxlo, pca, pptlBrushOrg, prclDest, prclSrc, pptlMask, HALFTONE); }
ULONG DrvDitherColor( DHPDEV dhpdev, ULONG iMode, ULONG rgb, ULONG *pul )
/*++
Routine Description:
Implementation of DDI entry point DrvDisableDriver. Please refer to DDK documentation for more details.
Arguments:
dhpdev - Driver device handle iMode - Determines the palette to dither against rgb - Specifies the RGB color that is to be dithered pul - Points to a memory location in which the dithering information is to be recorded
Return Value:
DCR_HALFTONE to indicate that the engine should create a halftone approximation for the driver.
--*/
{ return DCR_HALFTONE; }
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.
--*/
{ static ULONG paletteColors[2] = {
RGB_BLACK, RGB_WHITE, };
DEVINFO devinfo;
memset(&devinfo, 0, sizeof(devinfo));
//
// Fill in the graphics capabilities flags: we let the engine
// do almost everything. Also, we have to tell the engine not
// to do metafile spooling because we hook out DrvDocumentEvent.
//
devinfo.flGraphicsCaps = GCAPS_HALFTONE | GCAPS_MONO_DITHER | GCAPS_COLOR_DITHER | GCAPS_DONTJOURNAL;
//
// No device fonts
//
devinfo.cFonts = 0;
//
// Black and white palette: entry 0 is black and entry 1 is white
//
if (! (pdev->hpal = EngCreatePalette(PAL_INDEXED, 2, paletteColors, 0, 0, 0))) {
Error(("EngCreatePalette failed\n")); return FALSE; }
devinfo.hpalDefault = pdev->hpal; devinfo.iDitherFormat = BMF_1BPP; devinfo.cxDither = devinfo.cyDither = 4;
//
// Copy cb bytes from devinfo structure into the caller-provided buffer
//
if (cb > sizeof(devinfo)) { memset(pdevinfo, 0, cb); memcpy(pdevinfo, &devinfo, sizeof(devinfo)); } else memcpy(pdevinfo, &devinfo, cb);
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; LONG maxRes;
memset(&gdiinfo, 0, sizeof(gdiinfo));
//
// 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 the imageable area measured in microns.
// Remember to turn on the sign bit.
//
gdiinfo.ulHorzSize = - (pdev->imageArea.right - pdev->imageArea.left); gdiinfo.ulVertSize = - (pdev->imageArea.bottom - pdev->imageArea.top);
//
// Convert paper size and imageable area from microns to pixels
//
pdev->paperSize.cx = MicronToPixel(pdev->paperSize.cx, pdev->xres); pdev->paperSize.cy = MicronToPixel(pdev->paperSize.cy, pdev->yres);
pdev->imageArea.left = MicronToPixel(pdev->imageArea.left, pdev->xres); pdev->imageArea.right = MicronToPixel(pdev->imageArea.right, pdev->xres); pdev->imageArea.top = MicronToPixel(pdev->imageArea.top, pdev->yres); pdev->imageArea.bottom = MicronToPixel(pdev->imageArea.bottom, pdev->yres);
pdev->imageSize.cx = pdev->imageArea.right - pdev->imageArea.left; pdev->imageSize.cy = pdev->imageArea.bottom - pdev->imageArea.top;
//
// Width and height of the imageable area measured in device pixels
//
gdiinfo.ulHorzRes = pdev->imageSize.cx; gdiinfo.ulVertRes = pdev->imageSize.cy;
//
// Color depth information
//
gdiinfo.cBitsPixel = 1; gdiinfo.cPlanes = 1; gdiinfo.ulNumColors = 2;
//
// Resolution information
//
gdiinfo.ulLogPixelsX = pdev->xres; gdiinfo.ulLogPixelsY = pdev->yres;
//
// Win31 compatible text capability flags. Are they still used by anyone?
//
gdiinfo.flTextCaps = 0;
//
// Device pixel aspect ratio
//
gdiinfo.ulAspectX = pdev->yres; gdiinfo.ulAspectY = pdev->xres; gdiinfo.ulAspectXY = CalcHypot(pdev->xres, pdev->yres);
//
// Dotted line appears to be approximately 25dpi
// We assume either xres is a multiple of yres or yres is a multiple of xres
//
maxRes = max(pdev->xres, pdev->yres); Assert((maxRes % pdev->xres) == 0 && (maxRes % pdev->yres == 0));
gdiinfo.xStyleStep = maxRes / pdev->xres; gdiinfo.yStyleStep = maxRes / pdev->yres; gdiinfo.denStyleStep = maxRes / 25;
//
// Size and margins of physical surface measured in device pixels
//
gdiinfo.szlPhysSize.cx = pdev->paperSize.cx; gdiinfo.szlPhysSize.cy = pdev->paperSize.cy;
gdiinfo.ptlPhysOffset.x = pdev->imageArea.left; gdiinfo.ptlPhysOffset.y = pdev->imageArea.top;
//
// Use default halftone information
//
gdiinfo.ciDevice = DefDevHTInfo.ColorInfo; gdiinfo.ulDevicePelsDPI = max(pdev->xres, pdev->yres); gdiinfo.ulPrimaryOrder = PRIMARY_ORDER_CBA; gdiinfo.ulHTOutputFormat = HT_FORMAT_1BPP; gdiinfo.flHTFlags = HT_FLAG_HAS_BLACK_DYE; gdiinfo.ulHTPatternSize = HT_PATSIZE_4x4_M;
//
// Copy cb byte from gdiinfo structure into the caller-provided buffer
//
if (cb > sizeof(gdiinfo)) { memset(pgdiinfo, 0, cb); memcpy(pgdiinfo, &gdiinfo, sizeof(gdiinfo)); } else memcpy(pgdiinfo, &gdiinfo, cb);
return TRUE; }
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
--*/
{ if (pdev->hpal) EngDeletePalette(pdev->hpal);
//
// Close our preview file mapping if opened
//
#ifdef USERMODE_DRIVER
if (pdev->pTiffPageHeader) { UnmapViewOfFile(pdev->pTiffPageHeader); pdev->pTiffPageHeader = NULL; } if (pdev->hPreviewMapping) { CLOSE_HANDLE(pdev->hPreviewMapping); pdev->hPreviewMapping = NULL; } if (INVALID_HANDLE_VALUE != pdev->hPreviewFile) { CLOSE_HANDLE(pdev->hPreviewFile); pdev->hPreviewFile = INVALID_HANDLE_VALUE; }
#else
if (pdev->hPreviewMapping) { EngFreeModule(pdev->hPreviewMapping); }
#endif // USERMODE_DRIVER
MemFree(pdev->pFaxIFD); MemFree(pdev); }
VOID SelectPrinterForm( 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;
//
// Validate devmode form specification; use default form if it's invalid.
//
if (! ValidDevmodeForm(pdev->hPrinter, &pdev->dm.dmPublic, &formInfo)) {
memset(&formInfo, 0, sizeof(formInfo));
//
// Default to A4 paper
//
formInfo.Size.cx = formInfo.ImageableArea.right = A4_WIDTH; formInfo.Size.cy = formInfo.ImageableArea.bottom = A4_HEIGHT; }
Assert(formInfo.Size.cx > 0 && formInfo.Size.cy > 0); Assert(formInfo.ImageableArea.left >= 0 && formInfo.ImageableArea.top >= 0 && formInfo.ImageableArea.left < formInfo.ImageableArea.right && formInfo.ImageableArea.top < formInfo.ImageableArea.bottom && formInfo.ImageableArea.right <= formInfo.Size.cx && formInfo.ImageableArea.bottom <= formInfo.Size.cy);
//
// Take landscape into consideration
//
if (IsLandscapeMode(pdev)) {
LONG width, height;
//
// Swap the width and height
//
pdev->paperSize.cy = width = formInfo.Size.cx; pdev->paperSize.cx = height = formInfo.Size.cy;
//
// Rotate the coordinate system 90 degrees counterclockwise
//
pdev->imageArea.left = height - formInfo.ImageableArea.bottom; pdev->imageArea.top = formInfo.ImageableArea.left; pdev->imageArea.right = height - formInfo.ImageableArea.top; pdev->imageArea.bottom = formInfo.ImageableArea.right;
//
// Swap x and y resolution
//
pdev->xres = pdev->dm.dmPublic.dmYResolution; pdev->yres = pdev->dm.dmPublic.dmPrintQuality;
} else {
pdev->paperSize = formInfo.Size; pdev->imageArea = formInfo.ImageableArea;
pdev->xres = pdev->dm.dmPublic.dmPrintQuality; pdev->yres = pdev->dm.dmPublic.dmYResolution; } }
LONG CalcHypot( LONG x, LONG y )
/*++
Routine Description:
Returns the length of the hypotenouse of a right triangle
Arguments:
x, y - Edges of the right triangle
Return Value:
Hypotenouse of the right triangle
--*/
{ LONG hypo, delta, target;
//
// Take care of negative inputs
//
if (x < 0) x = -x;
if (y < 0) y = -y;
//
// 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 += (hypo << 1) + 1;
return hypo; }
|