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

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. custsize.c
  5. Abstract:
  6. Parser functions for handling custom page size feature
  7. Environment:
  8. Windows NT PostScript driver
  9. Revision History:
  10. 03/20/97 -davidx-
  11. Created it.
  12. --*/
  13. #include "lib.h"
  14. #include "ppd.h"
  15. BOOL
  16. BFixupCustomSizeDataFeedDirection(
  17. PUIINFO pUIInfo,
  18. PPPDDATA pPpdData,
  19. PCUSTOMSIZEDATA pCSData
  20. )
  21. /*++
  22. Routine Description:
  23. Validate the requested paper feed direction parameter
  24. Fix up any inconsistency if necessary
  25. Arguments:
  26. pPpdData - Points to PPDDATA structure
  27. pCSData - Specifies custom page size parameters
  28. Return Value:
  29. TRUE if we can find a feeding direction to fit the custom page size.
  30. FALSE otherwise.
  31. Note:
  32. See Figure 3 on page 109 of PPD 4.3 spec for more details.
  33. --*/
  34. #define ORIENTATION_AVAILABLE(iOrient) (dwFlags & (1 << (iOrient)))
  35. #define FIXUP_FEEDDIRECTION(iMainOrient, iAltOrient, wAltFeedDirection) \
  36. { \
  37. if (! ORIENTATION_AVAILABLE(iMainOrient)) \
  38. { \
  39. pCSData->wFeedDirection = \
  40. ORIENTATION_AVAILABLE(iAltOrient) ? \
  41. (wAltFeedDirection) : \
  42. MAX_FEEDDIRECTION; \
  43. } \
  44. }
  45. {
  46. static const DWORD adwMasks[4] = { 0x1, 0x3, 0x7, 0xf };
  47. DWORD dwFlags;
  48. BOOL bXGreaterThanY;
  49. BOOL bShortEdgeFirst;
  50. LONG lVal;
  51. WORD wFeedDirectionSave;
  52. //
  53. // Figure out which custom page size orientations are supported
  54. // dwFlags is DWORD value whose lower-order 4 bits are interpreted as flags:
  55. // If orientation N is supported, then bit 1 << N will be set
  56. //
  57. dwFlags = 0xf;
  58. if ((lVal = MINCUSTOMPARAM_ORIENTATION(pPpdData)) > 3)
  59. dwFlags = 0;
  60. else if (lVal > 0)
  61. dwFlags &= ~adwMasks[lVal - 1];
  62. if ((lVal = MAXCUSTOMPARAM_ORIENTATION(pPpdData)) < 3)
  63. dwFlags &= adwMasks[lVal];
  64. wFeedDirectionSave = pCSData->wFeedDirection;
  65. bXGreaterThanY = (pCSData->dwX > pCSData->dwY);
  66. //
  67. // First try to fit within the current feeding direction.
  68. //
  69. switch (pCSData->wFeedDirection)
  70. {
  71. case SHORTEDGEFIRST:
  72. if (bXGreaterThanY)
  73. {
  74. // orientation 0 (or 2)
  75. FIXUP_FEEDDIRECTION(0, 2, SHORTEDGEFIRST_FLIPPED);
  76. }
  77. else
  78. {
  79. // orientation 1 (or 3)
  80. FIXUP_FEEDDIRECTION(1, 3, SHORTEDGEFIRST_FLIPPED);
  81. }
  82. break;
  83. case SHORTEDGEFIRST_FLIPPED:
  84. if (bXGreaterThanY)
  85. {
  86. // orientation 2 (or 0)
  87. FIXUP_FEEDDIRECTION(2, 0, SHORTEDGEFIRST);
  88. }
  89. else
  90. {
  91. // orientation 3 (or 1)
  92. FIXUP_FEEDDIRECTION(3, 1, SHORTEDGEFIRST);
  93. }
  94. break;
  95. case LONGEDGEFIRST:
  96. if (bXGreaterThanY)
  97. {
  98. // orientation 1 (or 3)
  99. FIXUP_FEEDDIRECTION(1, 3, LONGEDGEFIRST_FLIPPED);
  100. }
  101. else
  102. {
  103. // orientation 0 (or 2)
  104. FIXUP_FEEDDIRECTION(0, 2, LONGEDGEFIRST_FLIPPED);
  105. }
  106. break;
  107. case LONGEDGEFIRST_FLIPPED:
  108. if (bXGreaterThanY)
  109. {
  110. // orientation 3 (or 1)
  111. FIXUP_FEEDDIRECTION(3, 1, LONGEDGEFIRST);
  112. }
  113. else
  114. {
  115. // orientation 2 (or 0)
  116. FIXUP_FEEDDIRECTION(2, 0, LONGEDGEFIRST);
  117. }
  118. break;
  119. }
  120. //
  121. // If the paper feed direction is not valid, we'll automatically
  122. // pick one here (default to long-edge-first if possible). This
  123. // should always change Long to Short, or Short to Long.
  124. //
  125. if (pCSData->wFeedDirection >= MAX_FEEDDIRECTION)
  126. {
  127. if (bXGreaterThanY)
  128. {
  129. if (ORIENTATION_AVAILABLE(1))
  130. pCSData->wFeedDirection = LONGEDGEFIRST;
  131. else if (ORIENTATION_AVAILABLE(3))
  132. pCSData->wFeedDirection = LONGEDGEFIRST_FLIPPED;
  133. else if (ORIENTATION_AVAILABLE(0))
  134. pCSData->wFeedDirection = SHORTEDGEFIRST;
  135. else // (ORIENTATION_AVAILABLE(2))
  136. pCSData->wFeedDirection = SHORTEDGEFIRST_FLIPPED;
  137. }
  138. else
  139. {
  140. if (ORIENTATION_AVAILABLE(0))
  141. pCSData->wFeedDirection = LONGEDGEFIRST;
  142. else if (ORIENTATION_AVAILABLE(2))
  143. pCSData->wFeedDirection = LONGEDGEFIRST_FLIPPED;
  144. else if (ORIENTATION_AVAILABLE(1))
  145. pCSData->wFeedDirection = SHORTEDGEFIRST;
  146. else // (ORIENTATION_AVAILABLE(3))
  147. pCSData->wFeedDirection = SHORTEDGEFIRST_FLIPPED;
  148. }
  149. }
  150. bShortEdgeFirst =
  151. (pCSData->wFeedDirection == SHORTEDGEFIRST ||
  152. pCSData->wFeedDirection == SHORTEDGEFIRST_FLIPPED);
  153. if ( (!bShortEdgeFirst && !LONGEDGEFIRST_SUPPORTED(pUIInfo, pPpdData)) ||
  154. (bShortEdgeFirst && !SHORTEDGEFIRST_SUPPORTED(pUIInfo, pPpdData)))
  155. {
  156. //
  157. // The other feeding direction we picked doesn't fit either, so we
  158. // have to stick with the original feeding direction.
  159. //
  160. pCSData->wFeedDirection = wFeedDirectionSave;
  161. //
  162. // Check the availability of orientations and flip the feed direction if necessary
  163. //
  164. if ((pCSData->wFeedDirection == LONGEDGEFIRST || pCSData->wFeedDirection == SHORTEDGEFIRST) &&
  165. !(ORIENTATION_AVAILABLE(0) || ORIENTATION_AVAILABLE(1)))
  166. {
  167. pCSData->wFeedDirection = (pCSData->wFeedDirection == LONGEDGEFIRST) ?
  168. LONGEDGEFIRST_FLIPPED : SHORTEDGEFIRST_FLIPPED;
  169. }
  170. else if ((pCSData->wFeedDirection == LONGEDGEFIRST_FLIPPED || pCSData->wFeedDirection == SHORTEDGEFIRST_FLIPPED) &&
  171. !(ORIENTATION_AVAILABLE(2) || ORIENTATION_AVAILABLE(3)))
  172. {
  173. pCSData->wFeedDirection = (pCSData->wFeedDirection == LONGEDGEFIRST_FLIPPED) ?
  174. LONGEDGEFIRST : SHORTEDGEFIRST;
  175. }
  176. return FALSE;
  177. }
  178. else
  179. return TRUE;
  180. }
  181. BOOL
  182. BValidateCustomPageSizeData(
  183. IN PRAWBINARYDATA pRawData,
  184. IN OUT PCUSTOMSIZEDATA pCSData
  185. )
  186. /*++
  187. Routine Description:
  188. Validate the specified custom page size parameters, and
  189. Fix up any inconsistencies found.
  190. Arguments:
  191. pRawData - Points to raw binary printer description data
  192. pCSData - Specifies the custom page size parameters to be validate
  193. Return Value:
  194. TRUE if the custom page size parameters are valid, FALSE otherwise.
  195. If FALSE is returned, custom page size parameters have been
  196. fixed up to a consistent state.
  197. --*/
  198. {
  199. PUIINFO pUIInfo;
  200. PPPDDATA pPpdData;
  201. PPAGESIZE pPageSize;
  202. CUSTOMSIZEDATA csdata;
  203. PDWORD pdwWidth, pdwHeight;
  204. DWORD dwTemp;
  205. BOOL bShortEdgeFirst, bXGreaterThanY;
  206. BOOL bFit;
  207. pUIInfo = GET_UIINFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  208. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  209. ASSERT(pUIInfo != NULL && pPpdData != NULL);
  210. if ((pPageSize = PGetCustomPageSizeOption(pUIInfo)) == NULL)
  211. {
  212. RIP(("Custom page size not supported\n"));
  213. return TRUE;
  214. }
  215. csdata = *pCSData;
  216. //
  217. // Width and height offset parameters are straightforward to verify
  218. //
  219. if ((LONG) csdata.dwWidthOffset < MINCUSTOMPARAM_WIDTHOFFSET(pPpdData))
  220. csdata.dwWidthOffset = MINCUSTOMPARAM_WIDTHOFFSET(pPpdData);
  221. else if ((LONG) csdata.dwWidthOffset > MAXCUSTOMPARAM_WIDTHOFFSET(pPpdData))
  222. csdata.dwWidthOffset = MAXCUSTOMPARAM_WIDTHOFFSET(pPpdData);
  223. if ((LONG) csdata.dwHeightOffset < MINCUSTOMPARAM_HEIGHTOFFSET(pPpdData))
  224. csdata.dwHeightOffset = MINCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
  225. else if ((LONG) csdata.dwHeightOffset > MAXCUSTOMPARAM_HEIGHTOFFSET(pPpdData))
  226. csdata.dwHeightOffset = MAXCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
  227. //
  228. // Validate cut-sheet vs. roll-fed selection
  229. //
  230. if (csdata.wCutSheet && !(pPpdData->dwCustomSizeFlags & CUSTOMSIZE_CUTSHEET))
  231. csdata.wCutSheet = FALSE;
  232. else if (!csdata.wCutSheet && !(pPpdData->dwCustomSizeFlags & CUSTOMSIZE_ROLLFED))
  233. csdata.wCutSheet = TRUE;
  234. //
  235. // Check if the specified paper feed direction can be satisfied
  236. //
  237. bFit = BFixupCustomSizeDataFeedDirection(pUIInfo, pPpdData, &csdata);
  238. //
  239. // If we haven't been able to fit the custom paper size in
  240. // correct feeding direction and orientation, then we have
  241. // to swap width and height here, because they will be opposite
  242. // of what PPD spec 4.3 page 109 Figure 3 specifies.
  243. //
  244. if (!bFit)
  245. {
  246. dwTemp = csdata.dwX;
  247. csdata.dwX = csdata.dwY;
  248. csdata.dwY = dwTemp;
  249. }
  250. //
  251. // Verify width and height parameters
  252. //
  253. bShortEdgeFirst =
  254. (csdata.wFeedDirection == SHORTEDGEFIRST ||
  255. csdata.wFeedDirection == SHORTEDGEFIRST_FLIPPED);
  256. bXGreaterThanY = (csdata.dwX > csdata.dwY);
  257. if ((bShortEdgeFirst && bXGreaterThanY) ||
  258. (!bShortEdgeFirst && !bXGreaterThanY))
  259. {
  260. // In this case: x <=> height, y <=> width
  261. pdwHeight = &csdata.dwX;
  262. pdwWidth = &csdata.dwY;
  263. }
  264. else
  265. {
  266. // In this case: x <=> width, y <=> height
  267. pdwWidth = &csdata.dwX;
  268. pdwHeight = &csdata.dwY;
  269. }
  270. if ((LONG) (*pdwWidth + csdata.dwWidthOffset) > pPageSize->szPaperSize.cx)
  271. {
  272. *pdwWidth = pPageSize->szPaperSize.cx - csdata.dwWidthOffset;
  273. if ((LONG) *pdwWidth < MINCUSTOMPARAM_WIDTH(pPpdData))
  274. {
  275. *pdwWidth = MINCUSTOMPARAM_WIDTH(pPpdData);
  276. csdata.dwWidthOffset = pPageSize->szPaperSize.cx - *pdwWidth;
  277. }
  278. }
  279. else if ((LONG) *pdwWidth < MINCUSTOMPARAM_WIDTH(pPpdData))
  280. {
  281. *pdwWidth = MINCUSTOMPARAM_WIDTH(pPpdData);
  282. }
  283. if ((LONG) (*pdwHeight + csdata.dwHeightOffset) > pPageSize->szPaperSize.cy)
  284. {
  285. *pdwHeight = pPageSize->szPaperSize.cy - csdata.dwHeightOffset;
  286. if ((LONG) *pdwHeight < MINCUSTOMPARAM_HEIGHT(pPpdData))
  287. {
  288. *pdwHeight = MINCUSTOMPARAM_HEIGHT(pPpdData);
  289. csdata.dwHeightOffset = pPageSize->szPaperSize.cy - *pdwHeight;
  290. }
  291. }
  292. else if ((LONG) *pdwHeight < MINCUSTOMPARAM_HEIGHT(pPpdData))
  293. {
  294. *pdwHeight = MINCUSTOMPARAM_HEIGHT(pPpdData);
  295. }
  296. //
  297. // Check if anything has changed and
  298. // return appropriate result value
  299. //
  300. if (memcmp(pCSData, &csdata, sizeof(csdata)) == 0)
  301. return TRUE;
  302. *pCSData = csdata;
  303. return FALSE;
  304. }
  305. VOID
  306. VFillDefaultCustomPageSizeData(
  307. IN PRAWBINARYDATA pRawData,
  308. OUT PCUSTOMSIZEDATA pCSData,
  309. IN BOOL bMetric
  310. )
  311. /*++
  312. Routine Description:
  313. Initialize the custom page size parameters to their default values
  314. Arguments:
  315. pRawData - Points to raw printer description data
  316. pCSData - Buffer for storing default custom page size parameters
  317. bMetric - Whether we're on a metric system
  318. Return Value:
  319. NONE
  320. --*/
  321. {
  322. PPPDDATA pPpdData;
  323. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  324. ASSERT(pPpdData != NULL);
  325. //
  326. // Default to Letter or A4 depending on whether
  327. // we're on metric system or not
  328. //
  329. if (bMetric)
  330. {
  331. pCSData->dwX = 210000; // 210mm
  332. pCSData->dwY = 297000; // 297mm
  333. }
  334. else
  335. {
  336. pCSData->dwX = 215900; // 8.5"
  337. pCSData->dwY = 279400; // 11"
  338. }
  339. //
  340. // Get default offsets and feed direction
  341. //
  342. pCSData->dwWidthOffset = MINCUSTOMPARAM_WIDTHOFFSET(pPpdData);
  343. pCSData->dwHeightOffset = MINCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
  344. pCSData->wFeedDirection =
  345. (pPpdData->dwCustomSizeFlags & CUSTOMSIZE_SHORTEDGEFEED) ?
  346. SHORTEDGEFIRST : LONGEDGEFIRST;
  347. //
  348. // Make sure the default custom page size parameters are consistent
  349. //
  350. (VOID) BValidateCustomPageSizeData(pRawData, pCSData);
  351. }
  352. VOID
  353. VGetCustomSizeParamRange(
  354. IN PRAWBINARYDATA pRawData,
  355. IN PCUSTOMSIZEDATA pCSData,
  356. OUT PCUSTOMSIZERANGE pCSRange
  357. )
  358. /*++
  359. Routine Description:
  360. Return the valid ranges for custom page size width, height,
  361. and offset parameters based on their current values
  362. Arguments:
  363. pRawData - Points to raw printer description data
  364. pCSData - Specifies the current custom page size parameter values
  365. pCSRange - Output buffer for returning custom page size parameter ranges
  366. It should point to an array of 4 CUSTOMSIZERANGE structures:
  367. 0 (CUSTOMPARAM_WIDTH)
  368. 1 (CUSTOMPARAM_HEIGHT)
  369. 2 (CUSTOMPARAM_WIDTHOFFSET)
  370. 3 (CUSTOMPARAM_HEIGHTOFFSET)
  371. Return Value:
  372. NONE
  373. --*/
  374. {
  375. PUIINFO pUIInfo;
  376. PPPDDATA pPpdData;
  377. BOOL bShortEdgeFirst, bXGreaterThanY;
  378. PPAGESIZE pPageSize;
  379. CUSTOMSIZEDATA csdata;
  380. PCUSTOMSIZERANGE pWidthRange, pHeightRange, pTempRange;
  381. BOOL bFit;
  382. pUIInfo = GET_UIINFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  383. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  384. ASSERT(pUIInfo != NULL && pPpdData != NULL);
  385. pPageSize = PGetCustomPageSizeOption(pUIInfo);
  386. ASSERT(pPageSize != NULL);
  387. //
  388. // The range for width and height offsets are predictable
  389. //
  390. pCSRange[CUSTOMPARAM_WIDTHOFFSET].dwMin = MINCUSTOMPARAM_WIDTHOFFSET(pPpdData);
  391. pCSRange[CUSTOMPARAM_WIDTHOFFSET].dwMax = MAXCUSTOMPARAM_WIDTHOFFSET(pPpdData);
  392. pCSRange[CUSTOMPARAM_HEIGHTOFFSET].dwMin = MINCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
  393. pCSRange[CUSTOMPARAM_HEIGHTOFFSET].dwMax = MAXCUSTOMPARAM_HEIGHTOFFSET(pPpdData);
  394. //
  395. // The range for width and height are affected by the selected paper feed direction
  396. //
  397. csdata = *pCSData;
  398. bFit = BFixupCustomSizeDataFeedDirection(pUIInfo, pPpdData, &csdata);
  399. bShortEdgeFirst =
  400. (csdata.wFeedDirection == SHORTEDGEFIRST ||
  401. csdata.wFeedDirection == SHORTEDGEFIRST_FLIPPED);
  402. bXGreaterThanY = (csdata.dwX > csdata.dwY);
  403. if ((bShortEdgeFirst && bXGreaterThanY) ||
  404. (!bShortEdgeFirst && !bXGreaterThanY))
  405. {
  406. //
  407. // Here user's logical x/y and custom page
  408. // size width/height are swapped
  409. //
  410. pWidthRange = pCSRange + CUSTOMPARAM_HEIGHT;
  411. pHeightRange = pCSRange + CUSTOMPARAM_WIDTH;
  412. }
  413. else
  414. {
  415. //
  416. // Here user's logical x/y correspond to
  417. // custom page size width/height
  418. //
  419. pWidthRange = pCSRange + CUSTOMPARAM_WIDTH;
  420. pHeightRange = pCSRange + CUSTOMPARAM_HEIGHT;
  421. }
  422. //
  423. // If we haven't been able to fit the custom paper size in
  424. // correct feeding direction and orientation, then we have
  425. // to swap width and height here, because they will be opposite
  426. // of what PPD spec 4.3 page 109 Figure 3 specifies.
  427. //
  428. if (!bFit)
  429. {
  430. pTempRange = pWidthRange;
  431. pWidthRange = pHeightRange;
  432. pHeightRange = pTempRange;
  433. }
  434. pWidthRange->dwMin = MINCUSTOMPARAM_WIDTH(pPpdData);
  435. pWidthRange->dwMax = MAXCUSTOMPARAM_WIDTH(pPpdData);
  436. pHeightRange->dwMin = MINCUSTOMPARAM_HEIGHT(pPpdData);
  437. pHeightRange->dwMax = MAXCUSTOMPARAM_HEIGHT(pPpdData);
  438. if (pWidthRange->dwMax > pPageSize->szPaperSize.cx - csdata.dwWidthOffset)
  439. pWidthRange->dwMax = pPageSize->szPaperSize.cx - csdata.dwWidthOffset;
  440. if (pHeightRange->dwMax > pPageSize->szPaperSize.cy - csdata.dwHeightOffset)
  441. pHeightRange->dwMax = pPageSize->szPaperSize.cy - csdata.dwHeightOffset;
  442. }
  443. BOOL
  444. BFormSupportedThruCustomSize(
  445. PRAWBINARYDATA pRawData,
  446. DWORD dwX,
  447. DWORD dwY,
  448. PWORD pwFeedDirection
  449. )
  450. /*++
  451. Routine Description:
  452. Determine whether a form can be supported through custom page size
  453. Arguments:
  454. pRawData - Points to raw printer description data
  455. dwX, dwY - Form width and height (in microns)
  456. pwFeedDirection - if not NULL, will be set to the selected feed direction
  457. Return Value:
  458. TRUE if the form can be supported through custom page size
  459. FALSE if not. In that case, pwFeedDirection will be LONGEDGEFIRST.
  460. --*/
  461. {
  462. PPPDDATA pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  463. static WORD awPrefFeedDir[] = {
  464. LONGEDGEFIRST,
  465. SHORTEDGEFIRST
  466. };
  467. CUSTOMSIZEDATA csdata;
  468. DWORD i;
  469. for (i = 0; i < (sizeof(awPrefFeedDir)/sizeof(WORD)); i++)
  470. {
  471. csdata.dwX = dwX;
  472. csdata.dwY = dwY;
  473. csdata.dwWidthOffset =
  474. csdata.dwHeightOffset = 0;
  475. csdata.wCutSheet = TRUE;
  476. csdata.wFeedDirection = awPrefFeedDir[i];
  477. (VOID) BValidateCustomPageSizeData(pRawData, &csdata);
  478. if (dwX == csdata.dwX && dwY == csdata.dwY && csdata.wFeedDirection != MAX_FEEDDIRECTION)
  479. {
  480. if (pwFeedDirection != NULL)
  481. *pwFeedDirection = csdata.wFeedDirection; // might be flipped
  482. return TRUE;
  483. }
  484. }
  485. if (pwFeedDirection != NULL)
  486. *pwFeedDirection = LONGEDGEFIRST; // just set a safe default, the return value should be checked !
  487. return FALSE;
  488. }