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.

1769 lines
50 KiB

  1. /*++
  2. Copyright (c) 1990-1999 Microsoft Corporation
  3. Module Name:
  4. stretch.c
  5. Abstract:
  6. This module contains all the StretchBlt/BitBlt codes which handle halftoned
  7. sources
  8. [Environment:]
  9. GDI Device Driver - Plotter.
  10. [Notes:]
  11. Revision History:
  12. --*/
  13. #include "raster.h"
  14. #define DW_ALIGN(x) (((DWORD)(x) + 3) & ~(DWORD)3)
  15. #define ROP4_NEED_MASK(Rop4) (((Rop4 >> 8) & 0xFF) != (Rop4 & 0xFF))
  16. #define ROP3_NEED_PAT(Rop3) (((Rop3 >> 4) & 0x0F) != (Rop3 & 0x0F))
  17. #define ROP3_NEED_SRC(Rop3) (((Rop3 >> 2) & 0x33) != (Rop3 & 0x33))
  18. #define ROP3_NEED_DST(Rop3) (((Rop3 >> 1) & 0x55) != (Rop3 & 0x55))
  19. #define ROP4_FG_ROP(Rop4) (Rop4 & 0xFF)
  20. #define ROP4_BG_ROP(Rop4) ((Rop4 >> 8) & 0xFF)
  21. #if DBG
  22. BOOL DbgWhiteRect = FALSE;
  23. BOOL DbgBitBlt = FALSE;
  24. BOOL DbgCopyBits = FALSE;
  25. #define _DBGP(i,x) if (i) { (DbgPrint x); }
  26. #else
  27. #define _DBGP(i,x)
  28. #endif //DBG
  29. #define DELETE_SURFOBJ(pso, phBmp) \
  30. { \
  31. if (pso) { EngUnlockSurface(pso); pso=NULL; } \
  32. if (*(phBmp)) { EngDeleteSurface((HSURF)*(phBmp)); *(phBmp)=NULL; } \
  33. }
  34. #ifdef WINNT_40 //NT 4.0
  35. #if DBG
  36. BOOL DbgDitherColor = FALSE;
  37. #endif
  38. extern HSEMAPHORE hSemBrushColor;
  39. extern LPDWORD pBrushSolidColor;
  40. #endif //WINNT_40
  41. ROP4 InvertROPs(
  42. ROP4 Rop4
  43. )
  44. /*++
  45. Routine Description:
  46. This function remaps ROPs intended for RGB mode into CMY mode for 8bpp
  47. monochrome printing.
  48. --*/
  49. {
  50. // Rops are remapped for CMY vs RGB rendering by reversing the order of
  51. // the bits in the ROP and inverting the result.
  52. //
  53. if ((Rop4 & 0xff) == ((Rop4 >> 8) & 0xff))
  54. {
  55. ROP4 NewRop = 0;
  56. if (Rop4 & 0x01) NewRop |= 0x8080;
  57. if (Rop4 & 0x02) NewRop |= 0x4040;
  58. if (Rop4 & 0x04) NewRop |= 0x2020;
  59. if (Rop4 & 0x08) NewRop |= 0x1010;
  60. if (Rop4 & 0x10) NewRop |= 0x0808;
  61. if (Rop4 & 0x20) NewRop |= 0x0404;
  62. if (Rop4 & 0x40) NewRop |= 0x0202;
  63. if (Rop4 & 0x80) NewRop |= 0x0101;
  64. NewRop ^= 0xFFFF;
  65. #ifdef DBGROP
  66. if (NewRop != Rop4)
  67. {
  68. DbgPrint ("ROP remapped: %4x -> %4x\n",Rop4,NewRop);
  69. }
  70. #endif
  71. Rop4 = NewRop;
  72. }
  73. /*
  74. if (Rop4 == 0xB8B8) // required for bug 22915
  75. Rop4 = 0xE2E2;
  76. else if (Rop4 == 0x0000) // BLACKNESS
  77. Rop4 = 0xFFFF;
  78. else if (Rop4 == 0xFFFF) // WHITENESS
  79. Rop4 = 0x0000;
  80. else if (Rop4 == 0x8888) // SRCAND, required for bug 36192
  81. Rop4 = 0xEEEE;
  82. else if (Rop4 == 0xEEEE) // SRCPAINT, remap so it differs from SCRAND
  83. Rop4 = 0x8888;
  84. else if (Rop4 == 0xC0C0) // MERGECOPY
  85. Rop4 = 0xFCFC;
  86. else if (Rop4 == 0xFBFB) // PATPAINT
  87. Rop4 = 0x2020;
  88. */
  89. return Rop4;
  90. }
  91. BOOL DrawWhiteRect(
  92. PDEV *pPDev,
  93. RECTL *pDest,
  94. CLIPOBJ *pco
  95. )
  96. /*++
  97. Routine Description:
  98. This function sends a white rectangle directly to the device if fonts
  99. have been sent to the printer for this band. This is used to clear
  100. the region where an image will be drawn.
  101. Arguments:
  102. pPDev - pointer to PDEV structure
  103. pDest - pointer to destination RECTL
  104. pco - pointer to CLIPOBJ
  105. --*/
  106. {
  107. RECTL rcClip;
  108. BYTE bMask;
  109. BOOL bSendRectFill;
  110. LONG i;
  111. PBYTE pbScanBuf;
  112. BOOL bMore;
  113. DWORD dwMaxRects;
  114. if (DRIVER_DEVICEMANAGED (pPDev)) // Device Managed Surface
  115. return 0;
  116. //
  117. // only send the clearing rectangle if the device supports rectangles,
  118. // text has been downloaded, it is not a complex clip region.
  119. //
  120. if (!(pPDev->fMode & PF_RECT_FILL) ||
  121. !(pPDev->fMode & PF_DOWNLOADED_TEXT) ||
  122. (pco && pco->iDComplexity == DC_COMPLEX && pco->iFComplexity != FC_RECT4) ||
  123. !(COMMANDPTR(pPDev->pDriverInfo,CMD_RECTWHITEFILL)) ||
  124. pPDev->pdmPrivate->dwFlags & DXF_TEXTASGRAPHICS ||
  125. pPDev->fMode2 & PF2_MIRRORING_ENABLED)
  126. {
  127. return 0;
  128. }
  129. //
  130. // if complex clip but FC_RECT4 then there won't be more than 4 rectangles
  131. //
  132. if (pco && pco->iFComplexity == FC_RECT4)
  133. {
  134. if (CLIPOBJ_cEnumStart(pco,TRUE,CT_RECTANGLES,CD_ANY,4) == -1)
  135. return 0;
  136. }
  137. bMore = FALSE;
  138. dwMaxRects = 0;
  139. do
  140. {
  141. //
  142. // clip to printable region or band
  143. //
  144. rcClip.left = MAX(0, pDest->left);
  145. rcClip.top = MAX(0, pDest->top);
  146. rcClip.right = MIN(pPDev->szBand.cx,pDest->right);
  147. rcClip.bottom = MIN(pPDev->szBand.cy,pDest->bottom);
  148. //
  149. // if clip rectangle or complex clip FC_RECT4 we need to apply
  150. // clip rectangle to input rectangle.
  151. //
  152. if (pco)
  153. {
  154. if (pco->iDComplexity == DC_RECT)
  155. {
  156. if (rcClip.left < pco->rclBounds.left)
  157. rcClip.left = pco->rclBounds.left;
  158. if (rcClip.top < pco->rclBounds.top)
  159. rcClip.top = pco->rclBounds.top;
  160. if (rcClip.right > pco->rclBounds.right)
  161. rcClip.right = pco->rclBounds.right;
  162. if (rcClip.bottom > pco->rclBounds.bottom)
  163. rcClip.bottom = pco->rclBounds.bottom;
  164. }
  165. else if (pco->iFComplexity == FC_RECT4)
  166. {
  167. ENUMRECTS eRect;
  168. bMore = CLIPOBJ_bEnum(pco,(ULONG)sizeof(ENUMRECTS),(ULONG *)&eRect);
  169. if (eRect.c != 1)
  170. continue;
  171. if (rcClip.left < eRect.arcl[0].left)
  172. rcClip.left = eRect.arcl[0].left;
  173. if (rcClip.top < eRect.arcl[0].top)
  174. rcClip.top = eRect.arcl[0].top;
  175. if (rcClip.right > eRect.arcl[0].right)
  176. rcClip.right = eRect.arcl[0].right;
  177. if (rcClip.bottom > eRect.arcl[0].bottom)
  178. rcClip.bottom = eRect.arcl[0].bottom;
  179. }
  180. }
  181. //
  182. // At this point we will check whether anything has been directly downloaded to the
  183. // printer (ie text) to see if we need to even bother drawing the erase rectangle.
  184. //
  185. bMask = BGetMask(pPDev, &rcClip);
  186. bSendRectFill = FALSE;
  187. for (i = rcClip.top; i < rcClip.bottom ; i++)
  188. {
  189. if (pPDev->pbScanBuf[i] & bMask)
  190. {
  191. bSendRectFill = TRUE;
  192. break;
  193. }
  194. }
  195. //
  196. // check if we end up with an empty rect.
  197. //
  198. if (bSendRectFill && rcClip.right > rcClip.left && rcClip.bottom > rcClip.top)
  199. {
  200. DRAWPATRECT PatRect;
  201. PatRect.wStyle = 1; // white rectangle
  202. PatRect.wPattern = 0; // pattern not used
  203. PatRect.ptPosition.x = rcClip.left;
  204. PatRect.ptPosition.y = rcClip.top;
  205. PatRect.ptSize.x = rcClip.right - rcClip.left;
  206. PatRect.ptSize.y = rcClip.bottom - rcClip.top;
  207. DrawPatternRect(pPDev,&PatRect);
  208. dwMaxRects++;
  209. _DBGP(DbgWhiteRect,("DrawWhiteRect (%d,%d) (%d,%d)\n",
  210. rcClip.left+pPDev->rcClipRgn.left,
  211. rcClip.top+pPDev->rcClipRgn.top,
  212. rcClip.right+pPDev->rcClipRgn.left,
  213. rcClip.bottom+pPDev->rcClipRgn.top));
  214. }
  215. } while (bMore && dwMaxRects < 4);
  216. return (BOOL)dwMaxRects;
  217. }
  218. LONG
  219. GetBmpDelta(
  220. DWORD SurfaceFormat,
  221. DWORD cx
  222. )
  223. /*++
  224. Routine Description:
  225. This function calculate total bytes needed for a single scan line in the
  226. bitmap according to its format and alignment requirement.
  227. Arguments:
  228. SurfaceFormat - Surface format of the bitmap, this is must one of the
  229. standard format which defined as BMF_xxx
  230. cx - Total Pels per scan line in the bitmap.
  231. Return Value:
  232. The return value is the total bytes in one scan line if it is greater than
  233. zero
  234. Author:
  235. 19-Jan-1994 Wed 16:19:39 created -by- Daniel Chou (danielc)
  236. Revision History:
  237. --*/
  238. {
  239. DWORD Delta = cx;
  240. switch (SurfaceFormat) {
  241. case BMF_32BPP:
  242. Delta <<= 5;
  243. break;
  244. case BMF_24BPP:
  245. Delta *= 24;
  246. break;
  247. case BMF_16BPP:
  248. Delta <<= 4;
  249. break;
  250. case BMF_8BPP:
  251. Delta <<= 3;
  252. break;
  253. case BMF_4BPP:
  254. Delta <<= 2;
  255. break;
  256. case BMF_1BPP:
  257. break;
  258. default:
  259. _DBGP(1, ("\nGetBmpDelta: Invalid BMF_xxx format = %ld", SurfaceFormat));
  260. break;
  261. }
  262. Delta = (DWORD)DW_ALIGN((Delta + 7) >> 3);
  263. return((LONG)Delta);
  264. }
  265. SURFOBJ *
  266. CreateBitmapSURFOBJ(
  267. PDEV *pPDev,
  268. HBITMAP *phBmp,
  269. LONG cxSize,
  270. LONG cySize,
  271. DWORD Format
  272. )
  273. /*++
  274. Routine Description:
  275. This function create a bitmap and lock the bitmap to return a SURFOBJ
  276. Arguments:
  277. pPDev - Pointer to our PDEV
  278. phBmp - Pointer the HBITMAP location to be returned for the bitmap
  279. cxSize - CX size of bitmap to be created
  280. cySize - CY size of bitmap to be created
  281. Format - one of BMF_xxx bitmap format to be created
  282. Return Value:
  283. SURFOBJ if sucessful, NULL if failed
  284. Author:
  285. 19-Jan-1994 Wed 16:31:50 created -by- Daniel Chou (danielc)
  286. Revision History:
  287. --*/
  288. {
  289. SURFOBJ *pso = NULL;
  290. SIZEL szlBmp;
  291. szlBmp.cx = cxSize;
  292. szlBmp.cy = cySize;
  293. if (*phBmp = EngCreateBitmap(szlBmp,
  294. GetBmpDelta(Format, cxSize),
  295. Format,
  296. BMF_TOPDOWN | BMF_NOZEROINIT,
  297. NULL)) {
  298. if (EngAssociateSurface((HSURF)*phBmp, (HDEV)pPDev->devobj.hEngine, 0)) {
  299. if (pso = EngLockSurface((HSURF)*phBmp)) {
  300. //
  301. // Sucessful lock it down, return it
  302. //
  303. return(pso);
  304. } else {
  305. _DBGP(1, ("\nCreateBmpSurfObj: EngLockSruface(hBmp) failed!"));
  306. }
  307. } else {
  308. _DBGP(1, ("\nCreateBmpSurfObj: EngAssociateSurface() failed!"));
  309. }
  310. } else {
  311. _DBGP(1, ("\nCreateBMPSurfObj: FAILED to create Bitmap Format=%ld, %ld x %ld",
  312. Format, cxSize, cySize));
  313. }
  314. DELETE_SURFOBJ(pso, phBmp);
  315. return(NULL);
  316. }
  317. BOOL
  318. IsHTCompatibleSurfObj(
  319. PAL_DATA *pPD,
  320. SURFOBJ *psoDst,
  321. SURFOBJ *psoSrc,
  322. XLATEOBJ *pxlo
  323. )
  324. /*++
  325. Routine Description:
  326. This function determine if the surface obj is compatble with plotter
  327. halftone output format.
  328. Arguments:
  329. pPD - Pointer to the PAL_DATA
  330. psoDst - Our desitnation format
  331. psoSrc - Source format to be checked againest
  332. pxlo - engine XLATEOBJ for source -> postscript translation
  333. Return Value:
  334. BOOLEAN true if the psoSrc is compatible with halftone output format, if
  335. return value is true, the pDrvHTInfo->pHTXB is a valid trnaslation from
  336. indices to 3 planes
  337. Revision History:
  338. --*/
  339. {
  340. ULONG *pSrcPal = NULL;
  341. UINT SrcBmpFormat;
  342. UINT DstBmpFormat;
  343. UINT cPal;
  344. BOOL Ok = TRUE;
  345. if ((SrcBmpFormat = (UINT)psoSrc->iBitmapFormat) >
  346. (DstBmpFormat = (UINT)psoDst->iBitmapFormat))
  347. {
  348. return(FALSE);
  349. }
  350. if ((!pxlo) || (pxlo->flXlate & XO_TRIVIAL))
  351. {
  352. #ifdef WINNT_40
  353. //
  354. // The palette in NT4 always indexed, so if the the xlate is trivial
  355. // but the Source type is not indexed then we have problem
  356. //
  357. if ((pxlo) &&
  358. ((pxlo->iSrcType & (PAL_INDEXED |
  359. PAL_BITFIELDS |
  360. PAL_BGR |
  361. PAL_RGB)) != PAL_INDEXED))
  362. {
  363. return FALSE;
  364. }
  365. #endif
  366. return((BOOL)(SrcBmpFormat == DstBmpFormat));
  367. }
  368. switch (DstBmpFormat)
  369. {
  370. case BMF_1BPP:
  371. case BMF_4BPP:
  372. case BMF_8BPP:
  373. //
  374. // If we cannot get the source palette memory, we will be in the
  375. // loop forever.
  376. //
  377. if ((pPD->wPalGdi > 0) &&
  378. (pxlo->flXlate & XO_TABLE) &&
  379. (cPal = (UINT)pxlo->cEntries))
  380. {
  381. if ((pSrcPal = (ULONG *)MemAlloc(cPal * sizeof(ULONG))))
  382. {
  383. ULONG *pUL;
  384. XLATEOBJ_cGetPalette(pxlo, XO_SRCPALETTE, cPal, pSrcPal);
  385. //
  386. // Assume palette is OK unless we can't find a match
  387. //
  388. pUL = pSrcPal;
  389. while (cPal--)
  390. {
  391. ULONG *pMyPal = pPD->ulPalCol;
  392. ULONG Pal = *pUL++;
  393. UINT j = (UINT)pPD->wPalGdi;
  394. do
  395. {
  396. if (*pMyPal++ == Pal)
  397. break;
  398. } while (--j);
  399. //
  400. // Didn't find matching color so set to FALSE
  401. //
  402. if (j == 0)
  403. {
  404. Ok = FALSE;
  405. break;
  406. }
  407. }
  408. MemFree(pSrcPal);
  409. }
  410. }
  411. else
  412. Ok = FALSE;
  413. break;
  414. case BMF_24BPP:
  415. //
  416. // Since device surface is 24-bpp, we will assume all source OK
  417. //
  418. break;
  419. default:
  420. _DBGP(1, ("\nUnidrv:IsHTCompatibleSurfObj: Invalid Dest format = %ld",
  421. DstBmpFormat));
  422. Ok = FALSE;
  423. break;
  424. }
  425. return(Ok);
  426. }
  427. BOOL
  428. CreateMaskSurface(
  429. SURFOBJ *psoSrc,
  430. SURFOBJ *psoMsk,
  431. ULONG iTransColor
  432. )
  433. /*++
  434. Routine Description:
  435. This function creates a mask surface based on the transparent color of the source surface.
  436. Arguments:
  437. psoMsk - Mask surface to be created
  438. psoSrc - Source format to be checked againest
  439. iTransColor - Transparent color to compare against
  440. Revision History:
  441. --*/
  442. {
  443. BYTE *pSrc;
  444. BYTE *pMsk;
  445. INT iRow,iCol;
  446. union {
  447. BYTE bColor[4];
  448. USHORT sColor[2];
  449. ULONG lColor;
  450. } u;
  451. //
  452. // Check for NULL pointers.
  453. // We dont create mask for 1bpp surface, because the
  454. // mask surface will either be identical to the original
  455. // surface or it will be its inverse. The same
  456. // affect can be achieved by manipulating the pxlo
  457. //
  458. if ( NULL == psoSrc ||
  459. NULL == psoMsk ||
  460. NULL == psoSrc->pvScan0 ||
  461. NULL == psoMsk->pvScan0 ||
  462. psoSrc->iBitmapFormat == BMF_1BPP )
  463. {
  464. ASSERT((FALSE, "Invalid Parameter"));
  465. return FALSE;
  466. }
  467. u.lColor = iTransColor;
  468. for (iRow = 0;iRow < psoSrc->sizlBitmap.cy;iRow++)
  469. {
  470. BYTE Mask = 0xFF;
  471. pSrc = (BYTE *)(psoSrc->pvScan0) + (psoSrc->lDelta * iRow);
  472. pMsk = (BYTE *)(psoMsk->pvScan0) + (psoMsk->lDelta * iRow);
  473. memset(pMsk,0xff,(psoMsk->sizlBitmap.cx+7) >> 3);
  474. if (psoSrc->iBitmapFormat == BMF_8BPP)
  475. {
  476. for (iCol = 0;iCol < psoSrc->sizlBitmap.cx;iCol++)
  477. {
  478. if (*pSrc == u.bColor[0])
  479. {
  480. pMsk[iCol >> 3] &= ~(0x80 >> (iCol & 7));
  481. }
  482. pSrc += 1;
  483. }
  484. }
  485. else if (psoSrc->iBitmapFormat == BMF_16BPP)
  486. {
  487. for (iCol = 0;iCol < psoSrc->sizlBitmap.cx;iCol++)
  488. {
  489. if (*(USHORT *)pSrc == u.sColor[0])
  490. {
  491. pMsk[iCol >> 3] &= ~(0x80 >> (iCol & 7));
  492. }
  493. pSrc += 2;
  494. }
  495. }
  496. else if (psoSrc->iBitmapFormat == BMF_24BPP)
  497. {
  498. for (iCol = 0;iCol < psoSrc->sizlBitmap.cx;iCol++)
  499. {
  500. if (pSrc[0] == u.bColor[0] && pSrc[1] == u.bColor[1] && pSrc[2] == u.bColor[2])
  501. {
  502. pMsk[iCol >> 3] &= ~(0x80 >> (iCol & 7));
  503. }
  504. pSrc += 3;
  505. }
  506. }
  507. else if (psoSrc->iBitmapFormat == BMF_32BPP)
  508. {
  509. for (iCol = 0;iCol < psoSrc->sizlBitmap.cx;iCol++)
  510. {
  511. if (*(ULONG *)pSrc == u.lColor)
  512. {
  513. pMsk[iCol >> 3] &= ~(0x80 >> (iCol & 7));
  514. }
  515. pSrc += 4;
  516. }
  517. }
  518. else if (psoSrc->iBitmapFormat == BMF_4BPP)
  519. {
  520. for (iCol = 0;iCol < psoSrc->sizlBitmap.cx;iCol++)
  521. {
  522. if (((*pSrc >> 4) & 0xf) == u.bColor[0])
  523. {
  524. pMsk[iCol >> 3] &= ~(0x80 >> (iCol & 7));
  525. }
  526. iCol++;
  527. if ((*pSrc & 0xf) == u.bColor[0])
  528. {
  529. pMsk[iCol >> 3] &= ~(0x80 >> (iCol & 7));
  530. }
  531. pSrc += 1;
  532. }
  533. }
  534. }
  535. return TRUE;
  536. }
  537. BOOL
  538. RMBitBlt(
  539. SURFOBJ *psoDst,
  540. SURFOBJ *psoSrc,
  541. SURFOBJ *psoMask,
  542. CLIPOBJ *pco,
  543. XLATEOBJ *pxlo,
  544. PRECTL prclDst,
  545. PPOINTL pptlSrc,
  546. PPOINTL pptlMask,
  547. BRUSHOBJ *pbo,
  548. PPOINTL pptlBrush,
  549. ROP4 Rop4
  550. )
  551. /*++
  552. Routine Description:
  553. This function will try to bitblt the source to the destination
  554. Arguments:
  555. per winddi spec.
  556. Return Value:
  557. BOOLEAN
  558. Author:
  559. 17-Feb-1993 Wed 12:39:03 created -by- Daniel Chou (danielc)
  560. NOTE: Currently only if SRCCOPY/SRCMASKCOPY will halftone
  561. Revision History:
  562. 01-Feb-1994 Tue 21:51:40 updated -by- Daniel Chou (danielc)
  563. Re-written, it now will handle any ROP4 which have soruces involved
  564. either foreground or background. It will half-tone the source first
  565. if it is not compatible with unidrv destiantion format, then it passed
  566. the compatible source to the EngBitBlt()
  567. 17-May-1995 Wed 23:08:15 updated -by- Daniel Chou (danielc)
  568. Updated so it will do the brush origin correctly, also speed up by
  569. calling EngStretchBlt directly when SRCCOPY (0xCCCC) is passed.
  570. --*/
  571. {
  572. PDEV *pPDev;
  573. SURFOBJ *psoNewSrc;
  574. HBITMAP hBmpNewSrc;
  575. RECTL rclNewSrc;
  576. RECTL rclOldSrc;
  577. POINTL BrushOrg;
  578. DWORD RopBG;
  579. DWORD RopFG;
  580. BOOL Ok;
  581. pPDev = (PDEV *)psoDst->dhpdev;
  582. // if this isn't a graphics band we will return true
  583. // without doing anything
  584. if (!(pPDev->fMode & PF_ENUM_GRXTXT))
  585. return TRUE;
  586. #ifndef DISABLE_NEWRULES
  587. if (pPDev->pbRulesArray && pPDev->dwRulesCount < (MAX_NUM_RULES-4) &&
  588. Rop4 == 0xF0F0 && pbo && pxlo == NULL &&
  589. (pco == NULL || pco->iDComplexity != DC_COMPLEX || pco->iFComplexity == FC_RECT4) &&
  590. ((psoDst->iBitmapFormat != BMF_24BPP &&
  591. pbo->iSolidColor == (ULONG)((PAL_DATA*)(pPDev->pPalData))->iBlackIndex) ||
  592. (psoDst->iBitmapFormat == BMF_24BPP &&
  593. pbo->iSolidColor == 0)))
  594. {
  595. //
  596. // if complexity is rect4 then we could add up to 4 rectangles
  597. //
  598. BOOL bMore = FALSE;
  599. if (pco && pco->iFComplexity == FC_RECT4)
  600. {
  601. if (CLIPOBJ_cEnumStart(pco,TRUE,CT_RECTANGLES,CD_ANY,4) == -1)
  602. goto SkipRules;
  603. }
  604. do
  605. {
  606. PRECTL pRect= &pPDev->pbRulesArray[pPDev->dwRulesCount];
  607. *pRect = *prclDst;
  608. //
  609. // if clip rectangle then clip the rule
  610. //
  611. if (pco)
  612. {
  613. if (pco->iDComplexity == DC_RECT)
  614. {
  615. if (pRect->left < pco->rclBounds.left)
  616. pRect->left = pco->rclBounds.left;
  617. if (pRect->top < pco->rclBounds.top)
  618. pRect->top = pco->rclBounds.top;
  619. if (pRect->right > pco->rclBounds.right)
  620. pRect->right = pco->rclBounds.right;
  621. if (pRect->bottom > pco->rclBounds.bottom)
  622. pRect->bottom = pco->rclBounds.bottom;
  623. }
  624. else if (pco->iFComplexity == FC_RECT4)
  625. {
  626. ENUMRECTS eRect;
  627. bMore = CLIPOBJ_bEnum(pco,(ULONG)sizeof(ENUMRECTS),(ULONG *)&eRect);
  628. if (eRect.c != 1)
  629. {
  630. continue;
  631. }
  632. if (pRect->left < eRect.arcl[0].left)
  633. pRect->left = eRect.arcl[0].left;
  634. if (pRect->top < eRect.arcl[0].top)
  635. pRect->top = eRect.arcl[0].top;
  636. if (pRect->right > eRect.arcl[0].right)
  637. pRect->right = eRect.arcl[0].right;
  638. if (pRect->bottom > eRect.arcl[0].bottom)
  639. pRect->bottom = eRect.arcl[0].bottom;
  640. }
  641. }
  642. if (pRect->left < pRect->right && pRect->top < pRect->bottom)
  643. {
  644. DWORD i;
  645. for (i = 0;i < pPDev->dwRulesCount;i++)
  646. {
  647. PRECTL pRect2= &pPDev->pbRulesArray[i];
  648. //
  649. // test if this rectangle can be combined with another
  650. //
  651. if (pRect->top == pRect2->top &&
  652. pRect->bottom == pRect2->bottom &&
  653. pRect->left <= pRect2->right &&
  654. pRect->right >= pRect2->left)
  655. {
  656. if (pRect2->left > pRect->left)
  657. pRect2->left = pRect->left;
  658. if (pRect2->right < pRect->right)
  659. pRect2->right = pRect->right;
  660. pPDev->dwRulesCount--;
  661. break;
  662. }
  663. else if (pRect->left == pRect2->left &&
  664. pRect->right == pRect2->right &&
  665. pRect->top <= pRect2->bottom &&
  666. pRect->bottom >= pRect2->top)
  667. {
  668. if (pRect2->top > pRect->top)
  669. pRect2->top = pRect->top;
  670. if (pRect2->bottom < pRect->bottom)
  671. pRect2->bottom = pRect->bottom;
  672. pPDev->dwRulesCount--;
  673. break;
  674. }
  675. }
  676. pPDev->dwRulesCount++;
  677. }
  678. } while (bMore && pPDev->dwRulesCount < MAX_NUM_RULES);
  679. return TRUE;
  680. }
  681. SkipRules:
  682. #endif
  683. //
  684. // Send white rectangle to printer to clear any previously
  685. // downloaded text or graphics for PATCOPY and SRCCOPY rops
  686. //
  687. if (Rop4 == 0xF0F0 || Rop4 == 0xCCCC)
  688. DrawWhiteRect(pPDev,prclDst,pco);
  689. //
  690. // We will looked if we need the source, if we do then we check if the
  691. // source is compatible with halftone format, if not then we halftone the
  692. // source and passed the new halftoned source along to the EngBitBlt()
  693. //
  694. psoNewSrc = NULL;
  695. hBmpNewSrc = NULL;
  696. RopBG = ROP4_BG_ROP(Rop4);
  697. RopFG = ROP4_FG_ROP(Rop4);
  698. if (((ROP3_NEED_PAT(RopBG)) ||
  699. (ROP3_NEED_PAT(RopBG))) &&
  700. (pptlBrush)) {
  701. BrushOrg = *pptlBrush;
  702. _DBGP(DbgBitBlt, ("\nRMBitBlt: BrushOrg for pattern PASSED IN as (%ld, %ld)",
  703. BrushOrg.x, BrushOrg.y));
  704. } else {
  705. BrushOrg.x =
  706. BrushOrg.y = 0;
  707. _DBGP(DbgBitBlt, ("\nRMBitBlt: BrushOrg SET by UNIDRV to (0,0), non-pattern"));
  708. }
  709. if (((ROP3_NEED_SRC(RopBG)) ||
  710. (ROP3_NEED_SRC(RopFG))) &&
  711. (!IsHTCompatibleSurfObj((PAL_DATA *)pPDev->pPalData,
  712. psoDst, psoSrc, pxlo)))
  713. {
  714. rclNewSrc.left =
  715. rclNewSrc.top = 0;
  716. rclNewSrc.right = prclDst->right - prclDst->left;
  717. rclNewSrc.bottom = prclDst->bottom - prclDst->top;
  718. rclOldSrc.left = pptlSrc->x;
  719. rclOldSrc.top = pptlSrc->y;
  720. rclOldSrc.right = rclOldSrc.left + rclNewSrc.right;
  721. rclOldSrc.bottom = rclOldSrc.top + rclNewSrc.bottom;
  722. _DBGP(DbgBitBlt, ("\nRMBitBlt: Blt Source=(%ld, %ld)-(%ld, %ld)=%ld x %ld [psoSrc=%ld x %ld]",
  723. rclOldSrc.left, rclOldSrc.top,
  724. rclOldSrc.right, rclOldSrc.bottom,
  725. rclOldSrc.right - rclOldSrc.left,
  726. rclOldSrc.bottom - rclOldSrc.top,
  727. psoSrc->sizlBitmap.cx, psoSrc->sizlBitmap.cy));
  728. _DBGP(DbgBitBlt, ("\nUnidrv!RMBitBlt: DestRect=(%ld, %ld)-(%ld, %ld), BrushOrg = (%ld, %ld)",
  729. prclDst->left, prclDst->top,
  730. prclDst->right, prclDst->bottom,
  731. BrushOrg.x, BrushOrg.y));
  732. //
  733. // If we have a SRCCOPY then call EngStretchBlt directly
  734. //
  735. if (Rop4 == 0xCCCC) {
  736. _DBGP(DbgBitBlt, ("\nUnidrv!RMBitBlt(SRCCOPY): No Clone, call EngStretchBlt() ONLY\n"));
  737. //
  738. // At here, the brush origin guaranteed at (0,0)
  739. //
  740. CheckBitmapSurface(psoDst,prclDst);
  741. return(EngStretchBlt(psoDst,
  742. psoSrc,
  743. psoMask,
  744. pco,
  745. pxlo,
  746. NULL,
  747. &BrushOrg,
  748. prclDst,
  749. &rclOldSrc,
  750. pptlMask,
  751. HALFTONE));
  752. }
  753. //
  754. // Modify the brush origin, because when we blt to the clipped bitmap
  755. // the origin is at bitmap's 0,0 minus the original location
  756. //
  757. BrushOrg.x -= prclDst->left;
  758. BrushOrg.y -= prclDst->top;
  759. _DBGP(DbgBitBlt, ("\nUnidrv!RMBitBlt: BrushOrg Change to (%ld, %ld)",
  760. BrushOrg.x, BrushOrg.y));
  761. _DBGP(DbgBitBlt, ("\nUnidrv!RMBitBlt: Clone SOURCE: from (%ld, %ld)-(%ld, %ld) to (%ld, %ld)-(%ld, %ld)=%ld x %ld\n",
  762. rclOldSrc.left, rclOldSrc.top,
  763. rclOldSrc.right, rclOldSrc.bottom,
  764. rclNewSrc.left, rclNewSrc.top,
  765. rclNewSrc.right, rclNewSrc.bottom,
  766. rclOldSrc.right - rclOldSrc.left,
  767. rclOldSrc.bottom - rclOldSrc.top));
  768. if ((psoNewSrc = CreateBitmapSURFOBJ(pPDev,
  769. &hBmpNewSrc,
  770. rclNewSrc.right,
  771. rclNewSrc.bottom,
  772. psoDst->iBitmapFormat)) &&
  773. (EngStretchBlt(psoNewSrc, // psoDst
  774. psoSrc, // psoSrc
  775. NULL, // psoMask
  776. NULL, // pco
  777. pxlo, // pxlo
  778. NULL, // pca
  779. &BrushOrg, // pptlBrushOrg
  780. &rclNewSrc, // prclDst
  781. &rclOldSrc, // prclSrc
  782. NULL, // pptlmask
  783. HALFTONE))) {
  784. //
  785. // If we cloning sucessful then the pxlo will be NULL because it
  786. // is identities for the halftoned surface to our engine managed
  787. // bitmap
  788. //
  789. psoSrc = psoNewSrc;
  790. pptlSrc = (PPOINTL)&(rclNewSrc.left);
  791. pxlo = NULL;
  792. BrushOrg.x =
  793. BrushOrg.y = 0;
  794. }
  795. else {
  796. _DBGP(1, ("\nUnidrv:RMBitblt: Clone Source to halftone FAILED"));
  797. }
  798. }
  799. //
  800. // Check if we need to clear the bitmap surface. If it hasn't been cleared
  801. // but we are only going to draw a white region on it we can skip the white
  802. // PATCOPY bitblt.
  803. //
  804. if (!(pPDev->fMode & PF_SURFACE_USED) &&
  805. Rop4 == 0xF0F0 && pbo &&
  806. #ifndef DISABLE_NEWRULES
  807. (pPDev->pbRulesArray == NULL || pPDev->dwRulesCount == 0) &&
  808. #endif
  809. ((psoDst->iBitmapFormat != BMF_24BPP &&
  810. pbo->iSolidColor == (ULONG)((PAL_DATA*)(pPDev->pPalData))->iWhiteIndex) ||
  811. (psoDst->iBitmapFormat == BMF_24BPP &&
  812. pbo->iSolidColor == 0x00FFFFFF)))
  813. {
  814. _DBGP (DbgBitBlt, ("\nUnidrv:RMBitblt: Skipping white bitblt\n"));
  815. Ok = TRUE;
  816. }
  817. else
  818. {
  819. // test whether to remap rops for 8bpp mono mode
  820. if (pPDev->fMode2 & PF2_INVERTED_ROP_MODE)
  821. {
  822. Rop4 = InvertROPs(Rop4);
  823. }
  824. // set dirty surface flag
  825. CheckBitmapSurface(psoDst,prclDst);
  826. Ok = EngBitBlt(psoDst,
  827. psoSrc,
  828. psoMask,
  829. pco,
  830. pxlo,
  831. prclDst,
  832. pptlSrc,
  833. pptlMask,
  834. pbo,
  835. &BrushOrg,
  836. Rop4);
  837. }
  838. DELETE_SURFOBJ(psoNewSrc, &hBmpNewSrc);
  839. return(Ok);
  840. }
  841. BOOL
  842. RMStretchBlt(
  843. SURFOBJ *psoDest,
  844. SURFOBJ *psoSrc,
  845. SURFOBJ *psoMask,
  846. CLIPOBJ *pco,
  847. XLATEOBJ *pxlo,
  848. COLORADJUSTMENT *pca,
  849. POINTL *pptlBrushOrg,
  850. RECTL *prclDest,
  851. RECTL *prclSrc,
  852. POINTL *pptlMask,
  853. ULONG BltMode
  854. )
  855. /*++
  856. Routine Description:
  857. This function do driver's stretch bitblt, it actually call HalftoneBlt()
  858. to do the actual work
  859. Arguments:
  860. per above
  861. Return Value:
  862. BOOLEAN
  863. Author:
  864. 24-Mar-1992 Tue 14:06:18 created -by- Daniel Chou (danielc)
  865. Revision History:
  866. 27-Jan-1993 Wed 07:29:00 updated -by- Daniel Chou (danielc)
  867. clean up, so gdi will do the work, we will always doing HALFTONE mode
  868. --*/
  869. {
  870. PDEV *pPDev; /* Our main PDEV */
  871. UNREFERENCED_PARAMETER(BltMode);
  872. pPDev = (PDEV *)psoDest->dhpdev;
  873. // if this isn't a graphics band we will return true
  874. // without doing anything
  875. if (!(pPDev->fMode & PF_ENUM_GRXTXT))
  876. return TRUE;
  877. // test whether we need to clear any device text that
  878. // may be under the graphics
  879. //
  880. DrawWhiteRect(pPDev,prclDest,pco);
  881. // set dirty surface flag since we're drawing in it
  882. CheckBitmapSurface(psoDest,prclDest);
  883. return(EngStretchBlt(psoDest,
  884. psoSrc,
  885. psoMask,
  886. pco,
  887. pxlo,
  888. pca,
  889. pptlBrushOrg,
  890. prclDest,
  891. prclSrc,
  892. pptlMask,
  893. HALFTONE));
  894. }
  895. BOOL
  896. RMStretchBltROP(
  897. SURFOBJ *psoDst,
  898. SURFOBJ *psoSrc,
  899. SURFOBJ *psoMask,
  900. CLIPOBJ *pco,
  901. XLATEOBJ *pxlo,
  902. COLORADJUSTMENT *pca,
  903. POINTL *pptlBrushOrg,
  904. RECTL *prclDst,
  905. RECTL *prclSrc,
  906. POINTL *pptlMask,
  907. ULONG iMode,
  908. BRUSHOBJ *pbo,
  909. DWORD rop4
  910. )
  911. /*++
  912. Routine Description:
  913. This function do driver's stretch bitblt, it actually call HalftoneBlt()
  914. to do the actual work
  915. Arguments:
  916. per above
  917. Return Value:
  918. BOOLEAN
  919. --*/
  920. {
  921. #ifndef WINNT_40
  922. PDEV *pPDev; /* Our main PDEV */
  923. pPDev = (PDEV *)psoDst->dhpdev;
  924. // if this isn't a graphics band we will return true
  925. // without doing anything
  926. if (!(pPDev->fMode & PF_ENUM_GRXTXT))
  927. return TRUE;
  928. // test whether we need to clear any device text that
  929. // may be under the graphics, rop must be SRCCOPY
  930. //
  931. if (rop4 == 0xCCCC)
  932. DrawWhiteRect(pPDev,prclDst,pco);
  933. // test whether to remap rops for 8bpp mono mode
  934. //
  935. if (pPDev->fMode2 & PF2_INVERTED_ROP_MODE)
  936. {
  937. rop4 = InvertROPs(rop4);
  938. }
  939. //
  940. // GDI doesn't support Halftoning for StretchBltROP unless the rop is SRCCOPY
  941. // Therefore to fix bug 36192, we will create a new surface to stretchblt with
  942. // halftone and then will bitblt the result to the actual destination with the rop4
  943. //
  944. #ifndef DISABLE_SBR_GDIWORKAROUND
  945. if (rop4 != 0xCCCC && psoMask == NULL &&
  946. ROP3_NEED_SRC(ROP4_FG_ROP(rop4)) &&
  947. psoDst->iBitmapFormat <= BMF_4BPP && psoSrc->iBitmapFormat >= BMF_4BPP)
  948. {
  949. SURFOBJ *psoNewSrc;
  950. HBITMAP hBmpNewSrc;
  951. RECTL rclNewSrc;
  952. POINTL BrushOrg;
  953. BOOL Ok;
  954. DWORD xHTOffset=0;
  955. DWORD yHTOffset=0;
  956. // DbgPrint("StretchBltROP: rop4=%x,iFormat=%d->%d, Dest=%d,%d\n",rop4,psoSrc->iBitmapFormat,psoDst->iBitmapFormat,prclDst->left,prclDst->top);
  957. //
  958. // determine offset into temporary surface to get halftone patterns to align
  959. //
  960. if (pPDev->dwHTPatSize > 0)
  961. {
  962. xHTOffset = prclDst->left % pPDev->dwHTPatSize;
  963. yHTOffset = prclDst->top % pPDev->dwHTPatSize;
  964. }
  965. rclNewSrc.left =
  966. rclNewSrc.top = 0;
  967. rclNewSrc.right = (prclDst->right - prclDst->left) + xHTOffset;
  968. rclNewSrc.bottom = (prclDst->bottom - prclDst->top) + yHTOffset;
  969. //
  970. // Modify the brush origin, because when we blt to the clipped bitmap
  971. // the origin is at bitmap's 0,0 minus the original location
  972. //
  973. BrushOrg.x = -prclDst->left;
  974. BrushOrg.y = -prclDst->top;
  975. if ((psoNewSrc = CreateBitmapSURFOBJ(pPDev,
  976. &hBmpNewSrc,
  977. rclNewSrc.right,
  978. rclNewSrc.bottom,
  979. psoDst->iBitmapFormat)))
  980. {
  981. rclNewSrc.left += xHTOffset;
  982. rclNewSrc.top += yHTOffset;
  983. if ((EngStretchBlt(psoNewSrc, // psoDst
  984. psoSrc, // psoSrc
  985. NULL, // psoMask
  986. NULL, // pco
  987. pxlo, // pxlo
  988. NULL, // pca
  989. pptlBrushOrg, // pptlBrushOrg
  990. &rclNewSrc, // prclDst
  991. prclSrc, // prclSrc
  992. NULL, // pptlmask
  993. HALFTONE)))
  994. {
  995. //
  996. // If we cloning sucessful then the pxlo will be NULL because it
  997. // is identities for the halftoned surface to our engine managed
  998. // bitmap
  999. //
  1000. PPOINTL pptlSrc = (PPOINTL)&(rclNewSrc.left);
  1001. pxlo = NULL;
  1002. BrushOrg.x =
  1003. BrushOrg.y = 0;
  1004. // set dirty surface flag
  1005. CheckBitmapSurface(psoDst,prclDst);
  1006. Ok = EngBitBlt(psoDst,
  1007. psoNewSrc,
  1008. psoMask,
  1009. pco,
  1010. pxlo,
  1011. prclDst,
  1012. pptlSrc,
  1013. pptlMask,
  1014. pbo,
  1015. &BrushOrg,
  1016. rop4);
  1017. DELETE_SURFOBJ(psoNewSrc, &hBmpNewSrc);
  1018. if (!Ok)
  1019. _DBGP(1,("RMStretchBltROP: Clone bitblt failed\n"));
  1020. return Ok;
  1021. }
  1022. else {
  1023. _DBGP(1,("RMStretchBltROP: Clone Source to halftone FAILED\n"));
  1024. }
  1025. }
  1026. DELETE_SURFOBJ(psoNewSrc, &hBmpNewSrc);
  1027. }
  1028. #endif
  1029. // set dirty surface flag since we're drawing in it
  1030. CheckBitmapSurface(psoDst,prclDst);
  1031. return(EngStretchBltROP(psoDst,
  1032. psoSrc,
  1033. psoMask,
  1034. pco,
  1035. pxlo,
  1036. pca,
  1037. pptlBrushOrg,
  1038. prclDst,
  1039. prclSrc,
  1040. pptlMask,
  1041. HALFTONE,
  1042. pbo,
  1043. rop4));
  1044. #else
  1045. return TRUE;
  1046. #endif
  1047. }
  1048. BOOL
  1049. RMPaint(
  1050. SURFOBJ *pso,
  1051. CLIPOBJ *pco,
  1052. BRUSHOBJ *pbo,
  1053. POINTL *pptlBrushOrg,
  1054. MIX mix)
  1055. /*++
  1056. Routine Description:
  1057. Implementation of DDI entry point DrvPaint.
  1058. Please refer to DDK documentation for more details.
  1059. Arguments:
  1060. pso - Defines the surface on which to draw
  1061. pco - Limits the area to be modified on the Dstination
  1062. pbo - Points to a BRUSHOBJ which defined the pattern and colors to fill with
  1063. pptlBrushOrg - Specifies the origin of the halftone brush
  1064. mix - Defines the foreground and background raster operations to use for
  1065. the brush
  1066. Return Value:
  1067. TRUE if successful, FALSE if there is an error
  1068. --*/
  1069. {
  1070. #define MIXCOPYPEN (R2_COPYPEN | (R2_COPYPEN << 8))
  1071. #define MIXWHITE (R2_WHITE | (R2_WHITE << 8))
  1072. PDEV *pPDev = (PDEV *)pso->dhpdev;
  1073. // if this isn't a graphics band we will return true
  1074. // without doing anything
  1075. if (!(pPDev->fMode & PF_ENUM_GRXTXT))
  1076. return TRUE;
  1077. //
  1078. // Send white rectangle to printer to clear any previously
  1079. // downloaded text or graphics for COPYPEN or WHITE rop2's
  1080. //
  1081. if ((mix == MIXCOPYPEN || mix == MIXWHITE) && pco && pco->iDComplexity == DC_RECT)
  1082. {
  1083. RECTL rclDst;
  1084. rclDst.left = pco->rclBounds.left;
  1085. rclDst.top = pco->rclBounds.top;
  1086. rclDst.right = pco->rclBounds.right;
  1087. rclDst.bottom = pco->rclBounds.bottom;
  1088. DrawWhiteRect(pPDev,&rclDst,pco);
  1089. }
  1090. //
  1091. // Check whether to erase surface
  1092. //
  1093. CheckBitmapSurface(pso,&pco->rclBounds);
  1094. //
  1095. // Call GDI to do the paint function
  1096. //
  1097. return EngPaint(pso, pco, pbo, pptlBrushOrg, mix);
  1098. }
  1099. BOOL
  1100. RMCopyBits(
  1101. SURFOBJ *psoDst,
  1102. SURFOBJ *psoSrc,
  1103. CLIPOBJ *pco,
  1104. XLATEOBJ *pxlo,
  1105. RECTL *prclDst,
  1106. POINTL *pptlSrc
  1107. )
  1108. /*++
  1109. Routine Description:
  1110. Convert between two bitmap formats
  1111. Arguments:
  1112. Per Engine spec.
  1113. Return Value:
  1114. BOOLEAN
  1115. Author:
  1116. 24-Jan-1996 Wed 16:08:57 created -by- Daniel Chou (danielc)
  1117. Revision History:
  1118. --*/
  1119. {
  1120. PDEV *pPDev; /* Our main PDEV */
  1121. pPDev = (PDEV *)psoDst->dhpdev;
  1122. // if this isn't a graphics band we will return true
  1123. // without doing anything
  1124. if (!(pPDev->fMode & PF_ENUM_GRXTXT))
  1125. return TRUE;
  1126. // Handle the case which has to be passed to Engine.
  1127. //
  1128. if (IsHTCompatibleSurfObj((PAL_DATA *)pPDev->pPalData,
  1129. psoDst, psoSrc, pxlo) )
  1130. {
  1131. DrawWhiteRect(pPDev,prclDst,pco);
  1132. CheckBitmapSurface(psoDst,prclDst);
  1133. return(EngCopyBits(psoDst, psoSrc, pco, pxlo, prclDst, pptlSrc));
  1134. }
  1135. else {
  1136. POINTL ptlBrushOrg;
  1137. RECTL rclSrc;
  1138. RECTL rclDst;
  1139. rclDst = *prclDst;
  1140. rclSrc.left = pptlSrc->x;
  1141. rclSrc.top = pptlSrc->y;
  1142. rclSrc.right = rclSrc.left + (rclDst.right - rclDst.left);
  1143. rclSrc.bottom = rclSrc.top + (rclDst.bottom - rclDst.top);
  1144. //
  1145. // Validate that we only BLT the available source size
  1146. //
  1147. if ((rclSrc.right > psoSrc->sizlBitmap.cx) ||
  1148. (rclSrc.bottom > psoSrc->sizlBitmap.cy)) {
  1149. WARNING(("RMCopyBits: Engine passed SOURCE != DEST size, CLIP IT"));
  1150. rclSrc.right = psoSrc->sizlBitmap.cx;
  1151. rclSrc.bottom = psoSrc->sizlBitmap.cy;
  1152. rclDst.right = (LONG)(rclSrc.right - rclSrc.left + rclDst.left);
  1153. rclDst.bottom = (LONG)(rclSrc.bottom - rclSrc.top + rclDst.top);
  1154. }
  1155. ptlBrushOrg.x =
  1156. ptlBrushOrg.y = 0;
  1157. _DBGP(DbgCopyBits, ("\nUnidrv!RMCopyBits: Format Src=%ld, Dest=%ld, Halftone it\n",
  1158. psoSrc->iBitmapFormat, psoDst->iBitmapFormat));
  1159. _DBGP(DbgCopyBits, ("\nUnidrv!RMCopyBits: Source Size: (%ld, %ld)-(%ld, %ld) = %ld x %ld\n",
  1160. rclSrc.left, rclSrc.top, rclSrc.right, rclSrc.bottom,
  1161. rclSrc.right - rclSrc.left, rclSrc.bottom - rclSrc.top));
  1162. _DBGP(DbgCopyBits, ("\nUnidrv!RMCopyBits: Dest Size: (%ld, %ld)-(%ld, %ld) = %ld x %ld\n",
  1163. rclDst.left, rclDst.top, rclDst.right, rclDst.bottom,
  1164. rclDst.right - rclDst.left, rclDst.bottom - rclDst.top));
  1165. return(DrvStretchBlt(psoDst,
  1166. psoSrc,
  1167. NULL,
  1168. pco,
  1169. pxlo,
  1170. NULL,
  1171. &ptlBrushOrg,
  1172. &rclDst,
  1173. &rclSrc,
  1174. NULL,
  1175. HALFTONE));
  1176. }
  1177. }
  1178. ULONG
  1179. RMDitherColor(
  1180. DHPDEV dhpdev,
  1181. ULONG iMode,
  1182. ULONG rgbColor,
  1183. ULONG *pulDither
  1184. )
  1185. /*++
  1186. Routine Description:
  1187. This is the hooked brush creation function, it ask CreateHalftoneBrush()
  1188. to do the actual work.
  1189. Arguments:
  1190. dhpdev - DHPDEV passed, it is our pDEV
  1191. iMode - Not used
  1192. rgbColor - Solid rgb color to be used
  1193. pulDither - buffer to put the halftone brush.
  1194. Return Value:
  1195. BOOLEAN
  1196. Author:
  1197. 24-Mar-1992 Tue 14:53:36 created -by- Daniel Chou (danielc)
  1198. Revision History:
  1199. 27-Jan-1993 Wed 07:29:00 updated -by- Daniel Chou (danielc)
  1200. clean up, so gdi will do the work.
  1201. --*/
  1202. {
  1203. #ifndef WINNT_40 //NT 5.0
  1204. UNREFERENCED_PARAMETER(dhpdev);
  1205. UNREFERENCED_PARAMETER(iMode);
  1206. UNREFERENCED_PARAMETER(rgbColor);
  1207. UNREFERENCED_PARAMETER(pulDither);
  1208. return(DCR_HALFTONE);
  1209. #else // NT 4.0
  1210. DWORD RetVal;
  1211. UNREFERENCED_PARAMETER(dhpdev);
  1212. UNREFERENCED_PARAMETER(iMode);
  1213. UNREFERENCED_PARAMETER(pulDither);
  1214. EngAcquireSemaphore(hSemBrushColor);
  1215. if (pBrushSolidColor) {
  1216. *pBrushSolidColor = (DWORD)(rgbColor & 0x00FFFFFF);
  1217. _DBGP(DbgDitherColor, ("\nDrvDitherColor(BRUSH=%08lx)\t\t",
  1218. *pBrushSolidColor));
  1219. pBrushSolidColor = NULL;
  1220. RetVal = DCR_SOLID;
  1221. } else {
  1222. _DBGP(DbgDitherColor, ("\nDrvDitherColor(HALFTONE=%08lx)\t\t", rgbColor));
  1223. RetVal = DCR_HALFTONE;
  1224. }
  1225. EngReleaseSemaphore(hSemBrushColor);
  1226. return(RetVal);
  1227. #endif //!WINNT_40
  1228. }
  1229. BOOL
  1230. RMPlgBlt(
  1231. SURFOBJ *psoDst,
  1232. SURFOBJ *psoSrc,
  1233. SURFOBJ *psoMask,
  1234. CLIPOBJ *pco,
  1235. XLATEOBJ *pxlo,
  1236. COLORADJUSTMENT *pca,
  1237. POINTL *pptlBrushOrg,
  1238. POINTFIX *pptfx,
  1239. RECTL *prclSrc,
  1240. POINTL *pptlMask,
  1241. ULONG BltMode
  1242. )
  1243. /*++
  1244. Routine Description:
  1245. This function does driver's plgblt.
  1246. Arguments:
  1247. per above
  1248. Return Value:
  1249. BOOLEAN
  1250. --*/
  1251. {
  1252. PDEV *pPDev; /* Our main PDEV */
  1253. pPDev = (PDEV *)psoDst->dhpdev;
  1254. // if this isn't a graphics band we will return true
  1255. // without doing anything
  1256. if (!(pPDev->fMode & PF_ENUM_GRXTXT))
  1257. return TRUE;
  1258. //
  1259. // test for no rotation, as this is another case the GDI EngPlgBlt call fails
  1260. // bug #336711, 3/8/01
  1261. //
  1262. if (pptfx[0].x == pptfx[2].x && pptfx[0].y == pptfx[1].y && pptfx[0].y < pptfx[2].y)
  1263. {
  1264. RECTL rclDst;
  1265. rclDst.top = pptfx[0].y >> 4;
  1266. rclDst.left = pptfx[0].x >> 4;
  1267. rclDst.bottom = pptfx[2].y >> 4;
  1268. rclDst.right = pptfx[1].x >> 4;
  1269. // blt surface into destination
  1270. //
  1271. CheckBitmapSurface(psoDst,&rclDst);
  1272. return EngStretchBlt(psoDst, // psoDst
  1273. psoSrc, // psoSrc
  1274. psoMask, // psoMask
  1275. pco, // pco
  1276. pxlo, // pxlo
  1277. pca, // pca
  1278. pptlBrushOrg, // pptlBrushOrg
  1279. &rclDst, // prclDst
  1280. prclSrc, // prclSrc
  1281. pptlMask, // pptlmask
  1282. HALFTONE);
  1283. }
  1284. // test for 90/270 rotation as GDI's EngPlgBlt sometimes fails if it has to do
  1285. // both rotation and scaling. In those case this function will rotate the
  1286. // data to an intermediate surface before scaling to the destination surface.
  1287. //
  1288. if (psoMask == NULL && pptfx[0].x == pptfx[1].x && pptfx[0].y == pptfx[2].y &&
  1289. (pPDev->pdmPrivate->iLayout == ONE_UP || psoSrc->iBitmapFormat == BMF_1BPP))
  1290. {
  1291. SURFOBJ *psoNewSrc = NULL;
  1292. HBITMAP hBmpNewSrc = NULL;
  1293. RECTL rclNewSrc;
  1294. BOOL iRet;
  1295. RECTL rclDst;
  1296. POINTFIX pFix[3];
  1297. rclNewSrc.left =
  1298. rclNewSrc.top = 0;
  1299. rclNewSrc.bottom = (prclSrc->right - prclSrc->left);
  1300. rclNewSrc.right = (prclSrc->bottom - prclSrc->top);
  1301. // rotate 90 degrees
  1302. //
  1303. if (pptfx[2].x < pptfx[0].x)
  1304. {
  1305. pFix[0].y = pFix[2].y = 0;
  1306. pFix[0].x = pFix[1].x = (rclNewSrc.right << 4);
  1307. pFix[2].x = 0;
  1308. pFix[1].y = (rclNewSrc.bottom << 4);
  1309. rclDst.top = pptfx[2].y >> 4;
  1310. rclDst.left = pptfx[2].x >> 4;
  1311. rclDst.bottom = pptfx[1].y >> 4;
  1312. rclDst.right = pptfx[1].x >> 4;
  1313. }
  1314. // rotate 270 degrees
  1315. //
  1316. else
  1317. {
  1318. pFix[0].y = pFix[2].y = (rclNewSrc.bottom << 4);
  1319. pFix[0].x = pFix[1].x = 0;
  1320. pFix[2].x = (rclNewSrc.right << 4);
  1321. pFix[1].y = 0;
  1322. rclDst.top = pptfx[1].y >> 4;
  1323. rclDst.left = pptfx[1].x >> 4;
  1324. rclDst.bottom = pptfx[2].y >> 4;
  1325. rclDst.right = pptfx[2].x >> 4;
  1326. }
  1327. // Only enable EngPlgBlt workaround when scaling up. EngPlgBlt appears to work
  1328. // ok when scaling down and it is more efficient in that mode. This also fixes
  1329. // the rounding error associated with scaling down (bug #356514).
  1330. //
  1331. if ((rclNewSrc.right < abs(rclDst.right - rclDst.left) &&
  1332. rclNewSrc.bottom < abs(rclDst.bottom - rclDst.top)) ||
  1333. psoSrc->iBitmapFormat == BMF_1BPP)
  1334. {
  1335. /*
  1336. #if DBG
  1337. DbgPrint("PlgBlt:Src=L%d,T%d,R%d,B%d;Dst=L%d,T%d,R%d,B%d\n",
  1338. prclSrc->left,prclSrc->top,prclSrc->right,prclSrc->bottom,
  1339. rclDst.left,rclDst.top,rclDst.right,rclDst.bottom);
  1340. #endif
  1341. */
  1342. // Create an intermediate surface and rotate the source data into
  1343. // the surface with no scaling.
  1344. //
  1345. if ((psoNewSrc = CreateBitmapSURFOBJ(pPDev,
  1346. &hBmpNewSrc,
  1347. rclNewSrc.right,
  1348. rclNewSrc.bottom,
  1349. psoSrc->iBitmapFormat)))
  1350. {
  1351. if ((iRet = EngPlgBlt(psoNewSrc,
  1352. psoSrc,
  1353. psoMask,
  1354. NULL,
  1355. NULL,
  1356. pca,
  1357. pptlBrushOrg,
  1358. pFix,
  1359. prclSrc,
  1360. pptlMask,
  1361. BltMode)))
  1362. {
  1363. // blt new surface into destination
  1364. //
  1365. if (psoSrc->iBitmapFormat != BMF_1BPP)
  1366. {
  1367. BltMode = HALFTONE;
  1368. }
  1369. CheckBitmapSurface(psoDst,&rclDst);
  1370. iRet = EngStretchBlt(psoDst, // psoDst
  1371. psoNewSrc, // psoSrc
  1372. NULL, // psoMask
  1373. pco, // pco
  1374. pxlo, // pxlo
  1375. pca, // pca
  1376. pptlBrushOrg, // pptlBrushOrg
  1377. &rclDst, // prclDst
  1378. &rclNewSrc, // prclSrc
  1379. NULL, // pptlmask
  1380. BltMode);
  1381. }
  1382. DELETE_SURFOBJ(psoNewSrc, &hBmpNewSrc);
  1383. return iRet;
  1384. }
  1385. }
  1386. }
  1387. // set dirty surface flag since we're drawing in it
  1388. CheckBitmapSurface(psoDst,NULL);
  1389. return(EngPlgBlt(psoDst,
  1390. psoSrc,
  1391. psoMask,
  1392. pco,
  1393. pxlo,
  1394. pca,
  1395. pptlBrushOrg,
  1396. pptfx,
  1397. prclSrc,
  1398. pptlMask,
  1399. HALFTONE));
  1400. }