Source code of Windows XP (NT5)
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.

1548 lines
32 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. enable.c
  5. Abstract:
  6. Implementation of device and surface related DDI entry points:
  7. DrvEnableDriver
  8. DrvDisableDriver
  9. DrvEnablePDEV
  10. DrvResetPDEV
  11. DrvCompletePDEV
  12. DrvDisablePDEV
  13. DrvEnableSurface
  14. DrvDisableSurface
  15. DrvBitBlt
  16. DrvStretchBlt
  17. DrvDitherColor
  18. DrvEscape
  19. Environment:
  20. Fax driver, kernel mode
  21. Revision History:
  22. 01/09/96 -davidx-
  23. Created it.
  24. mm/dd/yy -author-
  25. description
  26. --*/
  27. #include "faxdrv.h"
  28. #include "forms.h"
  29. //
  30. // Our DRVFN table which tells the engine where to find the routines we support.
  31. //
  32. static DRVFN FaxDriverFuncs[] =
  33. {
  34. { INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV },
  35. { INDEX_DrvResetPDEV, (PFN) DrvResetPDEV },
  36. { INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV },
  37. { INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV },
  38. { INDEX_DrvEnableSurface, (PFN) DrvEnableSurface },
  39. { INDEX_DrvDisableSurface, (PFN) DrvDisableSurface },
  40. { INDEX_DrvStartDoc, (PFN) DrvStartDoc },
  41. { INDEX_DrvEndDoc, (PFN) DrvEndDoc },
  42. { INDEX_DrvStartPage, (PFN) DrvStartPage },
  43. { INDEX_DrvSendPage, (PFN) DrvSendPage },
  44. { INDEX_DrvBitBlt, (PFN) DrvBitBlt },
  45. { INDEX_DrvStretchBlt, (PFN) DrvStretchBlt },
  46. { INDEX_DrvCopyBits, (PFN) DrvCopyBits },
  47. { INDEX_DrvDitherColor, (PFN) DrvDitherColor },
  48. { INDEX_DrvEscape, (PFN) DrvEscape },
  49. };
  50. //
  51. // Forward declaration of local functions
  52. //
  53. VOID SelectPrinterForm(PDEVDATA);
  54. BOOL FillDevInfo(PDEVDATA, ULONG, PVOID);
  55. BOOL FillGdiInfo(PDEVDATA, ULONG, PVOID);
  56. VOID FreeDevData(PDEVDATA);
  57. HINSTANCE ghInstance;
  58. BOOL
  59. DllEntryPoint(
  60. HANDLE hModule,
  61. ULONG ulReason,
  62. PCONTEXT pContext
  63. )
  64. /*++
  65. Routine Description:
  66. DLL initialization procedure.
  67. Arguments:
  68. hModule - DLL instance handle
  69. ulReason - Reason for the call
  70. pContext - Pointer to context (not used by us)
  71. Return Value:
  72. TRUE if DLL is initialized successfully, FALSE otherwise.
  73. --*/
  74. {
  75. switch (ulReason)
  76. {
  77. case DLL_PROCESS_ATTACH:
  78. ghInstance = hModule;
  79. break;
  80. case DLL_PROCESS_DETACH:
  81. break;
  82. }
  83. return TRUE;
  84. }
  85. BOOL
  86. DrvQueryDriverInfo(
  87. DWORD dwMode,
  88. PVOID pBuffer,
  89. DWORD cbBuf,
  90. PDWORD pcbNeeded
  91. )
  92. /*++
  93. Routine Description:
  94. Query driver information
  95. Arguments:
  96. dwMode - Specify the information being queried
  97. pBuffer - Points to output buffer
  98. cbBuf - Size of output buffer in bytes
  99. pcbNeeded - Return the expected size of output buffer
  100. Return Value:
  101. TRUE if successful, FALSE if there is an error
  102. --*/
  103. {
  104. switch (dwMode)
  105. {
  106. case DRVQUERY_USERMODE:
  107. Assert(pcbNeeded != NULL);
  108. *pcbNeeded = sizeof(DWORD);
  109. if (pBuffer == NULL || cbBuf < sizeof(DWORD))
  110. {
  111. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  112. return FALSE;
  113. }
  114. *((PDWORD) pBuffer) = TRUE;
  115. return TRUE;
  116. default:
  117. Error(("Unknown dwMode in DrvQueryDriverInfo: %d\n", dwMode));
  118. SetLastError(ERROR_INVALID_PARAMETER);
  119. return FALSE;
  120. }
  121. }
  122. BOOL
  123. DrvEnableDriver(
  124. ULONG iEngineVersion,
  125. ULONG cb,
  126. PDRVENABLEDATA pDrvEnableData
  127. )
  128. /*++
  129. Routine Description:
  130. Implementation of DDI entry point DrvEnableDriver.
  131. Please refer to DDK documentation for more details.
  132. Arguments:
  133. iEngineVersion - Specifies the DDI version number that GDI is written for
  134. cb - Size of the buffer pointed to by pDrvEnableData
  135. pDrvEnableData - Points to an DRVENABLEDATA structure
  136. Return Value:
  137. TRUE if successful, FALSE if there is an error
  138. --*/
  139. {
  140. Verbose(("Entering DrvEnableDriver...\n"));
  141. //
  142. // Make sure we have a valid engine version and
  143. // we're given enough room for the DRVENABLEDATA.
  144. //
  145. if (iEngineVersion < DDI_DRIVER_VERSION || cb < sizeof(DRVENABLEDATA)) {
  146. Error(("DrvEnableDriver failed\n"));
  147. SetLastError(ERROR_BAD_DRIVER_LEVEL);
  148. return FALSE;
  149. }
  150. //
  151. // Fill in the DRVENABLEDATA structure for the engine.
  152. //
  153. pDrvEnableData->iDriverVersion = DDI_DRIVER_VERSION;
  154. pDrvEnableData->c = sizeof(FaxDriverFuncs) / sizeof(DRVFN);
  155. pDrvEnableData->pdrvfn = FaxDriverFuncs;
  156. return TRUE;
  157. }
  158. DHPDEV
  159. DrvEnablePDEV(
  160. PDEVMODE pdm,
  161. PWSTR pLogAddress,
  162. ULONG cPatterns,
  163. HSURF *phsurfPatterns,
  164. ULONG cjGdiInfo,
  165. ULONG *pGdiInfo,
  166. ULONG cjDevInfo,
  167. DEVINFO *pDevInfo,
  168. HDEV hdev,
  169. PWSTR pDeviceName,
  170. HANDLE hPrinter
  171. )
  172. /*++
  173. Routine Description:
  174. Implementation of DDI entry point DrvEnablePDEV.
  175. Please refer to DDK documentation for more details.
  176. Arguments:
  177. pdm - Points to a DEVMODE structure that contains driver data
  178. pLogAddress - Points to the logical address string
  179. cPatterns - Specifies the number of standard patterns
  180. phsurfPatterns - Buffer to hold surface handles to standard patterns
  181. cjGdiInfo - Size of GDIINFO buffer
  182. pGdiInfo - Points to a GDIINFO structure
  183. cjDevInfo - Size of DEVINFO buffer
  184. pDevInfo - Points to a DEVINFO structure
  185. hdev - GDI device handle
  186. pDeviceName - Points to device name string
  187. hPrinter - Spooler printer handle
  188. Return Value:
  189. Driver device handle, NULL if there is an error
  190. --*/
  191. {
  192. PDEVDATA pdev;
  193. Verbose(("Entering DrvEnablePDEV...\n"));
  194. //
  195. // Allocate memory for our DEVDATA structure and initialize it
  196. //
  197. if (! (pdev = MemAllocZ(sizeof(DEVDATA)))) {
  198. Error(("Memory allocation failed\n"));
  199. return NULL;
  200. }
  201. pdev->hPrinter = hPrinter;
  202. pdev->startDevData = pdev;
  203. pdev->endDevData = pdev;
  204. //
  205. // Save and validate DEVMODE information
  206. // start with the driver default
  207. // then merge with the system default
  208. // finally merge with the input devmode
  209. //
  210. if (CurrentVersionDevmode(pdm)) {
  211. memcpy(&pdev->dm, pdm, sizeof(DRVDEVMODE));
  212. //
  213. // NOTE: We now use dmPrintQuality and dmYResolution fields
  214. // to store the resolution measured in dots-per-inch. Add
  215. // the following check as a safety precaution in case older
  216. // DEVMODE is passed to us.
  217. //
  218. if (pdev->dm.dmPublic.dmPrintQuality <= 0 ||
  219. pdev->dm.dmPublic.dmYResolution <= 0)
  220. {
  221. pdev->dm.dmPublic.dmPrintQuality = FAXRES_HORIZONTAL;
  222. pdev->dm.dmPublic.dmYResolution = FAXRES_VERTICAL;
  223. }
  224. } else {
  225. Error(("Bad DEVMODE passed to DrvEnablePDEV\n"));
  226. DriverDefaultDevmode(&pdev->dm, NULL, hPrinter);
  227. }
  228. //
  229. // Calculate the paper size information
  230. //
  231. SelectPrinterForm(pdev);
  232. //
  233. // Fill out GDIINFO and DEVINFO structure
  234. //
  235. if (! FillGdiInfo(pdev, cjGdiInfo, pGdiInfo) ||
  236. ! FillDevInfo(pdev, cjDevInfo, pDevInfo))
  237. {
  238. FreeDevData(pdev);
  239. return NULL;
  240. }
  241. //
  242. // Zero out the array of HSURF's so that the engine will
  243. // automatically simulate the standard patterns for us
  244. //
  245. memset(phsurfPatterns, 0, sizeof(HSURF) * cPatterns);
  246. //
  247. // Return a pointer to our DEVDATA structure
  248. //
  249. return (DHPDEV) pdev;
  250. }
  251. BOOL
  252. DrvResetPDEV(
  253. DHPDEV dhpdevOld,
  254. DHPDEV dhpdevNew
  255. )
  256. /*++
  257. Routine Description:
  258. Implementation of DDI entry point DrvResetPDEV.
  259. Please refer to DDK documentation for more details.
  260. Arguments:
  261. phpdevOld - Driver handle to the old device
  262. phpdevNew - Driver handle to the new device
  263. Return Value:
  264. TRUE if successful, FALSE if there is an error
  265. --*/
  266. {
  267. PDEVDATA pdevOld, pdevNew;
  268. Verbose(("Entering DrvResetPDEV...\n"));
  269. //
  270. // Validate both old and new device
  271. //
  272. pdevOld = (PDEVDATA) dhpdevOld;
  273. pdevNew = (PDEVDATA) dhpdevNew;
  274. if (! ValidDevData(pdevOld) || ! ValidDevData(pdevNew)) {
  275. Error(("ValidDevData failed\n"));
  276. SetLastError(ERROR_INVALID_PARAMETER);
  277. return FALSE;
  278. }
  279. Verbose(("Entering DrvResetPDEV...\n"));
  280. //
  281. // Transfer information from old device to new device
  282. //
  283. if (pdevOld->pageCount != 0) {
  284. pdevNew->pageCount = pdevOld->pageCount;
  285. pdevNew->flags |= PDEV_RESETPDEV;
  286. pdevNew->fileOffset = pdevOld->fileOffset;
  287. if (pdevOld->pFaxIFD) {
  288. pdevNew->pFaxIFD = pdevOld->pFaxIFD;
  289. pdevOld->pFaxIFD = NULL;
  290. }
  291. }
  292. //
  293. // Carry over relevant flag bits
  294. //
  295. pdevNew->flags |= pdevOld->flags & PDEV_CANCELLED;
  296. return TRUE;
  297. }
  298. VOID
  299. DrvCompletePDEV(
  300. DHPDEV dhpdev,
  301. HDEV hdev
  302. )
  303. /*++
  304. Routine Description:
  305. Implementation of DDI entry point DrvCompletePDEV.
  306. Please refer to DDK documentation for more details.
  307. Arguments:
  308. dhpdev - Driver device handle
  309. hdev - GDI device handle
  310. Return Value:
  311. NONE
  312. --*/
  313. {
  314. PDEVDATA pdev = (PDEVDATA) dhpdev;
  315. Verbose(("Entering DrvCompletePDEV...\n"));
  316. if (! ValidDevData(pdev)) {
  317. Assert(FALSE);
  318. return;
  319. }
  320. //
  321. // Remember the engine's handle to the physical device
  322. //
  323. pdev->hdev = hdev;
  324. }
  325. HSURF
  326. DrvEnableSurface(
  327. DHPDEV dhpdev
  328. )
  329. /*++
  330. Routine Description:
  331. Implementation of DDI entry point DrvEnableSurface.
  332. Please refer to DDK documentation for more details.
  333. Arguments:
  334. dhpdev - Driver device handle
  335. Return Value:
  336. Handle to newly created surface, NULL if there is an error
  337. --*/
  338. {
  339. PDEVDATA pdev = (PDEVDATA) dhpdev;
  340. FLONG flHooks;
  341. Verbose(("Entering DrvEnableSurface...\n"));
  342. //
  343. // Validate the pointer to our DEVDATA structure
  344. //
  345. if (! ValidDevData(pdev)) {
  346. Error(("ValidDevData failed\n"));
  347. SetLastError(ERROR_INVALID_PARAMETER);
  348. return NULL;
  349. }
  350. //
  351. // Adjust the bitmap size so that we always end up with 1728 pixels per scanline
  352. //
  353. Assert(MAX_WIDTH_PIXELS % DWORDBITS == 0);
  354. if (IsLandscapeMode(pdev)) {
  355. Assert(pdev->imageSize.cy <= MAX_WIDTH_PIXELS);
  356. pdev->imageSize.cy = MAX_WIDTH_PIXELS;
  357. pdev->imageSize.cx = ((pdev->imageSize.cx + (BYTEBITS - 1)) / BYTEBITS) * BYTEBITS;
  358. } else {
  359. Assert(pdev->imageSize.cx <= MAX_WIDTH_PIXELS);
  360. pdev->imageSize.cx = MAX_WIDTH_PIXELS;
  361. }
  362. pdev->lineOffset = PadBitsToBytes(pdev->imageSize.cx, sizeof(DWORD));
  363. //
  364. // Call the engine to create a standard bitmap surface for us
  365. //
  366. pdev->hbitmap = (HSURF) EngCreateBitmap(pdev->imageSize,
  367. pdev->lineOffset,
  368. BMF_1BPP,
  369. BMF_TOPDOWN | BMF_NOZEROINIT | BMF_USERMEM,
  370. NULL);
  371. if (pdev->hbitmap == NULL) {
  372. Error(("EngCreateBitmap failed\n"));
  373. return NULL;
  374. }
  375. //
  376. // Associate the surface with the device and inform the
  377. // engine which functions we have hooked out
  378. //
  379. if (pdev->dm.dmPrivate.flags & FAXDM_NO_HALFTONE)
  380. flHooks = 0;
  381. else
  382. flHooks = (HOOK_STRETCHBLT | HOOK_BITBLT | HOOK_COPYBITS);
  383. EngAssociateSurface(pdev->hbitmap, pdev->hdev, flHooks);
  384. //
  385. // Return the surface handle to the engine
  386. //
  387. return pdev->hbitmap;
  388. }
  389. VOID
  390. DrvDisableSurface(
  391. DHPDEV dhpdev
  392. )
  393. /*++
  394. Routine Description:
  395. Implementation of DDI entry point DrvDisableSurface.
  396. Please refer to DDK documentation for more details.
  397. Arguments:
  398. dhpdev - Driver device handle
  399. Return Value:
  400. NONE
  401. --*/
  402. {
  403. PDEVDATA pdev = (PDEVDATA) dhpdev;
  404. Verbose(("Entering DrvDisableSurface...\n"));
  405. if (! ValidDevData(pdev)) {
  406. Assert(FALSE);
  407. return;
  408. }
  409. //
  410. // Call the engine to delete the surface handle
  411. //
  412. if (pdev->hbitmap != NULL) {
  413. EngDeleteSurface(pdev->hbitmap);
  414. pdev->hbitmap = NULL;
  415. }
  416. }
  417. VOID
  418. DrvDisablePDEV(
  419. DHPDEV dhpdev
  420. )
  421. /*++
  422. Routine Description:
  423. Implementation of DDI entry point DrvDisablePDEV.
  424. Please refer to DDK documentation for more details.
  425. Arguments:
  426. dhpdev - Driver device handle
  427. Return Value:
  428. NONE
  429. --*/
  430. {
  431. PDEVDATA pdev = (PDEVDATA) dhpdev;
  432. Verbose(("Entering DrvDisablePDEV...\n"));
  433. if (! ValidDevData(pdev)) {
  434. Assert(FALSE);
  435. return;
  436. }
  437. //
  438. // Free up memory allocated for the current PDEV
  439. //
  440. FreeDevData(pdev);
  441. }
  442. VOID
  443. DrvDisableDriver(
  444. VOID
  445. )
  446. /*++
  447. Routine Description:
  448. Implementation of DDI entry point DrvDisableDriver.
  449. Please refer to DDK documentation for more details.
  450. Arguments:
  451. NONE
  452. Return Value:
  453. NONE
  454. --*/
  455. {
  456. Verbose(("Entering DrvDisableDriver...\n"));
  457. }
  458. BOOL
  459. IsCompatibleSurface(
  460. SURFOBJ *psoDst,
  461. SURFOBJ *psoSrc,
  462. XLATEOBJ *pxlo
  463. )
  464. /*++
  465. Routine Description:
  466. Check if the source surface is compatible with the destination surface
  467. i.e. we can bitblt without halftonig
  468. Arguments:
  469. psoDst - Specifies the destination surface
  470. psoSrc - Specifies the source surface
  471. pxlo - How to transform colors between the source surface and the destination surface
  472. Return Value:
  473. TRUE if the source surface is compatible with the destination surface
  474. FALSE otherwise
  475. --*/
  476. {
  477. BOOL result;
  478. //
  479. // We know our destination surface is always 1bpp
  480. //
  481. Assert(psoDst->iBitmapFormat == BMF_1BPP);
  482. //
  483. // Check whether the transformation is trivial
  484. //
  485. if (!pxlo || (pxlo->flXlate & XO_TRIVIAL)) {
  486. result = (psoSrc->iBitmapFormat == psoDst->iBitmapFormat);
  487. } else if ((pxlo->flXlate & XO_TABLE) && pxlo->cEntries <= 2) {
  488. ULONG srcPalette[2];
  489. srcPalette[0] = srcPalette[1] = RGB_BLACK;
  490. XLATEOBJ_cGetPalette(pxlo, XO_SRCPALETTE, pxlo->cEntries, srcPalette);
  491. result = (srcPalette[0] == RGB_BLACK || srcPalette[0] == RGB_WHITE) &&
  492. (srcPalette[1] == RGB_BLACK || srcPalette[1] == RGB_WHITE);
  493. } else
  494. result = FALSE;
  495. return result;
  496. }
  497. BOOL
  498. DrvCopyBits(
  499. SURFOBJ *psoTrg,
  500. SURFOBJ *psoSrc,
  501. CLIPOBJ *pco,
  502. XLATEOBJ *pxlo,
  503. RECTL *prclDst,
  504. POINTL *pptlSrc
  505. )
  506. /*++
  507. Routine Description:
  508. Implementation of DDI entry point DrvCopyBits.
  509. We need to hook out this function. Otherwise bitmaps won't be halftoned.
  510. Arguments:
  511. Please refer to DDK documentation for more details.
  512. Return Value:
  513. TRUE if successful, FALSE otherwise
  514. --*/
  515. {
  516. Verbose(("Entering DrvCopyBits ...\n"));
  517. //
  518. // Check if halftoning is necessary
  519. // If not, let the engine handle it
  520. //
  521. if ((psoSrc->iType != STYPE_BITMAP) ||
  522. (psoTrg->iType != STYPE_BITMAP) ||
  523. IsCompatibleSurface(psoTrg, psoSrc, pxlo))
  524. {
  525. return EngCopyBits(psoTrg, psoSrc, pco, pxlo, prclDst, pptlSrc);
  526. }
  527. else
  528. {
  529. POINTL ptlBrushOrg;
  530. RECTL rclDst, rclSrc;
  531. ptlBrushOrg.x = ptlBrushOrg.y = 0;
  532. rclDst = *prclDst;
  533. rclSrc.left = pptlSrc->x;
  534. rclSrc.top = pptlSrc->y;
  535. rclSrc.right = rclSrc.left + (rclDst.right - rclDst.left);
  536. rclSrc.bottom = rclSrc.top + (rclDst.bottom - rclDst.top);
  537. if ((rclSrc.right > psoSrc->sizlBitmap.cx) ||
  538. (rclSrc.bottom > psoSrc->sizlBitmap.cy))
  539. {
  540. rclSrc.right = psoSrc->sizlBitmap.cx;
  541. rclSrc.bottom = psoSrc->sizlBitmap.cy;
  542. rclDst.right = rclDst.left + (rclSrc.right - rclSrc.left);
  543. rclDst.bottom = rclDst.top + (rclSrc.bottom - rclSrc.top);
  544. }
  545. return EngStretchBlt(psoTrg,
  546. psoSrc,
  547. NULL,
  548. pco,
  549. pxlo,
  550. &DefHTClrAdj,
  551. &ptlBrushOrg,
  552. &rclDst,
  553. &rclSrc,
  554. NULL,
  555. HALFTONE);
  556. }
  557. }
  558. BOOL
  559. DrvBitBlt(
  560. SURFOBJ *psoTrg,
  561. SURFOBJ *psoSrc,
  562. SURFOBJ *psoMask,
  563. CLIPOBJ *pco,
  564. XLATEOBJ *pxlo,
  565. RECTL *prclTrg,
  566. POINTL *pptlSrc,
  567. POINTL *pptlMask,
  568. BRUSHOBJ *pbo,
  569. POINTL *pptlBrush,
  570. ROP4 rop4
  571. )
  572. /*++
  573. Routine Description:
  574. Implementation of DDI entry point DrvBitBlt.
  575. We need to hook out this function. Otherwise bitmaps won't be halftoned.
  576. Arguments:
  577. Please refer to DDK documentation for more details.
  578. Return Value:
  579. TRUE if successful, FALSE otherwise
  580. --*/
  581. {
  582. COLORADJUSTMENT *pca;
  583. PDEVDATA pdev;
  584. DWORD rop3Foreground, rop3Background;
  585. SURFOBJ *psoNewSrc;
  586. HBITMAP hbmpNewSrc;
  587. POINTL brushOrg;
  588. BOOL result;
  589. Verbose(("Entering DrvBitBlt...\n"));
  590. //
  591. // Validate input parameters
  592. //
  593. Assert(psoTrg != NULL);
  594. pdev = (PDEVDATA) psoTrg->dhpdev;
  595. if (! ValidDevData(pdev)) {
  596. Error(("ValidDevData failed\n"));
  597. SetLastError(ERROR_INVALID_PARAMETER);
  598. return FALSE;
  599. }
  600. //
  601. // Use the system default color adjustment information
  602. //
  603. pca = &DefHTClrAdj;
  604. //
  605. // Figure out the foreground and background ROP3
  606. //
  607. psoNewSrc = NULL;
  608. hbmpNewSrc = NULL;
  609. rop3Foreground = GetForegroundRop3(rop4);
  610. rop3Background = GetBackgroundRop3(rop4);
  611. if ((Rop3NeedPattern(rop3Foreground) || Rop3NeedPattern(rop3Background)) && pptlBrush) {
  612. brushOrg = *pptlBrush;
  613. } else {
  614. brushOrg.x = brushOrg.y = 0;
  615. }
  616. //
  617. // If a source bitmap is involved in the raster operation and
  618. // the source is not compatible with the destination surface,
  619. // then we'll halftone the source bitmap into a new bitmap and
  620. // bitblt the new bitmap onto the destination surface.
  621. //
  622. if ((Rop3NeedSource(rop3Foreground) || Rop3NeedSource(rop3Background)) &&
  623. !IsCompatibleSurface(psoTrg, psoSrc, pxlo))
  624. {
  625. RECTL rclNewSrc, rclOldSrc;
  626. SIZEL bmpSize;
  627. LONG lDelta;
  628. rclNewSrc.left = rclNewSrc.top = 0;
  629. rclNewSrc.right = prclTrg->right - prclTrg->left;
  630. rclNewSrc.bottom = prclTrg->bottom - prclTrg->top;
  631. rclOldSrc.left = pptlSrc->x;
  632. rclOldSrc.top = pptlSrc->y;
  633. rclOldSrc.right = rclOldSrc.left + rclNewSrc.right;
  634. rclOldSrc.bottom = rclOldSrc.top + rclNewSrc.bottom;
  635. //
  636. // Express path for the most common case: SRCCOPY
  637. //
  638. if (rop4 == 0xcccc) {
  639. return EngStretchBlt(psoTrg,
  640. psoSrc,
  641. psoMask,
  642. pco,
  643. pxlo,
  644. pca,
  645. &brushOrg,
  646. prclTrg,
  647. &rclOldSrc,
  648. pptlMask,
  649. HALFTONE);
  650. }
  651. //
  652. // Modify the brush origin, because when we blt to the clipped bitmap
  653. // the origin is at bitmap's (0, 0) minus the original location
  654. //
  655. brushOrg.x -= prclTrg->left;
  656. brushOrg.y -= prclTrg->top;
  657. //
  658. // Create a temporary bitmap surface
  659. // Halftone the source bitmap into the temporary bitmap
  660. //
  661. Assert(psoTrg->iBitmapFormat == BMF_1BPP);
  662. bmpSize.cx = rclNewSrc.right;
  663. bmpSize.cy = rclNewSrc.bottom;
  664. lDelta = PadBitsToBytes(bmpSize.cx, sizeof(DWORD));
  665. if (! (hbmpNewSrc = EngCreateBitmap(bmpSize,
  666. lDelta,
  667. BMF_1BPP,
  668. BMF_TOPDOWN | BMF_NOZEROINIT,
  669. NULL)) ||
  670. ! EngAssociateSurface((HSURF) hbmpNewSrc, pdev->hdev, 0) ||
  671. ! (psoNewSrc = EngLockSurface((HSURF) hbmpNewSrc)) ||
  672. ! EngStretchBlt(psoNewSrc,
  673. psoSrc,
  674. NULL,
  675. NULL,
  676. pxlo,
  677. pca,
  678. &brushOrg,
  679. &rclNewSrc,
  680. &rclOldSrc,
  681. NULL,
  682. HALFTONE))
  683. {
  684. if (psoNewSrc)
  685. EngUnlockSurface(psoNewSrc);
  686. if (hbmpNewSrc)
  687. EngDeleteSurface((HSURF) hbmpNewSrc);
  688. return FALSE;
  689. }
  690. //
  691. // Proceed to bitblt from the temporary bitmap to the destination
  692. //
  693. psoSrc = psoNewSrc;
  694. pptlSrc = (PPOINTL) &rclNewSrc.left;
  695. pxlo = NULL;
  696. brushOrg.x = brushOrg.y = 0;
  697. }
  698. //
  699. // Let engine do the work
  700. //
  701. result = EngBitBlt(psoTrg,
  702. psoSrc,
  703. psoMask,
  704. pco,
  705. pxlo,
  706. prclTrg,
  707. pptlSrc,
  708. pptlMask,
  709. pbo,
  710. &brushOrg,
  711. rop4);
  712. //
  713. // Clean up properly before returning
  714. //
  715. if (psoNewSrc)
  716. EngUnlockSurface(psoNewSrc);
  717. if (hbmpNewSrc)
  718. EngDeleteSurface((HSURF) hbmpNewSrc);
  719. return result;
  720. }
  721. BOOL
  722. DrvStretchBlt(
  723. SURFOBJ *psoDest,
  724. SURFOBJ *psoSrc,
  725. SURFOBJ *psoMask,
  726. CLIPOBJ *pco,
  727. XLATEOBJ *pxlo,
  728. COLORADJUSTMENT *pca,
  729. POINTL *pptlBrushOrg,
  730. RECTL *prclDest,
  731. RECTL *prclSrc,
  732. POINTL *pptlMask,
  733. ULONG iMode
  734. )
  735. /*++
  736. Routine Description:
  737. Implementation of DDI entry point DrvDisableDriver.
  738. We need to hook out this function. Otherwise bitmaps won't be halftoned.
  739. Arguments:
  740. Please refer to DDK documentation for more details.
  741. Return Value:
  742. TRUE if successful, FALSE if there is an error
  743. --*/
  744. {
  745. Verbose(("Entering DrvStretchBlt...\n"));
  746. //
  747. // If no color adjustment information is provided, use the system default
  748. //
  749. if (pca == NULL)
  750. pca = &DefHTClrAdj;
  751. //
  752. // Let engine do the work; make sure halftone is enabled
  753. //
  754. return EngStretchBlt(psoDest,
  755. psoSrc,
  756. psoMask,
  757. pco,
  758. pxlo,
  759. pca,
  760. pptlBrushOrg,
  761. prclDest,
  762. prclSrc,
  763. pptlMask,
  764. HALFTONE);
  765. }
  766. ULONG
  767. DrvDitherColor(
  768. DHPDEV dhpdev,
  769. ULONG iMode,
  770. ULONG rgb,
  771. ULONG *pul
  772. )
  773. /*++
  774. Routine Description:
  775. Implementation of DDI entry point DrvDisableDriver.
  776. Please refer to DDK documentation for more details.
  777. Arguments:
  778. dhpdev - Driver device handle
  779. iMode - Determines the palette to dither against
  780. rgb - Specifies the RGB color that is to be dithered
  781. pul - Points to a memory location in which the dithering information is to be recorded
  782. Return Value:
  783. DCR_HALFTONE to indicate that the engine should create a halftone
  784. approximation for the driver.
  785. --*/
  786. {
  787. return DCR_HALFTONE;
  788. }
  789. BOOL
  790. FillDevInfo(
  791. PDEVDATA pdev,
  792. ULONG cb,
  793. PVOID pdevinfo
  794. )
  795. /*++
  796. Routine Description:
  797. Fill in the DEVINFO structure pointed to by pdevinfo.
  798. Arguments:
  799. pdev - Pointer to our DEVDATA structure
  800. cb - Size of structure pointed to by pdevinfo
  801. pdevinfo - Pointer to DEVINFO structure
  802. [Notes:]
  803. Since we have to worry about not writing out more than cb bytes to
  804. pdevinfo, we will first fill in a local buffer, then copy cb bytes
  805. to pdevinfo.
  806. Return Value:
  807. TRUE if successful. FALSE otherwise.
  808. --*/
  809. {
  810. static ULONG paletteColors[2] = {
  811. RGB_BLACK,
  812. RGB_WHITE,
  813. };
  814. DEVINFO devinfo;
  815. memset(&devinfo, 0, sizeof(devinfo));
  816. //
  817. // Fill in the graphics capabilities flags: we let the engine
  818. // do almost everything. Also, we have to tell the engine not
  819. // to do metafile spooling because we hook out DrvDocumentEvent.
  820. //
  821. devinfo.flGraphicsCaps = GCAPS_HALFTONE |
  822. GCAPS_MONO_DITHER |
  823. GCAPS_COLOR_DITHER |
  824. GCAPS_DONTJOURNAL;
  825. //
  826. // No device fonts
  827. //
  828. devinfo.cFonts = 0;
  829. //
  830. // Black and white palette: entry 0 is black and entry 1 is white
  831. //
  832. if (! (pdev->hpal = EngCreatePalette(PAL_INDEXED, 2, paletteColors, 0, 0, 0))) {
  833. Error(("EngCreatePalette failed\n"));
  834. return FALSE;
  835. }
  836. devinfo.hpalDefault = pdev->hpal;
  837. devinfo.iDitherFormat = BMF_1BPP;
  838. devinfo.cxDither = devinfo.cyDither = 4;
  839. //
  840. // Copy cb bytes from devinfo structure into the caller-provided buffer
  841. //
  842. if (cb > sizeof(devinfo))
  843. {
  844. memset(pdevinfo, 0, cb);
  845. memcpy(pdevinfo, &devinfo, sizeof(devinfo));
  846. }
  847. else
  848. memcpy(pdevinfo, &devinfo, cb);
  849. return TRUE;
  850. }
  851. BOOL
  852. FillGdiInfo(
  853. PDEVDATA pdev,
  854. ULONG cb,
  855. PVOID pgdiinfo
  856. )
  857. /*++
  858. Routine Description:
  859. Fill in the device capabilities information for the engine.
  860. Arguments:
  861. pdev - Pointer to DEVDATA structure
  862. cb - Size of buffer pointed to by pgdiinfo
  863. pgdiinfo - Pointer to a GDIINFO buffer
  864. Return Value:
  865. NONE
  866. --*/
  867. {
  868. GDIINFO gdiinfo;
  869. LONG maxRes;
  870. memset(&gdiinfo, 0, sizeof(gdiinfo));
  871. //
  872. // This field doesn't seem to have any effect for printer drivers.
  873. // Put our driver version number in there anyway.
  874. //
  875. gdiinfo.ulVersion = DRIVER_VERSION;
  876. //
  877. // We're raster printers
  878. //
  879. gdiinfo.ulTechnology = DT_RASPRINTER;
  880. //
  881. // Width and height of the imageable area measured in microns.
  882. // Remember to turn on the sign bit.
  883. //
  884. gdiinfo.ulHorzSize = - (pdev->imageArea.right - pdev->imageArea.left);
  885. gdiinfo.ulVertSize = - (pdev->imageArea.bottom - pdev->imageArea.top);
  886. //
  887. // Convert paper size and imageable area from microns to pixels
  888. //
  889. pdev->paperSize.cx = MicronToPixel(pdev->paperSize.cx, pdev->xres);
  890. pdev->paperSize.cy = MicronToPixel(pdev->paperSize.cy, pdev->yres);
  891. pdev->imageArea.left = MicronToPixel(pdev->imageArea.left, pdev->xres);
  892. pdev->imageArea.right = MicronToPixel(pdev->imageArea.right, pdev->xres);
  893. pdev->imageArea.top = MicronToPixel(pdev->imageArea.top, pdev->yres);
  894. pdev->imageArea.bottom = MicronToPixel(pdev->imageArea.bottom, pdev->yres);
  895. pdev->imageSize.cx = pdev->imageArea.right - pdev->imageArea.left;
  896. pdev->imageSize.cy = pdev->imageArea.bottom - pdev->imageArea.top;
  897. //
  898. // Width and height of the imageable area measured in device pixels
  899. //
  900. gdiinfo.ulHorzRes = pdev->imageSize.cx;
  901. gdiinfo.ulVertRes = pdev->imageSize.cy;
  902. //
  903. // Color depth information
  904. //
  905. gdiinfo.cBitsPixel = 1;
  906. gdiinfo.cPlanes = 1;
  907. gdiinfo.ulNumColors = 2;
  908. //
  909. // Resolution information
  910. //
  911. gdiinfo.ulLogPixelsX = pdev->xres;
  912. gdiinfo.ulLogPixelsY = pdev->yres;
  913. //
  914. // Win31 compatible text capability flags. Are they still used by anyone?
  915. //
  916. gdiinfo.flTextCaps = 0;
  917. //
  918. // Device pixel aspect ratio
  919. //
  920. gdiinfo.ulAspectX = pdev->yres;
  921. gdiinfo.ulAspectY = pdev->xres;
  922. gdiinfo.ulAspectXY = CalcHypot(pdev->xres, pdev->yres);
  923. //
  924. // Dotted line appears to be approximately 25dpi
  925. // We assume either xres is a multiple of yres or yres is a multiple of xres
  926. //
  927. maxRes = max(pdev->xres, pdev->yres);
  928. Assert((maxRes % pdev->xres) == 0 && (maxRes % pdev->yres == 0));
  929. gdiinfo.xStyleStep = maxRes / pdev->xres;
  930. gdiinfo.yStyleStep = maxRes / pdev->yres;
  931. gdiinfo.denStyleStep = maxRes / 25;
  932. //
  933. // Size and margins of physical surface measured in device pixels
  934. //
  935. gdiinfo.szlPhysSize.cx = pdev->paperSize.cx;
  936. gdiinfo.szlPhysSize.cy = pdev->paperSize.cy;
  937. gdiinfo.ptlPhysOffset.x = pdev->imageArea.left;
  938. gdiinfo.ptlPhysOffset.y = pdev->imageArea.top;
  939. //
  940. // Use default halftone information
  941. //
  942. gdiinfo.ciDevice = DefDevHTInfo.ColorInfo;
  943. gdiinfo.ulDevicePelsDPI = max(pdev->xres, pdev->yres);
  944. gdiinfo.ulPrimaryOrder = PRIMARY_ORDER_CBA;
  945. gdiinfo.ulHTOutputFormat = HT_FORMAT_1BPP;
  946. gdiinfo.flHTFlags = HT_FLAG_HAS_BLACK_DYE;
  947. gdiinfo.ulHTPatternSize = HT_PATSIZE_4x4_M;
  948. //
  949. // Copy cb byte from gdiinfo structure into the caller-provided buffer
  950. //
  951. if (cb > sizeof(gdiinfo))
  952. {
  953. memset(pgdiinfo, 0, cb);
  954. memcpy(pgdiinfo, &gdiinfo, sizeof(gdiinfo));
  955. }
  956. else
  957. memcpy(pgdiinfo, &gdiinfo, cb);
  958. return TRUE;
  959. }
  960. VOID
  961. FreeDevData(
  962. PDEVDATA pdev
  963. )
  964. /*++
  965. Routine Description:
  966. Free up all memory associated with the specified PDEV
  967. Arguments:
  968. pdev Pointer to our DEVDATA structure
  969. Return Value:
  970. NONE
  971. --*/
  972. {
  973. if (pdev->hpal)
  974. EngDeletePalette(pdev->hpal);
  975. MemFree(pdev->pFaxIFD);
  976. MemFree(pdev);
  977. }
  978. VOID
  979. SelectPrinterForm(
  980. PDEVDATA pdev
  981. )
  982. /*++
  983. Routine Description:
  984. Store printer paper size information in our DEVDATA structure
  985. Arguments:
  986. pdev - Pointer to our DEVDATA structure
  987. Return Value:
  988. NONE
  989. --*/
  990. {
  991. FORM_INFO_1 formInfo;
  992. //
  993. // Validate devmode form specification; use default form if it's invalid.
  994. //
  995. if (! ValidDevmodeForm(pdev->hPrinter, &pdev->dm.dmPublic, &formInfo)) {
  996. memset(&formInfo, 0, sizeof(formInfo));
  997. //
  998. // Default to A4 paper
  999. //
  1000. formInfo.Size.cx = formInfo.ImageableArea.right = A4_WIDTH;
  1001. formInfo.Size.cy = formInfo.ImageableArea.bottom = A4_HEIGHT;
  1002. }
  1003. Assert(formInfo.Size.cx > 0 && formInfo.Size.cy > 0);
  1004. Assert(formInfo.ImageableArea.left >= 0 &&
  1005. formInfo.ImageableArea.top >= 0 &&
  1006. formInfo.ImageableArea.left < formInfo.ImageableArea.right &&
  1007. formInfo.ImageableArea.top < formInfo.ImageableArea.bottom &&
  1008. formInfo.ImageableArea.right <= formInfo.Size.cx &&
  1009. formInfo.ImageableArea.bottom <= formInfo.Size.cy);
  1010. //
  1011. // Take landscape into consideration
  1012. //
  1013. if (IsLandscapeMode(pdev)) {
  1014. LONG width, height;
  1015. //
  1016. // Swap the width and height
  1017. //
  1018. pdev->paperSize.cy = width = formInfo.Size.cx;
  1019. pdev->paperSize.cx = height = formInfo.Size.cy;
  1020. //
  1021. // Rotate the coordinate system 90 degrees counterclockwise
  1022. //
  1023. pdev->imageArea.left = height - formInfo.ImageableArea.bottom;
  1024. pdev->imageArea.top = formInfo.ImageableArea.left;
  1025. pdev->imageArea.right = height - formInfo.ImageableArea.top;
  1026. pdev->imageArea.bottom = formInfo.ImageableArea.right;
  1027. //
  1028. // Swap x and y resolution
  1029. //
  1030. pdev->xres = pdev->dm.dmPublic.dmYResolution;
  1031. pdev->yres = pdev->dm.dmPublic.dmPrintQuality;
  1032. } else {
  1033. pdev->paperSize = formInfo.Size;
  1034. pdev->imageArea = formInfo.ImageableArea;
  1035. pdev->xres = pdev->dm.dmPublic.dmPrintQuality;
  1036. pdev->yres = pdev->dm.dmPublic.dmYResolution;
  1037. }
  1038. }
  1039. LONG
  1040. CalcHypot(
  1041. LONG x,
  1042. LONG y
  1043. )
  1044. /*++
  1045. Routine Description:
  1046. Returns the length of the hypotenouse of a right triangle
  1047. Arguments:
  1048. x, y - Edges of the right triangle
  1049. Return Value:
  1050. Hypotenouse of the right triangle
  1051. --*/
  1052. {
  1053. LONG hypo, delta, target;
  1054. //
  1055. // Take care of negative inputs
  1056. //
  1057. if (x < 0)
  1058. x = -x;
  1059. if (y < 0)
  1060. y = -y;
  1061. //
  1062. // use sq(x) + sq(y) = sq(hypo);
  1063. // start with MAX(x, y),
  1064. // use sq(x + 1) = sq(x) + 2x + 1 to incrementally get to the target hypotenouse.
  1065. //
  1066. hypo = max(x, y);
  1067. target = min(x, y);
  1068. target *= target;
  1069. for(delta = 0; delta < target; hypo++)
  1070. delta += (hypo << 1) + 1;
  1071. return hypo;
  1072. }