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.
 
 
 
 
 
 

642 lines
18 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
custsize.c
Abstract:
Parser functions for handling custom page size feature
Environment:
Windows NT PostScript driver
Revision History:
03/20/97 -davidx-
Created it.
--*/
#include "lib.h"
#include "ppd.h"
BOOL
BFixupCustomSizeDataFeedDirection(
PUIINFO pUIInfo,
PPPDDATA pPpdData,
PCUSTOMSIZEDATA pCSData
)
/*++
Routine Description:
Validate the requested paper feed direction parameter
Fix up any inconsistency if necessary
Arguments:
pPpdData - Points to PPDDATA structure
pCSData - Specifies custom page size parameters
Return Value:
TRUE if we can find a feeding direction to fit the custom page size.
FALSE otherwise.
Note:
See Figure 3 on page 109 of PPD 4.3 spec for more details.
--*/
#define ORIENTATION_AVAILABLE(iOrient) (dwFlags & (1 << (iOrient)))
#define FIXUP_FEEDDIRECTION(iMainOrient, iAltOrient, wAltFeedDirection) \
{ \
if (! ORIENTATION_AVAILABLE(iMainOrient)) \
{ \
pCSData->wFeedDirection = \
ORIENTATION_AVAILABLE(iAltOrient) ? \
(wAltFeedDirection) : \
MAX_FEEDDIRECTION; \
} \
}
{
static const DWORD adwMasks[4] = { 0x1, 0x3, 0x7, 0xf };
DWORD dwFlags;
BOOL bXGreaterThanY;
BOOL bShortEdgeFirst;
LONG lVal;
WORD wFeedDirectionSave;
//
// Figure out which custom page size orientations are supported
// dwFlags is DWORD value whose lower-order 4 bits are interpreted as flags:
// If orientation N is supported, then bit 1 << N will be set
//
dwFlags = 0xf;
if ((lVal = MINCUSTOMPARAM_ORIENTATION(pPpdData)) > 3)
dwFlags = 0;
else if (lVal > 0)
dwFlags &= ~adwMasks[lVal - 1];
if ((lVal = MAXCUSTOMPARAM_ORIENTATION(pPpdData)) < 3)
dwFlags &= adwMasks[lVal];
wFeedDirectionSave = pCSData->wFeedDirection;
bXGreaterThanY = (pCSData->dwX > pCSData->dwY);
//
// First try to fit within the current feeding direction.
//
switch (pCSData->wFeedDirection)
{
case SHORTEDGEFIRST:
if (bXGreaterThanY)
{
// orientation 0 (or 2)
FIXUP_FEEDDIRECTION(0, 2, SHORTEDGEFIRST_FLIPPED);
}
else
{
// orientation 1 (or 3)
FIXUP_FEEDDIRECTION(1, 3, SHORTEDGEFIRST_FLIPPED);
}
break;
case SHORTEDGEFIRST_FLIPPED:
if (bXGreaterThanY)
{
// orientation 2 (or 0)
FIXUP_FEEDDIRECTION(2, 0, SHORTEDGEFIRST);
}
else
{
// orientation 3 (or 1)
FIXUP_FEEDDIRECTION(3, 1, SHORTEDGEFIRST);
}
break;
case LONGEDGEFIRST:
if (bXGreaterThanY)
{
// orientation 1 (or 3)
FIXUP_FEEDDIRECTION(1, 3, LONGEDGEFIRST_FLIPPED);
}
else
{
// orientation 0 (or 2)
FIXUP_FEEDDIRECTION(0, 2, LONGEDGEFIRST_FLIPPED);
}
break;
case LONGEDGEFIRST_FLIPPED:
if (bXGreaterThanY)
{
// orientation 3 (or 1)
FIXUP_FEEDDIRECTION(3, 1, LONGEDGEFIRST);
}
else
{
// orientation 2 (or 0)
FIXUP_FEEDDIRECTION(2, 0, LONGEDGEFIRST);
}
break;
}
//
// If the paper feed direction is not valid, we'll automatically
// pick one here (default to long-edge-first if possible). This
// should always change Long to Short, or Short to Long.
//
if (pCSData->wFeedDirection >= MAX_FEEDDIRECTION)
{
if (bXGreaterThanY)
{
if (ORIENTATION_AVAILABLE(1))
pCSData->wFeedDirection = LONGEDGEFIRST;
else if (ORIENTATION_AVAILABLE(3))
pCSData->wFeedDirection = LONGEDGEFIRST_FLIPPED;
else if (ORIENTATION_AVAILABLE(0))
pCSData->wFeedDirection = SHORTEDGEFIRST;
else // (ORIENTATION_AVAILABLE(2))
pCSData->wFeedDirection = SHORTEDGEFIRST_FLIPPED;
}
else
{
if (ORIENTATION_AVAILABLE(0))
pCSData->wFeedDirection = LONGEDGEFIRST;
else if (ORIENTATION_AVAILABLE(2))
pCSData->wFeedDirection = LONGEDGEFIRST_FLIPPED;
else if (ORIENTATION_AVAILABLE(1))
pCSData->wFeedDirection = SHORTEDGEFIRST;
else // (ORIENTATION_AVAILABLE(3))
pCSData->wFeedDirection = SHORTEDGEFIRST_FLIPPED;
}
}
bShortEdgeFirst =
(pCSData->wFeedDirection == SHORTEDGEFIRST ||
pCSData->wFeedDirection == SHORTEDGEFIRST_FLIPPED);
if ( (!bShortEdgeFirst && !LONGEDGEFIRST_SUPPORTED(pUIInfo, pPpdData)) ||
(bShortEdgeFirst && !SHORTEDGEFIRST_SUPPORTED(pUIInfo, pPpdData)))
{
//
// The other feeding direction we picked doesn't fit either, so we
// have to stick with the original feeding direction.
//
pCSData->wFeedDirection = wFeedDirectionSave;
//
// Check the availability of orientations and flip the feed direction if necessary
//
if ((pCSData->wFeedDirection == LONGEDGEFIRST || pCSData->wFeedDirection == SHORTEDGEFIRST) &&
!(ORIENTATION_AVAILABLE(0) || ORIENTATION_AVAILABLE(1)))
{
pCSData->wFeedDirection = (pCSData->wFeedDirection == LONGEDGEFIRST) ?
LONGEDGEFIRST_FLIPPED : SHORTEDGEFIRST_FLIPPED;
}
else if ((pCSData->wFeedDirection == LONGEDGEFIRST_FLIPPED || pCSData->wFeedDirection == SHORTEDGEFIRST_FLIPPED) &&
!(ORIENTATION_AVAILABLE(2) || ORIENTATION_AVAILABLE(3)))
{
pCSData->wFeedDirection = (pCSData->wFeedDirection == LONGEDGEFIRST_FLIPPED) ?
LONGEDGEFIRST : SHORTEDGEFIRST;
}
return FALSE;
}
else
return TRUE;
}
BOOL
BValidateCustomPageSizeData(
IN PRAWBINARYDATA pRawData,
IN OUT PCUSTOMSIZEDATA pCSData
)
/*++
Routine Description:
Validate the specified custom page size parameters, and
Fix up any inconsistencies found.
Arguments:
pRawData - Points to raw binary printer description data
pCSData - Specifies the custom page size parameters to be validate
Return Value:
TRUE if the custom page size parameters are valid, FALSE otherwise.
If FALSE is returned, custom page size parameters have been
fixed up to a consistent state.
--*/
{
PUIINFO pUIInfo;
PPPDDATA pPpdData;
PPAGESIZE pPageSize;
CUSTOMSIZEDATA csdata;
PDWORD pdwWidth, pdwHeight;
DWORD dwTemp;
BOOL bShortEdgeFirst, bXGreaterThanY;
BOOL bFit;
pUIInfo = GET_UIINFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
ASSERT(pUIInfo != NULL && pPpdData != NULL);
if ((pPageSize = PGetCustomPageSizeOption(pUIInfo)) == NULL)
{
RIP(("Custom page size not supported\n"));
return TRUE;
}
csdata = *pCSData;
//
// Width and height offset parameters are straightforward to verify
//
if ((LONG) csdata.dwWidthOffset < MINCUSTOMPARAM_WIDTHOFFSET(pPpdData))
csdata.dwWidthOffset = MINCUSTOMPARAM_WIDTHOFFSET(pPpdData);
else if ((LONG) csdata.dwWidthOffset > MAXCUSTOMPARAM_WIDTHOFFSET(pPpdData))
csdata.dwWidthOffset = MAXCUSTOMPARAM_WIDTHOFFSET(pPpdData);
if ((LONG) csdata.dwHeightOffset < MINCUSTOMPARAM_HEIGHTOFFSET(pPpdData))
csdata.dwHeightOffset = MINCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
else if ((LONG) csdata.dwHeightOffset > MAXCUSTOMPARAM_HEIGHTOFFSET(pPpdData))
csdata.dwHeightOffset = MAXCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
//
// Validate cut-sheet vs. roll-fed selection
//
if (csdata.wCutSheet && !(pPpdData->dwCustomSizeFlags & CUSTOMSIZE_CUTSHEET))
csdata.wCutSheet = FALSE;
else if (!csdata.wCutSheet && !(pPpdData->dwCustomSizeFlags & CUSTOMSIZE_ROLLFED))
csdata.wCutSheet = TRUE;
//
// Check if the specified paper feed direction can be satisfied
//
bFit = BFixupCustomSizeDataFeedDirection(pUIInfo, pPpdData, &csdata);
//
// If we haven't been able to fit the custom paper size in
// correct feeding direction and orientation, then we have
// to swap width and height here, because they will be opposite
// of what PPD spec 4.3 page 109 Figure 3 specifies.
//
if (!bFit)
{
dwTemp = csdata.dwX;
csdata.dwX = csdata.dwY;
csdata.dwY = dwTemp;
}
//
// Verify width and height parameters
//
bShortEdgeFirst =
(csdata.wFeedDirection == SHORTEDGEFIRST ||
csdata.wFeedDirection == SHORTEDGEFIRST_FLIPPED);
bXGreaterThanY = (csdata.dwX > csdata.dwY);
if ((bShortEdgeFirst && bXGreaterThanY) ||
(!bShortEdgeFirst && !bXGreaterThanY))
{
// In this case: x <=> height, y <=> width
pdwHeight = &csdata.dwX;
pdwWidth = &csdata.dwY;
}
else
{
// In this case: x <=> width, y <=> height
pdwWidth = &csdata.dwX;
pdwHeight = &csdata.dwY;
}
if ((LONG) (*pdwWidth + csdata.dwWidthOffset) > pPageSize->szPaperSize.cx)
{
*pdwWidth = pPageSize->szPaperSize.cx - csdata.dwWidthOffset;
if ((LONG) *pdwWidth < MINCUSTOMPARAM_WIDTH(pPpdData))
{
*pdwWidth = MINCUSTOMPARAM_WIDTH(pPpdData);
csdata.dwWidthOffset = pPageSize->szPaperSize.cx - *pdwWidth;
}
}
else if ((LONG) *pdwWidth < MINCUSTOMPARAM_WIDTH(pPpdData))
{
*pdwWidth = MINCUSTOMPARAM_WIDTH(pPpdData);
}
if ((LONG) (*pdwHeight + csdata.dwHeightOffset) > pPageSize->szPaperSize.cy)
{
*pdwHeight = pPageSize->szPaperSize.cy - csdata.dwHeightOffset;
if ((LONG) *pdwHeight < MINCUSTOMPARAM_HEIGHT(pPpdData))
{
*pdwHeight = MINCUSTOMPARAM_HEIGHT(pPpdData);
csdata.dwHeightOffset = pPageSize->szPaperSize.cy - *pdwHeight;
}
}
else if ((LONG) *pdwHeight < MINCUSTOMPARAM_HEIGHT(pPpdData))
{
*pdwHeight = MINCUSTOMPARAM_HEIGHT(pPpdData);
}
//
// Check if anything has changed and
// return appropriate result value
//
if (memcmp(pCSData, &csdata, sizeof(csdata)) == 0)
return TRUE;
*pCSData = csdata;
return FALSE;
}
VOID
VFillDefaultCustomPageSizeData(
IN PRAWBINARYDATA pRawData,
OUT PCUSTOMSIZEDATA pCSData,
IN BOOL bMetric
)
/*++
Routine Description:
Initialize the custom page size parameters to their default values
Arguments:
pRawData - Points to raw printer description data
pCSData - Buffer for storing default custom page size parameters
bMetric - Whether we're on a metric system
Return Value:
NONE
--*/
{
PPPDDATA pPpdData;
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
ASSERT(pPpdData != NULL);
//
// Default to Letter or A4 depending on whether
// we're on metric system or not
//
if (bMetric)
{
pCSData->dwX = 210000; // 210mm
pCSData->dwY = 297000; // 297mm
}
else
{
pCSData->dwX = 215900; // 8.5"
pCSData->dwY = 279400; // 11"
}
//
// Get default offsets and feed direction
//
pCSData->dwWidthOffset = MINCUSTOMPARAM_WIDTHOFFSET(pPpdData);
pCSData->dwHeightOffset = MINCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
pCSData->wFeedDirection =
(pPpdData->dwCustomSizeFlags & CUSTOMSIZE_SHORTEDGEFEED) ?
SHORTEDGEFIRST : LONGEDGEFIRST;
//
// Make sure the default custom page size parameters are consistent
//
(VOID) BValidateCustomPageSizeData(pRawData, pCSData);
}
VOID
VGetCustomSizeParamRange(
IN PRAWBINARYDATA pRawData,
IN PCUSTOMSIZEDATA pCSData,
OUT PCUSTOMSIZERANGE pCSRange
)
/*++
Routine Description:
Return the valid ranges for custom page size width, height,
and offset parameters based on their current values
Arguments:
pRawData - Points to raw printer description data
pCSData - Specifies the current custom page size parameter values
pCSRange - Output buffer for returning custom page size parameter ranges
It should point to an array of 4 CUSTOMSIZERANGE structures:
0 (CUSTOMPARAM_WIDTH)
1 (CUSTOMPARAM_HEIGHT)
2 (CUSTOMPARAM_WIDTHOFFSET)
3 (CUSTOMPARAM_HEIGHTOFFSET)
Return Value:
NONE
--*/
{
PUIINFO pUIInfo;
PPPDDATA pPpdData;
BOOL bShortEdgeFirst, bXGreaterThanY;
PPAGESIZE pPageSize;
CUSTOMSIZEDATA csdata;
PCUSTOMSIZERANGE pWidthRange, pHeightRange, pTempRange;
BOOL bFit;
pUIInfo = GET_UIINFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
ASSERT(pUIInfo != NULL && pPpdData != NULL);
pPageSize = PGetCustomPageSizeOption(pUIInfo);
ASSERT(pPageSize != NULL);
//
// The range for width and height offsets are predictable
//
pCSRange[CUSTOMPARAM_WIDTHOFFSET].dwMin = MINCUSTOMPARAM_WIDTHOFFSET(pPpdData);
pCSRange[CUSTOMPARAM_WIDTHOFFSET].dwMax = MAXCUSTOMPARAM_WIDTHOFFSET(pPpdData);
pCSRange[CUSTOMPARAM_HEIGHTOFFSET].dwMin = MINCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
pCSRange[CUSTOMPARAM_HEIGHTOFFSET].dwMax = MAXCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
//
// The range for width and height are affected by the selected paper feed direction
//
csdata = *pCSData;
bFit = BFixupCustomSizeDataFeedDirection(pUIInfo, pPpdData, &csdata);
bShortEdgeFirst =
(csdata.wFeedDirection == SHORTEDGEFIRST ||
csdata.wFeedDirection == SHORTEDGEFIRST_FLIPPED);
bXGreaterThanY = (csdata.dwX > csdata.dwY);
if ((bShortEdgeFirst && bXGreaterThanY) ||
(!bShortEdgeFirst && !bXGreaterThanY))
{
//
// Here user's logical x/y and custom page
// size width/height are swapped
//
pWidthRange = pCSRange + CUSTOMPARAM_HEIGHT;
pHeightRange = pCSRange + CUSTOMPARAM_WIDTH;
}
else
{
//
// Here user's logical x/y correspond to
// custom page size width/height
//
pWidthRange = pCSRange + CUSTOMPARAM_WIDTH;
pHeightRange = pCSRange + CUSTOMPARAM_HEIGHT;
}
//
// If we haven't been able to fit the custom paper size in
// correct feeding direction and orientation, then we have
// to swap width and height here, because they will be opposite
// of what PPD spec 4.3 page 109 Figure 3 specifies.
//
if (!bFit)
{
pTempRange = pWidthRange;
pWidthRange = pHeightRange;
pHeightRange = pTempRange;
}
pWidthRange->dwMin = MINCUSTOMPARAM_WIDTH(pPpdData);
pWidthRange->dwMax = MAXCUSTOMPARAM_WIDTH(pPpdData);
pHeightRange->dwMin = MINCUSTOMPARAM_HEIGHT(pPpdData);
pHeightRange->dwMax = MAXCUSTOMPARAM_HEIGHT(pPpdData);
if (pWidthRange->dwMax > pPageSize->szPaperSize.cx - csdata.dwWidthOffset)
pWidthRange->dwMax = pPageSize->szPaperSize.cx - csdata.dwWidthOffset;
if (pHeightRange->dwMax > pPageSize->szPaperSize.cy - csdata.dwHeightOffset)
pHeightRange->dwMax = pPageSize->szPaperSize.cy - csdata.dwHeightOffset;
}
BOOL
BFormSupportedThruCustomSize(
PRAWBINARYDATA pRawData,
DWORD dwX,
DWORD dwY,
PWORD pwFeedDirection
)
/*++
Routine Description:
Determine whether a form can be supported through custom page size
Arguments:
pRawData - Points to raw printer description data
dwX, dwY - Form width and height (in microns)
pwFeedDirection - if not NULL, will be set to the selected feed direction
Return Value:
TRUE if the form can be supported through custom page size
FALSE if not. In that case, pwFeedDirection will be LONGEDGEFIRST.
--*/
{
PPPDDATA pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
static WORD awPrefFeedDir[] = {
LONGEDGEFIRST,
SHORTEDGEFIRST
};
CUSTOMSIZEDATA csdata;
DWORD i;
for (i = 0; i < (sizeof(awPrefFeedDir)/sizeof(WORD)); i++)
{
csdata.dwX = dwX;
csdata.dwY = dwY;
csdata.dwWidthOffset =
csdata.dwHeightOffset = 0;
csdata.wCutSheet = TRUE;
csdata.wFeedDirection = awPrefFeedDir[i];
(VOID) BValidateCustomPageSizeData(pRawData, &csdata);
if (dwX == csdata.dwX && dwY == csdata.dwY && csdata.wFeedDirection != MAX_FEEDDIRECTION)
{
if (pwFeedDirection != NULL)
*pwFeedDirection = csdata.wFeedDirection; // might be flipped
return TRUE;
}
}
if (pwFeedDirection != NULL)
*pwFeedDirection = LONGEDGEFIRST; // just set a safe default, the return value should be checked !
return FALSE;
}