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.
919 lines
23 KiB
919 lines
23 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: print.c
|
|
*
|
|
* Created: 10-Feb-1995 07:42:16
|
|
* Author: Gerrit van Wingerden [gerritv]
|
|
*
|
|
* Copyright (c) 1993 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "nlsconv.h"
|
|
|
|
#if DBG
|
|
int gerritv = 0;
|
|
#endif
|
|
|
|
#if DBG
|
|
BOOL gbDownloadFonts = FALSE;
|
|
BOOL gbForceUFIMapping = TRUE;
|
|
#endif
|
|
|
|
VOID vFreeUFIHashTable( PUFIHASH pUFIHashBase );
|
|
BOOL bAddUFIEntry( PUFIHASH *ppHashBase, PUNIVERSAL_FONT_ID pufi );
|
|
|
|
#if PRINT_TIMER
|
|
BOOL bPrintTimer = TRUE;
|
|
#endif
|
|
|
|
|
|
/****************************************************************************
|
|
* int PutDCStateInMetafile( HDC hdcMeta, HDC hdcSrc )
|
|
*
|
|
* Captures state of a DC into a metafile.
|
|
*
|
|
*
|
|
* This routine captures the states of a DC into a METAFILE. This is important
|
|
* because we would like each page of the spooled metafile to be completely self
|
|
* contained. In order to do this it must complete capture the original state
|
|
* of the DC in which it was recorded.
|
|
*
|
|
* Gerrit van Wingerden [gerritv]
|
|
*
|
|
* 11-7-94 10:00:00
|
|
*
|
|
*****************************************************************************/
|
|
|
|
|
|
void PutDCStateInMetafile( HDC hdcMeta )
|
|
{
|
|
PLDC pldc;
|
|
POINT ptlCurPos;
|
|
ULONG ul;
|
|
|
|
// DC_PLDC(hdcMeta,pldc,0);
|
|
|
|
MFD1("Selecting pen into mf\n");
|
|
SelectObject( hdcMeta, (HGDIOBJ) GetDCObject(hdcMeta, LO_PEN_TYPE) );
|
|
|
|
MFD1("Selecting brush into mf\n");
|
|
SelectObject( hdcMeta, (HGDIOBJ) GetDCObject(hdcMeta, LO_BRUSH_TYPE) );
|
|
|
|
MFD1("Selecting logfont into mf\n");
|
|
SelectObject( hdcMeta, (HGDIOBJ) GetDCObject(hdcMeta, LO_FONT_TYPE) );
|
|
|
|
// DON'T TRY THIS AT HOME. We need to record the current state of the
|
|
// dc in the metafile. We have optimizations however, that keep us from
|
|
// setting the same attribute if it was just set.
|
|
|
|
if( GetBkColor( hdcMeta ) != 0xffffff )
|
|
{
|
|
MFD1("Changing backround color in mf\n");
|
|
SetBkColor( hdcMeta, GetBkColor( hdcMeta ) );
|
|
}
|
|
|
|
|
|
if( GetTextColor( hdcMeta ) != 0 )
|
|
{
|
|
MFD1("Changing text color in mf\n");
|
|
SetTextColor( hdcMeta, GetTextColor( hdcMeta ) );
|
|
}
|
|
|
|
if( GetBkMode( hdcMeta ) != OPAQUE )
|
|
{
|
|
MFD1("Changing Background Mode in mf\n");
|
|
SetBkMode( hdcMeta, GetBkMode( hdcMeta ) );
|
|
}
|
|
|
|
if( GetPolyFillMode( hdcMeta ) != ALTERNATE )
|
|
{
|
|
MFD1("Changing PolyFill mode in mf\n");
|
|
SetPolyFillMode( hdcMeta, GetPolyFillMode( hdcMeta ) );
|
|
}
|
|
|
|
if( GetROP2( hdcMeta ) != R2_COPYPEN )
|
|
{
|
|
MFD1("Changing ROP2 in mf\n");
|
|
SetROP2( hdcMeta, GetROP2( hdcMeta ) );
|
|
}
|
|
|
|
if( GetStretchBltMode( hdcMeta ) != BLACKONWHITE )
|
|
{
|
|
MFD1("Changing StrechBltMode in mf\n");
|
|
SetStretchBltMode( hdcMeta, GetStretchBltMode( hdcMeta ) );
|
|
}
|
|
|
|
if( GetTextAlign( hdcMeta ) != 0 )
|
|
{
|
|
MFD1("Changing TextAlign in mf\n");
|
|
SetTextAlign( hdcMeta, GetTextAlign( hdcMeta ) );
|
|
}
|
|
|
|
if( ( GetBreakExtra( hdcMeta ) != 0 )|| ( GetcBreak( hdcMeta ) != 0 ) )
|
|
{
|
|
MFD1("Setting Text Justification in mf\n");
|
|
SetTextJustification( hdcMeta, GetBreakExtra( hdcMeta ), GetcBreak( hdcMeta ) );
|
|
}
|
|
|
|
if( GetMapMode( hdcMeta ) != MM_TEXT )
|
|
{
|
|
INT iMapMode = GetMapMode( hdcMeta );
|
|
POINT ptlWindowOrg, ptlViewportOrg;
|
|
SIZEL WndExt, ViewExt;
|
|
|
|
// get these before we set the map mode to MM_TEXT
|
|
|
|
GetViewportExtEx( hdcMeta, &ViewExt );
|
|
GetWindowExtEx( hdcMeta, &WndExt );
|
|
|
|
GetWindowOrgEx( hdcMeta, &ptlWindowOrg );
|
|
GetViewportOrgEx( hdcMeta, &ptlViewportOrg );
|
|
|
|
// set it to MM_TEXT so it doesn't get optimized out
|
|
|
|
SetMapMode(hdcMeta,MM_TEXT);
|
|
|
|
MFD1("Setting ANISOTROPIC or ISOTROPIC mode in mf\n");
|
|
|
|
SetMapMode( hdcMeta, iMapMode );
|
|
|
|
if( iMapMode == MM_ANISOTROPIC || iMapMode == MM_ISOTROPIC )
|
|
{
|
|
SetWindowExtEx( hdcMeta, WndExt.cx, WndExt.cy, NULL );
|
|
SetViewportExtEx( hdcMeta, ViewExt.cx, ViewExt.cy, NULL );
|
|
}
|
|
|
|
SetWindowOrgEx( hdcMeta,
|
|
ptlWindowOrg.x,
|
|
ptlWindowOrg.y,
|
|
NULL );
|
|
|
|
SetViewportOrgEx( hdcMeta,
|
|
ptlViewportOrg.x,
|
|
ptlViewportOrg.y,
|
|
NULL );
|
|
}
|
|
|
|
|
|
if( GetCurrentPositionEx( hdcMeta, &ptlCurPos ) )
|
|
{
|
|
MFD1("Set CurPos in mf\n");
|
|
MoveToEx( hdcMeta, ptlCurPos.x, ptlCurPos.y, NULL );
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* int MFP_StartDocW( HDC hdc, CONST DOCINFOW * pDocInfo )
|
|
*
|
|
* Gerrit van Wingerden [gerritv]
|
|
*
|
|
* 11-7-94 10:00:00
|
|
*
|
|
*****************************************************************************/
|
|
|
|
|
|
//! this needs to be moved to a spooler header file
|
|
|
|
#define QSM_DOWNLOADFONTS 0x000000001
|
|
|
|
|
|
|
|
BOOL MFP_StartDocW( HDC hdc, CONST DOCINFOW * pDocInfo, BOOL bBanding )
|
|
{
|
|
BOOL bRet = FALSE;
|
|
PWSTR pstr = NULL;
|
|
BOOL bEpsPrinting;
|
|
PLDC pldc;
|
|
UINT cjEMFSH, Dummy, ulCopyCount;
|
|
FLONG flSpoolMode;
|
|
HANDLE hSpooler;
|
|
|
|
EMFSPOOLHEADER *pemfsh = NULL;
|
|
|
|
MFD1("Entering StartDocW\n");
|
|
|
|
if (!IS_ALTDC_TYPE(hdc))
|
|
return(bRet);
|
|
|
|
DC_PLDC(hdc,pldc,bRet);
|
|
|
|
if( !bBanding )
|
|
{
|
|
hSpooler = pldc->hSpooler;
|
|
cjEMFSH = sizeof(EMFSPOOLHEADER);
|
|
|
|
if( pDocInfo->lpszDocName != NULL )
|
|
{
|
|
cjEMFSH += ( wcslen( pDocInfo->lpszDocName ) + 1 ) * sizeof(WCHAR);
|
|
}
|
|
|
|
if( pDocInfo->lpszOutput != NULL )
|
|
{
|
|
cjEMFSH += ( wcslen( pDocInfo->lpszOutput ) + 1 ) * sizeof(WCHAR);
|
|
}
|
|
|
|
pemfsh = (EMFSPOOLHEADER*) LocalAlloc( LMEM_FIXED, cjEMFSH );
|
|
|
|
if( pemfsh == NULL )
|
|
{
|
|
WARNING("MFP_StartDOCW: out of memory.\n");
|
|
goto FREEPORT;
|
|
}
|
|
|
|
pemfsh->cjSize = cjEMFSH;
|
|
|
|
cjEMFSH = 0;
|
|
|
|
if( ( pDocInfo->lpszDocName ) != NULL )
|
|
{
|
|
pemfsh->dpszDocName = sizeof(EMFSPOOLHEADER);
|
|
wcscpy( (WCHAR*) (pemfsh+1), pDocInfo->lpszDocName );
|
|
cjEMFSH += ( wcslen( pDocInfo->lpszDocName ) + 1 ) * sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
pemfsh->dpszDocName = 0;
|
|
}
|
|
|
|
if( pDocInfo->lpszOutput != NULL )
|
|
{
|
|
pemfsh->dpszOutput = sizeof(EMFSPOOLHEADER) + cjEMFSH;
|
|
wcscpy((WCHAR*)(((BYTE*) pemfsh ) + pemfsh->dpszOutput),
|
|
pDocInfo->lpszOutput);
|
|
}
|
|
else
|
|
{
|
|
pemfsh->dpszOutput = 0;
|
|
}
|
|
|
|
ASSERTGDI(ghSpooler,"non null hSpooler with unloaded WINSPOOL\n");
|
|
|
|
if( !(*fpQuerySpoolMode)( hSpooler, &flSpoolMode, &(pemfsh->dwVersion)))
|
|
{
|
|
WARNING("MFP_StartDoc: QuerySpoolMode failed\n");
|
|
goto FREEPORT;
|
|
}
|
|
|
|
ASSERTGDI((pemfsh->dwVersion == 0x00010000),
|
|
"QuerySpoolMode version doesn't equal 1.0\n");
|
|
|
|
if( !(*fpWritePrinter)( hSpooler, (LPVOID) pemfsh, pemfsh->cjSize, &Dummy ))
|
|
{
|
|
WARNING("MFP_StartDOC: Write printer failed\n");
|
|
goto FREEPORT;
|
|
}
|
|
else
|
|
{
|
|
MFD1("Wrote EMFSPOOLHEADER to the spooler\n");
|
|
}
|
|
|
|
|
|
#if DBG
|
|
if( gbDownloadFonts )
|
|
{
|
|
flSpoolMode |= QSM_DOWNLOADFONTS;
|
|
}
|
|
#endif
|
|
|
|
if( flSpoolMode & QSM_DOWNLOADFONTS )
|
|
{
|
|
pldc->fl |= LDC_DOWNLOAD_FONTS;
|
|
pldc->ppUFIHash = LocalAlloc( LMEM_FIXED | LMEM_ZEROINIT,
|
|
sizeof( PUFIHASH ) * UFI_HASH_SIZE );
|
|
|
|
if( pldc->ppUFIHash == NULL )
|
|
{
|
|
WARNING("MFP_StartDocW: unable to allocate UFI hash table\n");
|
|
goto FREEPORT;
|
|
}
|
|
|
|
pldc->fl |= LDC_FORCE_MAPPING;
|
|
pldc->ufi.Index = 0xFFFFFFFF;
|
|
}
|
|
|
|
#if DBG
|
|
// If gbDownloadFonts is set then force all fonts to be downloaded. Even
|
|
// ones on the remote machine.
|
|
|
|
if( (flSpoolMode & QSM_DOWNLOADFONTS) && !gbDownloadFonts )
|
|
#else
|
|
if( flSpoolMode & QSM_DOWNLOADFONTS )
|
|
#endif
|
|
{
|
|
// query the spooler to get the list of fonts is has available
|
|
|
|
INT nBufferSize = 0;
|
|
PUNIVERSAL_FONT_ID pufi;
|
|
|
|
nBufferSize = (*fpQueryRemoteFonts)( pldc->hSpooler, NULL, 0 );
|
|
|
|
if( nBufferSize != -1 )
|
|
{
|
|
pufi = LocalAlloc( LMEM_FIXED, sizeof(UNIVERSAL_FONT_ID) * nBufferSize );
|
|
|
|
if( pufi )
|
|
{
|
|
nBufferSize = (*fpQueryRemoteFonts)( pldc->hSpooler,
|
|
pufi,
|
|
nBufferSize );
|
|
|
|
MFD2("Found %d fonts\n", nBufferSize );
|
|
|
|
if (nBufferSize > 0)
|
|
{
|
|
// next add all these fonts to UFI has table so we don't
|
|
//include them in the spool file.
|
|
|
|
while( nBufferSize-- )
|
|
{
|
|
bAddUFIEntry( pldc->ppUFIHash, &pufi[nBufferSize] );
|
|
MFD2("%x\n", pufi[nBufferSize].CheckSum );
|
|
}
|
|
}
|
|
LocalFree( pufi );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WARNING("QueryRemoteFonts failed. We will be including all fonts in \
|
|
the EMF spoolfile\n");
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
if( gbForceUFIMapping )
|
|
{
|
|
pldc->fl | LDC_FORCE_MAPPING;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
// we now need to create an EMF DC for this document
|
|
|
|
if (!AssociateEnhMetaFile(hdc))
|
|
{
|
|
WARNING("Failed to create spool metafile");
|
|
goto FREEPORT;
|
|
}
|
|
|
|
pldc->fl |= ( bBanding ) ? LDC_BANDING : 0;
|
|
|
|
// set the data for this lhe to that of the meta file
|
|
|
|
pldc->fl |= ( LDC_DOC_STARTED | LDC_META_PRINT | LDC_CALL_STARTPAGE |
|
|
LDC_FONT_CHANGE);
|
|
|
|
if (pldc->pfnAbort != NULL)
|
|
{
|
|
pldc->fl |= LDC_SAP_CALLBACK;
|
|
pldc->ulLastCallBack = GetTickCount();
|
|
}
|
|
|
|
bRet = TRUE;
|
|
|
|
FREEPORT:
|
|
|
|
if( pemfsh != NULL )
|
|
{
|
|
LOCALFREE(pemfsh);
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
* int WINAPI MFP_EndDoc(HDC hdc)
|
|
*
|
|
* Gerrit van Wingerden [gerritv]
|
|
*
|
|
* 11-7-94 10:00:00
|
|
*
|
|
*****************************************************************************/
|
|
|
|
int WINAPI MFP_EndDoc(HDC hdc)
|
|
{
|
|
int iRet = 1;
|
|
PLDC pldc;
|
|
HENHMETAFILE hmeta;
|
|
|
|
if (!IS_ALTDC_TYPE(hdc))
|
|
return(iRet);
|
|
|
|
DC_PLDC(hdc,pldc,0);
|
|
|
|
MFD1("MFP_EndDoc\n");
|
|
|
|
if ((pldc->fl & LDC_DOC_STARTED) == 0)
|
|
return(1);
|
|
|
|
if (pldc->fl & LDC_PAGE_STARTED)
|
|
{
|
|
MFP_EndPage(hdc);
|
|
}
|
|
|
|
ASSERTGDI(pldc->fl & LDC_META_PRINT,
|
|
"DetachPrintMetafile not called on metafile D.C.\n" );
|
|
|
|
// completely detach the metafile from the original printer DC
|
|
|
|
hmeta = UnassociateEnhMetaFile( hdc );
|
|
DeleteEnhMetaFile( hmeta );
|
|
|
|
// Clear the LDC_SAP_CALLBACK flag.
|
|
// Also clear the META_PRINT and DOC_STARTED flags
|
|
|
|
pldc->fl &= ~(LDC_SAP_CALLBACK | LDC_META_PRINT);
|
|
|
|
RESETUSERPOLLCOUNT();
|
|
|
|
MFD1("Caling spooler to end doc\n");
|
|
|
|
if( pldc->fl & LDC_BANDING )
|
|
{
|
|
pldc->fl &= ~LDC_BANDING;
|
|
EndDoc( hdc );
|
|
}
|
|
else
|
|
{
|
|
pldc->fl &= ~LDC_DOC_STARTED;
|
|
(*fpEndDocPrinter)(pldc->hSpooler);
|
|
}
|
|
#if PRINT_TIMER
|
|
if( bPrintTimer )
|
|
{
|
|
DWORD tc;
|
|
|
|
tc = GetTickCount();
|
|
|
|
DbgPrint("Document took %d.%d seconds to spool\n",
|
|
(tc - pldc->msStartDoc) / 1000,
|
|
(tc - pldc->msStartDoc) % 1000 );
|
|
|
|
}
|
|
#endif
|
|
|
|
return(iRet);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* int WINAPI MFP_StartPage(HDC hdc)
|
|
*
|
|
* Gerrit van Wingerden [gerritv]
|
|
*
|
|
* 11-7-94 10:00:00
|
|
*
|
|
*****************************************************************************/
|
|
|
|
int MFP_StartPage( HDC hdc )
|
|
{
|
|
PLDC pldc;
|
|
int iRet = 1;
|
|
|
|
if (!IS_ALTDC_TYPE(hdc))
|
|
return(0);
|
|
|
|
DC_PLDC(hdc,pldc,0);
|
|
|
|
MFD1("Entering MFP_StartPage\n");
|
|
|
|
pldc->fl &= ~LDC_CALL_STARTPAGE;
|
|
|
|
// Do nothing if page has already been started.
|
|
|
|
if (pldc->fl & LDC_PAGE_STARTED)
|
|
return(1);
|
|
|
|
pldc->fl |= LDC_PAGE_STARTED;
|
|
|
|
RESETUSERPOLLCOUNT();
|
|
|
|
if( pldc->fl & LDC_BANDING )
|
|
{
|
|
iRet = SP_ERROR;
|
|
|
|
//BUGBUG maybe we can delay the call here and do it right before we start
|
|
// banding.
|
|
|
|
MakeInfoDC( hdc, FALSE );
|
|
|
|
|
|
iRet = NtGdiStartPage(hdc);
|
|
|
|
MakeInfoDC( hdc, TRUE );
|
|
}
|
|
else
|
|
{
|
|
// before the start page, we need to see if the copyCount or EPS mode has
|
|
// changed since the start doc.
|
|
|
|
EMFITEMPRESTARTPAGE emfiPre;
|
|
|
|
NtGdiGetAndSetDCDword(
|
|
hdc,
|
|
GASDDW_COPYCOUNT,
|
|
(DWORD) -1,
|
|
&emfiPre.ulCopyCount);
|
|
|
|
NtGdiGetAndSetDCDword(
|
|
hdc,
|
|
GASDDW_EPSPRINTESCCALLED,
|
|
(DWORD) FALSE,
|
|
&emfiPre.bEPS);
|
|
|
|
// make sure it is true or false
|
|
|
|
emfiPre.bEPS = !!emfiPre.bEPS;
|
|
|
|
// is there anything we will need to do? If so record the record
|
|
|
|
if ((emfiPre.ulCopyCount != (ULONG) -1) || emfiPre.bEPS)
|
|
{
|
|
int i;
|
|
EMFITEMHEADER emfiHeader;
|
|
|
|
emfiHeader.ulID = EMRI_PRESTARTPAGE;
|
|
emfiHeader.cjSize = sizeof(emfiPre);
|
|
|
|
if ((!(*fpWritePrinter)( pldc->hSpooler, (LPVOID) &emfiHeader, sizeof(emfiHeader), &i)) ||
|
|
(!(*fpWritePrinter)( pldc->hSpooler, (LPVOID) &emfiPre, sizeof(emfiPre), &i)))
|
|
{
|
|
WARNING("MFP_StartPage: Write printer failed for PRESTARTPAGE\n");
|
|
return(SP_ERROR);
|
|
}
|
|
}
|
|
|
|
// Metafile the start page call. Now all the play journal code has to do is
|
|
// play back the metafile and the StartPage call will happen automatically
|
|
// at the right place in the metafile.
|
|
|
|
if( !(*fpStartPagePrinter)( pldc->hSpooler ) )
|
|
{
|
|
WARNING("MFP_StarPage: StartPagePrinter failed\n");
|
|
return(SP_ERROR);
|
|
}
|
|
}
|
|
|
|
return(iRet);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* BOOL StartBanding( HDC hdc, POINTL *pptl )
|
|
*
|
|
* Tells the printer driver to get ready for banding and asks for the origin
|
|
* of the first band.
|
|
*
|
|
*
|
|
* Gerrit van Wingerden [gerritv]
|
|
*
|
|
* 1-7-95 10:00:00
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL StartBanding( HDC hdc, POINTL *pptl, SIZE *pSize )
|
|
{
|
|
return (NtGdiDoBanding(hdc, TRUE, pptl, pSize));
|
|
}
|
|
|
|
/****************************************************************************
|
|
* BOOL NextBand( HDC hdc, POINTL *pptl )
|
|
*
|
|
* Tells the driver to realize the image accumlated in the DC and then
|
|
* asks for the origin of the next band. If the origin is (-1,-1) the
|
|
* driver is through banding.
|
|
*
|
|
*
|
|
* Gerrit van Wingerden [gerritv]
|
|
*
|
|
* 1-7-95 10:00:00
|
|
*
|
|
*****************************************************************************/
|
|
|
|
BOOL NextBand( HDC hdc, POINTL *pptl )
|
|
{
|
|
BOOL bRet=FALSE;
|
|
SIZE szScratch;
|
|
|
|
bRet = NtGdiDoBanding(hdc, FALSE, pptl, &szScratch);
|
|
|
|
// reset the page started flag if this is the next band
|
|
|
|
if( bRet && ( pptl->x == -1 ) )
|
|
{
|
|
PLDC pldc;
|
|
DC_PLDC(hdc,pldc,0);
|
|
|
|
pldc->fl &= ~LDC_PAGE_STARTED;
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* int WINAPI MFP_EndPage(HDC hdc)
|
|
*
|
|
* Closes the EMF attached to the DC and writes it to the spooler. Then
|
|
* it creates a new metafile and binds it to the DC.
|
|
*
|
|
* Gerrit van Wingerden [gerritv]
|
|
*
|
|
* 11-7-94 10:00:00
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#if DBG
|
|
BOOL gbWriteEMF = FALSE;
|
|
#endif
|
|
|
|
int WINAPI MFP_EndPage(HDC hdc)
|
|
{
|
|
PLDC pldc;
|
|
HENHMETAFILE hmeta;
|
|
BOOL bOk;
|
|
int iRet = SP_ERROR;
|
|
|
|
MFD1("Entering MFP_EndPage\n");
|
|
|
|
if (!IS_ALTDC_TYPE(hdc))
|
|
return(0);
|
|
|
|
DC_PLDC(hdc,pldc,0);
|
|
|
|
if ((pldc->fl & LDC_DOC_CANCELLED) ||
|
|
((pldc->fl & LDC_PAGE_STARTED) == 0))
|
|
{
|
|
GdiSetLastError(ERROR_INVALID_PARAMETER);
|
|
return(SP_ERROR);
|
|
}
|
|
|
|
if (pldc->fl & LDC_SAP_CALLBACK)
|
|
vSAPCallback(pldc);
|
|
|
|
pldc->fl &= ~LDC_PAGE_STARTED;
|
|
|
|
// Metafile the EndPage call.
|
|
|
|
MFD1("MFP_EndPage: Closing metafile\n");
|
|
|
|
hmeta = UnassociateEnhMetaFile(hdc);
|
|
|
|
if( hmeta == NULL )
|
|
{
|
|
WARNING("Closing the Enhanced Metafile Failed\n");
|
|
return(SP_ERROR);
|
|
}
|
|
|
|
// now write the metafile to the spooler
|
|
|
|
if( pldc->fl & LDC_BANDING )
|
|
{
|
|
// play back the metafile in bands
|
|
|
|
RECT rect;
|
|
POINTL ptlOrigin;
|
|
POINT ptlWindowOrg;
|
|
SIZE szWindowExt;
|
|
SIZE szViewportExt;
|
|
SIZE szSurface; // for open gl printing optimization
|
|
XFORM xf;
|
|
ULONG ulMapMode;
|
|
|
|
#if DBG
|
|
if (gbWriteEMF)
|
|
WriteMetafileTmp(hmeta);
|
|
#endif
|
|
|
|
// get bounding rectangle
|
|
|
|
rect.left = rect.top = 0;
|
|
rect.right = GetDeviceCaps(hdc, DESKTOPHORZRES);
|
|
rect.bottom = GetDeviceCaps(hdc, DESKTOPVERTRES);
|
|
|
|
#if DBG
|
|
DbgPrint("Playing banding metafile\n");
|
|
#endif
|
|
|
|
//BUGBUG check return values
|
|
|
|
// temporarily reset LDC_META_PRINT flag so we don't try to record
|
|
// during playback
|
|
|
|
pldc->fl &= ~LDC_META_PRINT;
|
|
|
|
bOk = StartBanding( hdc, &ptlOrigin, &szSurface );
|
|
|
|
// we need to clear the transform during this operation
|
|
|
|
GetWindowOrgEx(hdc,&ptlWindowOrg);
|
|
GetWindowExtEx(hdc,&szWindowExt);
|
|
GetViewportExtEx(hdc,&szViewportExt);
|
|
GetWorldTransform(hdc,&xf);
|
|
|
|
ulMapMode = SetMapMode(hdc,MM_TEXT);
|
|
SetWindowOrgEx(hdc,0,0,NULL);
|
|
ModifyWorldTransform(hdc,NULL,MWT_IDENTITY);
|
|
|
|
if( bOk )
|
|
{
|
|
do
|
|
{
|
|
SetViewportOrgEx( hdc, -ptlOrigin.x, -ptlOrigin.y, NULL );
|
|
PlayEnhMetaFile( hdc, hmeta, &rect );
|
|
bOk = NextBand( hdc, &ptlOrigin );
|
|
|
|
} while( ptlOrigin.x != -1 && bOk );
|
|
}
|
|
|
|
SetMapMode(hdc,ulMapMode);
|
|
|
|
SetWorldTransform(hdc,&xf);
|
|
SetWindowOrgEx(hdc,ptlWindowOrg.x,ptlWindowOrg.y,NULL);
|
|
SetWindowExtEx(hdc,szWindowExt.cx,szWindowExt.cy,NULL);
|
|
SetViewportExtEx(hdc,szViewportExt.cx,szViewportExt.cy,NULL);
|
|
|
|
// reset the flag for the next page
|
|
|
|
pldc->fl |= LDC_META_PRINT;
|
|
|
|
if( !bOk )
|
|
{
|
|
WARNING("MFP_EndPage: Error doing banding\n");
|
|
}
|
|
else
|
|
{
|
|
// if we got here we suceeded
|
|
iRet = 1;
|
|
}
|
|
|
|
#if DBG
|
|
DbgPrint("Done playing banding metafile\n");
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// if ResetDC was called record the devmode in the metafile stream
|
|
|
|
bOk = TRUE;
|
|
|
|
if( pldc->fl & LDC_RESETDC_CALLED )
|
|
{
|
|
EMFITEMHEADER emfi;
|
|
DWORD dummy;
|
|
|
|
emfi.ulID = EMRI_DEVMODE;
|
|
emfi.cjSize = ( pldc->pDevMode ) ?
|
|
pldc->pDevMode->dmSize + pldc->pDevMode->dmDriverExtra : 0 ;
|
|
|
|
if( !(*fpWritePrinter)( pldc->hSpooler,
|
|
(PBYTE) &emfi, sizeof(emfi), &dummy ) ||
|
|
!(*fpWritePrinter)( pldc->hSpooler, (PBYTE) pldc->pDevMode,
|
|
emfi.cjSize, &dummy ))
|
|
{
|
|
WARNING("Writing DEVMODE to spooler failed.\n");
|
|
bOk = FALSE;
|
|
}
|
|
|
|
if( pldc->pDevMode )
|
|
{
|
|
LOCALFREE(pldc->pDevMode);
|
|
pldc->pDevMode = NULL;
|
|
}
|
|
|
|
pldc->fl &= ~(LDC_RESETDC_CALLED);
|
|
}
|
|
|
|
// now write the metafile to the spooler
|
|
|
|
if( !bOk || !WriteEnhMetaFileToSpooler( hmeta, pldc->hSpooler ) )
|
|
{
|
|
WARNING("Writing the metafile to the spooler failed\n");
|
|
}
|
|
else
|
|
{
|
|
// if we got here we succeeded
|
|
|
|
iRet = 1;
|
|
}
|
|
|
|
}
|
|
|
|
// At this point if we suceede iRet should be 1 otherwise it should be SP_ERROR
|
|
// even if we encountered an error we still want to try to associate a new
|
|
// metafile with this DC. That whether the app calls EndPage, AbortDoc, or
|
|
// EndDoc next, things will happend more smoothly.
|
|
|
|
DeleteEnhMetaFile(hmeta);
|
|
|
|
// next create a new metafile for the next page
|
|
|
|
if (!AssociateEnhMetaFile(hdc))
|
|
{
|
|
WARNING("StartPage: error creating metafile\n");
|
|
iRet = SP_ERROR;
|
|
}
|
|
|
|
// reset user's poll count so it counts this as output
|
|
|
|
RESETUSERPOLLCOUNT();
|
|
|
|
if( !(pldc->fl & LDC_BANDING ) )
|
|
{
|
|
if( !(*fpEndPagePrinter)( pldc->hSpooler ) )
|
|
{
|
|
WARNING("MFP_StarPage: EndPagePrinter failed\n");
|
|
iRet = SP_ERROR;
|
|
}
|
|
}
|
|
|
|
pldc->fl |= LDC_CALL_STARTPAGE;
|
|
|
|
#if PRINT_TIMER
|
|
if( bPrintTimer )
|
|
{
|
|
DWORD tc;
|
|
tc = GetTickCount();
|
|
DbgPrint("Page took %d.%d seconds to print\n",
|
|
(tc - pldc->msStartPage) / 1000,
|
|
(tc - pldc->msStartPage) % 1000 );
|
|
|
|
}
|
|
#endif
|
|
|
|
return(iRet);
|
|
}
|
|
|
|
|
|
|
|
BOOL MFP_ResetDCW( HDC hdc, DEVMODEW *pdmw )
|
|
{
|
|
PLDC pldc;
|
|
HENHMETAFILE hmeta;
|
|
ULONG cjDevMode;
|
|
|
|
DC_PLDC(hdc,pldc,0);
|
|
|
|
MFD1("MFP_ResetDCW Called\n");
|
|
|
|
pldc->fl |= LDC_RESETDC_CALLED;
|
|
|
|
// finally associate a new metafile since call to ResetDC could have changed
|
|
// the dimensions of the DC
|
|
|
|
hmeta = UnassociateEnhMetaFile( hdc );
|
|
DeleteEnhMetaFile( hmeta );
|
|
|
|
if( !AssociateEnhMetaFile( hdc ) )
|
|
{
|
|
WARNING("MFP_ResetDCW is unable to associate a new metafile\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
BOOL MFP_ResetBanding( HDC hdc, BOOL bBanding )
|
|
{
|
|
PLDC pldc;
|
|
HENHMETAFILE hmeta;
|
|
DC_PLDC(hdc,pldc,0);
|
|
|
|
if( pldc->fl & LDC_BANDING )
|
|
{
|
|
// we were banding before so we must remove the old metafile from the DC
|
|
// since we might not be banding any more or the surface dimenstions could
|
|
// have changed requiring us to have a new metafile
|
|
|
|
hmeta = UnassociateEnhMetaFile( hdc );
|
|
DeleteEnhMetaFile( hmeta );
|
|
|
|
pldc->fl &= ~(LDC_BANDING|LDC_META_PRINT);
|
|
|
|
MFD1("Remove old banding metafile\n");
|
|
|
|
}
|
|
|
|
if( bBanding )
|
|
{
|
|
// if we are banding after the ResetDC then we must attach a new metafile
|
|
|
|
if( !AssociateEnhMetaFile(hdc) )
|
|
{
|
|
WARNING("MFP_ResetBanding: Failed to attach banding metafile spool metafile");
|
|
return(FALSE);
|
|
}
|
|
|
|
pldc->fl |= LDC_BANDING|LDC_META_PRINT;
|
|
|
|
MFD1("Adding new banding metafile\n");
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|