📄 emf.cpp
字号:
} else {
rectDocument->top += (LONG) (ldY / 2.0);
rectDocument->bottom -= (LONG) (ldY / 2.0);
}
}
// Adjust to get the Printable Area on the rectangle
lXOffset = GetDeviceCaps(hPrinterDC, PHYSICALOFFSETX) * yResolution;
lYOffset = GetDeviceCaps(hPrinterDC, PHYSICALOFFSETY) * xResolution;
dXleft = ( lXOffset * 1.0) / lXPhyPage;
dYtop = ( lYOffset * 1.0) / lYPhyPage;
dXright = ((lXPhyPage - (lXOffset + lXPrintPage)) * 1.0) / lXPhyPage;
dYbottom = ((lYPhyPage - (lYOffset + lYPrintPage)) * 1.0) / lYPhyPage;
lXNewPhyPage = rectDocument->right - rectDocument->left;
lYNewPhyPage = rectDocument->bottom - rectDocument->top;
if (*pbRotate) {
ltemp = lXNewPhyPage; lXNewPhyPage = lYNewPhyPage; lYNewPhyPage = ltemp;
rectDocument->left += (LONG) (dYtop * lYNewPhyPage);
rectDocument->right -= (LONG) (dYbottom * lYNewPhyPage);
rectDocument->top += (LONG) (dXright * lXNewPhyPage);
rectDocument->bottom -= (LONG) (dXleft * lXNewPhyPage);
} else {
rectDocument->left += (LONG) (dXleft * lXNewPhyPage);
rectDocument->right -= (LONG) (dXright * lXNewPhyPage);
rectDocument->top += (LONG) (dYtop * lYNewPhyPage);
rectDocument->bottom -= (LONG) (dYbottom * lYNewPhyPage);
}
if (xResolution!=yResolution)
{
rectDocument->left = rectDocument->left / yResolution;
rectDocument->right = rectDocument->right / yResolution;
rectDocument->top = rectDocument->top / xResolution;
rectDocument->bottom = rectDocument->bottom / xResolution;
}
return TRUE;
}
BOOL
WINAPI
PlayEMFPage(
HANDLE hSpoolHandle,
HDC hPrinterDC,
HANDLE hEMF,
DWORD dwNumberOfPagesPerSide,
DWORD dwPageNumber,
DWORD dwPageIndex,
DWORD dwNupBorderFlags,
DWORD dwAngle)
/*++
Function Description: PlayEMFPage plays the EMF in the appropriate rectangle. It performs
the required scaling, rotation and translation.
Parameters: hSpoolHandle -- handle the spool file handle
hPrinterDC -- handle to the printer device context
hEMF -- handle to the contents of the page in the spool file
dwNumberOfPagesPerSide -- number of pages to be printed per side
dwPageNumber -- page number in the document
dwPageIndex -- page number in the side. (1 based)
dwNupBorderFlags -- border printing options for nup
dwAngle -- angle for rotation (if neccesary)
Return Values: TRUE if successful
FALSE otherwise
--*/
{
BOOL bReturn = FALSE, bRotate;
RECT rectDocument, rectPrinter, rectBorder = {-1, -1, -1, -1};
RECT *prectClip = NULL;
XFORM TransXForm = {1, 0, 0, 1, 0, 0}, RotateXForm = {0, -1, 1, 0, 0, 0};
// Compute the rectangle for one page.
if ( FALSE == GetPageCoordinatesForNUp(hPrinterDC,
&rectDocument,
&rectBorder,
dwNumberOfPagesPerSide,
dwPageIndex,
dwNupBorderFlags,
&bRotate) )
{
goto CleanUp;
}
// If swap flag is set, reverse rotate flag
//
if (dwAngle & EMF_DEGREE_SWAP)
bRotate = !bRotate;
if (dwAngle & EMF_DEGREE_270) {
RotateXForm.eM12 = 1;
RotateXForm.eM21 = -1;
} // EMF_DEGREE_90 case is the initialization
if (bRotate) {
rectPrinter.top = 0;
rectPrinter.bottom = rectDocument.right - rectDocument.left;
rectPrinter.left = 0;
rectPrinter.right = rectDocument.bottom - rectDocument.top;
// Set the translation matrix
if (dwAngle & EMF_DEGREE_270) {
TransXForm.eDx = (float) rectDocument.right;
TransXForm.eDy = (float) rectDocument.top;
} else {
// EMF_DEGREE_90
TransXForm.eDx = (float) rectDocument.left;
TransXForm.eDy = (float) rectDocument.bottom;
}
// Set the transformation matrix
if (!SetWorldTransform(hPrinterDC, &RotateXForm) ||
!ModifyWorldTransform(hPrinterDC, &TransXForm, MWT_RIGHTMULTIPLY)) {
ODS(("Setting transformation matrix failed\n"));
goto CleanUp;
}
}
// Add clipping for Nup
if (dwNumberOfPagesPerSide != 1) {
prectClip = &rectDocument;
}
// Print the page.
if (bRotate) {
GdiPlayPageEMF(hSpoolHandle, hEMF, &rectPrinter, &rectBorder, prectClip);
} else {
GdiPlayPageEMF(hSpoolHandle, hEMF, &rectDocument, &rectBorder, prectClip);
}
bReturn = TRUE;
CleanUp:
if (!ModifyWorldTransform(hPrinterDC, NULL, MWT_IDENTITY)) {
ODS(("Setting Identity Transformation failed\n"));
bReturn = FALSE;
}
return bReturn;
}
BOOL
SetDrvCopies(
HDC hPrinterDC,
LPDEVMODEW pDevmode,
DWORD dwNumberOfCopies)
/*++
Function Description: SetDrvCopies sets the dmCopies field in pDevmode and resets
hPrinterDC with this devmode
Parameters: hPrinterDC -- handle to the printer device context
pDevmode -- pointer to devmode
dwNumberOfCopies -- value for dmCopies
Return Values: TRUE if successful
FALSE otherwise
--*/
{
BOOL bReturn;
DWORD dmFields;
if ((pDevmode->dmFields & DM_COPIES) &&
(pDevmode->dmCopies == (short) dwNumberOfCopies)) {
return TRUE;
}
// Save the old fields structure
dmFields = pDevmode->dmFields;
pDevmode->dmFields |= DM_COPIES;
pDevmode->dmCopies = (short) dwNumberOfCopies;
if (!ResetDC(hPrinterDC, pDevmode)) {
bReturn = FALSE;
} else {
bReturn = TRUE;
}
// Restore the fields structure
pDevmode->dmFields = dmFields;
if (!SetGraphicsMode(hPrinterDC,GM_ADVANCED)) {
ODS(("Setting graphics mode failed\n"));
bReturn = FALSE;
}
return bReturn;
}
BOOL
DifferentDevmodes(
LPDEVMODE pDevmode1,
LPDEVMODE pDevmode2
)
/*++
Function Description: Compares the devmodes for differences other than dmTTOption
Parameters: pDevmode1 - devmode 1
pDevmode2 - devmode 2
Return Values: TRUE if different ; FALSE otherwise
--*/
{
DWORD dwSize1, dwSize2, dwTTOffset, dwSpecOffset, dwLogOffset;
// Same pointers are the same devmode
if (pDevmode1 == pDevmode2) {
return FALSE;
}
// Check for Null devmodes
if (!pDevmode1 || !pDevmode2) {
return TRUE;
}
dwSize1 = pDevmode1->dmSize + pDevmode1->dmDriverExtra;
dwSize2 = pDevmode2->dmSize + pDevmode2->dmDriverExtra;
// Compare devmode sizes
if (dwSize1 != dwSize2) {
return TRUE;
}
dwTTOffset = FIELD_OFFSET(DEVMODE, dmTTOption);
dwSpecOffset = FIELD_OFFSET(DEVMODE, dmSpecVersion);
dwLogOffset = FIELD_OFFSET(DEVMODE, dmLogPixels);
if (wcscmp(pDevmode1->dmDeviceName,
pDevmode2->dmDeviceName)) {
// device names are different
return TRUE;
}
if (dwTTOffset < dwSpecOffset ||
dwSize1 < dwLogOffset) {
// incorrent devmode offsets
return TRUE;
}
if (memcmp((LPBYTE) pDevmode1 + dwSpecOffset,
(LPBYTE) pDevmode2 + dwSpecOffset,
dwTTOffset - dwSpecOffset)) {
// Front half is different
return TRUE;
}
// Ignore the dmTTOption setting.
if ((pDevmode1->dmCollate != pDevmode2->dmCollate) ||
wcscmp(pDevmode1->dmFormName, pDevmode2->dmFormName)) {
// form name or collate option is different
return TRUE;
}
if (memcmp((LPBYTE) pDevmode1 + dwLogOffset,
(LPBYTE) pDevmode2 + dwLogOffset,
dwSize1 - dwLogOffset)) {
// Back half is different
return TRUE;
}
return FALSE;
}
BOOL
ResetDCForNewDevmode(
HANDLE hSpoolHandle,
HDC hPrinterDC,
DWORD dwPageNumber,
BOOL bInsidePage,
DWORD dwOptimization,
LPBOOL pbNewDevmode,
LPDEVMODE pDevmode,
LPDEVMODE *pCurrentDevmode
)
/*++
Function Description: Determines if the devmode for the page is different from the
current devmode for the printer dc and resets the dc if necessary.
The parameters allow dmTTOption to be ignored in devmode comparison.
Parameters: hSpoolHandle - spool file handle
hPrinterDC - printer dc
dwPageNumber - page number before which we search for the devmode
bInsidePage - flag to ignore changes in TT options and call EndPage
before ResetDC
dwOptimization - optimization flags
pbNewDevmode - pointer to flag to indicate if ResetDC was called
pDevmode - devmode containing changed resolution settings
Return Values: TRUE if successful; FALSE otherwise
--*/
{
BOOL bReturn = FALSE;
LPDEVMODE pLastDM, pCurrDM;
// Initialize OUT parameters
*pbNewDevmode = FALSE;
// Get the devmode just before the page
if (!GdiGetDevmodeForPagePvt(hSpoolHandle,
dwPageNumber,
&pCurrDM,
&pLastDM)) {
ODS(("GdiGetDevmodeForPagePvt failed\n"));
return bReturn;
}
// Save pointer to current devmode
if (pCurrentDevmode)
*pCurrentDevmode = pCurrDM;
// Check if the devmodes are different
if (pLastDM != pCurrDM) {
// If the pointers are different the devmodes are always different
if (!bInsidePage ||
DifferentDevmodes(pLastDM, pCurrDM)) {
*pbNewDevmode = TRUE;
}
}
// Call ResetDC on the hPrinterDC if necessary
if (*pbNewDevmode) {
if (bInsidePage &&
!GdiEndPageEMF(hSpoolHandle, dwOptimization)) {
ODS(("EndPage failed\n"));
return bReturn;
}
if (pCurrDM) {
pCurrDM->dmPrintQuality = pDevmode->dmPrintQuality;
pCurrDM->dmYResolution = pDevmode->dmYResolution;
pCurrDM->dmCopies = pDevmode->dmCopies;
if ( IS_DMSIZE_VALID ( pCurrDM, dmCollate ) )
{
if ( IS_DMSIZE_VALID ( pDevmode, dmCollate ) )
{
pCurrDM->dmCollate = pDevmode->dmCollate;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -