📄 emf.c
字号:
/*++
Copyright (c) 1990-1998 Microsoft Corporation
All rights reserved
Abstract:
Routines to facilitate printing of EMF jobs.
--*/
#include "local.h"
#include "stddef.h"
#include <windef.h>
#include <messages.h>
#include <winppi.h>
#define EMF_DUP_NONE 0
#define EMF_DUP_VERT 1
#define EMF_DUP_HORZ 2
#define EMF_DEGREE_90 1
#define EMF_DEGREE_270 2
// PAGE_NUMBER is used to save a list of the page numbers to start new sides while
// Reverse Printing.
typedef struct _PAGE_NUMBER {
struct _PAGE_NUMBER *pNext;
DWORD dwPageNumber;
} PAGE_NUMBER, *PPAGE_NUMBER;
typedef struct _UpdateRect {
double top;
double bottom;
double left;
double right;
} UpdateRect;
// The update factors for the different nup options. These factors when multiplied
// with the horizontal and vertical resolutions give the coordinates for the rectangle
// where the EMF page is to be played.
UpdateRect URect21[] = {{0, 0.5, 0, 1},
{0.5, 1, 0, 1}};
UpdateRect URect21R[] = {{0.5, 1, 0, 1},
{0, 0.5, 0, 1}};
UpdateRect URect22[] = {{0, 1, 0, 0.5},
{0, 1, 0.5, 1}};
UpdateRect URect4[] = {{0, 0.5, 0, 0.5},
{0, 0.5, 0.5, 1},
{0.5, 1, 0, 0.5},
{0.5, 1, 0.5, 1}};
UpdateRect URect61[] = {{0, 1.0/3.0, 0, 0.5},
{0, 1.0/3.0, 0.5, 1},
{1.0/3.0, 2.0/3.0, 0, 0.5},
{1.0/3.0, 2.0/3.0, 0.5, 1},
{2.0/3.0, 1, 0, 0.5},
{2.0/3.0, 1, 0.5, 1}};
UpdateRect URect61R[] = {{2.0/3.0, 1, 0, 0.5},
{1.0/3.0, 2.0/3.0, 0, 0.5},
{0, 1.0/3.0, 0, 0.5},
{2.0/3.0, 1, 0.5, 1},
{1.0/3.0, 2.0/3.0, 0.5, 1},
{0, 1.0/3.0, 0.5, 1}};
UpdateRect URect62[] = {{0, 0.5, 0, 1.0/3.0},
{0, 0.5, 1.0/3.0, 2.0/3.0},
{0, 0.5, 2.0/3.0, 1},
{0.5, 1, 0, 1.0/3.0},
{0.5, 1, 1.0/3.0, 2.0/3.0},
{0.5, 1, 2.0/3.0, 1}};
UpdateRect URect62R[] = {{0.5, 1, 0, 1.0/3.0},
{0, 0.5, 0, 1.0/3.0},
{0.5, 1, 1.0/3.0, 2.0/3.0},
{0, 0.5, 1.0/3.0, 2.0/3.0},
{0.5, 1, 2.0/3.0, 1},
{0, 0.5, 2.0/3.0, 1}};
UpdateRect URect9[] = {{0, 1.0/3.0, 0, 1.0/3.0},
{0, 1.0/3.0, 1.0/3.0, 2.0/3.0},
{0, 1.0/3.0, 2.0/3.0, 1},
{1.0/3.0, 2.0/3.0, 0, 1.0/3.0},
{1.0/3.0, 2.0/3.0, 1.0/3.0, 2.0/3.0},
{1.0/3.0, 2.0/3.0, 2.0/3.0, 1},
{2.0/3.0, 1, 0, 1.0/3.0},
{2.0/3.0, 1, 1.0/3.0, 2.0/3.0},
{2.0/3.0, 1, 2.0/3.0, 1}};
UpdateRect URect16[] = {{0, 0.25, 0, 0.25},
{0, 0.25, 0.25, 0.5},
{0, 0.25, 0.5, 0.75},
{0, 0.25, 0.75, 1},
{0.25, 0.5, 0, 0.25},
{0.25, 0.5, 0.25, 0.5},
{0.25, 0.5, 0.5, 0.75},
{0.25, 0.5, 0.75, 1},
{0.5, 0.75, 0, 0.25},
{0.5, 0.75, 0.25, 0.5},
{0.5, 0.75, 0.5, 0.75},
{0.5, 0.75, 0.75, 1},
{0.75, 1, 0, 0.25},
{0.75, 1, 0.25, 0.5},
{0.75, 1, 0.5, 0.75},
{0.75, 1, 0.75, 1}};
BOOL
ValidNumberForNUp(
DWORD dwPages)
/*++
Function Description: Checks if the number of pages printed on a single side is Valid.
Parameters: dwPages - Number of pages printed on a single side
Return Values: TRUE if (dwPages = 1|2|4|6|9|16)
FALSE otherwise.
--*/
{
return ((dwPages == 1) || (dwPages == 2) || (dwPages == 4) ||
(dwPages == 6) || (dwPages == 9) || (dwPages == 16));
}
VOID
GetPageCoordinatesForNUp(
HDC hPrinterDC,
RECT *rectDocument,
RECT *rectBorder,
DWORD dwTotalNumberOfPages,
UINT uCurrentPageNumber,
DWORD dwNupBorderFlags,
LPBOOL pbRotate
)
/*++
Function Description: GetPageCoordinatesForNUp computes the rectangle on the Page where the
EMF file is to be played. It also determines if the picture is to
rotated.
Parameters: hPrinterDC - Printer Device Context
*rectDocument - pointer to RECT where the coordinates to play the
page will be returned.
*rectBorder - pointer to RECT where the page borders are to drawn.
dwTotalNumberOfPages - Total number of pages on 1 side.
uCurrentPageNumber - 1 based page number on the side.
dwNupBorderFlags - flags to draw border along logical pages.
pbRotate - pointer to BOOL which indicates if the picture must be
rotated.
Return Values: NONE.
--*/
{
UpdateRect *URect;
LONG lXPrintPage,lYPrintPage,lXPhyPage,lYPhyPage,lXFrame,lYFrame,ltemp,ldX,ldY;
LONG lXNewPhyPage,lYNewPhyPage,lXOffset,lYOffset,lNumRowCol,lRowIndex,lColIndex;
double dXleft,dXright,dYtop,dYbottom;
LONG xResolution = GetDeviceCaps(hPrinterDC, LOGPIXELSX);
LONG yResolution = GetDeviceCaps(hPrinterDC, LOGPIXELSY);
// Get the 0-based array index for the current page
uCurrentPageNumber = uCurrentPageNumber - 1;
if (dwTotalNumberOfPages==1 || xResolution==yResolution)
{
xResolution = yResolution = 1;
}
rectDocument->top = rectDocument->bottom = lYPrintPage = (GetDeviceCaps(hPrinterDC, DESKTOPVERTRES)-1) * xResolution;
rectDocument->left = rectDocument->right = lXPrintPage = (GetDeviceCaps(hPrinterDC, DESKTOPHORZRES)-1) * yResolution;
lXPhyPage = GetDeviceCaps(hPrinterDC, PHYSICALWIDTH) * yResolution;
lYPhyPage = GetDeviceCaps(hPrinterDC, PHYSICALHEIGHT) * xResolution;
*pbRotate = FALSE;
// Select the array containing the update factors
switch (dwTotalNumberOfPages) {
case 1: rectDocument->top = rectDocument->left = 0;
rectDocument->right += 1;
rectDocument->bottom += 1;
return;
case 2: if (lXPrintPage > lYPrintPage) { // cut vertically
URect = URect22;
lXFrame = (LONG) (lXPrintPage / 2.0);
lYFrame = lYPrintPage;
} else { // cut horizontally
URect = URect21;
lYFrame = (LONG) (lYPrintPage / 2.0);
lXFrame = lXPrintPage;
}
break;
case 4: URect = URect4;
lXFrame = (LONG) (lXPrintPage / 2.0);
lYFrame = (LONG) (lYPrintPage / 2.0);
break;
case 6: if (lXPrintPage > lYPrintPage) { // cut vertically twice
URect = URect62;
lXFrame = (LONG) (lXPrintPage / 3.0);
lYFrame = (LONG) (lYPrintPage / 2.0);
} else { // cut horizontally twice
URect = URect61;
lYFrame = (LONG) (lYPrintPage / 3.0);
lXFrame = (LONG) (lXPrintPage / 2.0);
}
break;
case 9: URect = URect9;
lXFrame = (LONG) (lXPrintPage / 3.0);
lYFrame = (LONG) (lYPrintPage / 3.0);
break;
case 16: URect = URect16;
lXFrame = (LONG) (lXPrintPage / 4.0);
lYFrame = (LONG) (lYPrintPage / 4.0);
break;
default: // Should Not Occur.
return;
}
// Set the flag if the picture has to be rotated
*pbRotate = !((lXPhyPage >= lYPhyPage) && (lXFrame >= lYFrame)) &&
!((lXPhyPage < lYPhyPage) && (lXFrame < lYFrame));
// If the picture is to be rotated, modify the rectangle selected.
if ((dwTotalNumberOfPages == 2) || (dwTotalNumberOfPages == 6)) {
if (*pbRotate) {
switch (dwTotalNumberOfPages) {
case 2: if (lXPrintPage <= lYPrintPage) {
URect = URect21R;
} // URect22 = URect22R
break;
case 6: if (lXPrintPage <= lYPrintPage) {
URect = URect61R;
} else {
URect = URect62R;
}
break;
}
}
} else {
if (*pbRotate) {
// get the number of rows/columns. switch is faster than sqrt.
switch (dwTotalNumberOfPages) {
case 4: lNumRowCol = 2;
break;
case 9: lNumRowCol = 3;
break;
case 16: lNumRowCol = 4;
break;
}
lRowIndex = (LONG) (uCurrentPageNumber / lNumRowCol);
lColIndex = (LONG) (uCurrentPageNumber % lNumRowCol);
uCurrentPageNumber = (lNumRowCol - 1 - lColIndex) * lNumRowCol + lRowIndex;
}
}
// Update the Page Coordinates.
rectDocument->top = (LONG) (rectDocument->top * URect[uCurrentPageNumber].top);
rectDocument->bottom = (LONG) (rectDocument->bottom * URect[uCurrentPageNumber].bottom);
rectDocument->left = (LONG) (rectDocument->left * URect[uCurrentPageNumber].left);
rectDocument->right = (LONG) (rectDocument->right * URect[uCurrentPageNumber].right);
// If the page border has to drawn, return the corresponding coordinates in rectBorder.
if (dwNupBorderFlags == BORDER_PRINT) {
rectBorder->top = rectDocument->top/xResolution;
rectBorder->bottom = rectDocument->bottom/xResolution - 1;
rectBorder->left = rectDocument->left/yResolution;
rectBorder->right = rectDocument->right/yResolution - 1;
}
if (*pbRotate) {
ltemp = lXFrame; lXFrame = lYFrame; lYFrame = ltemp;
}
// Get the new size of the rectangle to keep the X/Y ratio constant.
if ( ((LONG) (lYFrame*((lXPhyPage*1.0)/lYPhyPage))) >= lXFrame) {
ldX = 0;
ldY = lYFrame - ((LONG) (lXFrame*((lYPhyPage*1.0)/lXPhyPage)));
} else {
ldY = 0;
ldX = lXFrame - ((LONG) (lYFrame*((lXPhyPage*1.0)/lYPhyPage)));
}
// Adjust the position of the rectangle.
if (*pbRotate) {
if (ldX) {
rectDocument->bottom -= (LONG) (ldX / 2.0);
rectDocument->top += (LONG) (ldX / 2.0);
} else {
rectDocument->right -= (LONG) (ldY / 2.0);
rectDocument->left += (LONG) (ldY / 2.0);
}
} else {
if (ldX) {
rectDocument->left += (LONG) (ldX / 2.0);
rectDocument->right -= (LONG) (ldX / 2.0);
} 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -