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.

1208 lines
28 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. print.c
  5. Abstract:
  6. Implementation of document and page related DDI entry points:
  7. DrvStartDoc
  8. DrvEndDoc
  9. DrvStartPage
  10. DrvSendPage
  11. DrvNextBand
  12. DrvStartBanding
  13. Environment:
  14. Windows NT Unidrv driver
  15. Revision History:
  16. 10/14/96 -amandan-
  17. Created
  18. 03/31/97 -zhanw-
  19. Added OEM customization support
  20. --*/
  21. #include "unidrv.h"
  22. //
  23. // Forward declaration for local functions
  24. //
  25. VOID VEndPage ( PDEV *);
  26. BOOL BEndDoc ( PDEV *, SURFOBJ *, FLONG flags);
  27. VOID VSendSequenceCmd(PDEV *, DWORD);
  28. BOOL
  29. DrvStartDoc(
  30. SURFOBJ *pso,
  31. PWSTR pDocName,
  32. DWORD jobId
  33. )
  34. /*++
  35. Routine Description:
  36. Implementation of DDI entry point DrvStartDoc.
  37. Please refer to DDK documentation for more details.
  38. Arguments:
  39. pso - Defines the surface object
  40. pDocName - Specifies a Unicode document name
  41. jobId - Identifies the print job
  42. Return Value:
  43. TRUE if successful, FALSE if there is an error
  44. --*/
  45. {
  46. PDEV *pPDev = (PDEV*)pso->dhpdev;
  47. VERBOSE(("Entering DrvStartDoc...\n"));
  48. ASSERT_VALID_PDEV(pPDev);
  49. //
  50. // use driver managed surface
  51. //
  52. if (pPDev->pso)
  53. pso = pPDev->pso;
  54. //
  55. // Handle OEM hooks
  56. //
  57. HANDLE_OEMHOOKS(pPDev,
  58. EP_OEMStartDoc,
  59. PFN_OEMStartDoc,
  60. BOOL,
  61. (pso,
  62. pDocName,
  63. jobId));
  64. HANDLE_VECTORHOOKS(pPDev,
  65. EP_OEMStartDoc,
  66. VMStartDoc,
  67. BOOL,
  68. (pso,
  69. pDocName,
  70. jobId));
  71. //
  72. // We might get a DrvResetPDEV before this and get another DrvStartDoc
  73. // without a DrvEndDoc so check for that condition and call BEndDoc
  74. // to clean up the previous instance before continuing.
  75. //
  76. if (pPDev->fMode & PF_DOC_SENT)
  77. {
  78. BEndDoc(pPDev, pso, 0); // this flag also suppresses
  79. // emission of EndDoc commands to the printer
  80. // since they may cause a page ejection and
  81. // we are only interested in freeing memory and
  82. // performing pdev cleanup at this point.
  83. pPDev->fMode &= ~PF_DOC_SENT;
  84. }
  85. else
  86. pPDev->dwPageNumber = 1 ; // first page of document
  87. //
  88. // Call Raster and Font module
  89. //
  90. if (!(((PRMPROCS)(pPDev->pRasterProcs))->RMStartDoc(pso, pDocName, jobId)) ||
  91. !(((PFMPROCS)(pPDev->pFontProcs))->FMStartDoc(pso, pDocName, jobId)) )
  92. {
  93. return FALSE;
  94. }
  95. //
  96. // Send JobSetup and DocSetup Sequence Cmds at DrvStartPage instead
  97. // of here since the driver can get a new DrvStartDoc after each
  98. // DrvResetPDEV
  99. //
  100. return TRUE;
  101. }
  102. BOOL
  103. DrvStartPage(
  104. SURFOBJ *pso
  105. )
  106. /*++
  107. Routine Description:
  108. Implementation of DDI entry point DrvStartPage.
  109. Please refer to DDK documentation for more details.
  110. Arguments:
  111. pso - Defines the surface object
  112. Return Value:
  113. TRUE if successful, FALSE if there is an error
  114. --*/
  115. {
  116. PDEV *pPDev = (PDEV *)pso->dhpdev;
  117. PAL_DATA *pPD = pPDev->pPalData;
  118. VERBOSE(("Entering DrvStartPage...\n"));
  119. ASSERT_VALID_PDEV(pPDev);
  120. //
  121. // use driver managed surface
  122. //
  123. if (pPDev->pso)
  124. pso = pPDev->pso;
  125. //
  126. // Handle OEM hooks
  127. //
  128. HANDLE_OEMHOOKS(pPDev,
  129. EP_OEMStartPage,
  130. PFN_OEMStartPage,
  131. BOOL,
  132. (pso));
  133. HANDLE_VECTORHOOKS(pPDev,
  134. EP_OEMStartPage,
  135. VMStartPage,
  136. BOOL,
  137. (pso));
  138. //
  139. // clear flags at start of page
  140. //
  141. pPDev->fMode &= ~(PF_SURFACE_USED | PF_SURFACE_ERASED);
  142. pPDev->fMode &= ~PF_DOWNLOADED_TEXT;
  143. //
  144. // only a bitmap surface driver needs to have a band
  145. //
  146. if (!DRIVER_DEVICEMANAGED (pPDev))
  147. {
  148. ZeroMemory(pPDev->pbScanBuf, pPDev->szBand.cy);
  149. ZeroMemory(pPDev->pbRasterScanBuf, (pPDev->szBand.cy / LINESPERBLOCK)+1);
  150. #ifndef DISABLE_NEWRULES
  151. pPDev->dwRulesCount = 0;
  152. #endif
  153. }
  154. //
  155. // Send JobSetup, DocSetup cmd and Download the Palette if necessary.
  156. //
  157. if (!(pPDev->fMode & PF_JOB_SENT))
  158. {
  159. VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwJobSetupIndex);
  160. pPDev->fMode |= PF_JOB_SENT;
  161. }
  162. if (!(pPDev->fMode & PF_DOC_SENT))
  163. {
  164. VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwDocSetupIndex);
  165. pPDev->fMode |= PF_DOC_SENT; // this flag is cleared
  166. // by StartDoc
  167. //
  168. // PF_DOCSTARTED - Signify DrvStartDoc is called, for DrvResetPDEV
  169. // this flag is cleared only at EndJob.
  170. pPDev->fMode |= PF_DOCSTARTED;
  171. }
  172. pPDev->fMode &= ~PF_SEND_ONLY_NOEJECT_CMDS ;
  173. if ( (pPD->fFlags & PDF_DL_PAL_EACH_DOC) &&
  174. (!DRIVER_DEVICEMANAGED (pPDev)) )
  175. {
  176. VLoadPal(pPDev);
  177. }
  178. //
  179. // Set PF_ENUM_GRXTXT
  180. //
  181. pPDev->fMode |= PF_ENUM_GRXTXT;
  182. //
  183. // Call Raster and Font module.
  184. //
  185. if ( !( ((PRMPROCS)(pPDev->pRasterProcs))->RMStartPage(pso) ) ||
  186. !( ((PFMPROCS)(pPDev->pFontProcs))->FMStartPage(pso) ))
  187. {
  188. return FALSE;
  189. }
  190. //
  191. // BUG_BUG, should we check for PF_SEND_ONLY_NOEJECT_CMDS here?
  192. // Assumes that GPD writer does not put page ejection code
  193. // in PageSetup Cmds since we might get a ResetPDEV between pages.
  194. // This bit is set when we get DrvResetPDev where we are doing duplexing
  195. // and paper size and source, and orienation is the same. Detecting this
  196. // condition allows us to skip page ejection cmds or any cmds that
  197. // could cause page ejection but if the GPD writer does not put page
  198. // ejection code in PageSetup cmd, we are OK.
  199. // If pageSetup commands caused pages to be ejected, we would
  200. // always get one or more blank pages for every one that was printed.
  201. // this is a needless concern.
  202. //
  203. // initialize the cursor position at the start of each page
  204. //
  205. pPDev->ctl.ptCursor.x = pPDev->ctl.ptCursor.y = 0;
  206. pPDev->ctl.dwMode |= MODE_CURSOR_UNINITIALIZED; // both X & Y
  207. //
  208. // Send PageSetup sequence Cmds
  209. //
  210. VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwPageSetupIndex);
  211. //Download the Palette if necessary.
  212. if ( (pPD->fFlags & PDF_DL_PAL_EACH_PAGE) &&
  213. (!DRIVER_DEVICEMANAGED (pPDev)) )
  214. {
  215. VLoadPal(pPDev);
  216. }
  217. //
  218. // Set the current position to some illegal position, so that
  219. // we make no assumptions about where we are
  220. //
  221. //
  222. // Flush the spool buffer with the setup commands to give serial printers
  223. // a head start on loading paper and cleaning their jets.
  224. //
  225. if (pPDev->pGlobals->printertype == PT_SERIAL)
  226. FlushSpoolBuf (pPDev);
  227. return TRUE;
  228. }
  229. BOOL
  230. DrvSendPage(
  231. SURFOBJ *pso
  232. )
  233. /*++
  234. Routine Description:
  235. Implementation of DDI entry point DrvSendPage.
  236. Please refer to DDK documentation for more details.
  237. Arguments:
  238. pso - Defines the surface object
  239. Return Value:
  240. TRUE if successful, FALSE if there is an error
  241. --*/
  242. {
  243. BOOL bRet = FALSE;
  244. PDEV * pPDev = (PDEV *)pso->dhpdev;
  245. VERBOSE(("Entering DrvSendPage...\n"));
  246. ASSERT_VALID_PDEV(pPDev);
  247. //
  248. // use driver managed surface
  249. //
  250. if (pPDev->pso)
  251. pso = pPDev->pso;
  252. //
  253. // Handle OEM hooks
  254. //
  255. HANDLE_OEMHOOKS(pPDev,
  256. EP_OEMSendPage,
  257. PFN_OEMSendPage,
  258. BOOL,
  259. (pso));
  260. HANDLE_VECTORHOOKS(pPDev,
  261. EP_OEMSendPage,
  262. VMSendPage,
  263. BOOL,
  264. (pso));
  265. //Reset the brush, before calling render module.
  266. GSResetBrush(pPDev);
  267. switch( pso->iType )
  268. {
  269. case STYPE_BITMAP:
  270. //
  271. // Engine managed bitmap
  272. //
  273. //
  274. // Call Raster and Font module
  275. //
  276. if ( !(((PRMPROCS)(pPDev->pRasterProcs))->RMSendPage(pso)) ||
  277. !(((PFMPROCS)(pPDev->pFontProcs))->FMSendPage(pso) ) )
  278. {
  279. return FALSE;
  280. }
  281. //
  282. // VEndPage should take care of sending PageFinish sequence Cmds
  283. //
  284. VEndPage( pPDev );
  285. bRet = TRUE;
  286. break;
  287. case STYPE_DEVICE:
  288. //
  289. // Device managed surface
  290. //
  291. VERBOSE(("DrvSendPage: pso->iType == STYPE_DEVICE \n" ));
  292. //
  293. // Call Raster and Font module if needed.
  294. //
  295. //
  296. // VEndPage should take care of sending PageFinish sequence Cmds
  297. //
  298. VEndPage( pPDev );
  299. bRet = TRUE;
  300. break;
  301. default:
  302. VERBOSE(("DrvSendPage: pso->iType is unknown \n"));
  303. break;
  304. }
  305. return bRet;
  306. }
  307. BOOL
  308. DrvEndDoc(
  309. SURFOBJ *pso,
  310. FLONG flags
  311. )
  312. /*++
  313. Routine Description:
  314. Implementation of DDI entry point DrvEndDoc.
  315. Please refer to DDK documentation for more details.
  316. Arguments:
  317. pso - Defines the surface object
  318. flags - A set of flag bits
  319. Return Value:
  320. TRUE if successful, FALSE if there is an error
  321. --*/
  322. {
  323. PDEV *pPDev = (PDEV *)pso->dhpdev;
  324. VERBOSE(("Entering DrvEndDoc...\n"));
  325. ASSERT_VALID_PDEV(pPDev);
  326. //
  327. // use driver managed surface
  328. //
  329. if (pPDev->pso)
  330. pso = pPDev->pso;
  331. //
  332. // if we've detected an aborted job because WritePrinter has failed we will set the
  333. // ED_ABORTDOC flag for the OEM plugins since GDI only sets this for direct printing
  334. //
  335. if (pPDev->fMode & PF_ABORTED)
  336. flags |= ED_ABORTDOC;
  337. //
  338. // Handle OEM hooks
  339. //
  340. HANDLE_OEMHOOKS(pPDev,
  341. EP_OEMEndDoc,
  342. PFN_OEMEndDoc,
  343. BOOL,
  344. (pso,
  345. flags));
  346. HANDLE_VECTORHOOKS(pPDev,
  347. EP_OEMEndDoc,
  348. VMEndDoc,
  349. BOOL,
  350. (pso,
  351. flags));
  352. pPDev->fMode &= ~PF_DOC_SENT;
  353. // we are going to send the EndDoc commands to the printer.
  354. return ( BEndDoc(pPDev, pso, flags) );
  355. }
  356. BOOL
  357. DrvNextBand(
  358. SURFOBJ *pso,
  359. POINTL *pptl
  360. )
  361. /*++
  362. Routine Description:
  363. Implementation of DDI entry point DrvNextBand.
  364. Please refer to DDK documentation for more details.
  365. Arguments:
  366. pso - Defines the surface object
  367. pptl - Pointer to origin of next band (to return to GDI)
  368. Return Value:
  369. TRUE if successful, FALSE if there is an error
  370. --*/
  371. {
  372. PDEV *pPDev = (PDEV *)pso->dhpdev;
  373. BOOL bMore, bRet;
  374. VERBOSE(("Entering DrvNextBand...\n"));
  375. ASSERT_VALID_PDEV(pPDev);
  376. //
  377. // use driver managed surface
  378. //
  379. if (pPDev->pso)
  380. pso = pPDev->pso;
  381. //
  382. // Handle OEM hooks
  383. //
  384. HANDLE_OEMHOOKS(pPDev,
  385. EP_OEMNextBand,
  386. PFN_OEMNextBand,
  387. BOOL,
  388. (pso,
  389. pptl));
  390. HANDLE_VECTORHOOKS(pPDev,
  391. EP_OEMNextBand,
  392. VMNextBand,
  393. BOOL,
  394. (pso,
  395. pptl));
  396. //Reset the brush, before calling render module.
  397. GSResetBrush(pPDev);
  398. //
  399. // Call Raster and Font module
  400. //
  401. if (! (((PRMPROCS)(pPDev->pRasterProcs))->RMNextBand(pso, pptl)) ||
  402. ! (((PFMPROCS)(pPDev->pFontProcs))->FMNextBand(pso, pptl)) )
  403. {
  404. return FALSE;
  405. }
  406. //
  407. // Clear the band surface, szBand is in Graphic units
  408. //
  409. pPDev->fMode &= ~(PF_SURFACE_USED | PF_SURFACE_ERASED);
  410. pPDev->fMode &= ~PF_DOWNLOADED_TEXT;
  411. if (!DRIVER_DEVICEMANAGED (pPDev)) // bitmap surface
  412. {
  413. ZeroMemory(pPDev->pbScanBuf, pPDev->szBand.cy);
  414. ZeroMemory(pPDev->pbRasterScanBuf, (pPDev->szBand.cy / LINESPERBLOCK)+1);
  415. #ifndef DISABLE_NEWRULES
  416. pPDev->dwRulesCount = 0;
  417. #endif
  418. }
  419. //
  420. // If PF_REPLAY_BAND is set, then replay the last band enumerate to
  421. // GDI
  422. //
  423. if (pPDev->fMode & PF_REPLAY_BAND)
  424. {
  425. pptl->x = pPDev->rcClipRgn.left;
  426. pptl->y = pPDev->rcClipRgn.top;
  427. VERBOSE(("DrvNextBand: Next Band is %d , %d \n", pptl->x, pptl->y));
  428. pPDev->fMode &= ~PF_REPLAY_BAND;
  429. return TRUE;
  430. }
  431. switch( pPDev->iBandDirection )
  432. {
  433. case SW_DOWN:
  434. //
  435. // Moving down the page
  436. //
  437. pPDev->rcClipRgn.top += pPDev->szBand.cy;
  438. pPDev->rcClipRgn.bottom += pPDev->szBand.cy;
  439. //
  440. // Make sure we do not run off the bottom
  441. //
  442. bMore = pPDev->rcClipRgn.top < pPDev->sf.szImageAreaG.cy;
  443. if( pPDev->rcClipRgn.bottom > pPDev->sf.szImageAreaG.cy )
  444. {
  445. //
  446. // Partial band
  447. //
  448. pPDev->rcClipRgn.bottom = pPDev->sf.szImageAreaG.cy;
  449. }
  450. break;
  451. case SW_RTOL:
  452. //
  453. // LaserJet style, RTOL
  454. //
  455. pPDev->rcClipRgn.left -= pPDev->szBand.cx;
  456. pPDev->rcClipRgn.right -= pPDev->szBand.cx;
  457. bMore = pPDev->rcClipRgn.right > 0;
  458. //
  459. // if the left position is negative that is
  460. // what must be reported to GDI to render the
  461. // band correctly so we don't change the clip region.
  462. //
  463. break;
  464. case SW_LTOR:
  465. //
  466. // Dot matrix, left to right
  467. //
  468. pPDev->rcClipRgn.left += pPDev->szBand.cx;
  469. pPDev->rcClipRgn.right += pPDev->szBand.cx;
  470. bMore = pPDev->rcClipRgn.left < pPDev->sf.szImageAreaG.cx;
  471. if( pPDev->rcClipRgn.right > pPDev->sf.szImageAreaG.cx )
  472. {
  473. //
  474. // Partial band
  475. //
  476. pPDev->rcClipRgn.right = pPDev->sf.szImageAreaG.cx;
  477. }
  478. break;
  479. case SW_UP:
  480. //
  481. // Moving up the page
  482. //
  483. pPDev->rcClipRgn.top -= pPDev->szBand.cy;
  484. pPDev->rcClipRgn.bottom -= pPDev->szBand.cy;
  485. //
  486. // Make sure we do not run off the top
  487. //
  488. bMore = pPDev->rcClipRgn.bottom > 0 ;
  489. if( pPDev->rcClipRgn.top < 0 )
  490. {
  491. //
  492. // Partial band
  493. //
  494. pPDev->rcClipRgn.top = 0;
  495. }
  496. break;
  497. default:
  498. VERBOSE((" DrvNextBand, unknown banding direction \n"));
  499. return(FALSE);
  500. }
  501. if( bMore )
  502. {
  503. pptl->x = pPDev->rcClipRgn.left;
  504. pptl->y = pPDev->rcClipRgn.top;
  505. VERBOSE(("DrvNextBand: Next Band is %d , %d \n", pptl->x, pptl->y));
  506. }
  507. else
  508. {
  509. //
  510. // No more band for the page, send the page to printer
  511. //
  512. if ( !(((PRMPROCS)(pPDev->pRasterProcs))->RMSendPage(pso)) ||
  513. !(((PFMPROCS)(pPDev->pFontProcs))->FMSendPage(pso)) )
  514. {
  515. bRet = FALSE;
  516. }
  517. else
  518. bRet = TRUE;
  519. //
  520. // Send PageFinish sequence commands
  521. //
  522. VEndPage( pPDev );
  523. pptl->x = pptl->y = -1;
  524. return(bRet);
  525. }
  526. return(TRUE);
  527. }
  528. BOOL
  529. DrvStartBanding(
  530. SURFOBJ *pso,
  531. POINTL *pptl
  532. )
  533. /*++
  534. Routine Description:
  535. Implementation of DDI entry point DrvStartBanding.
  536. Please refer to DDK documentation for more details.
  537. Note: DrvStartBanding is called to prepare the driver
  538. for banding, call only once per page (not at everyband!!)
  539. Arguments:
  540. pso - Defines the surface object
  541. pptl - Pointer to origin of next band (to return to GDI)
  542. Return Value:
  543. Fill out pptl to contain the origin of the first band
  544. TRUE if successful, FALSE if there is an error
  545. --*/
  546. {
  547. PDEV *pPDev = (PDEV *)pso->dhpdev;
  548. VERBOSE(("Entering DrvStartBanding...\n"));
  549. ASSERT_VALID_PDEV(pPDev);
  550. //
  551. // use driver managed surface
  552. //
  553. if (pPDev->pso)
  554. pso = pPDev->pso;
  555. //
  556. // Handle OEM hooks
  557. //
  558. HANDLE_OEMHOOKS(pPDev,
  559. EP_OEMStartBanding,
  560. PFN_OEMStartBanding,
  561. BOOL,
  562. (pso,
  563. pptl));
  564. HANDLE_VECTORHOOKS(pPDev,
  565. EP_OEMStartBanding,
  566. VMStartBanding,
  567. BOOL,
  568. (pso,
  569. pptl));
  570. //
  571. // Set PF_ENUM_GRXTXT
  572. //
  573. pPDev->fMode |= PF_ENUM_GRXTXT;
  574. pPDev->fMode &= ~(PF_SURFACE_USED | PF_SURFACE_ERASED);
  575. pPDev->fMode &= ~PF_DOWNLOADED_TEXT;
  576. if (!DRIVER_DEVICEMANAGED (pPDev)) // bitmap surface
  577. {
  578. ZeroMemory(pPDev->pbScanBuf, pPDev->szBand.cy);
  579. ZeroMemory(pPDev->pbRasterScanBuf, (pPDev->szBand.cy / LINESPERBLOCK)+1);
  580. #ifndef DISABLE_NEWRULES
  581. pPDev->dwRulesCount = 0;
  582. #endif
  583. }
  584. //
  585. //
  586. // Call Raster and Font module
  587. //
  588. if (! (((PRMPROCS)(pPDev->pRasterProcs))->RMStartBanding(pso, pptl)) ||
  589. ! (((PFMPROCS)(pPDev->pFontProcs))->FMStartBanding(pso, pptl)) )
  590. {
  591. return FALSE;
  592. }
  593. if( pPDev->fMode & PF_ROTATE )
  594. {
  595. pPDev->rcClipRgn.top = 0;
  596. pPDev->rcClipRgn.bottom = pPDev->sf.szImageAreaG.cy;
  597. if( pPDev->fMode & PF_CCW_ROTATE90 )
  598. {
  599. //
  600. // LaserJet style rotation
  601. //
  602. if( // if duplexing is enabled...
  603. (pPDev->pdm->dmFields & DM_DUPLEX) &&
  604. (pPDev->pdm->dmDuplex == DMDUP_VERTICAL) &&
  605. !(pPDev->dwPageNumber % 2) &&
  606. pPDev->pUIInfo->dwFlags & FLAG_REVERSE_BAND_ORDER)
  607. {
  608. pPDev->rcClipRgn.left = 0;
  609. pPDev->rcClipRgn.right = pPDev->szBand.cx;
  610. pPDev->iBandDirection = SW_LTOR;
  611. }
  612. else
  613. {
  614. pPDev->rcClipRgn.left = pPDev->sf.szImageAreaG.cx - pPDev->szBand.cx;
  615. pPDev->rcClipRgn.right = pPDev->sf.szImageAreaG.cx;
  616. pPDev->iBandDirection = SW_RTOL;
  617. }
  618. }
  619. else
  620. {
  621. //
  622. // Dot matrix style rotation
  623. //
  624. if( // if duplexing is enabled...
  625. (pPDev->pdm->dmFields & DM_DUPLEX) &&
  626. (pPDev->pdm->dmDuplex == DMDUP_VERTICAL) &&
  627. !(pPDev->dwPageNumber % 2) &&
  628. pPDev->pUIInfo->dwFlags & FLAG_REVERSE_BAND_ORDER)
  629. {
  630. pPDev->rcClipRgn.left = pPDev->sf.szImageAreaG.cx - pPDev->szBand.cx;
  631. pPDev->rcClipRgn.right = pPDev->sf.szImageAreaG.cx;
  632. pPDev->iBandDirection = SW_RTOL;
  633. }
  634. else
  635. {
  636. pPDev->rcClipRgn.left = 0;
  637. pPDev->rcClipRgn.right = pPDev->szBand.cx;
  638. pPDev->iBandDirection = SW_LTOR;
  639. }
  640. }
  641. }
  642. else
  643. {
  644. pPDev->rcClipRgn.left = 0;
  645. pPDev->rcClipRgn.right = pPDev->szBand.cx;
  646. if( // if duplexing is enabled...
  647. (pPDev->pdm->dmFields & DM_DUPLEX) &&
  648. (pPDev->pdm->dmDuplex == DMDUP_VERTICAL) &&
  649. !(pPDev->dwPageNumber % 2) &&
  650. pPDev->pUIInfo->dwFlags & FLAG_REVERSE_BAND_ORDER)
  651. {
  652. pPDev->rcClipRgn.top = pPDev->sf.szImageAreaG.cy - pPDev->szBand.cy;
  653. pPDev->rcClipRgn.bottom = pPDev->sf.szImageAreaG.cy ;
  654. pPDev->iBandDirection = SW_UP;
  655. }
  656. else
  657. {
  658. pPDev->rcClipRgn.top = 0;
  659. pPDev->rcClipRgn.bottom = pPDev->szBand.cy;
  660. pPDev->iBandDirection = SW_DOWN;
  661. }
  662. }
  663. pptl->x = pPDev->rcClipRgn.left;
  664. pptl->y = pPDev->rcClipRgn.top;
  665. return TRUE;
  666. }
  667. VOID
  668. VEndPage (
  669. PDEV *pPDev
  670. )
  671. /*++
  672. Routine Description:
  673. This function is called when the page has been rendered. Mainly used to
  674. complete the page printing process. Called at DrvSendPage or at
  675. DrvNextBand and no more band to process for the page or at
  676. DrvEndDoc where the job is aborted.
  677. Arguments:
  678. pPDev - Pointer to PDEVICE
  679. Return Value:
  680. None
  681. --*/
  682. {
  683. //
  684. // Eject the page for device that use FF to eject a page, else
  685. // move the cursor to the bottom of the page.
  686. //
  687. if (pPDev->pGlobals->bEjectPageWithFF == TRUE)
  688. {
  689. if ( !(pPDev->bTTY) ||
  690. pPDev->fMode2 & PF2_DRVTEXTOUT_CALLED_FOR_TTY ||
  691. !(pPDev->fMode2 & PF2_PASSTHROUGH_CALLED_FOR_TTY) )
  692. {
  693. WriteChannel(pPDev, COMMANDPTR(pPDev->pDriverInfo, CMD_FORMFEED));
  694. if (pPDev->fMode & PF_RESELECTFONT_AFTER_FF)
  695. {
  696. VResetFont(pPDev);
  697. }
  698. }
  699. }
  700. else
  701. {
  702. //
  703. // Note: sf.szImageAreaG.cx and sf.szImageAreaG.cy are swapped already
  704. // if the page is printed in landscape mode. Need to unswap it
  705. // for moving the cursor to the end of the page
  706. //
  707. INT iYEnd; // Last scan line on page
  708. iYEnd = pPDev->pdm->dmOrientation == DMORIENT_LANDSCAPE ?
  709. pPDev->sf.szImageAreaG.cx : pPDev->sf.szImageAreaG.cy;
  710. YMoveTo(pPDev, iYEnd, MV_GRAPHICS);
  711. }
  712. //
  713. // Send PageFinish sequence Cmds
  714. //
  715. VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwPageFinishIndex);
  716. //
  717. // Reset and and free up realized brush for this page
  718. //
  719. GSResetBrush(pPDev);
  720. GSUnRealizeBrush(pPDev);
  721. FlushSpoolBuf( pPDev );
  722. pPDev->dwPageNumber++ ;
  723. //
  724. // Clear PF2_XXX_TTY flags
  725. //
  726. pPDev->fMode2 &= ~( PF2_DRVTEXTOUT_CALLED_FOR_TTY |
  727. PF2_PASSTHROUGH_CALLED_FOR_TTY );
  728. }
  729. BOOL
  730. BEndDoc (
  731. PDEV *pPDev,
  732. SURFOBJ *pso,
  733. FLONG flags
  734. )
  735. /*++
  736. Routine Description:
  737. This function can be called from two places - DrvEndDoc and DrvStartDoc.
  738. In the case of a DrvResetPDEV, the driver might get another DrvStartDoc
  739. without a DrvEndDoc. So need to check for previous DrvStartDoc and call
  740. VEndDoc to clean up previous instance before initializing the new one.
  741. Arguments:
  742. pPDev - Pointer to PDEVICE
  743. pso - Pointer to surface object
  744. flags - EndDoc flags from DrvEndDoc, zero if called from DrvStartDoc
  745. Return Value:
  746. TRUE for success and FALSE for failure
  747. --*/
  748. {
  749. //
  750. // Call Raster and Font module for cleaning up
  751. //
  752. if (! (((PRMPROCS)(pPDev->pRasterProcs))->RMEndDoc(pso, flags)) ||
  753. ! (((PFMPROCS)(pPDev->pFontProcs))->FMEndDoc(pso, flags)) )
  754. {
  755. return FALSE;
  756. }
  757. //
  758. // If the job is aborted, send the
  759. // PageFinish sequence Cmds (via. VEndPage)
  760. //
  761. if( flags & ED_ABORTDOC )
  762. VEndPage( pPDev);
  763. //
  764. // Send DocFinish, JobFinish sequence Cmds
  765. //
  766. // flag is cleared if called from DrvEndDoc, this is the only time we
  767. // should actually send the EndDoc commands to the printer.
  768. if (!(pPDev->fMode & PF_DOC_SENT))
  769. {
  770. if (pPDev->fMode & PF_DOCSTARTED)
  771. {
  772. VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwDocFinishIndex);
  773. // print state has been forgotten, All start doc commands must be resent.
  774. pPDev->fMode &= ~PF_DOCSTARTED;
  775. }
  776. if (pPDev->fMode & PF_JOB_SENT)
  777. {
  778. VSendSequenceCmd(pPDev, pPDev->pDriverInfo->dwJobFinishIndex);
  779. pPDev->fMode &= ~PF_JOB_SENT;
  780. }
  781. }
  782. FlushSpoolBuf( pPDev );
  783. //
  784. // Clear the PF_DOCSTARTED, PF_FORCE_BANDING,
  785. // PF_ENUM_TEXT, PF_ENUM_GRXTXT, PF_REPLAY_BAND flags
  786. //
  787. pPDev->fMode &= ~PF_FORCE_BANDING;
  788. pPDev->fMode &= ~PF_ENUM_TEXT;
  789. pPDev->fMode &= ~PF_ENUM_GRXTXT;
  790. pPDev->fMode &= ~PF_REPLAY_BAND;
  791. return TRUE;
  792. }
  793. VOID
  794. VSendSequenceCmd(
  795. PDEV *pPDev,
  796. DWORD dwSectionIndex
  797. )
  798. /*++
  799. Routine Description:
  800. This function is called to send a sequence of commands to the printer.
  801. Arguments:
  802. pPDev - Pointer to PDEVICE
  803. dwSectionIndex - specifies the index into the command array
  804. for one of the following seq section.
  805. SS_JOBSETUP,
  806. SS_DOCSETUP,
  807. SS_PAGESETUP,
  808. SS_PAGEFINISH,
  809. SS_DOCFINISH,
  810. SS_JOBFINISH,
  811. Return Value:
  812. None
  813. Note:
  814. There are two types of command supported by the driver:
  815. - Predefined Commands, these commands are predefined in GPD specification
  816. and assigned an COMMAND ID (as enumerated in CMDINDEX).
  817. - Sequence Commands, these commands are not predefined. They are
  818. commands that the GPD writer define to configure commands.
  819. - DT_LOCALLISTNODE is only used to hold a list of sequence commands
  820. --*/
  821. {
  822. LISTNODE *pListNode;
  823. COMMAND *pSeqCmd;
  824. //
  825. // Get the first node in the list
  826. //
  827. pListNode = LOCALLISTNODEPTR(pPDev->pDriverInfo, dwSectionIndex);
  828. while( pListNode )
  829. {
  830. //
  831. // Get pointer to command pointer using pListNode->dwData, which is
  832. // the index into the command array
  833. //
  834. pSeqCmd = INDEXTOCOMMANDPTR(pPDev->pDriverInfo, pListNode->dwData);
  835. //
  836. // Send the sequence command - but only if page ejection is
  837. // not currently suppressed or this command does not
  838. // cause a page to be ejected.
  839. //
  840. if(!(pPDev->fMode & PF_SEND_ONLY_NOEJECT_CMDS) ||
  841. (pSeqCmd->bNoPageEject))
  842. WriteChannel(pPDev, pSeqCmd);
  843. //
  844. // Get the next command in the list or exit if it's the end of list
  845. //
  846. if (pListNode->dwNextItem == END_OF_LIST)
  847. break;
  848. else
  849. pListNode = LOCALLISTNODEPTR(pPDev->pDriverInfo, pListNode->dwNextItem);
  850. }
  851. }
  852. BYTE
  853. BGetMask(
  854. PDEV * pPDev,
  855. RECTL * pRect
  856. )
  857. /*++
  858. Routine Description:
  859. Given a rectangle, calculate the mask for determining the
  860. present of text, for z-ordering fix
  861. Arguments:
  862. pPDev - Pointer to PDEVICE
  863. pRect - Pointer to rectangle defining the clip box for
  864. text or graphics
  865. Return Value:
  866. None
  867. Note:
  868. First mark all columm as dirty then work from the left and the right
  869. to figure out which one should be cleared.
  870. --*/
  871. {
  872. BYTE bMask = 0xFF;
  873. INT i, iRight;
  874. iRight = MAX_COLUMM -1;
  875. if(! (pRect && pPDev->pbScanBuf && pRect->left <= pRect->right) )
  876. return 0;
  877. for (i = 0; i < MAX_COLUMM ; i++)
  878. {
  879. if (pRect->left >= (LONG)(pPDev->dwDelta * (i+1)) )
  880. bMask &= ~(1 << i);
  881. else
  882. break;
  883. }
  884. for (i = iRight; i >= 0; i--)
  885. {
  886. if (pRect->right < (LONG)(pPDev->dwDelta * i ))
  887. bMask &= ~(1 << i);
  888. else
  889. break;
  890. }
  891. return bMask;
  892. }