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.

2493 lines
76 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. bitblt.c
  5. Abstract:
  6. This module contains functions which implement bitmap handling for the
  7. plotter driver.
  8. Author:
  9. 19:15 on Mon 15 Apr 1991
  10. Created it
  11. 15-Nov-1993 Mon 19:24:36 updated
  12. fixed, clean up
  13. 18-Dec-1993 Sat 10:52:07 updated
  14. Move some functions from bitbltp.c and move others to htblt.c and
  15. bitmap.c. This file mainly has DrvXXXXX() which related to the
  16. bitblt or drawing.
  17. 27-Jan-1994 Thu 23:41:23 updated
  18. Revised bitblt so it will handle better ROP3/Rop4 support, also it
  19. will check the PCD file's ROP caps
  20. [Environment:]
  21. GDI Device Driver - Plotter.
  22. [Notes:]
  23. Revision History:
  24. --*/
  25. #include "precomp.h"
  26. #pragma hdrstop
  27. #define DBG_PLOTFILENAME DbgBitBlt
  28. #define DBG_COPYBITS 0x00000001
  29. #define DBG_BITBLT 0x00000002
  30. #define DBG_DRVPAINT 0x00000004
  31. #define DBG_DRVFILLPATH 0x00000008
  32. #define DBG_DRVSTROKEANDFILL 0x00000010
  33. #define DBG_MIXTOROP4 0x00000020
  34. #define DBG_TEMPSRC 0x00000040
  35. #define DBG_STRETCHBLT 0x00000080
  36. #define DBG_BANDINGHTBLT 0x00000100
  37. #define DBG_DOFILL 0x00000200
  38. #define DBG_CSI 0x00000400
  39. DEFINE_DBGVAR(0);
  40. //
  41. // This is the default BANDING size (2MB) for the DrvStretchBlt()
  42. //
  43. #if DBG
  44. LPSTR pCSIName[] = { "SRC", "PAT", "TMP" };
  45. DWORD MAX_STRETCH_BLT_SIZE = (2 * 1024 * 1024);
  46. #else
  47. #define MAX_STRETCH_BLT_SIZE (2 * 1024 * 1024)
  48. #endif
  49. //
  50. // This table converts MIX-1 to ROP3 value
  51. //
  52. static BYTE amixToRop4[] = {
  53. 0x00, // R2_BLACK 0
  54. 0x05, // R2_NOTMERGEPEN DPon
  55. 0x0a, // R2_MASKNOTPEN DPna
  56. 0x0f, // R2_NOTCOPYPEN PN
  57. 0x50, // R2_MASKPENNOT PDna
  58. 0x55, // R2_NOT Dn
  59. 0x5a, // R2_XORPEN DPx
  60. 0x5f, // R2_NOTMASKPEN DPan
  61. 0xa0, // R2_MASKPEN DPa
  62. 0xa5, // R2_NOTXORPEN DPxn
  63. 0xaa, // R2_NOP D
  64. 0xaf, // R2_MERGENOTPEN DPno
  65. 0xf0, // R2_COPYPEN P
  66. 0xf5, // R2_MERGEPENNOT PDno
  67. 0xfa, // R2_MERGEPEN DPo
  68. 0xff, // R2_WHITE 1
  69. };
  70. extern const POINTL ptlZeroOrigin;
  71. ROP4
  72. MixToRop4(
  73. MIX mix
  74. )
  75. /*++
  76. Routine Description:
  77. This function converts a MIX value to a ROP4 value
  78. Arguments:
  79. mix - MIX value to convert, this is defined in wingdi.h and represents
  80. one of 16 different ROP2 values
  81. Return Value:
  82. ROP4 - the converted value
  83. Author:
  84. 18-Dec-1993 Sat 09:34:06 created
  85. Revision History:
  86. --*/
  87. {
  88. ROP4 rop4Return;
  89. //
  90. // Now pack the two new values by looking up the correct rop codes in our
  91. // table.
  92. //
  93. rop4Return = amixToRop4[((mix & 0xff) - 1)];
  94. rop4Return |= ( amixToRop4[((( mix >> 8) & 0xff ) - 1 )] << 8 );
  95. PLOTDBG(DBG_MIXTOROP4, ("MixToRop4 before %x after %x", (int) mix,(int) rop4Return));
  96. return(rop4Return);
  97. }
  98. BOOL
  99. BandingHTBlt(
  100. PPDEV pPDev,
  101. SURFOBJ *psoDst,
  102. SURFOBJ *psoSrc,
  103. SURFOBJ *psoMask,
  104. CLIPOBJ *pco,
  105. XLATEOBJ *pxlo,
  106. COLORADJUSTMENT *pca,
  107. POINTL *pptlBrushOrg,
  108. PRECTL prclDst,
  109. PRECTL prclSrc,
  110. PPOINTL pptlMask,
  111. WORD HTRop3,
  112. BOOL InvertMask
  113. )
  114. /*++
  115. Routine Description:
  116. This is our internal version of StretchBlt() which always does halftoning
  117. and banding if the destination bitmap is too large. Since the target
  118. surface can pottentially be 3 feet by 3 feet, we don't want to
  119. have a bitmap created that large because of memory requirements. So
  120. we review the memory requirements and if they are too large we simply
  121. band, by setting a clip region that moves down the page via a loop. This
  122. effectively has the halftoning engine simply working on much smaller
  123. more manageable bitmaps, and we end up sending out virtually the same
  124. number of bytes.
  125. Arguments:
  126. pPDev - Pointer to our PDEV
  127. psoDst - This is a pointer to a SURFOBJ. It identifies the surface
  128. on which to draw.
  129. psoSrc - This SURFOBJ defines the source for the Blt operation. The
  130. driver must call GDI Services to find out if this is a device
  131. managed surface or a bitmap managed by GDI.
  132. psoMask - This optional surface provides a mask for the source. It is
  133. defined by a logic map, i.e. a bitmap with one bit per pel.
  134. The mask is used to limit the area of the source that is
  135. copied. When a mask is provided there is an implicit rop4 of
  136. 0xCCAA, which means that the source should be copied wherever
  137. the mask is 1, but the destination should be left alone
  138. wherever the mask is 0.
  139. When this argument is NULL there is an implicit rop4 of
  140. 0xCCCC, which means that the source should be copied
  141. everywhere in the source rectangle.
  142. The mask will always be large enough to contain the source
  143. rectangle, tiling does not need to be done.
  144. pco - This is a pointer to a CLIPOBJ. GDI Services are provided
  145. to enumerate the clipping region as a set of rectangles or
  146. trapezoids. This limits the area of the destination that will
  147. be modified.
  148. Whenever possible, GDI will simplify the clipping involved.
  149. However, unlike DrvBitBlt, DrvStretchBlt may be called with a
  150. single clipping rectangle. This is necessary to prevent
  151. roundoff errors in clipping the output.
  152. pxlo - This is a pointer to an XLATEOBJ. It tells how color indices
  153. should be translated between the source and target surfaces.
  154. The XLATEOBJ can also be queried to find the RGB color for
  155. any source index. A high quality stretching Blt will need
  156. to interpolate colors in some cases.
  157. pca - This is a pointer to COLORADJUSTMENT structure, if NULL it
  158. specifies that appiclation did not set any color adjustment
  159. for this DC, and it is up to the driver to provide a default
  160. adjustment
  161. pptlBrushOrg- Pointer to the POINT structure which specifies the location
  162. where the halftone brush should alignment to, if this pointer
  163. is NULL, then we assume that (0, 0) is the brush origin.
  164. prclDst - This RECTL defines the area in the coordinate system of the
  165. destination surface that should be modified.
  166. The rectangle is defined by two points. These points are
  167. not well ordered, i.e. the coordinates of the second point
  168. are not necessarily larger than those of the first point.
  169. The rectangle they describe does not include the lower and
  170. right edges. DrvStretchBlt will never be called with an
  171. empty destination rectangle.
  172. DrvStretchBlt can do inversions in both x and y, this happens
  173. when the destination rectangle is not well ordered.
  174. prclSrc - This RECTL defines the area in the coordinate system of the
  175. source surface that will be copied. The rectangle is defined
  176. by two points, and will map onto the rectangle defined by
  177. prclDst. The points of the source rectangle are well
  178. ordered. DrvStretch will never be given an empty source
  179. rectangle.
  180. Note that the mapping to be done is defined by prclSrc and
  181. prclDsst. To be precise, the given points in prclDst and
  182. prclSrc lie on integer coordinates, which we consider to
  183. correspond to pel centers. A rectangle defined by two such
  184. points should be considered a geometric rectangle with two
  185. vertices whose coordinates are the given points, but with 0.5
  186. subtracted from each coordinate. (The POINTLs should just be
  187. considered a shorthand notation for specifying these
  188. fractional coordinate vertices.) Note thate the edges of any
  189. such rectangle never intersect a pel, but go around a set of
  190. pels. Note also that the pels that are inside the rectangle
  191. are just what you would expect for a "bottom-right exclusive"
  192. rectangle. The mapping to be done by DrvStretchBlt will map
  193. the geometric source rectangle exactly onto the geometric
  194. destination rectangle.
  195. pptlMask - This POINTL specifies which pel in the given mask corresponds
  196. to the upper left pel in the source rectangle. Ignore this
  197. argument if there is no mask.
  198. HTRop3 - HIBYTE(HTRop3) when psoMask is not NULL and
  199. LOBYTE(HTRop3) when psoMask is NULL
  200. InvertMask - TRUE if the mask must be inverted
  201. Return Value:
  202. TRUE if sucessful FALSE if failed
  203. Author:
  204. 07-Mar-1994 Mon 12:52:41 created
  205. Revision History:
  206. 16-Mar-1994 Wed 15:20:42 updated
  207. Updated for banding the mask so it will works correcly for the engine
  208. problem.
  209. 04-May-1994 Wed 11:27:39 updated
  210. Make rotate type (landscape mode) banding from right to left rather
  211. than top to bottom
  212. 29-Nov-1995 Wed 13:00:30 updated
  213. Mark not reentratable for the same PDEV, this is signal that called to
  214. the EngStretchBlt(HALFTONE) is failing for some reason
  215. --*/
  216. {
  217. CLIPOBJ *pcoNew;
  218. CLIPOBJ coSave;
  219. RECTL rclMask;
  220. RECTL rclBounds;
  221. DWORD MaskRop3;
  222. UINT Loop;
  223. BOOL DoRotate;
  224. BOOL Ok;
  225. if (!IS_RASTER(pPDev)) {
  226. PLOTDBG(DBG_BANDINGHTBLT, ("BandingHTBlt: Pen Plotter: IGNORE and return OK"));
  227. return(TRUE);
  228. }
  229. if (pPDev->pPlotGPC->ROPLevel < ROP_LEVEL_1) {
  230. PLOTDBG(DBG_BITBLT, ("BandingHTBlt: RopLevel < 1, Cannot Do it"));
  231. return(TRUE);
  232. }
  233. if (pPDev->Flags & PDEVF_IN_BANDHTBLT) {
  234. //
  235. // Something is wrong here
  236. //
  237. PLOTERR(("BandingHTBlt: Recursive is not allowed, FAILED"));
  238. return(FALSE);
  239. }
  240. //
  241. // Turn on the flag now
  242. //
  243. pPDev->Flags |= PDEVF_IN_BANDHTBLT;
  244. if ((!pca) || (pca->caFlags & ~(CA_NEGATIVE | CA_LOG_FILTER))) {
  245. //
  246. // If we have a NULL or invalid flag then use the default one
  247. //
  248. PLOTWARN(("DrvStretchBlt: INVALID ColorAdjustment Flags=%04lx, USE DEFAULT",
  249. (pca) ? pca->caFlags : 0));
  250. pca = &(pPDev->PlotDM.ca);
  251. }
  252. if (!pptlBrushOrg) {
  253. pptlBrushOrg = (PPOINTL)&(ptlZeroOrigin);
  254. }
  255. if (pPDev->PlotDM.Flags & PDMF_PLOT_ON_THE_FLY) {
  256. if (psoMask) {
  257. PLOTWARN(("BandingHTBlt: PosterMode -> Ignored MASK"));
  258. psoMask = NULL;
  259. }
  260. }
  261. if (psoMask) {
  262. //
  263. // If we have a source mask then we will first do (S|D)=0xEE or
  264. // (~S|D)=0xBB to white out the mask area then use (S&D)=0x88 to AND
  265. // in the halftoned bitmap. This is done to simulate the desired ROP
  266. // since the target device can't handle this on its own.
  267. //
  268. rclMask.left = pptlMask->x;
  269. rclMask.top = pptlMask->y;
  270. rclMask.right = rclMask.left + (prclSrc->right - prclSrc->left);
  271. rclMask.bottom = rclMask.top + (prclSrc->bottom - prclSrc->top);
  272. HTRop3 = (WORD)HIBYTE(HTRop3);
  273. MaskRop3 = (DWORD)((InvertMask) ? 0xBB : 0xEE);
  274. Loop = 2;
  275. //
  276. // We must call this function to set up the xlate table correctly
  277. //
  278. IsHTCompatibleSurfObj(pPDev,
  279. psoMask,
  280. NULL,
  281. ISHTF_ALTFMT | ISHTF_HTXB | ISHTF_DSTPRIM_OK);
  282. } else {
  283. HTRop3 = (WORD)LOBYTE(HTRop3);
  284. Loop = 1;
  285. }
  286. if (!HTRop3) {
  287. HTRop3 = 0xCC;
  288. }
  289. //
  290. // Now look at how we can modify the clipping rect, in case we need
  291. // to band.
  292. //
  293. if (pco) {
  294. //
  295. // Save the original clipping object so we can restore it before exiting
  296. //
  297. pcoNew = NULL;
  298. coSave = *pco;
  299. } else {
  300. PLOTDBG(DBG_BANDINGHTBLT, ("BandingHTBlt: Create NEW EMPTY pco"));
  301. if (!(pcoNew = pco = EngCreateClip())) {
  302. PLOTERR(("BandingHTBlt: EngCreateClip() FAILED, got NO CLIP"));
  303. pPDev->Flags &= ~PDEVF_IN_BANDHTBLT;
  304. return(FALSE);
  305. }
  306. pco->iDComplexity = DC_TRIVIAL;
  307. }
  308. PLOTDBG(DBG_BANDINGHTBLT, ("BandingHTBlt: The pco->iDComplexity=%ld",
  309. pco->iDComplexity));
  310. if (pco->iDComplexity == DC_TRIVIAL) {
  311. //
  312. // Since it is trivial, we just draw the whole destination
  313. //
  314. pco->iDComplexity = DC_RECT;
  315. pco->rclBounds = *prclDst;
  316. }
  317. //
  318. // Now make sure our bounds will not go outside of the surface
  319. //
  320. rclBounds.left =
  321. rclBounds.top = 0;
  322. rclBounds.right = psoDst->sizlBitmap.cx;
  323. rclBounds.bottom = psoDst->sizlBitmap.cy;
  324. if (IntersectRECTL(&rclBounds, &(pco->rclBounds))) {
  325. PLOTDBG(DBG_BANDINGHTBLT,
  326. ("BandingHTBlt: rclBounds=(%ld, %ld)-(%ld, %ld), %ld x %ld, ROP=%02lx",
  327. rclBounds.left, rclBounds.top,
  328. rclBounds.right, rclBounds.bottom,
  329. rclBounds.right - rclBounds.left,
  330. rclBounds.bottom - rclBounds.top, (DWORD)HTRop3));
  331. } else {
  332. PLOTDBG(DBG_BANDINGHTBLT, ("BandingHTBlt: rclBounds=NULL, NOTHING TO DO"));
  333. Loop = 0;
  334. }
  335. //
  336. // Now let's band it through
  337. //
  338. DoRotate = (BOOL)(pPDev->PlotForm.BmpRotMode == BMP_ROT_RIGHT_90);
  339. Ok = TRUE;
  340. while ((Ok) && (Loop--) && (!PLOT_CANCEL_JOB(pPDev))) {
  341. RECTL rclDst;
  342. SIZEL szlDst;
  343. LONG cScan;
  344. DWORD BmpFormat;
  345. DWORD OHTFlags;
  346. //
  347. // When Loop = 1 then we are doing the MASK
  348. // When Loop = 0 then we are doing the SOURCE
  349. //
  350. // We will band only MAX_STRETCH_BLT_SIZE at once
  351. //
  352. rclDst = *prclDst;
  353. szlDst.cx = rclDst.right - rclDst.left;
  354. szlDst.cy = rclDst.bottom - rclDst.top;
  355. BmpFormat = (DWORD)((Loop) ? BMF_1BPP : HTBMPFORMAT(pPDev));
  356. cScan = (LONG)(MAX_STRETCH_BLT_SIZE /
  357. GetBmpDelta(BmpFormat, (DoRotate) ? szlDst.cy :
  358. szlDst.cx));
  359. //
  360. // We always want at least 8 scan lines and also a multiple of 8.
  361. //
  362. if (!cScan) {
  363. cScan = 8;
  364. } else if (cScan & 0x07) {
  365. cScan = (LONG)((cScan + 7) & ~(DWORD)0x07);
  366. }
  367. PLOTDBG(DBG_BANDINGHTBLT, ("BandingHTBlt: cScan=%ld, Total=%ld",
  368. cScan, (DoRotate) ? szlDst.cx : szlDst.cy));
  369. OHTFlags = 0;
  370. while ((Ok) &&
  371. (!PLOT_CANCEL_JOB(pPDev)) &&
  372. (rclDst.top < prclDst->bottom) &&
  373. (rclDst.right > prclDst->left)) {
  374. if (DoRotate) {
  375. if ((rclDst.left = rclDst.right - cScan) < prclDst->left) {
  376. rclDst.left = prclDst->left;
  377. }
  378. } else {
  379. if ((rclDst.bottom = rclDst.top + cScan) > prclDst->bottom) {
  380. rclDst.bottom = prclDst->bottom;
  381. }
  382. }
  383. pco->rclBounds = rclBounds;
  384. if (IntersectRECTL(&(pco->rclBounds), &rclDst)) {
  385. PLOTDBG(DBG_BANDINGHTBLT,
  386. ("BandingHTBlt: Banding RECTL=(%ld, %ld)-(%ld, %ld), %ld x %ld",
  387. pco->rclBounds.left, pco->rclBounds.top,
  388. pco->rclBounds.right, pco->rclBounds.bottom,
  389. pco->rclBounds.right - pco->rclBounds.left,
  390. pco->rclBounds.bottom - pco->rclBounds.top));
  391. if (Loop) {
  392. SURFOBJ *psoNew;
  393. HBITMAP hNewBmp;
  394. RECTL rclNew;
  395. //
  396. // We have a mask, so create a 1BPP bitmap, and stretch it
  397. // to the new destination size, then output it using
  398. // MaskRop3
  399. //
  400. Ok = FALSE;
  401. PLOTDBG(DBG_CSI, ("BandingHTBlt: CreateBitmapSURFOBJ(MASK)"));
  402. if (psoNew = CreateBitmapSURFOBJ(pPDev,
  403. &hNewBmp,
  404. pco->rclBounds.right -
  405. pco->rclBounds.left,
  406. pco->rclBounds.bottom -
  407. pco->rclBounds.top,
  408. BMF_1BPP,
  409. NULL)) {
  410. rclNew.left = prclDst->left - pco->rclBounds.left;
  411. rclNew.top = prclDst->top - pco->rclBounds.top;
  412. rclNew.right = rclNew.left + szlDst.cx;
  413. rclNew.bottom = rclNew.top + szlDst.cy;
  414. PLOTDBG(DBG_BANDINGHTBLT,
  415. ("BandingHTBlt: Banding MASK RECTL=(%ld, %ld)-(%ld, %ld), %ld x %ld",
  416. rclNew.left, rclNew.top,
  417. rclNew.right, rclNew.bottom,
  418. psoNew->sizlBitmap.cx,
  419. psoNew->sizlBitmap.cy));
  420. if (EngStretchBlt(psoNew, // psoDst
  421. psoMask, // psoSrc
  422. NULL, // psoMask,
  423. NULL, // pco
  424. NULL, // pxlo
  425. NULL, // pca
  426. pptlBrushOrg, // pptlHTOrg
  427. &rclNew, // prclDst
  428. &rclMask, // prclSrc
  429. NULL, // pptlMask
  430. BLACKONWHITE)) {
  431. if (!(Ok = OutputHTBitmap(pPDev,
  432. psoNew,
  433. NULL,
  434. (PPOINTL)&rclDst,
  435. NULL,
  436. MaskRop3,
  437. &OHTFlags))) {
  438. PLOTERR(("BandingHTBlt: OutputHTBitmap(M|D) FAILED"));
  439. }
  440. } else {
  441. PLOTERR(("BandingHTBlt: EngStretchBlt(MASK B/W) FAILED"));
  442. }
  443. //
  444. // Delete this band of the mask bitmap
  445. //
  446. EngUnlockSurface(psoNew);
  447. PLOTDBG(DBG_CSI, ("BandingHTBlt: EngDeleteSuface(MASK)"));
  448. if (!EngDeleteSurface((HSURF)hNewBmp)) {
  449. PLOTERR(("PLOTTER: BandingHTBlt, EngDeleteSurface(%p) FAILED",
  450. (DWORD_PTR)hNewBmp));
  451. }
  452. } else {
  453. PLOTERR(("BandingHTBlt: Create MASK SURFOBJ (%ld x %ld) failed",
  454. pco->rclBounds.right - pco->rclBounds.left,
  455. pco->rclBounds.bottom - pco->rclBounds.top));
  456. }
  457. } else {
  458. //
  459. // We must pass the psoMask/pptlMask so the haltone
  460. // operations will not overwrite the non masked
  461. // area (erasing it).
  462. //
  463. pPDev->Rop3CopyBits = HTRop3;
  464. if (!(Ok = EngStretchBlt(psoDst, // psoDst
  465. psoSrc, // psoSrc
  466. psoMask, // psoMask,
  467. pco, // pco
  468. pxlo, // pxlo
  469. pca, // pca
  470. pptlBrushOrg, // pptlHTOrg
  471. prclDst, // prclDst
  472. prclSrc, // prclSrc
  473. pptlMask, // pptlMask
  474. HALFTONE))) {
  475. PLOTERR(("BandingHTBlt: EngStretchBlt(Halftone:S&D) FAILED"));
  476. }
  477. }
  478. }
  479. if (DoRotate) {
  480. rclDst.right = rclDst.left;
  481. } else {
  482. rclDst.top = rclDst.bottom;
  483. }
  484. }
  485. //
  486. // We must do this in order to exit HPGL/2 mode. This is because the
  487. // next call for the source will go through EngStrecthBlt(HALFTONE)
  488. // which will re-enter RTL mode again.
  489. //
  490. if (OHTFlags & OHTF_MASK) {
  491. OHTFlags |= OHTF_EXIT_TO_HPGL2;
  492. OutputHTBitmap(pPDev, NULL, NULL, NULL, NULL, 0xAA, &OHTFlags);
  493. }
  494. }
  495. if (pcoNew) {
  496. EngDeleteClip(pcoNew);
  497. } else {
  498. *pco = coSave;
  499. }
  500. pPDev->Flags &= ~PDEVF_IN_BANDHTBLT;
  501. return(Ok);
  502. }
  503. BOOL
  504. DoFill(
  505. SURFOBJ *psoDst,
  506. SURFOBJ *psoSrc,
  507. CLIPOBJ *pco,
  508. XLATEOBJ *pxlo,
  509. PRECTL prclDst,
  510. PPOINTL pptlSrc,
  511. BRUSHOBJ *pbo,
  512. PPOINTL pptlBrush,
  513. ROP4 Rop4
  514. )
  515. /*++
  516. Routine Description:
  517. This function fills a RECT area with a brush and takes clipping into
  518. consideration
  519. Arguments:
  520. psoDst - Destination surface obj
  521. psoSrc - source surface obj
  522. pco - Clip obj
  523. pxlo - translate obj
  524. prclDst - destination rect area
  525. pptlSrc - point where source starts
  526. pbo - Brush obj to fill with
  527. pptlBrush - Brush alignment origin
  528. Rop4 - ROP4 to use
  529. Return Value:
  530. TRUE if ok, FALSE if failed
  531. Author:
  532. Created -
  533. 18-Dec-1993 Sat 09:34:06 created
  534. Clean up formal argumeneted, commented
  535. 15-Jan-1994 Sat 01:41:48 updated
  536. added rclDst to DoFill() in case pco is NULL
  537. 10-Mar-1994 Thu 00:35:06 updated
  538. Fixed so when we call DoPolygon it will take prclDst (if not NULL)
  539. into account by intersect it with the rclBounds in the pco first
  540. 25-Mar-1994 update
  541. Modified function to enumerate clipping region if destination
  542. rectangle exists.
  543. Revision History:
  544. --*/
  545. {
  546. PPDEV pPDev;
  547. RECTL rclDst;
  548. if (!(pPDev = SURFOBJ_GETPDEV(psoDst))) {
  549. PLOTERR(("DoFill: Invalid pPDev in psoDst"));
  550. return(FALSE);
  551. }
  552. //
  553. // Here we have to see if the clip obj is trivial or non existant, in which
  554. // case we pass this directly to fill rect.
  555. //
  556. if ((!pco) ||
  557. (pco->iDComplexity == DC_RECT) ||
  558. (pco->iDComplexity == DC_TRIVIAL)) {
  559. if ((pco) && (pco->iDComplexity == DC_RECT)) {
  560. PLOTDBG(DBG_DOFILL,
  561. ("DoFill: pco = RECT %s", (prclDst) ? ", WITH dest rect" : "" ));
  562. //
  563. // First grab the destination as the bounding rect since,
  564. // we have a RECT clipping region
  565. //
  566. rclDst = pco->rclBounds;
  567. //
  568. // Now if we also had a destination rect passed in as well,
  569. // intersect down to the final rect
  570. //
  571. if (prclDst) {
  572. if ( !IntersectRECTL(&rclDst, prclDst)) {
  573. return( TRUE );
  574. }
  575. }
  576. //
  577. // And finally point to the new rect for the fill
  578. //
  579. prclDst = &rclDst;
  580. } else if (!prclDst) {
  581. PLOTWARN(
  582. ("DoFill: No destination rectange and NULL or TRIVIAL pco!"));
  583. //
  584. // We don't have any clipping so fill the target rect
  585. //
  586. rclDst.left =
  587. rclDst.top = 0;
  588. rclDst.right = psoDst->sizlBitmap.cx;
  589. rclDst.bottom = psoDst->sizlBitmap.cy;
  590. prclDst = &rclDst;
  591. }
  592. return(DoRect(pPDev,
  593. prclDst,
  594. pbo,
  595. NULL,
  596. pptlBrush,
  597. Rop4,
  598. NULL,
  599. FPOLY_FILL));
  600. } else {
  601. BOOL Ok = TRUE;
  602. BOOL bMore;
  603. HTENUMRCL EnumRects;
  604. PRECTL pCurClipRect;
  605. //
  606. // We have complex clipping but we also have a destination rect to
  607. // fill, this means we have to enum the clipping region as rects
  608. // so we can intersect each one with the target rect..
  609. //
  610. PLOTDBG(DBG_DOFILL,
  611. ("DoFill: pco = COMPLEX %s", (prclDst) ? ", WITH dest rect" : "" ));
  612. if (prclDst) {
  613. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  614. bMore = TRUE;
  615. do {
  616. //
  617. // See if the job has been aborted
  618. //
  619. if (PLOT_CANCEL_JOB(pPDev)) {
  620. break;
  621. }
  622. //
  623. // Grab the next batch of rectangles
  624. //
  625. if (bMore) {
  626. bMore = CLIPOBJ_bEnum(pco, sizeof(EnumRects), (ULONG *)&EnumRects);
  627. }
  628. if (bMore == DDI_ERROR)
  629. {
  630. bMore = FALSE;
  631. Ok = FALSE;
  632. break;
  633. }
  634. //
  635. /// Set up for enuming the clip rectangles
  636. //
  637. pCurClipRect = (PRECTL)&EnumRects.rcl[0];
  638. while ((Ok) && (EnumRects.c--)) {
  639. rclDst = *pCurClipRect;
  640. //
  641. // Make sure we have something left to fill after the
  642. // intersect
  643. //
  644. if( IntersectRECTL(&rclDst, prclDst) ) {
  645. Ok = DoRect( pPDev,
  646. &rclDst,
  647. pbo,
  648. NULL,
  649. pptlBrush,
  650. Rop4,
  651. NULL,
  652. FPOLY_FILL );
  653. }
  654. pCurClipRect++;
  655. }
  656. } while ( bMore );
  657. } else {
  658. Ok = DoPolygon(pPDev,
  659. NULL,
  660. pco,
  661. NULL,
  662. pptlBrush,
  663. pbo,
  664. NULL,
  665. Rop4,
  666. NULL,
  667. FPOLY_FILL);
  668. }
  669. return(Ok);
  670. }
  671. }
  672. BOOL
  673. DrvPaint(
  674. SURFOBJ *psoDst,
  675. CLIPOBJ *pco,
  676. BRUSHOBJ *pbo,
  677. PPOINTL pptlBrushOrg,
  678. MIX Mix
  679. )
  680. /*++
  681. Routine Description:
  682. This function is the most basic drawing function in the driver. As graphic
  683. calls get failed, the NT graphics engine will reduce those other calls
  684. (if we fail them) down to DrvPaint. We cannot fail DrvPaint as the engine
  685. has nowhere else to go.
  686. Arguments:
  687. Per DDI Spec.
  688. Return Value:
  689. TRUE of OK, FALSE if falied
  690. Author:
  691. Created
  692. 18-Dec-1993 Sat 09:27:29 updated
  693. Updated, commented, change to correct formal header
  694. 15-Jan-1994 Sat 00:38:41 updated
  695. Re-arranged and call DrvBitBlt() if can do a damm thing.
  696. Revision History:
  697. --*/
  698. {
  699. PPDEV pPDev;
  700. RECTL rclDst;
  701. DWORD Rop4;
  702. //
  703. // get our PDEV from the SURFOBJ
  704. //
  705. if (!(pPDev = SURFOBJ_GETPDEV(psoDst))) {
  706. PLOTERR(("DrvPaint: Invalid pPDev in pso"));
  707. return(FALSE);
  708. }
  709. PLOTASSERT(0, "DrvPaint: WARNING: pco [%08lx] is NULL or DC_TRIVIAL???",
  710. (pco) && (pco->iDComplexity != DC_TRIVIAL), pco);
  711. if ((pco) &&
  712. (pco->iDComplexity == DC_TRIVIAL) &&
  713. (pco->iFComplexity == FC_RECT)) {
  714. PLOTWARN(("DrvPaint: <pco> DC_TRIVIAL but NOT FC_RECT, make DC_RECT ??? (%ld,%ld)-(%ld,%ld)",
  715. pco->rclBounds.left,
  716. pco->rclBounds.top,
  717. pco->rclBounds.right,
  718. pco->rclBounds.bottom));
  719. pco->iDComplexity = DC_RECT;
  720. }
  721. //
  722. // Make sure we don't pass a NULL rect.
  723. //
  724. if ((pco) && (pco->iDComplexity != DC_TRIVIAL)) {
  725. rclDst = pco->rclBounds;
  726. } else {
  727. rclDst.left =
  728. rclDst.top = 0;
  729. rclDst.right = psoDst->sizlBitmap.cx;
  730. rclDst.bottom = psoDst->sizlBitmap.cy;
  731. }
  732. Rop4 = MixToRop4(Mix);
  733. //
  734. // If we can actually draw the passed object with device brushes (etc)
  735. // then do it now. Otherwise, we will have to simulate it via DrvBitBlt
  736. //
  737. if (GetColor(pPDev, pbo, NULL, NULL, Rop4) > 0) {
  738. PLOTDBG(DBG_DRVPAINT, ("DrvPAINT: Calling DoFill()"));
  739. return(DoFill(psoDst, // psoDst
  740. NULL, // psoSrc
  741. pco, // pco
  742. NULL, // pxlo
  743. NULL, // prclDest only fill based on pco
  744. NULL, // prclSrc
  745. pbo, // pbo
  746. pptlBrushOrg, // pptlBrushOrg
  747. Rop4)); // Rop4
  748. } else {
  749. PLOTDBG(DBG_DRVPAINT, ("DrvPAINT: Can't do it Calling DrvBitBlt()"));
  750. return(DrvBitBlt(psoDst, // psoDst
  751. NULL, // psoSrc
  752. NULL, // psoMask
  753. pco, // pco
  754. NULL, // pxlo
  755. &rclDst, // prclDst
  756. (PPOINTL)&rclDst, // pptlSrc
  757. NULL, // pptlMask
  758. pbo, // pbo,
  759. pptlBrushOrg, // pptlBrushOrg,
  760. Rop4)); // Rop4
  761. }
  762. }
  763. BOOL
  764. DrvFillPath(
  765. SURFOBJ *pso,
  766. PATHOBJ *ppo,
  767. CLIPOBJ *pco,
  768. BRUSHOBJ *pbo,
  769. POINTL *pptlBrushOrg,
  770. MIX Mix,
  771. FLONG flOptions
  772. )
  773. /*++
  774. Routine Description:
  775. This function will take a PATHOBJ as a parameter and fill in
  776. the closed region with the specified brush.
  777. Arguments:
  778. Per DDI spec.
  779. Return Value:
  780. TRUE if ok, FALSE if error
  781. Author:
  782. 18-Dec-1993 Sat 09:27:29 created
  783. Updated, commented
  784. Created
  785. Revision History:
  786. --*/
  787. {
  788. PPDEV pPDev;
  789. ULONG ulOptions;
  790. ROP4 rop4;
  791. BOOL bRetVal;
  792. //
  793. // Convert the mix to a rop since we use it more than once
  794. //
  795. rop4 = MixToRop4(Mix);
  796. PLOTDBG(DBG_DRVFILLPATH, ("DrvFillPath: Mix = %x, Rop4 = %x", Mix, rop4));
  797. if (!(pPDev = SURFOBJ_GETPDEV(pso))) {
  798. PLOTERR(("DrvFillPath: Invalid pPDev in pso"));
  799. return(FALSE);
  800. }
  801. //
  802. // Get color will tell us if the requested op can be done in HPGL2 mode
  803. // if it cant, we have to simulate via DrvBitBlt
  804. //
  805. if (GetColor(pPDev, pbo, NULL, NULL, rop4) > 0 ) {
  806. ulOptions = FPOLY_FILL;
  807. if (flOptions & FP_WINDINGMODE) {
  808. //
  809. // Set the flag to notify the generic path code about the fill type
  810. //
  811. ulOptions |= FPOLY_WINDING;
  812. }
  813. bRetVal = DoPolygon(pPDev,
  814. NULL,
  815. pco,
  816. ppo,
  817. pptlBrushOrg,
  818. pbo,
  819. NULL,
  820. rop4,
  821. NULL,
  822. ulOptions);
  823. } else {
  824. bRetVal = FALSE;
  825. PLOTDBG(DBG_DRVFILLPATH, ("DrvFillPath: Failing because GetColor <= 0 "));
  826. }
  827. return( bRetVal );
  828. }
  829. BOOL
  830. DrvStrokeAndFillPath(
  831. SURFOBJ *pso,
  832. PATHOBJ *ppo,
  833. CLIPOBJ *pco,
  834. XFORMOBJ *pxo,
  835. BRUSHOBJ *pboStroke,
  836. LINEATTRS *plineattrs,
  837. BRUSHOBJ *pboFill,
  838. POINTL *pptlBrushOrg,
  839. MIX MixFill,
  840. FLONG flOptions
  841. )
  842. /*++
  843. Routine Description:
  844. This function will take a PATHOBJ as a parameter, fill in
  845. the closed region with the FILL brush, and stroke the path with
  846. the STROKE brush.
  847. Arguments:
  848. Per DDI
  849. Return Value:
  850. TRUE if ok, FALSE if error
  851. Author:
  852. 18-Dec-1993 Sat 09:27:29 created
  853. Updated, commented
  854. Created by
  855. Revision History:
  856. --*/
  857. {
  858. PPDEV pPDev;
  859. ULONG ulOptions;
  860. BOOL bRetVal;
  861. ROP4 rop4;
  862. //
  863. // Convert the mix to a rop since we use it more than once
  864. //
  865. rop4 = MixToRop4(MixFill);
  866. PLOTDBG(DBG_DRVSTROKEANDFILL, ("DrvStrokeAndFillPath: Mix = %x, Rop4 = %x", MixFill, rop4));
  867. if (!(pPDev = SURFOBJ_GETPDEV(pso))) {
  868. PLOTERR(("DrvStrokeAndFillPath: Invalid pPDev in pso"));
  869. return(FALSE);
  870. }
  871. if (GetColor(pPDev, pboFill, NULL, NULL, rop4) > 0 ) {
  872. ulOptions = FPOLY_STROKE | FPOLY_FILL;
  873. if (flOptions & FP_WINDINGMODE) {
  874. ulOptions |= FPOLY_WINDING;
  875. }
  876. bRetVal = DoPolygon(pPDev,
  877. NULL,
  878. pco,
  879. ppo,
  880. pptlBrushOrg,
  881. pboFill,
  882. pboStroke,
  883. rop4,
  884. plineattrs,
  885. ulOptions);
  886. } else {
  887. bRetVal = FALSE;
  888. PLOTDBG(DBG_DRVSTROKEANDFILL,
  889. ("DrvStrokeAndFillPath: Failing because GetColor is <= 0",
  890. MixFill, rop4));
  891. }
  892. return(bRetVal);
  893. }
  894. BOOL
  895. DrvCopyBits(
  896. SURFOBJ *psoDst,
  897. SURFOBJ *psoSrc,
  898. CLIPOBJ *pco,
  899. XLATEOBJ *pxlo,
  900. RECTL *prclDst,
  901. POINTL *pptlSrc
  902. )
  903. /*++
  904. Routine Description:
  905. Convert between two bitmap formats
  906. Arguments:
  907. Per Engine spec.
  908. Return Value:
  909. BOOLEAN
  910. Author:
  911. 11-Feb-1993 Thu 21:00:43 created
  912. 09-Feb-1994 Wed 16:49:17 updated
  913. Adding rclHTBlt to have psoHTBlt correctly tiled, also check if the
  914. pco is passed.
  915. 19-Jan-1994 Wed 14:28:45 updated
  916. Adding hack to handle EngStretchBlt() to our own temp surfobj
  917. 06-Jan-1994 Thu 04:34:37 updated
  918. Make sure we do not do this for pen plotter
  919. 01-Mar-1994 Tue 10:51:58 updated
  920. Make the call to BandingHTBlt() rather to EngStretchBlt()
  921. Revision History:
  922. --*/
  923. {
  924. SURFOBJ *psoHTBlt;
  925. PPDEV pPDev;
  926. RECTL rclDst;
  927. //
  928. // Copy down the destination rectangle
  929. //
  930. rclDst = *prclDst;
  931. PLOTDBG(DBG_COPYBITS, ("DrvCopyBits: Dst=(%ld, %ld)-(%ld-%ld) [%ld x %ld]",
  932. rclDst.left, rclDst.top, rclDst.right, rclDst.bottom,
  933. rclDst.right - rclDst.left,
  934. rclDst.bottom - rclDst.top));
  935. //
  936. // The DrvCopyBits() function lets applicatiosn convert between bitmap and
  937. // device formats.
  938. //
  939. // BUT... for our plotter device we cannot read the printer surface
  940. // bitmap back, so tell the caller that we cannot do it if they
  941. // really called us with that sort of request.
  942. //
  943. if (psoSrc->iType != STYPE_BITMAP) {
  944. DWORD Color = 0xFFFFFF;
  945. PLOTASSERT(1, "DrvCopyBits: psoSrc->iType not STYPE_DEVICE",
  946. psoSrc->iType == STYPE_DEVICE, psoSrc->iType);
  947. //
  948. // Someone tried to copy from a non-bitmap surface, ie STYPE_DEVICE
  949. //
  950. if (pxlo) {
  951. Color = XLATEOBJ_iXlate(pxlo, Color);
  952. }
  953. //
  954. // If we doing XOR then we want to have all area = 0 first
  955. //
  956. if (!(pPDev = SURFOBJ_GETPDEV(psoSrc))) {
  957. PLOTERR(("DrvCopyBits: invalid pPDev"));
  958. return(FALSE);
  959. }
  960. if (pPDev->Rop3CopyBits == 0x66) {
  961. PLOTWARN(("DrvCopyBits: Rop3CopyBits = 0x66, Color = 0x0"));
  962. Color = 0;
  963. }
  964. PLOTWARN(("DrvCopyBits: Cannot copy from DEVICE, Do EngErase=(%ld,%ld)-(%ld, %ld), COLOR=%08lx)",
  965. rclDst.left, rclDst.top, rclDst.right, rclDst.bottom, Color));
  966. return(EngEraseSurface(psoDst, prclDst, Color));
  967. }
  968. if (psoDst->iType != STYPE_DEVICE) {
  969. //
  970. // Someone tried to copy to bitmap surface, ie STYPE_BITMAP
  971. //
  972. PLOTWARN(("DrvCopyBits: Cannot copy to NON-DEVICE destination"));
  973. SetLastError(ERROR_INVALID_PARAMETER);
  974. return(FALSE);
  975. }
  976. if (!(pPDev = SURFOBJ_GETPDEV(psoDst))) {
  977. PLOTERR(("DrvCopyBits: invalid pPDev"));
  978. return(FALSE);
  979. }
  980. //
  981. // If this is us calling ourselves during bitmap handling do it now.
  982. //
  983. if (psoHTBlt = pPDev->psoHTBlt) {
  984. PLOTDBG(DBG_TEMPSRC, ("DrvCopyBits: psoHTBlt=%ld x %ld, psoSrc=%ld x %ld, pptlSrc=(%ld, %ld)",
  985. psoHTBlt->sizlBitmap.cx, psoHTBlt->sizlBitmap.cy,
  986. psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy,
  987. pptlSrc->x, pptlSrc->y));
  988. PLOTDBG(DBG_TEMPSRC, ("DrvCopyBits: szlHTBlt=(%ld, %ld)-(%ld, %ld) = %ld x %ld",
  989. pPDev->rclHTBlt.left, pPDev->rclHTBlt.top,
  990. pPDev->rclHTBlt.right, pPDev->rclHTBlt.bottom,
  991. pPDev->rclHTBlt.right - pPDev->rclHTBlt.left,
  992. pPDev->rclHTBlt.bottom - pPDev->rclHTBlt.top));
  993. PLOTASSERT(1, "DrvCopyBits: psoHTBlt Type != psoSrc Type",
  994. psoHTBlt->iType == psoSrc->iType, 0);
  995. PLOTASSERT(0, "DrvCopyBits: ??? pptlSrc [%08lx] != (0, 0)",
  996. (pptlSrc->x == 0) && (pptlSrc->y == 0), pptlSrc);
  997. if ((!pco) || (pco->iDComplexity == DC_TRIVIAL)) {
  998. PLOTASSERT(1, "DrvCopyBits: psoHTBlt Size < psoSrc Size",
  999. (psoHTBlt->sizlBitmap.cx >= psoSrc->sizlBitmap.cx) &&
  1000. (psoHTBlt->sizlBitmap.cy >= psoSrc->sizlBitmap.cy), 0);
  1001. PLOTASSERT(1, "DrvCopyBits: rclHTBlt > psoHTBlt size",
  1002. (pPDev->rclHTBlt.left <= psoHTBlt->sizlBitmap.cx) &&
  1003. (pPDev->rclHTBlt.right <= psoHTBlt->sizlBitmap.cx) &&
  1004. (pPDev->rclHTBlt.top <= psoHTBlt->sizlBitmap.cy) &&
  1005. (pPDev->rclHTBlt.bottom <= psoHTBlt->sizlBitmap.cy),
  1006. 0);
  1007. PLOTASSERT(1, "DrvCopyBits: pPDev->rclHTBlt Size != psoSrc Size",
  1008. ((pPDev->rclHTBlt.right - pPDev->rclHTBlt.left) ==
  1009. psoSrc->sizlBitmap.cx) &&
  1010. ((pPDev->rclHTBlt.bottom - pPDev->rclHTBlt.top) ==
  1011. psoSrc->sizlBitmap.cy),
  1012. 0);
  1013. } else if (pco->iDComplexity == DC_RECT) {
  1014. PLOTWARN(("DrvCopyBits: **** MAY BE EngStretchBlt(HALFTONE) FAILED but we got EngStretchBlt(COLORONCOLOR) instead"));
  1015. PLOTASSERT(1, "DrvCopyBits: rclHTBlt != pco->rclBounds, pco=%08lx",
  1016. ((pPDev->rclHTBlt.right - pPDev->rclHTBlt.left) ==
  1017. (pco->rclBounds.right - pco->rclBounds.left)) &&
  1018. ((pPDev->rclHTBlt.bottom - pPDev->rclHTBlt.top) ==
  1019. (pco->rclBounds.bottom - pco->rclBounds.top)), pco);
  1020. } else {
  1021. PLOTASSERT(1, "DrvCopyBits: <psoHTBlt>, pco [%08lx] is Complex.",
  1022. pco->iDComplexity != DC_COMPLEX, pco);
  1023. }
  1024. if (!EngCopyBits(psoHTBlt, // psoDst
  1025. psoSrc, // psoSrc
  1026. pco, // pco
  1027. NULL, // pxlo
  1028. &(pPDev->rclHTBlt), // prclDst
  1029. pptlSrc)) { // pptlSrc
  1030. PLOTERR(("DrvCopyBits: EngCopyBits(psoHTBlt, psoSrc) Failed"));
  1031. }
  1032. return(TRUE);
  1033. }
  1034. if (!IS_RASTER(pPDev)) {
  1035. PLOTDBG(DBG_COPYBITS, ("DrvCopyBits: Pen Plotter: IGNORE and return OK"));
  1036. return(TRUE);
  1037. }
  1038. //
  1039. // First validate everything to see if this one is the halftoned result
  1040. // or is compatible with halftoned result, otherwise we will call
  1041. // EngStretchBlt(HALFTONE) halftone the sources then it will eventually
  1042. // come back to this function to output the halftoned result.
  1043. //
  1044. if (IsHTCompatibleSurfObj(pPDev,
  1045. psoSrc,
  1046. pxlo,
  1047. ISHTF_ALTFMT | ISHTF_HTXB | ISHTF_DSTPRIM_OK)) {
  1048. DWORD Rop;
  1049. if (!(Rop = (DWORD)(pPDev->Rop3CopyBits & 0xFF))) {
  1050. Rop = 0xCC;
  1051. }
  1052. PLOTDBG(DBG_COPYBITS, ("DrvCopyBits: HTCompatible: Rop=%08lx", Rop));
  1053. pPDev->Rop3CopyBits = 0xCC; // RESET!!!
  1054. return(OutputHTBitmap(pPDev,
  1055. psoSrc,
  1056. pco,
  1057. (PPOINTL)&rclDst,
  1058. NULL,
  1059. Rop,
  1060. NULL));
  1061. } else {
  1062. RECTL rclSrc;
  1063. rclSrc.left = pptlSrc->x;
  1064. rclSrc.top = pptlSrc->y;
  1065. rclSrc.right = rclSrc.left + (rclDst.right - rclDst.left);
  1066. rclSrc.bottom = rclSrc.top + (rclDst.bottom - rclDst.top);
  1067. //
  1068. // Validate that we only BLT the available source size
  1069. //
  1070. if ((rclSrc.right > psoSrc->sizlBitmap.cx) ||
  1071. (rclSrc.bottom > psoSrc->sizlBitmap.cy)) {
  1072. PLOTWARN(("DrvCopyBits: Engine passed SOURCE != DEST size, CLIP IT"));
  1073. rclSrc.right = psoSrc->sizlBitmap.cx;
  1074. rclSrc.bottom = psoSrc->sizlBitmap.cy;
  1075. rclDst.right = (LONG)(rclSrc.right - rclSrc.left + rclDst.left);
  1076. rclDst.bottom = (LONG)(rclSrc.bottom - rclSrc.top + rclDst.top);
  1077. }
  1078. PLOTDBG(DBG_COPYBITS, ("DrvCopyBits CALLING BandingHTBlt()"));
  1079. return(BandingHTBlt(pPDev, // pPDev
  1080. psoDst, // psoDst
  1081. psoSrc, // psoSrc
  1082. NULL, // psoMask,
  1083. pco, // pco
  1084. pxlo, // pxlo
  1085. NULL, // pca
  1086. NULL, // pptlHTOrg
  1087. &rclDst, // prclDst
  1088. &rclSrc, // prclSrc
  1089. NULL, // pptlMask
  1090. 0xCCCC, // HTRop3
  1091. FALSE)); // InvertMask
  1092. }
  1093. }
  1094. BOOL
  1095. DrvStretchBlt(
  1096. SURFOBJ *psoDst,
  1097. SURFOBJ *psoSrc,
  1098. SURFOBJ *psoMask,
  1099. CLIPOBJ *pco,
  1100. XLATEOBJ *pxlo,
  1101. COLORADJUSTMENT *pca,
  1102. POINTL *pptlBrushOrg,
  1103. PRECTL prclDst,
  1104. PRECTL prclSrc,
  1105. PPOINTL pptlMask,
  1106. ULONG iMode
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. This function halftones a source rectangle and optionally can invert
  1111. the source and handle a mask.
  1112. It also provides, StretchBlt capabilities between Device managed and
  1113. GDI managed surfaces. We want the driver to be able to write on GDI
  1114. managed bitmaps, especially when doing halftoning. This allows the same
  1115. algorithm to be used for both GDI and device surfaces.
  1116. This function is optional in drivers, it can return FALSE if it does
  1117. not know how to handle the work.
  1118. Arguments:
  1119. psoDst - This is a pointer to a SURFOBJ. It identifies the surface
  1120. on which to draw.
  1121. psoSrc - This SURFOBJ defines the source for the Blt operation. The
  1122. driver must call GDI Services to find out if this is a device
  1123. managed surface or a bitmap managed by GDI.
  1124. psoMask - This optional surface provides a mask for the source. It is
  1125. defined by a logic map, i.e. a bitmap with one bit per pel.
  1126. The mask is used to limit the area of the source that is
  1127. copied. When a mask is provided there is an implicit rop4 of
  1128. 0xCCAA, which means that the source should be copied wherever
  1129. the mask is 1, but the destination should be left alone
  1130. wherever the mask is 0.
  1131. When this argument is NULL there is an implicit rop4 of
  1132. 0xCCCC, which means that the source should be copied
  1133. everywhere in the source rectangle.
  1134. The mask will always be large enough to contain the source
  1135. rectangle, tiling does not need to be done.
  1136. pco - This is a pointer to a CLIPOBJ. GDI Services are provided
  1137. to enumerate the clipping region as a set of rectangles or
  1138. trapezoids. This limits the area of the destination that will
  1139. be modified.
  1140. Whenever possible, GDI will simplify the clipping involved.
  1141. However, unlike DrvBitBlt, DrvStretchBlt may be called with a
  1142. single clipping rectangle. This is necessary to prevent
  1143. roundoff errors in clipping the output.
  1144. pxlo - This is a pointer to an XLATEOBJ. It tells how color indices
  1145. should be translated between the source and target surfaces.
  1146. The XLATEOBJ can also be queried to find the RGB color for
  1147. any source index. A high quality stretching Blt will need
  1148. to interpolate colors in some cases.
  1149. pca - This is a pointer to COLORADJUSTMENT structure, if NULL it
  1150. specified that appiclation did not set any color adjustment
  1151. for this DC, and is up to the driver to provide default
  1152. adjustment
  1153. pptlBrushOrg- Pointer to the POINT structure to specified the location
  1154. where halftone brush should alignment to, if this pointer is
  1155. NULL then it assume that (0, 0) as origin of the brush
  1156. prclDst - This RECTL defines the area in the coordinate system of the
  1157. destination surface that can be modified.
  1158. The rectangle is defined by two points. These points are
  1159. not well ordered, i.e. the coordinates of the second point
  1160. are not necessarily larger than those of the first point.
  1161. The rectangle they describe does not include the lower and
  1162. right edges. DrvStretchBlt will never be called with an
  1163. empty destination rectangle.
  1164. DrvStretchBlt can do inversions in both x and y, this happens
  1165. when the destination rectangle is not well ordered.
  1166. prclSrc - This RECTL defines the area in the coordinate system of the
  1167. source surface that will be copied. The rectangle is defined
  1168. by two points, and will map onto the rectangle defined by
  1169. prclDst. The points of the source rectangle are well
  1170. ordered. DrvStretch will never be given an empty source
  1171. rectangle.
  1172. Note that the mapping to be done is defined by prclSrc and
  1173. prclDsst. To be precise, the given points in prclDst and
  1174. prclSrc lie on integer coordinates, which we consider to
  1175. correspond to pel centers. A rectangle defined by two such
  1176. points should be considered a geometric rectangle with two
  1177. vertices whose coordinates are the given points, but with 0.5
  1178. subtracted from each coordinate. (The POINTLs should just be
  1179. considered a shorthand notation for specifying these
  1180. fractional coordinate vertices.) Note thate the edges of any
  1181. such rectangle never intersect a pel, but go around a set of
  1182. pels. Note also that the pels that are inside the rectangle
  1183. are just what you would expect for a "bottom-right exclusive"
  1184. rectangle. The mapping to be done by DrvStretchBlt will map
  1185. the geometric source rectangle exactly onto the geometric
  1186. destination rectangle.
  1187. pptlMask - This POINTL specifies which pel in the given mask corresponds
  1188. to the upper left pel in the source rectangle. Ignore this
  1189. argument if there is no given mask.
  1190. iMode - This defines how source pels should be combined to get output
  1191. pels. The methods SB_OR, SB_AND, and SB_IGNORE are all simple
  1192. and fast. They provide compatibility for old applications,
  1193. but don't produce the best looking results for color surfaces.
  1194. SB_OR On a shrinking Blt the pels should be combined
  1195. with an OR operation. On a stretching Blt pels
  1196. should be replicated.
  1197. SB_AND On a shrinking Blt the pels should be combined
  1198. with an AND operation. On a stretching Blt
  1199. pels should be replicated.
  1200. SB_IGNORE On a shrinking Blt enough pels should be
  1201. ignored so that pels don't need to be combined.
  1202. On a stretching Blt pels should be replicated.
  1203. SB_BLEND RGB colors of output pels should be a linear
  1204. blending of the RGB colors of the pels that get
  1205. mapped onto them.
  1206. SB_HALFTONE The driver may use groups of pels in the output
  1207. surface to best approximate the color or gray
  1208. level of the input.
  1209. For this function we will ignored this parameter and always
  1210. output the SB_HALFTONE result
  1211. Return Value:
  1212. TRUE if sucessful FALSE if failed
  1213. Author:
  1214. 11-Feb-1993 Thu 19:52:29 created
  1215. 06-Jan-1994 Thu 04:34:37 updated
  1216. Make sure we do not do this for pen plotter
  1217. 23-Feb-1994 Wed 11:02:45 updated
  1218. Re-write and take banding the bitmap into account
  1219. 01-Mar-1994 Tue 10:55:03 updated
  1220. spawan out to a separate function and Make call to BandingHTBlt()
  1221. Revision History:
  1222. --*/
  1223. {
  1224. PPDEV pPDev;
  1225. UNREFERENCED_PARAMETER(iMode); // we always do HALFTONE
  1226. //
  1227. // get the pointer to our DEVDATA structure and make sure it is ours.
  1228. //
  1229. if (!(pPDev = SURFOBJ_GETPDEV(psoDst))) {
  1230. PLOTERR(("DrvStretchBlt: invalid pPDev"));
  1231. return(FALSE);
  1232. }
  1233. return(BandingHTBlt(pPDev, // pPDev
  1234. psoDst, // psoDst
  1235. psoSrc, // psoSrc
  1236. psoMask, // psoMask,
  1237. pco, // pco
  1238. pxlo, // pxlo
  1239. pca, // pca
  1240. pptlBrushOrg, // pptlHTOrg
  1241. prclDst, // prclDst
  1242. prclSrc, // prclSrc
  1243. pptlMask, // pptlMask
  1244. 0x88CC, // HTRo3
  1245. FALSE)); // InvertMask
  1246. }
  1247. BOOL
  1248. DrvBitBlt(
  1249. SURFOBJ *psoDst,
  1250. SURFOBJ *psoSrc,
  1251. SURFOBJ *psoMask,
  1252. CLIPOBJ *pco,
  1253. XLATEOBJ *pxlo,
  1254. PRECTL prclDst,
  1255. PPOINTL pptlSrc,
  1256. PPOINTL pptlMask,
  1257. BRUSHOBJ *pbo,
  1258. PPOINTL pptlBrushOrg,
  1259. ROP4 Rop4
  1260. )
  1261. /*++
  1262. Routine Description:
  1263. Provides general Blt capabilities to device managed surfaces. The Blt
  1264. might be from an Engine managed bitmap. In that case, the bitmap is
  1265. one of the standard format bitmaps. The driver will never be asked
  1266. to Blt to an Engine managed surface.
  1267. This function is required if any drawing is done to device managed
  1268. surfaces. The basic functionality required is:
  1269. 1 Blt from any standard format bitmap or device surface to a device
  1270. surface,
  1271. 2 with any ROP,
  1272. 3 optionally masked,
  1273. 4 with color index translation,
  1274. 5 with arbitrary clipping.
  1275. Engine services allow the clipping to be reduced to a series of clip
  1276. rectangles. A translation vector is provided to assist in color index
  1277. translation for palettes.
  1278. This is a large and complex function. It represents most of the work
  1279. in writing a driver for a raster display device that does not have
  1280. a standard format frame buffer. The Microsoft VGA driver provides
  1281. example code that supports the basic function completely for a planar
  1282. device.
  1283. NOTE: Plotters do not support copying from device bitmaps. Nor can they
  1284. perform raster operations on bitmaps. Therefore, it is not possible
  1285. to support ROPs which interact with the destination (ie inverting
  1286. the destination). The driver will do its best to map these ROPs
  1287. into ROPs utilizing functions on the Source or Pattern.
  1288. This driver supports the bitblt cases indicated below:
  1289. Device -> Memory No
  1290. Device -> Device No
  1291. Memory -> Memory No
  1292. Memory -> Device Yes
  1293. Brush -> Memory No
  1294. Brush -> Device Yes
  1295. Arguments:
  1296. psoDest - This is a pointer to a device managed SURFOBJ. It
  1297. identifies the surface on which to draw.
  1298. psoSrc - If the rop requires it, this SURFOBJ defines the source
  1299. for the Blt operation. The driver must call the Engine
  1300. Services to find out if this is a device managed surface
  1301. or a bitmap managed by the Engine.
  1302. psoMask - This optional surface provides another input for the
  1303. Rop4. It is defined by a logic map, i.e. a bitmap with
  1304. one bit per pel. The mask is typically used to limit the
  1305. area of the destination that should be modified. This
  1306. masking is accomplished by a Rop4 whose lower byte is AA,
  1307. leaving the destination unaffected when the mask is 0.
  1308. This mask, like a brush, may be of any size and is
  1309. assumed to tile to cover the destination of the Blt. If
  1310. this argument is NULL and a mask is required by the Rop4,
  1311. the implicit mask in the brush will be used.
  1312. pco - This is a pointer to a CLIPOBJ. Engine Services are
  1313. provided to enumerate the clipping region as a set of
  1314. rectangles or trapezoids. This limits the area of the
  1315. destination that will be modified. Whenever possible,
  1316. the Graphics Engine will simplify the clipping involved.
  1317. For example, BitBlt will never be called with exactly one
  1318. clipping rectangle. The Engine will have clipped the
  1319. destination rectangle before calling, so that no clipping
  1320. needs to be considered.
  1321. pxlo - This is a pointer to an XLATEOBJ. It tells how color
  1322. indices should be translated between the source and
  1323. target surfaces.
  1324. If the source surface is palette managed, then its colors
  1325. are represented by indices into a list of RGB colors.
  1326. In this case, the XLATEOBJ can be queried to get a
  1327. translate vector that will allow the device driver to
  1328. quickly translate any source index into a color index for
  1329. the destination.
  1330. The situation is more complicated when the source is, for
  1331. example, RGB but the destination is palette managed. In
  1332. this case a closest match to each source RGB must be
  1333. found in the destination palette. The XLATEOBJ provides
  1334. a service routine to do this matching. (The device
  1335. driver is allowed to do the matching itself when the
  1336. target palette is the default device palette.)
  1337. prclDst - This RECTL defines the area in the coordinate system of
  1338. the destination surface that will be modified. The
  1339. rectangle is defined as two points, upper left and lower
  1340. right. The lower and right edges of this rectangle are
  1341. not part of the Blt, i.e. the rectangle is lower right
  1342. exclusive. vBitBlt will never be called with an empty
  1343. destination rectangle, and the two points of the
  1344. rectangle will always be well ordered.
  1345. pptlSrc - This POINTL defines the upper left corner of the source
  1346. rectangle, if there is a source. Ignore this argument
  1347. if there is no source.
  1348. pptlMask - This POINTL defines which pel in the mask corresponds to
  1349. the upper left corner of the destination rectangle.
  1350. Ignore this argument if no mask is provided with psoMask.
  1351. pdbrush - This is a pointer to the device's realization of the
  1352. brush to be used in the Blt. The pattern for the Blt is
  1353. defined by this brush. Ignore this argument if the Rop4
  1354. does not require a pattern.
  1355. pptlBrushOrg - This is a pointer to a POINTL which defines the origin of
  1356. the brush. The upper left pel of the brush is aligned
  1357. here and the brush repeats according to its dimensions.
  1358. Ignore this argument if the Rop4 does not require a
  1359. pattern.
  1360. Rop4 - This raster operation defines how the mask, pattern,
  1361. source, and destination pels should be combined to
  1362. determine an output pel to be written on the destination
  1363. surface.
  1364. This is a quaternary raster operation, which is a natural
  1365. extension of the usual ternary rop3. There are 16
  1366. relevant bits in the Rop4, these are like the 8 defining
  1367. bits of a rop3. (We ignore the other bits of the rop3,
  1368. which are redundant.) The simplest way to implement a
  1369. Rop4 is to consider its two bytes separately. The lower
  1370. byte specifies a rop3 that should be computed wherever
  1371. the mask is 0. The high byte specifies a rop3 that
  1372. should then be computed and applied wherever the mask
  1373. is 1.
  1374. Return Value:
  1375. TRUE if sucessfule FALSE otherwise
  1376. Author:
  1377. 04-Dec-1990
  1378. Wrote it.
  1379. 27-Mar-1992 Fri 00:08:43 updated
  1380. 1) Remove 'pco' parameter and replaced it with prclClipBound parameter,
  1381. since pco is never referenced, prclClipBound is used for the
  1382. halftone.
  1383. 2) Add another parameter to do NOTSRCCOPY
  1384. 11-Feb-1993 Thu 21:29:15 updated
  1385. Modified so that it call DrvStretchBlt(HALFTONE) when it can.
  1386. 18-Dec-1993 Sat 09:08:16 updated
  1387. Clean up for plotter driver
  1388. 06-Jan-1994 Thu 04:34:37 updated
  1389. Make sure we do not do this for pen plotter
  1390. 15-Jan-1994 Sat 04:02:22 updated
  1391. Re-write
  1392. 17-Mar-1994 Thu 22:36:42 updated
  1393. Changed it so we only use PATTERN=psoMask if the ROP4 do not required
  1394. PATTERNs and a MASK is required
  1395. Revision History:
  1396. --*/
  1397. {
  1398. PPDEV pPDev;
  1399. DWORD Rop3FG;
  1400. DWORD Rop3BG;
  1401. RECTL rclSrc;
  1402. RECTL rclPat;
  1403. UINT i;
  1404. BOOL Ok = TRUE;
  1405. //
  1406. // if the source is NULL it must be a fill, so call the fill code,
  1407. //
  1408. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: ROP4 = %08lx", Rop4));
  1409. PLOTASSERT(1, "DrvBitBlt: Invalid ROP code = %08lx",
  1410. (Rop4 & 0xffff0000) == 0, Rop4);
  1411. //
  1412. // get the pointer to our DEVDATA structure and make sure it is ours.
  1413. //
  1414. if (!(pPDev = SURFOBJ_GETPDEV(psoDst))) {
  1415. PLOTERR(("DrvBithBlt: invalid pPDev"));
  1416. return(FALSE);
  1417. }
  1418. if (IS_RASTER(pPDev)) {
  1419. i = (UINT)pPDev->pPlotGPC->ROPLevel;
  1420. } else {
  1421. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: Pen Plotter: TRY ROP_LEVEL_0"));
  1422. i = ROP_LEVEL_0;
  1423. }
  1424. Rop3BG = (DWORD)ROP4_BG_ROP(Rop4);
  1425. Rop3FG = (DWORD)ROP4_FG_ROP(Rop4);
  1426. switch (i) {
  1427. case ROP_LEVEL_0:
  1428. //
  1429. // For RopLevel 0, or Pen Plotter we will only process the pattern
  1430. // which is compatible with our device
  1431. //
  1432. if (ROP3_NEED_PAT(Rop3FG)) {
  1433. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: Device ROP_LEVEL_0, NEED PAT"));
  1434. if (GetColor(pPDev, pbo, NULL, NULL, Rop3FG) <= 0) {
  1435. PLOTWARN(("DrvBitBlt: NOT Device Comptible PAT"));
  1436. return(TRUE);
  1437. }
  1438. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: Device ROP_LEVEL_0, TRY COMPATIBLE PAT"));
  1439. } else {
  1440. PLOTWARN(("DrvBitBlt: Device ROP_LEVEL_0, CANNOT Do RASTER BLT"));
  1441. return(TRUE);
  1442. }
  1443. //
  1444. // Make it PAT Copy
  1445. //
  1446. Rop4 = 0xF0F0;
  1447. Rop3BG =
  1448. Rop3FG = 0xF0;
  1449. break;
  1450. case ROP_LEVEL_1:
  1451. //
  1452. // Can only do ROP1 SRC COPY/NOT SRCCOPY
  1453. //
  1454. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: Device ROP_LEVEL_1, Rop4=%08lx", Rop4));
  1455. switch(Rop4 = ROP4_FG_ROP(Rop4)) {
  1456. case 0xAA:
  1457. case 0xCC:
  1458. case 0x33:
  1459. break;
  1460. default:
  1461. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: Make ROP4 = 0xCC"));
  1462. Rop4 = 0xCC;
  1463. break;
  1464. }
  1465. Rop4 |= (Rop4 << 8);
  1466. break;
  1467. case ROP_LEVEL_2:
  1468. case ROP_LEVEL_3:
  1469. break;
  1470. default:
  1471. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: Device RopLevel=%ld, do nothing",
  1472. (DWORD)pPDev->pPlotGPC->ROPLevel));
  1473. return(TRUE);
  1474. }
  1475. //
  1476. // Do DrvStrethcBlt (HALFTONE) first if we can. Since there is no way
  1477. // for us to read back the device surface we can only try our best
  1478. // to simulate the requested drawing operation.
  1479. //
  1480. if (pptlSrc) {
  1481. rclSrc.left = pptlSrc->x;
  1482. rclSrc.top = pptlSrc->y;
  1483. } else {
  1484. rclSrc.left =
  1485. rclSrc.top = 0;
  1486. }
  1487. rclSrc.right = rclSrc.left + (prclDst->right - prclDst->left);
  1488. rclSrc.bottom = rclSrc.top + (prclDst->bottom - prclDst->top);
  1489. switch (Rop4) {
  1490. case 0xAAAA: // D
  1491. return(TRUE);
  1492. case 0xAACC:
  1493. case 0xCCAA:
  1494. case 0xAA33:
  1495. case 0x33AA:
  1496. //
  1497. // If we have ~S (NOT SOURCE) then we want to make the non-mask area
  1498. // black , we do this using S^D (0x66).
  1499. //
  1500. if ((Rop4 == 0xAA33) || (Rop4 == 0x33AA)) {
  1501. Rop4 = 0x6666;
  1502. } else {
  1503. Rop4 = 0x8888;
  1504. }
  1505. return(BandingHTBlt(pPDev, // pPDev
  1506. psoDst, // psoDst
  1507. psoSrc, // psoSrc
  1508. psoMask, // psoMask,
  1509. pco, // pco
  1510. pxlo, // pxlo
  1511. NULL, // pca
  1512. pptlBrushOrg, // pptlHTOrg
  1513. prclDst, // prclDst
  1514. &rclSrc, // prclSrc
  1515. pptlMask, // pptlMask
  1516. (WORD)Rop4, // HTRo3
  1517. Rop3FG == 0xAA)); // InvertMask
  1518. case 0x3333: // ~S
  1519. case 0xCCCC: // S
  1520. //
  1521. // We will output the bitmap directly to the surface if the following
  1522. // conditions are all met
  1523. //
  1524. // 1. SRC = STYPE_BITMAP
  1525. // 2. Format is compatible with HT
  1526. //
  1527. if ((psoSrc->iType == STYPE_BITMAP) &&
  1528. (IsHTCompatibleSurfObj(pPDev,
  1529. psoSrc,
  1530. pxlo,
  1531. ISHTF_ALTFMT |
  1532. ISHTF_HTXB |
  1533. ISHTF_DSTPRIM_OK))) {
  1534. return(OutputHTBitmap(pPDev,
  1535. psoSrc,
  1536. pco,
  1537. (PPOINTL)prclDst,
  1538. &rclSrc,
  1539. Rop4 & 0xFF,
  1540. NULL));
  1541. } else {
  1542. //
  1543. // Call BandingHTBlt(Rop4) to do the job
  1544. //
  1545. return(BandingHTBlt(pPDev, // pPDev
  1546. psoDst, // psoDst
  1547. psoSrc, // psoSrc
  1548. NULL, // psoMask,
  1549. pco, // pco
  1550. pxlo, // pxlo
  1551. NULL, // pca
  1552. pptlBrushOrg, // pptlHTOrg
  1553. prclDst, // prclDst
  1554. &rclSrc, // prclSrc
  1555. NULL, // pptlMask
  1556. (WORD)Rop4, // HTRo3
  1557. FALSE)); // InvertMask
  1558. }
  1559. break;
  1560. default:
  1561. if ((Rop3BG != Rop3FG) && // NEED MASK?
  1562. (!ROP3_NEED_DST(Rop3BG)) &&
  1563. (!ROP3_NEED_DST(Rop3FG))) {
  1564. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: Not required DEST, Calling EngBitBlt()"));
  1565. if (!(Ok = EngBitBlt(psoDst, // psoDst
  1566. psoSrc, // psoSrc
  1567. psoMask, // psoMask
  1568. pco, // pco
  1569. pxlo, // pxlo
  1570. prclDst, // prclDst
  1571. pptlSrc, // pptlSrc
  1572. pptlMask, // pptlMask
  1573. pbo, // pbo
  1574. pptlBrushOrg, // pptlBrushOrg ZERO
  1575. Rop4))) {
  1576. PLOTERR(("DrvBitBlt: EngBitBlt(%04lx) FAILED", Rop4));
  1577. }
  1578. } else {
  1579. CLONESO CloneSO[CSI_TOTAL];
  1580. //
  1581. // Clear all the clone surface memory
  1582. //
  1583. ZeroMemory(CloneSO, sizeof(CloneSO));
  1584. //
  1585. // We will using psoMask as Pattern ONLY IF
  1586. //
  1587. // 1. ROP4 required a MASK
  1588. // 2. Forground NOT required a PATTERN
  1589. // 3. Background NOT reauired a PATTERN
  1590. //
  1591. if ((Rop3BG != Rop3FG) &&
  1592. (!ROP3_NEED_PAT(Rop3BG)) &&
  1593. (!ROP3_NEED_PAT(Rop3FG))) {
  1594. //
  1595. // We will condense the ROP4 to a ROP3 and use the psoMAsk
  1596. // as the Pattern. We must make sure the pptlBrushOrg is NULL
  1597. // so we DON'T align rclPat on the destination.
  1598. //
  1599. Rop3FG = (Rop3BG & 0xF0) | (Rop3FG & 0x0F);
  1600. Rop3BG = 0xAA;
  1601. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: Rop4=%04lx, Pattern=psoMask=%08lx, Rop3=%02lx/%02lx",
  1602. Rop4, psoMask, Rop3BG, Rop3FG));
  1603. rclPat.left = pptlMask->x;
  1604. rclPat.top = pptlMask->y;
  1605. rclPat.right = rclPat.left + (rclSrc.right - rclSrc.left);
  1606. rclPat.bottom = rclPat.top + (rclSrc.bottom - rclSrc.top);
  1607. pptlBrushOrg = NULL;
  1608. } else {
  1609. //
  1610. // We will NOT do the background operation for now
  1611. //
  1612. if (Rop3FG == 0xAA) {
  1613. Rop3FG = Rop3BG;
  1614. } else {
  1615. Rop3BG = Rop3FG;
  1616. }
  1617. //
  1618. // We have a real pattern so make sure we aligned rclPat on
  1619. // the destination correctly by passing a valid pptlBrushOrg,
  1620. // NOTE: The rclPat will be setup by CloneBitBltSURFOBJ()
  1621. //
  1622. psoMask = NULL;
  1623. if (!pptlBrushOrg) {
  1624. pptlBrushOrg = (PPOINTL)&ptlZeroOrigin;
  1625. }
  1626. }
  1627. if (!(Ok = CloneBitBltSURFOBJ(pPDev,
  1628. psoDst,
  1629. psoSrc,
  1630. psoMask,
  1631. pxlo,
  1632. prclDst,
  1633. &rclSrc,
  1634. &rclPat,
  1635. pbo,
  1636. CloneSO,
  1637. Rop3BG,
  1638. Rop3FG))) {
  1639. PLOTDBG(DBG_BITBLT, ("DrvBitBlt: CloneBitbltSURFOBJ: failed"));
  1640. }
  1641. if (CloneSO[CSI_SRC].pso) {
  1642. psoSrc = CloneSO[CSI_SRC].pso;
  1643. pxlo = NULL;
  1644. }
  1645. //
  1646. // Only do background if BG != FG, and BG != DEST
  1647. //
  1648. if ((Ok) && (Rop3BG != Rop3FG) && (Rop3BG != 0xAA)) {
  1649. if (!(Ok = DoRop3(pPDev,
  1650. psoDst,
  1651. psoSrc,
  1652. CloneSO[CSI_PAT].pso,
  1653. CloneSO[CSI_TMP].pso,
  1654. pco,
  1655. pxlo,
  1656. prclDst,
  1657. &rclSrc,
  1658. &rclPat,
  1659. pptlBrushOrg,
  1660. pbo,
  1661. Rop3BG))) {
  1662. PLOTERR(("DrvBitBlt(Rop3BG=%02lx) FAILED", Rop3BG));
  1663. }
  1664. }
  1665. if ((Ok) && (Rop3FG != 0xAA)) {
  1666. if (!(Ok = DoRop3(pPDev,
  1667. psoDst,
  1668. psoSrc,
  1669. CloneSO[CSI_PAT].pso,
  1670. CloneSO[CSI_TMP].pso,
  1671. pco,
  1672. pxlo,
  1673. prclDst,
  1674. &rclSrc,
  1675. &rclPat,
  1676. pptlBrushOrg,
  1677. pbo,
  1678. Rop3FG))) {
  1679. PLOTERR(("DrvBitBlt(Rop3FG=%02lx) FAILED", Rop3FG));
  1680. }
  1681. }
  1682. //
  1683. // Release all cloned objects
  1684. //
  1685. for (i = 0; i < CSI_TOTAL; i++) {
  1686. if (CloneSO[i].pso) {
  1687. PLOTDBG(DBG_CSI, ("DrvBitBlt: EngUnlockSuface(%hs)", pCSIName[i]));
  1688. EngUnlockSurface(CloneSO[i].pso);
  1689. }
  1690. if (CloneSO[i].hBmp) {
  1691. PLOTDBG(DBG_CSI, ("DrvBitBlt: EngDeleteSurface(%hs)", pCSIName[i]));
  1692. if (!EngDeleteSurface((HSURF)CloneSO[i].hBmp)) {
  1693. PLOTERR(("PLOTTER: DrvBitBlt, EngDeleteSurface(%ld:%p) FAILED",
  1694. (DWORD)i, (DWORD_PTR)CloneSO[i].hBmp));
  1695. }
  1696. }
  1697. }
  1698. }
  1699. break;
  1700. }
  1701. return(Ok);
  1702. }
  1703. ULONG
  1704. DrvDitherColor(
  1705. DHPDEV dhpdev,
  1706. ULONG iMode,
  1707. ULONG rgbColor,
  1708. ULONG *pulDither
  1709. )
  1710. /*++
  1711. Routine Description:
  1712. This is the hooked brush creation function, it asks CreateHalftoneBrush()
  1713. to do the actual work (By returning DCR_HALFTONE).
  1714. Arguments:
  1715. dhpdev - DHPDEV passed, it is our pDEV
  1716. iMode - Not used
  1717. rgbColor - Solid rgb color to be used
  1718. pulDither - buffer to put the halftone brush.
  1719. Return Value:
  1720. BOOLEAN
  1721. Author:
  1722. 02-May-1995 Tue 10:34:10 created
  1723. Revision History:
  1724. --*/
  1725. {
  1726. UNREFERENCED_PARAMETER(dhpdev);
  1727. UNREFERENCED_PARAMETER(iMode);
  1728. UNREFERENCED_PARAMETER(rgbColor);
  1729. UNREFERENCED_PARAMETER(pulDither);
  1730. return(DCR_HALFTONE);
  1731. }