Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1208 lines
28 KiB

/*++
Copyright (c) 1996-1999 Microsoft Corporation
Module Name:
print.c
Abstract:
Implementation of document and page related DDI entry points:
DrvStartDoc
DrvEndDoc
DrvStartPage
DrvSendPage
DrvNextBand
DrvStartBanding
Environment:
Windows NT Unidrv driver
Revision History:
10/14/96 -amandan-
Created
03/31/97 -zhanw-
Added OEM customization support
--*/
#include "unidrv.h"
//
// Forward declaration for local functions
//
VOID VEndPage ( PDEV *);
BOOL BEndDoc ( PDEV *, SURFOBJ *, FLONG flags);
VOID VSendSequenceCmd(PDEV *, DWORD);
BOOL
DrvStartDoc(
SURFOBJ *pso,
PWSTR pDocName,
DWORD jobId
)
/*++
Routine Description:
Implementation of DDI entry point DrvStartDoc.
Please refer to DDK documentation for more details.
Arguments:
pso - Defines the surface object
pDocName - Specifies a Unicode document name
jobId - Identifies the print job
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
PDEV *pPDev = (PDEV*)pso->dhpdev;
VERBOSE(("Entering DrvStartDoc...\n"));
ASSERT_VALID_PDEV(pPDev);
//
// use driver managed surface
//
if (pPDev->pso)
pso = pPDev->pso;
//
// Handle OEM hooks
//
HANDLE_OEMHOOKS(pPDev,
EP_OEMStartDoc,
PFN_OEMStartDoc,
BOOL,
(pso,
pDocName,
jobId));
HANDLE_VECTORHOOKS(pPDev,
EP_OEMStartDoc,
VMStartDoc,
BOOL,
(pso,
pDocName,
jobId));
//
// We might get a DrvResetPDEV before this and get another DrvStartDoc
// without a DrvEndDoc so check for that condition and call BEndDoc
// to clean up the previous instance before continuing.
//
if (pPDev->fMode & PF_DOC_SENT)
{
BEndDoc(pPDev, pso, 0); // this flag also suppresses
// emission of EndDoc commands to the printer
// since they may cause a page ejection and
// we are only interested in freeing memory and
// performing pdev cleanup at this point.
pPDev->fMode &= ~PF_DOC_SENT;
}
else
pPDev->dwPageNumber = 1 ; // first page of document
//
// Call Raster and Font module
//
if (!(((PRMPROCS)(pPDev->pRasterProcs))->RMStartDoc(pso, pDocName, jobId)) ||
!(((PFMPROCS)(pPDev->pFontProcs))->FMStartDoc(pso, pDocName, jobId)) )
{
return FALSE;
}
//
// Send JobSetup and DocSetup Sequence Cmds at DrvStartPage instead
// of here since the driver can get a new DrvStartDoc after each
// DrvResetPDEV
//
return TRUE;
}
BOOL
DrvStartPage(
SURFOBJ *pso
)
/*++
Routine Description:
Implementation of DDI entry point DrvStartPage.
Please refer to DDK documentation for more details.
Arguments:
pso - Defines the surface object
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
PDEV *pPDev = (PDEV *)pso->dhpdev;
PAL_DATA *pPD = pPDev->pPalData;
VERBOSE(("Entering DrvStartPage...\n"));
ASSERT_VALID_PDEV(pPDev);
//
// use driver managed surface
//
if (pPDev->pso)
pso = pPDev->pso;
//
// Handle OEM hooks
//
HANDLE_OEMHOOKS(pPDev,
EP_OEMStartPage,
PFN_OEMStartPage,
BOOL,
(pso));
HANDLE_VECTORHOOKS(pPDev,
EP_OEMStartPage,
VMStartPage,
BOOL,
(pso));
//
// clear flags at start of page
//
pPDev->fMode &= ~(PF_SURFACE_USED | PF_SURFACE_ERASED);
pPDev->fMode &= ~PF_DOWNLOADED_TEXT;
//
// only a bitmap surface driver needs to have a band
//
if (!DRIVER_DEVICEMANAGED (pPDev))
{
ZeroMemory(pPDev->pbScanBuf, pPDev->szBand.cy);
ZeroMemory(pPDev->pbRasterScanBuf, (pPDev->szBand.cy / LINESPERBLOCK)+1);
#ifndef DISABLE_NEWRULES
pPDev->dwRulesCount = 0;
#endif
}
//
// Send JobSetup, DocSetup cmd and Download the Palette if necessary.
//
if (!(pPDev->fMode & PF_JOB_SENT))
{
VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwJobSetupIndex);
pPDev->fMode |= PF_JOB_SENT;
}
if (!(pPDev->fMode & PF_DOC_SENT))
{
VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwDocSetupIndex);
pPDev->fMode |= PF_DOC_SENT; // this flag is cleared
// by StartDoc
//
// PF_DOCSTARTED - Signify DrvStartDoc is called, for DrvResetPDEV
// this flag is cleared only at EndJob.
pPDev->fMode |= PF_DOCSTARTED;
}
pPDev->fMode &= ~PF_SEND_ONLY_NOEJECT_CMDS ;
if ( (pPD->fFlags & PDF_DL_PAL_EACH_DOC) &&
(!DRIVER_DEVICEMANAGED (pPDev)) )
{
VLoadPal(pPDev);
}
//
// Set PF_ENUM_GRXTXT
//
pPDev->fMode |= PF_ENUM_GRXTXT;
//
// Call Raster and Font module.
//
if ( !( ((PRMPROCS)(pPDev->pRasterProcs))->RMStartPage(pso) ) ||
!( ((PFMPROCS)(pPDev->pFontProcs))->FMStartPage(pso) ))
{
return FALSE;
}
//
// BUG_BUG, should we check for PF_SEND_ONLY_NOEJECT_CMDS here?
// Assumes that GPD writer does not put page ejection code
// in PageSetup Cmds since we might get a ResetPDEV between pages.
// This bit is set when we get DrvResetPDev where we are doing duplexing
// and paper size and source, and orienation is the same. Detecting this
// condition allows us to skip page ejection cmds or any cmds that
// could cause page ejection but if the GPD writer does not put page
// ejection code in PageSetup cmd, we are OK.
// If pageSetup commands caused pages to be ejected, we would
// always get one or more blank pages for every one that was printed.
// this is a needless concern.
//
// initialize the cursor position at the start of each page
//
pPDev->ctl.ptCursor.x = pPDev->ctl.ptCursor.y = 0;
pPDev->ctl.dwMode |= MODE_CURSOR_UNINITIALIZED; // both X & Y
//
// Send PageSetup sequence Cmds
//
VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwPageSetupIndex);
//Download the Palette if necessary.
if ( (pPD->fFlags & PDF_DL_PAL_EACH_PAGE) &&
(!DRIVER_DEVICEMANAGED (pPDev)) )
{
VLoadPal(pPDev);
}
//
// Set the current position to some illegal position, so that
// we make no assumptions about where we are
//
//
// Flush the spool buffer with the setup commands to give serial printers
// a head start on loading paper and cleaning their jets.
//
if (pPDev->pGlobals->printertype == PT_SERIAL)
FlushSpoolBuf (pPDev);
return TRUE;
}
BOOL
DrvSendPage(
SURFOBJ *pso
)
/*++
Routine Description:
Implementation of DDI entry point DrvSendPage.
Please refer to DDK documentation for more details.
Arguments:
pso - Defines the surface object
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
BOOL bRet = FALSE;
PDEV * pPDev = (PDEV *)pso->dhpdev;
VERBOSE(("Entering DrvSendPage...\n"));
ASSERT_VALID_PDEV(pPDev);
//
// use driver managed surface
//
if (pPDev->pso)
pso = pPDev->pso;
//
// Handle OEM hooks
//
HANDLE_OEMHOOKS(pPDev,
EP_OEMSendPage,
PFN_OEMSendPage,
BOOL,
(pso));
HANDLE_VECTORHOOKS(pPDev,
EP_OEMSendPage,
VMSendPage,
BOOL,
(pso));
//Reset the brush, before calling render module.
GSResetBrush(pPDev);
switch( pso->iType )
{
case STYPE_BITMAP:
//
// Engine managed bitmap
//
//
// Call Raster and Font module
//
if ( !(((PRMPROCS)(pPDev->pRasterProcs))->RMSendPage(pso)) ||
!(((PFMPROCS)(pPDev->pFontProcs))->FMSendPage(pso) ) )
{
return FALSE;
}
//
// VEndPage should take care of sending PageFinish sequence Cmds
//
VEndPage( pPDev );
bRet = TRUE;
break;
case STYPE_DEVICE:
//
// Device managed surface
//
VERBOSE(("DrvSendPage: pso->iType == STYPE_DEVICE \n" ));
//
// Call Raster and Font module if needed.
//
//
// VEndPage should take care of sending PageFinish sequence Cmds
//
VEndPage( pPDev );
bRet = TRUE;
break;
default:
VERBOSE(("DrvSendPage: pso->iType is unknown \n"));
break;
}
return bRet;
}
BOOL
DrvEndDoc(
SURFOBJ *pso,
FLONG flags
)
/*++
Routine Description:
Implementation of DDI entry point DrvEndDoc.
Please refer to DDK documentation for more details.
Arguments:
pso - Defines the surface object
flags - A set of flag bits
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
PDEV *pPDev = (PDEV *)pso->dhpdev;
VERBOSE(("Entering DrvEndDoc...\n"));
ASSERT_VALID_PDEV(pPDev);
//
// use driver managed surface
//
if (pPDev->pso)
pso = pPDev->pso;
//
// if we've detected an aborted job because WritePrinter has failed we will set the
// ED_ABORTDOC flag for the OEM plugins since GDI only sets this for direct printing
//
if (pPDev->fMode & PF_ABORTED)
flags |= ED_ABORTDOC;
//
// Handle OEM hooks
//
HANDLE_OEMHOOKS(pPDev,
EP_OEMEndDoc,
PFN_OEMEndDoc,
BOOL,
(pso,
flags));
HANDLE_VECTORHOOKS(pPDev,
EP_OEMEndDoc,
VMEndDoc,
BOOL,
(pso,
flags));
pPDev->fMode &= ~PF_DOC_SENT;
// we are going to send the EndDoc commands to the printer.
return ( BEndDoc(pPDev, pso, flags) );
}
BOOL
DrvNextBand(
SURFOBJ *pso,
POINTL *pptl
)
/*++
Routine Description:
Implementation of DDI entry point DrvNextBand.
Please refer to DDK documentation for more details.
Arguments:
pso - Defines the surface object
pptl - Pointer to origin of next band (to return to GDI)
Return Value:
TRUE if successful, FALSE if there is an error
--*/
{
PDEV *pPDev = (PDEV *)pso->dhpdev;
BOOL bMore, bRet;
VERBOSE(("Entering DrvNextBand...\n"));
ASSERT_VALID_PDEV(pPDev);
//
// use driver managed surface
//
if (pPDev->pso)
pso = pPDev->pso;
//
// Handle OEM hooks
//
HANDLE_OEMHOOKS(pPDev,
EP_OEMNextBand,
PFN_OEMNextBand,
BOOL,
(pso,
pptl));
HANDLE_VECTORHOOKS(pPDev,
EP_OEMNextBand,
VMNextBand,
BOOL,
(pso,
pptl));
//Reset the brush, before calling render module.
GSResetBrush(pPDev);
//
// Call Raster and Font module
//
if (! (((PRMPROCS)(pPDev->pRasterProcs))->RMNextBand(pso, pptl)) ||
! (((PFMPROCS)(pPDev->pFontProcs))->FMNextBand(pso, pptl)) )
{
return FALSE;
}
//
// Clear the band surface, szBand is in Graphic units
//
pPDev->fMode &= ~(PF_SURFACE_USED | PF_SURFACE_ERASED);
pPDev->fMode &= ~PF_DOWNLOADED_TEXT;
if (!DRIVER_DEVICEMANAGED (pPDev)) // bitmap surface
{
ZeroMemory(pPDev->pbScanBuf, pPDev->szBand.cy);
ZeroMemory(pPDev->pbRasterScanBuf, (pPDev->szBand.cy / LINESPERBLOCK)+1);
#ifndef DISABLE_NEWRULES
pPDev->dwRulesCount = 0;
#endif
}
//
// If PF_REPLAY_BAND is set, then replay the last band enumerate to
// GDI
//
if (pPDev->fMode & PF_REPLAY_BAND)
{
pptl->x = pPDev->rcClipRgn.left;
pptl->y = pPDev->rcClipRgn.top;
VERBOSE(("DrvNextBand: Next Band is %d , %d \n", pptl->x, pptl->y));
pPDev->fMode &= ~PF_REPLAY_BAND;
return TRUE;
}
switch( pPDev->iBandDirection )
{
case SW_DOWN:
//
// Moving down the page
//
pPDev->rcClipRgn.top += pPDev->szBand.cy;
pPDev->rcClipRgn.bottom += pPDev->szBand.cy;
//
// Make sure we do not run off the bottom
//
bMore = pPDev->rcClipRgn.top < pPDev->sf.szImageAreaG.cy;
if( pPDev->rcClipRgn.bottom > pPDev->sf.szImageAreaG.cy )
{
//
// Partial band
//
pPDev->rcClipRgn.bottom = pPDev->sf.szImageAreaG.cy;
}
break;
case SW_RTOL:
//
// LaserJet style, RTOL
//
pPDev->rcClipRgn.left -= pPDev->szBand.cx;
pPDev->rcClipRgn.right -= pPDev->szBand.cx;
bMore = pPDev->rcClipRgn.right > 0;
//
// if the left position is negative that is
// what must be reported to GDI to render the
// band correctly so we don't change the clip region.
//
break;
case SW_LTOR:
//
// Dot matrix, left to right
//
pPDev->rcClipRgn.left += pPDev->szBand.cx;
pPDev->rcClipRgn.right += pPDev->szBand.cx;
bMore = pPDev->rcClipRgn.left < pPDev->sf.szImageAreaG.cx;
if( pPDev->rcClipRgn.right > pPDev->sf.szImageAreaG.cx )
{
//
// Partial band
//
pPDev->rcClipRgn.right = pPDev->sf.szImageAreaG.cx;
}
break;
case SW_UP:
//
// Moving up the page
//
pPDev->rcClipRgn.top -= pPDev->szBand.cy;
pPDev->rcClipRgn.bottom -= pPDev->szBand.cy;
//
// Make sure we do not run off the top
//
bMore = pPDev->rcClipRgn.bottom > 0 ;
if( pPDev->rcClipRgn.top < 0 )
{
//
// Partial band
//
pPDev->rcClipRgn.top = 0;
}
break;
default:
VERBOSE((" DrvNextBand, unknown banding direction \n"));
return(FALSE);
}
if( bMore )
{
pptl->x = pPDev->rcClipRgn.left;
pptl->y = pPDev->rcClipRgn.top;
VERBOSE(("DrvNextBand: Next Band is %d , %d \n", pptl->x, pptl->y));
}
else
{
//
// No more band for the page, send the page to printer
//
if ( !(((PRMPROCS)(pPDev->pRasterProcs))->RMSendPage(pso)) ||
!(((PFMPROCS)(pPDev->pFontProcs))->FMSendPage(pso)) )
{
bRet = FALSE;
}
else
bRet = TRUE;
//
// Send PageFinish sequence commands
//
VEndPage( pPDev );
pptl->x = pptl->y = -1;
return(bRet);
}
return(TRUE);
}
BOOL
DrvStartBanding(
SURFOBJ *pso,
POINTL *pptl
)
/*++
Routine Description:
Implementation of DDI entry point DrvStartBanding.
Please refer to DDK documentation for more details.
Note: DrvStartBanding is called to prepare the driver
for banding, call only once per page (not at everyband!!)
Arguments:
pso - Defines the surface object
pptl - Pointer to origin of next band (to return to GDI)
Return Value:
Fill out pptl to contain the origin of the first band
TRUE if successful, FALSE if there is an error
--*/
{
PDEV *pPDev = (PDEV *)pso->dhpdev;
VERBOSE(("Entering DrvStartBanding...\n"));
ASSERT_VALID_PDEV(pPDev);
//
// use driver managed surface
//
if (pPDev->pso)
pso = pPDev->pso;
//
// Handle OEM hooks
//
HANDLE_OEMHOOKS(pPDev,
EP_OEMStartBanding,
PFN_OEMStartBanding,
BOOL,
(pso,
pptl));
HANDLE_VECTORHOOKS(pPDev,
EP_OEMStartBanding,
VMStartBanding,
BOOL,
(pso,
pptl));
//
// Set PF_ENUM_GRXTXT
//
pPDev->fMode |= PF_ENUM_GRXTXT;
pPDev->fMode &= ~(PF_SURFACE_USED | PF_SURFACE_ERASED);
pPDev->fMode &= ~PF_DOWNLOADED_TEXT;
if (!DRIVER_DEVICEMANAGED (pPDev)) // bitmap surface
{
ZeroMemory(pPDev->pbScanBuf, pPDev->szBand.cy);
ZeroMemory(pPDev->pbRasterScanBuf, (pPDev->szBand.cy / LINESPERBLOCK)+1);
#ifndef DISABLE_NEWRULES
pPDev->dwRulesCount = 0;
#endif
}
//
//
// Call Raster and Font module
//
if (! (((PRMPROCS)(pPDev->pRasterProcs))->RMStartBanding(pso, pptl)) ||
! (((PFMPROCS)(pPDev->pFontProcs))->FMStartBanding(pso, pptl)) )
{
return FALSE;
}
if( pPDev->fMode & PF_ROTATE )
{
pPDev->rcClipRgn.top = 0;
pPDev->rcClipRgn.bottom = pPDev->sf.szImageAreaG.cy;
if( pPDev->fMode & PF_CCW_ROTATE90 )
{
//
// LaserJet style rotation
//
if( // if duplexing is enabled...
(pPDev->pdm->dmFields & DM_DUPLEX) &&
(pPDev->pdm->dmDuplex == DMDUP_VERTICAL) &&
!(pPDev->dwPageNumber % 2) &&
pPDev->pUIInfo->dwFlags & FLAG_REVERSE_BAND_ORDER)
{
pPDev->rcClipRgn.left = 0;
pPDev->rcClipRgn.right = pPDev->szBand.cx;
pPDev->iBandDirection = SW_LTOR;
}
else
{
pPDev->rcClipRgn.left = pPDev->sf.szImageAreaG.cx - pPDev->szBand.cx;
pPDev->rcClipRgn.right = pPDev->sf.szImageAreaG.cx;
pPDev->iBandDirection = SW_RTOL;
}
}
else
{
//
// Dot matrix style rotation
//
if( // if duplexing is enabled...
(pPDev->pdm->dmFields & DM_DUPLEX) &&
(pPDev->pdm->dmDuplex == DMDUP_VERTICAL) &&
!(pPDev->dwPageNumber % 2) &&
pPDev->pUIInfo->dwFlags & FLAG_REVERSE_BAND_ORDER)
{
pPDev->rcClipRgn.left = pPDev->sf.szImageAreaG.cx - pPDev->szBand.cx;
pPDev->rcClipRgn.right = pPDev->sf.szImageAreaG.cx;
pPDev->iBandDirection = SW_RTOL;
}
else
{
pPDev->rcClipRgn.left = 0;
pPDev->rcClipRgn.right = pPDev->szBand.cx;
pPDev->iBandDirection = SW_LTOR;
}
}
}
else
{
pPDev->rcClipRgn.left = 0;
pPDev->rcClipRgn.right = pPDev->szBand.cx;
if( // if duplexing is enabled...
(pPDev->pdm->dmFields & DM_DUPLEX) &&
(pPDev->pdm->dmDuplex == DMDUP_VERTICAL) &&
!(pPDev->dwPageNumber % 2) &&
pPDev->pUIInfo->dwFlags & FLAG_REVERSE_BAND_ORDER)
{
pPDev->rcClipRgn.top = pPDev->sf.szImageAreaG.cy - pPDev->szBand.cy;
pPDev->rcClipRgn.bottom = pPDev->sf.szImageAreaG.cy ;
pPDev->iBandDirection = SW_UP;
}
else
{
pPDev->rcClipRgn.top = 0;
pPDev->rcClipRgn.bottom = pPDev->szBand.cy;
pPDev->iBandDirection = SW_DOWN;
}
}
pptl->x = pPDev->rcClipRgn.left;
pptl->y = pPDev->rcClipRgn.top;
return TRUE;
}
VOID
VEndPage (
PDEV *pPDev
)
/*++
Routine Description:
This function is called when the page has been rendered. Mainly used to
complete the page printing process. Called at DrvSendPage or at
DrvNextBand and no more band to process for the page or at
DrvEndDoc where the job is aborted.
Arguments:
pPDev - Pointer to PDEVICE
Return Value:
None
--*/
{
//
// Eject the page for device that use FF to eject a page, else
// move the cursor to the bottom of the page.
//
if (pPDev->pGlobals->bEjectPageWithFF == TRUE)
{
if ( !(pPDev->bTTY) ||
pPDev->fMode2 & PF2_DRVTEXTOUT_CALLED_FOR_TTY ||
!(pPDev->fMode2 & PF2_PASSTHROUGH_CALLED_FOR_TTY) )
{
WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_FORMFEED));
if (pPDev->fMode & PF_RESELECTFONT_AFTER_FF)
{
VResetFont(pPDev);
}
}
}
else
{
//
// Note: sf.szImageAreaG.cx and sf.szImageAreaG.cy are swapped already
// if the page is printed in landscape mode. Need to unswap it
// for moving the cursor to the end of the page
//
INT iYEnd; // Last scan line on page
iYEnd = pPDev->pdm->dmOrientation == DMORIENT_LANDSCAPE ?
pPDev->sf.szImageAreaG.cx : pPDev->sf.szImageAreaG.cy;
YMoveTo(pPDev, iYEnd, MV_GRAPHICS);
}
//
// Send PageFinish sequence Cmds
//
VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwPageFinishIndex);
//
// Reset and and free up realized brush for this page
//
GSResetBrush(pPDev);
GSUnRealizeBrush(pPDev);
FlushSpoolBuf( pPDev );
pPDev->dwPageNumber++ ;
//
// Clear PF2_XXX_TTY flags
//
pPDev->fMode2 &= ~( PF2_DRVTEXTOUT_CALLED_FOR_TTY |
PF2_PASSTHROUGH_CALLED_FOR_TTY );
}
BOOL
BEndDoc (
PDEV *pPDev,
SURFOBJ *pso,
FLONG flags
)
/*++
Routine Description:
This function can be called from two places - DrvEndDoc and DrvStartDoc.
In the case of a DrvResetPDEV, the driver might get another DrvStartDoc
without a DrvEndDoc. So need to check for previous DrvStartDoc and call
VEndDoc to clean up previous instance before initializing the new one.
Arguments:
pPDev - Pointer to PDEVICE
pso - Pointer to surface object
flags - EndDoc flags from DrvEndDoc, zero if called from DrvStartDoc
Return Value:
TRUE for success and FALSE for failure
--*/
{
//
// Call Raster and Font module for cleaning up
//
if (! (((PRMPROCS)(pPDev->pRasterProcs))->RMEndDoc(pso, flags)) ||
! (((PFMPROCS)(pPDev->pFontProcs))->FMEndDoc(pso, flags)) )
{
return FALSE;
}
//
// If the job is aborted, send the
// PageFinish sequence Cmds (via. VEndPage)
//
if( flags & ED_ABORTDOC )
VEndPage( pPDev);
//
// Send DocFinish, JobFinish sequence Cmds
//
// flag is cleared if called from DrvEndDoc, this is the only time we
// should actually send the EndDoc commands to the printer.
if (!(pPDev->fMode & PF_DOC_SENT))
{
if (pPDev->fMode & PF_DOCSTARTED)
{
VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwDocFinishIndex);
// print state has been forgotten, All start doc commands must be resent.
pPDev->fMode &= ~PF_DOCSTARTED;
}
if (pPDev->fMode & PF_JOB_SENT)
{
VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwJobFinishIndex);
pPDev->fMode &= ~PF_JOB_SENT;
}
}
FlushSpoolBuf( pPDev );
//
// Clear the PF_DOCSTARTED, PF_FORCE_BANDING,
// PF_ENUM_TEXT, PF_ENUM_GRXTXT, PF_REPLAY_BAND flags
//
pPDev->fMode &= ~PF_FORCE_BANDING;
pPDev->fMode &= ~PF_ENUM_TEXT;
pPDev->fMode &= ~PF_ENUM_GRXTXT;
pPDev->fMode &= ~PF_REPLAY_BAND;
return TRUE;
}
VOID
VSendSequenceCmd(
PDEV *pPDev,
DWORD dwSectionIndex
)
/*++
Routine Description:
This function is called to send a sequence of commands to the printer.
Arguments:
pPDev - Pointer to PDEVICE
dwSectionIndex - specifies the index into the command array
for one of the following seq section.
SS_JOBSETUP,
SS_DOCSETUP,
SS_PAGESETUP,
SS_PAGEFINISH,
SS_DOCFINISH,
SS_JOBFINISH,
Return Value:
None
Note:
There are two types of command supported by the driver:
- Predefined Commands, these commands are predefined in GPD specification
and assigned an COMMAND ID (as enumerated in CMDINDEX).
- Sequence Commands, these commands are not predefined. They are
commands that the GPD writer define to configure commands.
- DT_LOCALLISTNODE is only used to hold a list of sequence commands
--*/
{
LISTNODE *pListNode;
COMMAND *pSeqCmd;
//
// Get the first node in the list
//
pListNode = LOCALLISTNODEPTR(pPDev->pDriverInfo, dwSectionIndex);
while( pListNode )
{
//
// Get pointer to command pointer using pListNode->dwData, which is
// the index into the command array
//
pSeqCmd = INDEXTOCOMMANDPTR(pPDev->pDriverInfo, pListNode->dwData);
//
// Send the sequence command - but only if page ejection is
// not currently suppressed or this command does not
// cause a page to be ejected.
//
if(!(pPDev->fMode & PF_SEND_ONLY_NOEJECT_CMDS) ||
(pSeqCmd->bNoPageEject))
WriteChannel(pPDev, pSeqCmd);
//
// Get the next command in the list or exit if it's the end of list
//
if (pListNode->dwNextItem == END_OF_LIST)
break;
else
pListNode = LOCALLISTNODEPTR(pPDev->pDriverInfo, pListNode->dwNextItem);
}
}
BYTE
BGetMask(
PDEV * pPDev,
RECTL * pRect
)
/*++
Routine Description:
Given a rectangle, calculate the mask for determining the
present of text, for z-ordering fix
Arguments:
pPDev - Pointer to PDEVICE
pRect - Pointer to rectangle defining the clip box for
text or graphics
Return Value:
None
Note:
First mark all columm as dirty then work from the left and the right
to figure out which one should be cleared.
--*/
{
BYTE bMask = 0xFF;
INT i, iRight;
iRight = MAX_COLUMM -1;
if(! (pRect && pPDev->pbScanBuf && pRect->left <= pRect->right) )
return 0;
for (i = 0; i < MAX_COLUMM ; i++)
{
if (pRect->left >= (LONG)(pPDev->dwDelta * (i+1)) )
bMask &= ~(1 << i);
else
break;
}
for (i = iRight; i >= 0; i--)
{
if (pRect->right < (LONG)(pPDev->dwDelta * i ))
bMask &= ~(1 << i);
else
break;
}
return bMask;
}