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.

1873 lines
57 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: plgblt.cxx
  3. *
  4. * This contains the API and DDI entry points to the graphics engine
  5. * for PlgBlt and EngPlgBlt.
  6. *
  7. * Created: 21-Oct-1990 14:15:53
  8. * Author: Donald Sidoroff [donalds]
  9. *
  10. * Copyright (c) 1990-1999 Microsoft Corporation
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. #include "rotate.hxx"
  14. /******************************Public*Routine******************************\
  15. * GrePlgBlt
  16. *
  17. * API for blting to a parallelogram from a rectangle.
  18. *
  19. * History:
  20. * Tue 02-Jun-1992 -by- Patrick Haluptzok [patrickh]
  21. * fix clipping bugs
  22. *
  23. * 21-Mar-1992 -by- Donald Sidoroff [donalds]
  24. * Rewrote it.
  25. *
  26. * Wed 15-Jan-1992 -by- Patrick Haluptzok [patrickh]
  27. * Add mask support
  28. *
  29. * 26-Mar-1991 -by- Patrick Haluptzok patrickh
  30. * Wrote it.
  31. \**************************************************************************/
  32. BOOL GrePlgBlt(
  33. HDC hdcTrg,
  34. LPPOINT pptlTrg,
  35. HDC hdcSrc,
  36. int xSrc,
  37. int ySrc,
  38. int cxSrc,
  39. int cySrc,
  40. HBITMAP hbmMask,
  41. int xMask,
  42. int yMask,
  43. DWORD crBackColor
  44. )
  45. {
  46. GDITraceHandle3(GrePlgBlt, "(%X, %p, %X, %d, %d, %d, %d, %X, %d, %d, %X)\n", (va_list)&hdcTrg, hdcTrg, hdcSrc, hbmMask);
  47. BLTRECORD blt;
  48. ULONG ulAvec;
  49. // Lock the DC's, no optimization is made for same surface
  50. DCOBJ dcoTrg(hdcTrg);
  51. DCOBJ dcoSrc(hdcSrc);
  52. if (!dcoTrg.bValid() || !dcoSrc.bValid())
  53. {
  54. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  55. return(FALSE);
  56. }
  57. if (dcoTrg.bStockBitmap())
  58. {
  59. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  60. return(FALSE);
  61. }
  62. // Lock the surface and the Rao region
  63. DEVLOCKBLTOBJ dlo(dcoTrg, dcoSrc);
  64. if (!dlo.bValid())
  65. {
  66. return(dcoTrg.bFullScreen() || dcoSrc.bFullScreen());
  67. }
  68. if (!dcoTrg.bValidSurf() || !dcoSrc.bValidSurf() || !dcoSrc.pSurface()->bReadable())
  69. {
  70. ULONG ulDirty = dcoTrg.pdc->ulDirty();
  71. if ( ulDirty & DC_BRUSH_DIRTY)
  72. {
  73. GreDCSelectBrush (dcoTrg.pdc,dcoTrg.pdc->hbrush());
  74. }
  75. ulDirty = dcoSrc.pdc->ulDirty();
  76. if ( ulDirty & DC_BRUSH_DIRTY)
  77. {
  78. GreDCSelectBrush (dcoSrc.pdc,dcoSrc.pdc->hbrush());
  79. }
  80. // I wanted to cheat, but InfoDCs need the right answer here...
  81. if ((dcoTrg.dctp() == DCTYPE_INFO) || !dcoSrc.bValidSurf())
  82. {
  83. if (dcoTrg.fjAccum())
  84. {
  85. blt.pxoTrg()->vInit(dcoTrg,WORLD_TO_DEVICE);
  86. if (!blt.TrgPlg(pptlTrg))
  87. {
  88. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  89. return(FALSE);
  90. }
  91. // Complete the parallelogram and find the extrema.
  92. blt.vExtrema();
  93. // Get the bounding rectangle
  94. ERECTL erclBnd;
  95. blt.vBound(&erclBnd);
  96. dcoTrg.vAccumulate(erclBnd);
  97. }
  98. }
  99. // Do the security test on SCREEN to MEMORY blits.
  100. if (dcoSrc.bDisplay() && !dcoTrg.bDisplay())
  101. {
  102. if (!UserScreenAccessCheck())
  103. {
  104. SAVE_ERROR_CODE(ERROR_ACCESS_DENIED);
  105. return(FALSE);
  106. }
  107. }
  108. // If the source isn't a DISPLAY we should exit unless there is no
  109. // destination surface.
  110. if( !dcoSrc.bDisplay() )
  111. {
  112. return( dcoTrg.pSurface() == NULL );
  113. }
  114. }
  115. if (dcoTrg.bDisplay() && !dcoTrg.bRedirection() && dcoSrc.bValidSurf() && !dcoSrc.bDisplay() && !UserScreenAccessCheck())
  116. {
  117. SAVE_ERROR_CODE(ERROR_ACCESS_DENIED);
  118. return(FALSE);
  119. }
  120. // Fill the BLTRECORD
  121. blt.pxoTrg()->vInit(dcoTrg,WORLD_TO_DEVICE);
  122. blt.pSurfTrg(dcoTrg.pSurfaceEff());
  123. blt.ppoTrg()->ppalSet(blt.pSurfTrg()->ppal());
  124. blt.ppoTrgDC()->ppalSet(dcoTrg.ppal());
  125. blt.pxoSrc()->vInit(dcoSrc,WORLD_TO_DEVICE);
  126. blt.pSurfSrc(dcoSrc.pSurfaceEff());
  127. blt.ppoSrc()->ppalSet(blt.pSurfSrc()->ppal());
  128. blt.ppoSrcDC()->ppalSet(dcoSrc.ppal());
  129. // Initialize the color translation object.
  130. //
  131. // No ICM with PlgBlt(), so pass NULL color transform to XLATEOBJ.
  132. if (!blt.pexlo()->bInitXlateObj(NULL, // hColorTransform
  133. dcoTrg.pdc->lIcmMode(), // ICM mode
  134. *blt.ppoSrc(),
  135. *blt.ppoTrg(),
  136. *blt.ppoSrcDC(),
  137. *blt.ppoTrgDC(),
  138. dcoTrg.pdc->crTextClr(),
  139. dcoTrg.pdc->crBackClr(),
  140. crBackColor
  141. ))
  142. {
  143. WARNING("bInitXlateObj failed in PlgBlt\n");
  144. return(FALSE);
  145. }
  146. blt.flSet(BLTREC_PXLO);
  147. blt.pbo(NULL);
  148. // Set the source rectangle.
  149. if (blt.pxoSrc()->bRotation() || !blt.Src(xSrc, ySrc, cxSrc, cySrc))
  150. {
  151. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  152. return(FALSE);
  153. }
  154. // Deal with the mask if provided
  155. if (hbmMask == (HBITMAP) 0)
  156. {
  157. blt.pSurfMsk((SURFACE *) NULL);
  158. blt.rop(0x0000CCCC);
  159. ulAvec = AVEC_S;
  160. }
  161. else
  162. {
  163. SURFREF soMsk((HSURF) hbmMask);
  164. if (!soMsk.bValid())
  165. {
  166. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  167. return(FALSE);
  168. }
  169. soMsk.vKeepIt();
  170. blt.pSurfMsk((SURFACE *) soMsk.ps);
  171. blt.rop(0x0000AACC);
  172. ulAvec = AVEC_NEED_MASK | AVEC_S;
  173. blt.flSet(BLTREC_MASK_NEEDED | BLTREC_MASK_LOCKED);
  174. if (
  175. (blt.pSurfMsk()->iType() != STYPE_BITMAP) ||
  176. (blt.pSurfMsk()->iFormat() != BMF_1BPP)
  177. )
  178. {
  179. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  180. return(FALSE);
  181. }
  182. blt.Msk(xMask, yMask);
  183. }
  184. // We must first transform the target. We might be rotating because of
  185. // the transform or the specified parallelogram.
  186. if (!blt.TrgPlg(pptlTrg))
  187. {
  188. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  189. return(FALSE);
  190. }
  191. // If the parallelogram is rotated, skewed or has fractional endpoints
  192. // send the call to bRotate.
  193. if (blt.bRotated())
  194. {
  195. return(blt.bRotate(dcoTrg, dcoSrc, ulAvec, dcoTrg.pdc->jStretchBltMode()));
  196. }
  197. // If we are halftoning or the extents aren't equal, call bStretch.
  198. if ((dcoTrg.pdc->jStretchBltMode() == HALFTONE) || !blt.bEqualExtents())
  199. {
  200. return(blt.bStretch(dcoTrg, dcoSrc, ulAvec, dcoTrg.pdc->jStretchBltMode()));
  201. }
  202. return(blt.bBitBlt(dcoTrg, dcoSrc, ulAvec));
  203. }
  204. BOOL
  205. APIENTRY
  206. NtGdiPlgBlt(
  207. HDC hdcTrg,
  208. LPPOINT pptlTrg,
  209. HDC hdcSrc,
  210. int xSrc,
  211. int ySrc,
  212. int cxSrc,
  213. int cySrc,
  214. HBITMAP hbmMask,
  215. int xMask,
  216. int yMask,
  217. DWORD crBackColor
  218. )
  219. {
  220. GDITraceHandle3(NtGdiPlgBlt, "(%X, %p, %X, %d, %d, %d, %d, %X, %d, %d, %X)\n", (va_list)&hdcTrg, hdcTrg, hdcSrc, hbmMask);
  221. BOOL bRet;
  222. POINT aptDst[3];
  223. __try
  224. {
  225. ProbeForRead(pptlTrg, sizeof(aptDst), sizeof(DWORD));
  226. RtlMoveMemory(aptDst, pptlTrg, sizeof(aptDst));
  227. pptlTrg = aptDst;
  228. bRet = TRUE;
  229. }
  230. __except(EXCEPTION_EXECUTE_HANDLER)
  231. {
  232. // SetLastError(GetExceptionCode());
  233. bRet = FALSE;
  234. }
  235. if (bRet)
  236. {
  237. bRet = GrePlgBlt(hdcTrg, pptlTrg, hdcSrc, xSrc, ySrc, cxSrc, cySrc,
  238. hbmMask, xMask, yMask, crBackColor);
  239. }
  240. return(bRet);
  241. }
  242. /******************************Public*Routine******************************\
  243. * BOOL BLTRECORD::bRotate(dcoTrg, dcoSrc, ulAvec)
  244. *
  245. * Do a rotate blt from the blt record
  246. *
  247. * History:
  248. * 21-Mar-1992 -by- Donald Sidoroff [donalds]
  249. * Rewrote it.
  250. \**************************************************************************/
  251. BOOL
  252. BLTRECORD::bRotate(
  253. DCOBJ& dcoTrg,
  254. DCOBJ& dcoSrc,
  255. ULONG ulAvec,
  256. BYTE jMode
  257. )
  258. {
  259. //
  260. // Complete the parallelogram and find the extrema
  261. //
  262. vExtrema();
  263. //
  264. // We might be here on behalf of MaskBlt and need to rotate the mask
  265. // before we do a pattern only blt.
  266. //
  267. BOOL bReturn;
  268. if (!(ulAvec & AVEC_NEED_SOURCE))
  269. {
  270. vOrder(perclMask());
  271. if (MIRRORED_DC(dcoTrg.pdc)) {
  272. LONG x = aptlMask[0].x;
  273. aptlMask[0].x = aptlMask[1].x;
  274. aptlMask[1].x = x;
  275. }
  276. //
  277. // Before we call to the driver, validate that the mask will actually
  278. // cover the entire target.
  279. //
  280. if (pSurfMskOut() != (SURFACE *) NULL)
  281. {
  282. if (
  283. (aptlMask[0].x < 0) ||
  284. (aptlMask[0].y < 0) ||
  285. (aptlMask[1].x > pSurfMsk()->sizl().cx) ||
  286. (aptlMask[1].y > pSurfMsk()->sizl().cy)
  287. )
  288. {
  289. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  290. return(FALSE);
  291. }
  292. }
  293. SURFMEM dimoMask;
  294. //
  295. // If there is a mask, rotate it.
  296. //
  297. if ((ulAvec & AVEC_NEED_MASK) && !bRotate(dimoMask, (ULONG) jMode))
  298. {
  299. return(FALSE);
  300. }
  301. //
  302. // Since this is going to bBitBlt, we need to create a target rectangle.
  303. //
  304. vBound(perclTrg());
  305. //
  306. // Create a region from the parallelogram and select it into the
  307. // clipping pipeline. This is to make sure no bits are altered
  308. // outside when BitBlt is called.
  309. //
  310. if (!bCreateRegion(dcoTrg, aptfxTrg))
  311. {
  312. return(FALSE);
  313. }
  314. bReturn = bBitBlt(dcoTrg, dcoSrc, ulAvec);
  315. //
  316. // Remember to clean up after ourselves!
  317. //
  318. dcoTrg.pdc->prgnAPI(NULL);
  319. return(bReturn);
  320. }
  321. //
  322. // Make the source rectangle well ordered remembering all the flips.
  323. //
  324. vOrder(perclSrc());
  325. perclMask()->vOrder();
  326. if (MIRRORED_DC(dcoTrg.pdc)) {
  327. int x = aptlMask[0].x;
  328. aptlMask[0].x = aptlMask[1].x;
  329. aptlMask[1].x = x;
  330. }
  331. //
  332. // Before we get too involved, validate that the mask will actually
  333. // cover the entire source.
  334. //
  335. if (pSurfMskOut() != (SURFACE *) NULL)
  336. {
  337. if (
  338. (aptlMask[0].x < 0) ||
  339. (aptlMask[0].y < 0) ||
  340. (aptlMask[1].x > pSurfMsk()->sizl().cx) ||
  341. (aptlMask[1].y > pSurfMsk()->sizl().cy)
  342. )
  343. {
  344. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  345. return(FALSE);
  346. }
  347. }
  348. //
  349. // If the devices are on different PDEV's we can only succeed if the Engine
  350. // manages one or both of the surfaces. Check for this.
  351. //
  352. if (
  353. (dcoTrg.hdev() != dcoSrc.hdev()) &&
  354. (dcoTrg.pSurfaceEff()->iType() != STYPE_BITMAP) &&
  355. (dcoSrc.pSurfaceEff()->iType() != STYPE_BITMAP)
  356. )
  357. {
  358. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  359. return(FALSE);
  360. }
  361. //
  362. // We might be here with a ROP, again on behalf of MaskBlt. If it
  363. // isn't one of the basic PlgBlt rops, create a rotated shadow and mask
  364. // and call BitBlt to finish the job for us.
  365. //
  366. if ((rop4 != 0x0000CCCC) && (rop4 != 0x0000AACC))
  367. {
  368. SURFMEM dimoMask;
  369. SURFMEM dimoShadow;
  370. // WINBUG #263939 3-5-2000 bhouse Watchdog timeout problems
  371. // We suspend the watchdog here ... GDI is brain dead and will
  372. // create a temporary shadow surface the size of the destination
  373. // mapping. This is crazy when the destination mapping far excceeds
  374. // the actual size of the destination. Maybe one day we will
  375. // re-write this brain dead code.... I'm not holding my breadth.
  376. PDEVOBJ pdoTrg(pSurfTrg()->hdev());
  377. if(pdoTrg.bDisplayPDEV())
  378. GreSuspendWatch(pdoTrg.ppdev, WD_DEVLOCK);
  379. bReturn = bRotate(dcoSrc, dimoShadow, dimoMask, ulAvec, (ULONG) jMode);
  380. if(pdoTrg.bDisplayPDEV())
  381. GreResumeWatch(pdoTrg.ppdev, WD_DEVLOCK);
  382. if(!bReturn)
  383. return(FALSE);
  384. //
  385. // Since this is going to bBitBlt, we need to create a target rectangle.
  386. //
  387. vBound(perclTrg());
  388. //
  389. // Create a region from the parallelogram and select it into the
  390. // clipping pipeline. This is to make sure no bits are altered
  391. // outside when BitBlt is called.
  392. //
  393. if (!bCreateRegion(dcoTrg, aptfxTrg))
  394. {
  395. return(FALSE);
  396. }
  397. bReturn = bBitBlt(dcoTrg, dcoSrc, ulAvec);
  398. //
  399. // Remember to clean up after ourselves!
  400. //
  401. dcoTrg.pdc->prgnAPI(NULL);
  402. return(bReturn);
  403. }
  404. //
  405. // Get the bounding rectangle
  406. //
  407. ERECTL erclBound;
  408. vBound(&erclBound);
  409. //
  410. // Adjust bounds for inclusive/inclusive
  411. //
  412. erclBound.right += 1;
  413. erclBound.bottom += 1;
  414. //
  415. // Accumulate bounds. We can do this before knowing if the operation is
  416. // successful because bounds can be loose.
  417. //
  418. if (dcoTrg.fjAccum())
  419. {
  420. dcoTrg.vAccumulate(erclBound);
  421. }
  422. //
  423. // With a fixed DC origin we can change parallelogram and rectangle to
  424. // SCREEN coordinates
  425. //
  426. vOffset(dcoTrg.eptlOrigin());
  427. *perclSrc() += dcoSrc.eptlOrigin();
  428. erclBound += dcoTrg.eptlOrigin();
  429. //
  430. // Compute the clipping complexity and maybe reduce the exclusion rectangle.
  431. //
  432. ECLIPOBJ eco(dcoTrg.prgnEffRao(), erclBound);
  433. //
  434. // Check the destination which is reduced by clipping.
  435. //
  436. if (eco.erclExclude().bEmpty())
  437. {
  438. return(TRUE);
  439. }
  440. //
  441. // Compute the exclusion rectangle.
  442. //
  443. ERECTL erclExclude = eco.erclExclude();
  444. //
  445. // If we are going to the same source, prevent bad overlap situations
  446. //
  447. if (dcoSrc.pSurface() == dcoTrg.pSurface())
  448. {
  449. if (perclSrc()->left < erclExclude.left)
  450. {
  451. erclExclude.left = perclSrc()->left;
  452. }
  453. if (perclSrc()->top < erclExclude.top)
  454. {
  455. erclExclude.top = perclSrc()->top;
  456. }
  457. if (perclSrc()->right > erclExclude.right)
  458. {
  459. erclExclude.right = perclSrc()->right;
  460. }
  461. if (perclSrc()->bottom > erclExclude.bottom)
  462. {
  463. erclExclude.bottom = perclSrc()->bottom;
  464. }
  465. }
  466. //
  467. // We might have to exclude the source or the target, get ready to do either.
  468. //
  469. DEVEXCLUDEOBJ dxo;
  470. PDEVOBJ pdoTrg(pSurfTrg()->hdev());
  471. //
  472. // They can't both be display
  473. //
  474. if (dcoSrc.bDisplay())
  475. {
  476. ERECTL ercl(0,0,pSurfSrc()->sizl().cx,pSurfSrc()->sizl().cy);
  477. if (dcoSrc.pSurface() == dcoTrg.pSurface())
  478. {
  479. ercl *= erclExclude;
  480. }
  481. else
  482. {
  483. ercl *= *perclSrc();
  484. }
  485. dxo.vExclude(dcoSrc.hdev(),&ercl,NULL);
  486. }
  487. else if (dcoTrg.bDisplay())
  488. {
  489. dxo.vExclude(dcoTrg.hdev(),&erclExclude,&eco);
  490. }
  491. //
  492. // Handle target mirroring
  493. //
  494. vMirror(aptfxTrg);
  495. //
  496. // Inc the target surface uniqueness
  497. //
  498. INC_SURF_UNIQ(pSurfTrg());
  499. return((*PPFNGET(pdoTrg, PlgBlt, pSurfTrg()->flags()))(
  500. pSurfTrg()->pSurfobj(),
  501. pSurfSrc()->pSurfobj(),
  502. (rop4 == 0x0000CCCC) ? (SURFOBJ *) NULL : pSurfMskOut()->pSurfobj(),
  503. &eco,
  504. pexlo()->pxlo(),
  505. (dcoTrg.pColorAdjustment()->caFlags & CA_DEFAULT) ?
  506. (PCOLORADJUSTMENT)NULL : dcoTrg.pColorAdjustment(),
  507. &dcoTrg.pdc->ptlFillOrigin(),
  508. aptfxTrg,
  509. perclSrc(),
  510. aptlMask,
  511. jMode));
  512. }
  513. /******************************Public*Routine******************************\
  514. * BOOL BLTRECORD::bRotate(dimo, iMode)
  515. *
  516. * Rotate just the mask.
  517. *
  518. * History:
  519. * 23-Mar-1992 -by- Donald Sidoroff [donalds]
  520. * Wrote it.
  521. \**************************************************************************/
  522. BOOL BLTRECORD::bRotate(
  523. SURFMEM& dimo,
  524. ULONG iMode)
  525. {
  526. ERECTL erclTrg;
  527. vBound(&erclTrg);
  528. // Fill in the bitmap info.
  529. DEVBITMAPINFO dbmi;
  530. dbmi.iFormat = BMF_1BPP;
  531. dbmi.cxBitmap = erclTrg.right - erclTrg.left;
  532. dbmi.cyBitmap = erclTrg.bottom - erclTrg.top;
  533. dbmi.hpal = (HPALETTE) 0;
  534. dbmi.fl = pSurfMskOut()->bUMPD() ? UMPD_SURFACE : 0;
  535. dimo.bCreateDIB(&dbmi, (VOID *) NULL);
  536. if (!dimo.bValid())
  537. {
  538. return(FALSE);
  539. }
  540. // Build a shadow parallelogram.
  541. POINTFIX aptfxShadow[4];
  542. aptfxShadow[0].x = aptfxTrg[0].x - FIX_FROM_LONG(erclTrg.left);
  543. aptfxShadow[0].y = aptfxTrg[0].y - FIX_FROM_LONG(erclTrg.top);
  544. aptfxShadow[1].x = aptfxTrg[1].x - FIX_FROM_LONG(erclTrg.left);
  545. aptfxShadow[1].y = aptfxTrg[1].y - FIX_FROM_LONG(erclTrg.top);
  546. aptfxShadow[2].x = aptfxTrg[2].x - FIX_FROM_LONG(erclTrg.left);
  547. aptfxShadow[2].y = aptfxTrg[2].y - FIX_FROM_LONG(erclTrg.top);
  548. aptfxShadow[3].x = aptfxTrg[3].x - FIX_FROM_LONG(erclTrg.left);
  549. aptfxShadow[3].y = aptfxTrg[3].y - FIX_FROM_LONG(erclTrg.top);
  550. // Take care of mirroring.
  551. vMirror(aptfxShadow);
  552. // Call EngPlgBlt to rotate the mask.
  553. EPOINTL ptl(0,0);
  554. if (!EngPlgBlt(
  555. dimo.pSurfobj(),
  556. pSurfMskOut()->pSurfobj(),
  557. (SURFOBJ *) NULL,
  558. (CLIPOBJ *) NULL,
  559. NULL,
  560. NULL,
  561. (POINTL *)&ptl,
  562. aptfxShadow,
  563. perclMask(),
  564. (POINTL *) NULL,
  565. iMode)
  566. )
  567. return(FALSE);
  568. // Release the previous pSurfMask, tell ~BLTRECORD its gone and put the
  569. // new DIB in its place. Remember to adjust the mask origin.
  570. flState &= ~BLTREC_MASK_LOCKED;
  571. pSurfMsk()->vAltUnlockFast();
  572. pSurfMsk((SURFACE *) dimo.ps);
  573. aptlMask[0].x = 0;
  574. aptlMask[0].y = 0;
  575. return(TRUE);
  576. }
  577. /******************************Public*Routine******************************\
  578. * BOOL BLTRECORD::bRotate(dcoSrc, dimoShadow, dimoMask, ulAvec, iMode)
  579. *
  580. * Rotate the shadow and mask.
  581. *
  582. * History:
  583. * 24-Mar-1992 -by- Donald Sidoroff [donalds]
  584. * Wrote it.
  585. \**************************************************************************/
  586. BOOL
  587. BLTRECORD::bRotate(
  588. DCOBJ& dcoSrc,
  589. SURFMEM& dimoShadow,
  590. SURFMEM& dimoMask,
  591. ULONG ulAvec,
  592. ULONG iMode
  593. )
  594. {
  595. // If there is a mask, rotate it.
  596. if ((ulAvec & AVEC_NEED_MASK) && !bRotate(dimoMask, iMode))
  597. {
  598. return(FALSE);
  599. }
  600. ERECTL erclTrg;
  601. vBound(&erclTrg);
  602. // Fill in the bitmap info.
  603. DEVBITMAPINFO dbmi;
  604. dbmi.cxBitmap = erclTrg.right - erclTrg.left;
  605. dbmi.cyBitmap = erclTrg.bottom - erclTrg.top;
  606. dbmi.hpal = (HPALETTE) 0;
  607. dbmi.iFormat = pSurfSrc()->iFormat();
  608. dbmi.fl = pSurfSrc()->bUMPD() ? UMPD_SURFACE : 0;
  609. dimoShadow.bCreateDIB(&dbmi, (VOID *) NULL);
  610. if (!dimoShadow.bValid())
  611. {
  612. return(FALSE);
  613. }
  614. // Build a shadow parallelogram.
  615. POINTFIX aptfxShadow[4];
  616. aptfxShadow[0].x = aptfxTrg[0].x - FIX_FROM_LONG(erclTrg.left);
  617. aptfxShadow[0].y = aptfxTrg[0].y - FIX_FROM_LONG(erclTrg.top);
  618. aptfxShadow[1].x = aptfxTrg[1].x - FIX_FROM_LONG(erclTrg.left);
  619. aptfxShadow[1].y = aptfxTrg[1].y - FIX_FROM_LONG(erclTrg.top);
  620. aptfxShadow[2].x = aptfxTrg[2].x - FIX_FROM_LONG(erclTrg.left);
  621. aptfxShadow[2].y = aptfxTrg[2].y - FIX_FROM_LONG(erclTrg.top);
  622. aptfxShadow[3].x = aptfxTrg[3].x - FIX_FROM_LONG(erclTrg.left);
  623. aptfxShadow[3].y = aptfxTrg[3].y - FIX_FROM_LONG(erclTrg.top);
  624. // Take care of mirroring.
  625. vMirror(aptfxShadow);
  626. // Now comes the tricky part. The source may be a display. While it may
  627. // be somewhat faster to assume it isn't, code would be much more complex.
  628. {
  629. // Adjust the source rectangle.
  630. *perclSrc() += dcoSrc.eptlOrigin();
  631. // Exclude the pointer.
  632. ERECTL ercl(0,0,pSurfSrc()->sizl().cx,pSurfSrc()->sizl().cy);
  633. ercl *= *perclSrc();
  634. DEVEXCLUDEOBJ dxo(dcoSrc, &ercl);
  635. // Rotate the bits to the DIB.
  636. EPOINTL ptl(0,0);
  637. if (!EngPlgBlt(
  638. dimoShadow.pSurfobj(),
  639. pSurfSrc()->pSurfobj(),
  640. (SURFOBJ *) NULL,
  641. (CLIPOBJ *) NULL,
  642. NULL,
  643. NULL,
  644. (POINTL *)&ptl,
  645. aptfxShadow,
  646. perclSrc(),
  647. (POINTL *) NULL,
  648. iMode)
  649. )
  650. {
  651. return(FALSE);
  652. }
  653. // Update the source surface and set the source rectangle for
  654. // BitBlt or MaskBlt.
  655. pSurfSrc((SURFACE *) dimoShadow.ps);
  656. perclSrc()->left = -dcoSrc.eptlOrigin().x;
  657. perclSrc()->top = -dcoSrc.eptlOrigin().y;
  658. perclSrc()->right = dbmi.cxBitmap - dcoSrc.eptlOrigin().x;
  659. perclSrc()->bottom = dbmi.cyBitmap - dcoSrc.eptlOrigin().y;
  660. }
  661. return(TRUE);
  662. }
  663. /******************************Public*Routine******************************\
  664. * BOOL BLTRECORD::bRotated()
  665. *
  666. * Checks if the target parallelogram is skewed or rotated.
  667. *
  668. * History:
  669. * 25-Mar-1992 -by- Donald Sidoroff [donalds]
  670. * Wrote it.
  671. \**************************************************************************/
  672. BOOL BLTRECORD::bRotated()
  673. {
  674. // Test for rotation or skew.
  675. if (
  676. ((aptfxTrg[1].y - aptfxTrg[0].y) != 0) ||
  677. ((aptfxTrg[2].x - aptfxTrg[0].x) != 0)
  678. )
  679. {
  680. return(TRUE);
  681. }
  682. // We might have fractional endpoints. If so, we still need to call
  683. // bRotate since StretchBlt at the DDI takes integer coordinates.
  684. if (
  685. (aptfxTrg[0].x & 0x0f) || (aptfxTrg[0].y & 0x0f) ||
  686. (aptfxTrg[1].x & 0x0f) || (aptfxTrg[1].y & 0x0f) ||
  687. (aptfxTrg[2].x & 0x0f) || (aptfxTrg[2].y & 0x0f)
  688. )
  689. {
  690. return(TRUE);
  691. }
  692. // OK, we don't have to call bRotate. Set up the target rectangle and
  693. // return FALSE.
  694. aptlTrg[0].x = LONG_FLOOR_OF_FIX(aptfxTrg[0].x);
  695. aptlTrg[0].y = LONG_FLOOR_OF_FIX(aptfxTrg[0].y);
  696. aptlTrg[1].x = LONG_FLOOR_OF_FIX(aptfxTrg[1].x);
  697. aptlTrg[1].y = LONG_FLOOR_OF_FIX(aptfxTrg[2].y);
  698. return(FALSE);
  699. }
  700. /******************************Public*Routine******************************\
  701. * VOID BLTRECORD::vExtrema()
  702. *
  703. * Complete the parallelogram and find the extrema. Uses ChuckWh's trick.
  704. *
  705. * History:
  706. * 28-Jan-1993 -by- Donald Sidoroff [donalds]
  707. * Wrote it.
  708. \**************************************************************************/
  709. VOID BLTRECORD::vExtrema()
  710. {
  711. aptfxTrg[3].x = aptfxTrg[1].x + aptfxTrg[2].x - aptfxTrg[0].x;
  712. aptfxTrg[3].y = aptfxTrg[1].y + aptfxTrg[2].y - aptfxTrg[0].y;
  713. iLeft = (aptfxTrg[1].x > aptfxTrg[0].x) == (aptfxTrg[1].x > aptfxTrg[3].x);
  714. iTop = (aptfxTrg[1].y > aptfxTrg[0].y) == (aptfxTrg[1].y > aptfxTrg[3].y);
  715. }
  716. /******************************Public*Routine******************************\
  717. * VOID BLTRECORD::vBound(percl)
  718. *
  719. * Make a well ordered bounding rectangle from the parallelogram
  720. *
  721. * History:
  722. * 28-Jan-1993 -by- Donald Sidoroff [donalds]
  723. * Wrote it.
  724. \**************************************************************************/
  725. VOID BLTRECORD::vBound(ERECTL *percl)
  726. {
  727. percl->left = LONG_CEIL_OF_FIX(aptfxTrg[iLeft].x);
  728. percl->top = LONG_CEIL_OF_FIX(aptfxTrg[iTop].y);
  729. percl->right = LONG_CEIL_OF_FIX(aptfxTrg[iLeft ^ 3].x);
  730. percl->bottom = LONG_CEIL_OF_FIX(aptfxTrg[iTop ^ 3].y);
  731. // Make it well ordered!
  732. percl->vOrder();
  733. }
  734. /******************************Public*Routine******************************\
  735. * VOID BLTRECORD::vMirror(pptfx)
  736. *
  737. * Flip the parallelogram according to the mirroring flags
  738. *
  739. * History:
  740. * 24-Mar-1992 -by- Donald Sidoroff [donalds]
  741. * Wrote it.
  742. \**************************************************************************/
  743. VOID BLTRECORD::vMirror(POINTFIX *pptfx)
  744. {
  745. FIX fx;
  746. if (flState & BLTREC_MIRROR_X)
  747. {
  748. fx = pptfx[1].x, pptfx[1].x = pptfx[0].x, pptfx[0].x = fx;
  749. fx = pptfx[1].y, pptfx[1].y = pptfx[0].y, pptfx[0].y = fx;
  750. fx = pptfx[3].x, pptfx[3].x = pptfx[2].x, pptfx[2].x = fx;
  751. fx = pptfx[3].y, pptfx[3].y = pptfx[2].y, pptfx[2].y = fx;
  752. }
  753. if (flState & BLTREC_MIRROR_Y)
  754. {
  755. fx = pptfx[2].x, pptfx[2].x = pptfx[0].x, pptfx[0].x = fx;
  756. fx = pptfx[2].y, pptfx[2].y = pptfx[0].y, pptfx[0].y = fx;
  757. fx = pptfx[3].x, pptfx[3].x = pptfx[1].x, pptfx[1].x = fx;
  758. fx = pptfx[3].y, pptfx[3].y = pptfx[1].y, pptfx[1].y = fx;
  759. }
  760. }
  761. /******************************Public*Routine******************************\
  762. * BOOL BLTRECORD::bCreateRegion(dco, pptfx)
  763. *
  764. * Create a region from the parallelogram and add it to the clipping
  765. * pipeline.
  766. *
  767. * History:
  768. * 24-Mar-1992 -by- Donald Sidoroff [donalds]
  769. * Wrote it.
  770. \**************************************************************************/
  771. BOOL BLTRECORD::bCreateRegion(
  772. DCOBJ& dco,
  773. POINTFIX *pptfx
  774. )
  775. {
  776. // First, take care of any mirroring that might have occured.
  777. vMirror(pptfx);
  778. // Create a path
  779. PATHMEMOBJ pmo;
  780. if (!pmo.bValid())
  781. {
  782. return(FALSE);
  783. }
  784. // Create a parallelogram in drawing order.
  785. POINTL aptl[4];
  786. aptl[0].x = pptfx[0].x;
  787. aptl[0].y = pptfx[0].y;
  788. aptl[1].x = pptfx[1].x;
  789. aptl[1].y = pptfx[1].y;
  790. aptl[2].x = pptfx[3].x;
  791. aptl[2].y = pptfx[3].y;
  792. aptl[3].x = pptfx[2].x;
  793. aptl[3].y = pptfx[2].y;
  794. // Construct a path around the parallelogram
  795. if (!pmo.bMoveTo((EXFORMOBJ *) NULL, &aptl[0]))
  796. {
  797. return(FALSE);
  798. }
  799. if (!pmo.bPolyLineTo((EXFORMOBJ *) NULL, &aptl[1], 3))
  800. {
  801. return(FALSE);
  802. }
  803. // Create a region from it.
  804. prmo()->vCreate(pmo, ALTERNATE);
  805. if (!prmo()->bValid())
  806. {
  807. return(FALSE);
  808. }
  809. // Tell ~BLTRECORD it has something to clean up.
  810. flState |= BLTREC_PRO;
  811. // Select the region into the DC's clipping pipeline. This will dirty
  812. // the Rao so it gets merged in when bCompute is called.
  813. dco.pdc->prgnAPI(prmo()->prgnGet());
  814. return(TRUE);
  815. }
  816. #ifdef DBG_PLGBLT
  817. LONG gflPlgBlt = PLGBLT_ENABLE;
  818. VOID vShowRect(
  819. CHAR *psz,
  820. RECTL *prcl)
  821. {
  822. if (gflPlgBlt & PLGBLT_RECTS)
  823. {
  824. DbgPrint("%s [(%ld,%ld) (%ld,%ld)]\n",
  825. psz, prcl->left, prcl->top, prcl->right, prcl->bottom);
  826. }
  827. #endif
  828. /******************************Public*Routine******************************\
  829. * EngPlgBlt
  830. *
  831. * This does parallelogram bltting. This gets called to PlgBlt between
  832. * two engine managed surfaces or if the driver has chosen not to handle
  833. * EngPlgBlt.
  834. *
  835. * The API passes in prclSrc which is the rectangle on the left, and
  836. * also passes in 3 points which define A,B,C of the paralellogram on the
  837. * right. The points are assumed to be in that order A,B,C.
  838. * The lower-left of the src rect goes to the third point, the upper-left of
  839. * the src rect goes to the first point, and the upper-right of the source
  840. * rect goes to the second point.
  841. *
  842. * NOTE! The source rectangle MUST BE WELL ORDERED IN DEVICE SPACE.
  843. *
  844. * A-----B B A----------------B
  845. * | | / \ | |
  846. * | | ---> / \ | |
  847. * | | / \ or | |
  848. * C-----D A \ | |
  849. * \ D | |
  850. * \ / | |
  851. * \ / | |
  852. * \ / | |
  853. * C C----------------D
  854. *
  855. *
  856. * This call returns TRUE for success, FALSE for ERROR.
  857. *
  858. * History:
  859. * 27-Jul-1992 -by- Donald Sidoroff [donalds]
  860. * Wrote.
  861. \**************************************************************************/
  862. BOOL
  863. EngPlgBlt(
  864. SURFOBJ *psoTrg,
  865. SURFOBJ *psoSrc,
  866. SURFOBJ *psoMsk,
  867. CLIPOBJ *pco,
  868. XLATEOBJ *pxlo,
  869. COLORADJUSTMENT *pca,
  870. POINTL *pptlBrushOrg,
  871. POINTFIX *pptfx,
  872. RECTL *prcl,
  873. POINTL *pptl,
  874. ULONG iMode)
  875. {
  876. PSURFACE pSurfTrg = SURFOBJ_TO_SURFACE(psoTrg);
  877. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  878. PSURFACE pSurfMsk = SURFOBJ_TO_SURFACE(psoMsk);
  879. BOOL bRet = FALSE;
  880. //
  881. // Added HALFTONE support if iMode passed in is HALFTONE.
  882. // This is to ensure n-up printing on PCL printers
  883. // will look decent.
  884. // Note that we are currently not supporting HALFTONE
  885. // if there is mask. [lingyunw]
  886. //
  887. BOOL bHalftone = ((iMode == HALFTONE) && !pSurfMsk);
  888. //
  889. // Prevent bad driver call backs
  890. //
  891. if ((iMode == 0) || (iMode > MAXSTRETCHBLTMODE))
  892. {
  893. WARNING1("EngPlgBlt: Unsupported iMode\n");
  894. return(FALSE);
  895. }
  896. //
  897. // Can't PlgBlt to an RLE
  898. // Can't PlgBlt to/from a JPEG or PNG
  899. //
  900. if ((pSurfTrg->iFormat() == BMF_4RLE) ||
  901. (pSurfTrg->iFormat() == BMF_8RLE) ||
  902. (pSurfTrg->iFormat() == BMF_JPEG) ||
  903. (pSurfSrc->iFormat() == BMF_JPEG) ||
  904. (pSurfTrg->iFormat() == BMF_PNG ) ||
  905. (pSurfSrc->iFormat() == BMF_PNG ))
  906. {
  907. WARNING("EngPlgBlt: Unsupported source/target\n");
  908. return(FALSE);
  909. }
  910. //
  911. // We may need to do a WHITEONBLACK or BLACKONWHITE from a monochrome source.
  912. // Find out and set the bogusity flag.
  913. //
  914. BOOL bBogus = (
  915. (iMode < COLORONCOLOR) &&
  916. (pSurfMsk == (SURFACE *) NULL) &&
  917. ((pSurfSrc->iFormat() == BMF_1BPP) ||
  918. (pSurfTrg->iFormat() == BMF_1BPP))
  919. );
  920. if ((!bBogus) && (iMode < COLORONCOLOR))
  921. {
  922. iMode = COLORONCOLOR;
  923. }
  924. //
  925. // Get the LDEV's for the target and source surfaces
  926. //
  927. PDEVOBJ pdoTrg(pSurfTrg->hdev());
  928. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  929. //
  930. // Set up frame variables for possible switch to temporary output surface
  931. //
  932. SURFMEM dimoOut;
  933. SURFACE *pSurfOut;
  934. POINTFIX aptfxOut[4];
  935. POINTFIX *pptfxOut;
  936. ECLIPOBJ ecoOut;
  937. CLIPOBJ *pcoOut;
  938. ERECTL erclDev;
  939. EPOINTL eptlDev;
  940. XLATEOBJ *pxloOut;
  941. RGNMEMOBJTMP rmoOut;
  942. ERECTL erclTrim(0, 0, pSurfSrc->sizl().cx, pSurfSrc->sizl().cy);
  943. //
  944. // Multimon negative offset case
  945. //
  946. if ((pdoSrc.bValid()) && (pdoSrc.bPrimary(pSurfSrc) && (pdoSrc.bMetaDriver())))
  947. {
  948. erclTrim += *pdoSrc.pptlOrigin();
  949. }
  950. //
  951. // If the target is not a DIB, or the target and source are on the same
  952. // surface and the extents overlap, create a target DIB of the needed
  953. // size and format. We will also create a target DIB if we need to do
  954. // the evil BLACKONWHITE or WHITEONBLACK modes.
  955. //
  956. if ( !bBogus &&
  957. (pSurfTrg->iType() == STYPE_BITMAP) &&
  958. (pSurfTrg->hsurf() != pSurfSrc->hsurf()) &&
  959. !bHalftone )
  960. {
  961. pSurfOut = pSurfTrg;
  962. pptfxOut = pptfx;
  963. pcoOut = pco;
  964. }
  965. else
  966. {
  967. aptfxOut[0] = pptfx[0];
  968. aptfxOut[1] = pptfx[1];
  969. aptfxOut[2] = pptfx[2];
  970. aptfxOut[3].x = pptfx[1].x + pptfx[2].x - pptfx[0].x;
  971. aptfxOut[3].y = pptfx[1].y + pptfx[2].y - pptfx[0].y;
  972. //
  973. // Compute the extrema
  974. //
  975. int iLeft = (aptfxOut[1].x > aptfxOut[0].x) == (aptfxOut[1].x > aptfxOut[3].x);
  976. int iTop = (aptfxOut[1].y > aptfxOut[0].y) == (aptfxOut[1].y > aptfxOut[3].y);
  977. if (aptfxOut[iLeft].x > aptfxOut[iLeft ^ 3].x)
  978. {
  979. iLeft ^= 3;
  980. }
  981. if (aptfxOut[iTop].y > aptfxOut[iTop ^ 3].y)
  982. {
  983. iTop ^= 3;
  984. }
  985. //
  986. // This will be the area we copy dimoOut to in the target surface.
  987. //
  988. erclDev.left = LONG_FLOOR_OF_FIX(aptfxOut[iLeft].x) - 1;
  989. erclDev.top = LONG_FLOOR_OF_FIX(aptfxOut[iTop].y) - 1;
  990. erclDev.right = LONG_CEIL_OF_FIX(aptfxOut[iLeft ^ 3].x) + 1;
  991. erclDev.bottom = LONG_CEIL_OF_FIX(aptfxOut[iTop ^ 3].y) + 1;
  992. //
  993. // Trim to the target surface.
  994. //
  995. ERECTL erclTrg(0, 0, pSurfTrg->sizl().cx, pSurfTrg->sizl().cy);
  996. //
  997. // Multimon negative offset case
  998. //
  999. if ((pdoTrg.bValid()) && (pdoTrg.bPrimary(pSurfTrg) && (pdoTrg.bMetaDriver())))
  1000. {
  1001. erclTrg += *pdoTrg.pptlOrigin();
  1002. }
  1003. erclDev *= erclTrg;
  1004. //
  1005. // If we have nothing left, we're done.
  1006. //
  1007. if (erclDev.bEmpty())
  1008. {
  1009. return(TRUE);
  1010. }
  1011. //
  1012. // If we are only here on possible overlap, test for misses
  1013. //
  1014. if ( !bBogus &&
  1015. (pSurfTrg->iType() == STYPE_BITMAP) &&
  1016. (!bHalftone) &&
  1017. ( (erclDev.left > prcl->right) ||
  1018. (erclDev.right < prcl->left) ||
  1019. (erclDev.top > prcl->bottom) ||
  1020. (erclDev.bottom < prcl->top) ) )
  1021. {
  1022. pSurfOut = pSurfTrg;
  1023. pptfxOut = pptfx;
  1024. pcoOut = pco;
  1025. }
  1026. else
  1027. {
  1028. // Compute the adjusted parallelogram in the temporary surface.
  1029. aptfxOut[0].x -= FIX_FROM_LONG(erclDev.left);
  1030. aptfxOut[0].y -= FIX_FROM_LONG(erclDev.top);
  1031. aptfxOut[1].x -= FIX_FROM_LONG(erclDev.left);
  1032. aptfxOut[1].y -= FIX_FROM_LONG(erclDev.top);
  1033. aptfxOut[2].x -= FIX_FROM_LONG(erclDev.left);
  1034. aptfxOut[2].y -= FIX_FROM_LONG(erclDev.top);
  1035. DEVBITMAPINFO dbmi;
  1036. dbmi.cxBitmap = erclDev.right - erclDev.left + 1;
  1037. dbmi.cyBitmap = erclDev.bottom - erclDev.top + 1;
  1038. dbmi.hpal = (HPALETTE) 0;
  1039. dbmi.iFormat = pSurfTrg->iFormat();
  1040. dbmi.fl = pSurfTrg->bUMPD() ? UMPD_SURFACE : 0;
  1041. //
  1042. // If this is a bogus call, build a monochrome target.
  1043. //
  1044. if (bBogus)
  1045. {
  1046. dbmi.iFormat = BMF_1BPP;
  1047. }
  1048. else if (bHalftone)
  1049. {
  1050. //
  1051. // if HALFTONE, make the target same format as source
  1052. // so latter on we can stretch with HALFTONE
  1053. //
  1054. dbmi.iFormat = pSurfSrc->iFormat();
  1055. }
  1056. dimoOut.bCreateDIB(&dbmi, (VOID *) NULL);
  1057. if (!dimoOut.bValid())
  1058. {
  1059. return(FALSE);
  1060. }
  1061. //
  1062. // What point in the target surface is 0,0 in temporary surface.
  1063. //
  1064. eptlDev = *((EPOINTL *) &erclDev);
  1065. //
  1066. // Build a CLIPOBJ for the new surface.
  1067. //
  1068. if (!rmoOut.bValid())
  1069. {
  1070. return(FALSE);
  1071. }
  1072. erclDev.left = 0;
  1073. erclDev.top = 0;
  1074. erclDev.right -= eptlDev.x;
  1075. erclDev.bottom -= eptlDev.y;
  1076. rmoOut.vSet((RECTL *) &erclDev);
  1077. ecoOut.vSetup(rmoOut.prgnGet(), erclDev, CLIP_FORCE);
  1078. //
  1079. // Synchronize with the device driver before touching the device surface.
  1080. //
  1081. pdoTrg.vSync(psoTrg,NULL,0);
  1082. //
  1083. // If there is a mask, copy the actual target to the temporary.
  1084. //
  1085. if (pSurfMsk != (SURFACE *) NULL)
  1086. {
  1087. (*PPFNGET(pdoTrg,CopyBits,pSurfTrg->flags()))(
  1088. dimoOut.pSurfobj(),
  1089. pSurfTrg->pSurfobj(),
  1090. (CLIPOBJ *) NULL,
  1091. &xloIdent,
  1092. &erclDev,
  1093. &eptlDev);
  1094. }
  1095. //
  1096. // If we are doing BLACKONWHITE or WHITEONBLACK we need to
  1097. // initialize the DIB appropriately.
  1098. //
  1099. if (bBogus)
  1100. {
  1101. if (!EngEraseSurface(dimoOut.pSurfobj(),
  1102. &erclDev,
  1103. iMode == BLACKONWHITE ? ~0L : 0L))
  1104. return(FALSE);
  1105. }
  1106. //
  1107. // Point to the new target.
  1108. //
  1109. pSurfOut = dimoOut.ps;
  1110. pptfxOut = &aptfxOut[0];
  1111. pcoOut = &ecoOut;
  1112. if ((bBogus && (pSurfSrc->iFormat() == BMF_1BPP)) || bHalftone)
  1113. {
  1114. pxloOut = pxlo;
  1115. pxlo = NULL;
  1116. }
  1117. else
  1118. {
  1119. pxloOut = &xloIdent;
  1120. }
  1121. }
  1122. }
  1123. //
  1124. // Synchronize with the device driver before touching the device surface.
  1125. //
  1126. pdoSrc.vSync(psoSrc,NULL,0);
  1127. //
  1128. // Compute what area of the source surface will actually be used. We do
  1129. // this so we never read off the end of the surface and fault or worse,
  1130. // write bad pixels onto the target. Trim the source rectangle to the
  1131. // source surface.
  1132. //
  1133. erclTrim *= *prcl;
  1134. // WINBUG #263939 3-5-2000 bhouse Watchdog timeout problems
  1135. // We suspend the watchdog here ... This code is just brain
  1136. // dead and for various scenarios can cause us to hang within GDI
  1137. // giving false positive WatchDog timeouts. Maybe one day we will
  1138. // re-write this brain dead code.... I'm not holding my breadth.
  1139. if(pdoTrg.bValid() && pdoTrg.bDisplayPDEV())
  1140. GreSuspendWatch(pdoTrg.ppdev, WD_DEVLOCK);
  1141. if(pdoSrc.bValid() && pdoSrc.bDisplayPDEV())
  1142. GreSuspendWatch(pdoSrc.ppdev, WD_DEVLOCK);
  1143. //
  1144. // If we have nothing left, we're done.
  1145. //
  1146. if (erclTrim.bEmpty())
  1147. {
  1148. bRet = TRUE;
  1149. }
  1150. else
  1151. {
  1152. //
  1153. // Now we must worry about the source surface. Its possible we are blitting
  1154. // from an RLE to the VGA for instance. We convert the surface to the same
  1155. // bitmap format as the target for convience.
  1156. //
  1157. SURFMEM dimoIn;
  1158. SURFACE *pSurfIn;
  1159. RECTL rclIn;
  1160. RECTL *prclIn;
  1161. XLATEOBJ *pxloIn;
  1162. if (! ((pSurfSrc->iType() != STYPE_BITMAP) ||
  1163. (pSurfSrc->iFormat() == BMF_4RLE) ||
  1164. (pSurfSrc->iFormat() == BMF_8RLE) )
  1165. )
  1166. {
  1167. pSurfIn = pSurfSrc;
  1168. pxloIn = pxlo;
  1169. prclIn = prcl;
  1170. }
  1171. else
  1172. {
  1173. DEVBITMAPINFO dbmi;
  1174. dbmi.cxBitmap = erclTrim.right - erclTrim.left + 1;
  1175. dbmi.cyBitmap = erclTrim.bottom - erclTrim.top + 1;
  1176. dbmi.hpal = (HPALETTE) 0;
  1177. dbmi.iFormat = pSurfOut->iFormat();
  1178. dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
  1179. dimoIn.bCreateDIB(&dbmi, (VOID *) NULL);
  1180. if (!dimoIn.bValid())
  1181. {
  1182. bRet = FALSE;
  1183. goto exit;
  1184. }
  1185. // The cursor should already be excluded at this point, so just copy
  1186. // to the DIB.
  1187. rclIn.left = 0;
  1188. rclIn.top = 0;
  1189. rclIn.right = erclTrim.right - erclTrim.left;
  1190. rclIn.bottom = erclTrim.bottom - erclTrim.top;
  1191. (*PPFNGET(pdoSrc,CopyBits,pSurfSrc->flags()))(
  1192. dimoIn.pSurfobj(),
  1193. pSurfSrc->pSurfobj(),
  1194. (CLIPOBJ *) NULL,
  1195. pxlo,
  1196. &rclIn,
  1197. (POINTL *) &erclTrim);
  1198. // Point at the new source
  1199. rclIn.left = prcl->left - erclTrim.left;
  1200. rclIn.top = prcl->top - erclTrim.top;
  1201. rclIn.right = prcl->right - erclTrim.left;
  1202. rclIn.bottom = prcl->bottom - erclTrim.top;
  1203. pSurfIn = dimoIn.ps;
  1204. pxloIn = NULL;
  1205. prclIn = &rclIn;
  1206. // Adjust the trimmed source origin and extent
  1207. erclTrim.right -= erclTrim.left;
  1208. erclTrim.bottom -= erclTrim.top;
  1209. erclTrim.left = 0;
  1210. erclTrim.top = 0;
  1211. }
  1212. // Synchronize with the device driver before touching the device surface.
  1213. {
  1214. PDEVOBJ po(pSurfOut->hdev());
  1215. po.vSync(pSurfOut->pSurfobj(),NULL,0);
  1216. }
  1217. //
  1218. // Initialize the DDA
  1219. //
  1220. PLGDDA *pdda = (PLGDDA *)PALLOCMEM(sizeof(PLGDDA),'addG');
  1221. if (pdda)
  1222. {
  1223. if (!bInitPlgDDA(pdda, (RECTL *) &erclTrim, prclIn, pptfxOut))
  1224. {
  1225. bRet = TRUE;
  1226. }
  1227. else
  1228. {
  1229. PFN_PLGREAD pfnRead = apfnRead[pSurfIn->iFormat()];
  1230. PFN_PLGWRITE pfnWrite;
  1231. PLGRUN *prun;
  1232. LONG cjSpace = lSizeDDA(pdda) * (erclTrim.right - erclTrim.left + 2);
  1233. if (bBogus)
  1234. {
  1235. pdda->bOverwrite = TRUE;
  1236. pfnWrite = apfnBogus[iMode];
  1237. }
  1238. else
  1239. {
  1240. pdda->bOverwrite = FALSE;
  1241. pfnWrite = apfnWrite[pSurfOut->iFormat()];
  1242. }
  1243. if (prun = (PLGRUN *) PALLOCMEM(cjSpace,'addG'))
  1244. {
  1245. BYTE *pjSrc = (BYTE *) pSurfIn->pvScan0() + pSurfIn->lDelta() * erclTrim.top;
  1246. BYTE *pjMask;
  1247. POINTL ptlMask;
  1248. if (pSurfMsk == (SURFACE *) NULL)
  1249. {
  1250. pjMask = (BYTE *) NULL;
  1251. }
  1252. else
  1253. {
  1254. ptlMask.x = erclTrim.left - prclIn->left + pptl->x;
  1255. ptlMask.y = erclTrim.top - prclIn->top + pptl->y;
  1256. pjMask = (BYTE *) pSurfMsk->pvScan0() + pSurfMsk->lDelta() * ptlMask.y;
  1257. }
  1258. // See if we can accelerate anything.
  1259. if ((pxloIn != NULL) && (pxloIn->flXlate & XO_TRIVIAL))
  1260. {
  1261. pxloIn = NULL;
  1262. }
  1263. //
  1264. // force DDA into clipping to destination surface!, this can be
  1265. // removed once dda doesn't go negatice!
  1266. //
  1267. if ((pcoOut == NULL) || (pcoOut->iDComplexity == DC_TRIVIAL))
  1268. {
  1269. ERECTL erclDest(0,0,pSurfOut->sizl().cx,pSurfOut->sizl().cy);
  1270. rmoOut.vSet((RECTL *) &erclDest);
  1271. ecoOut.vSetup(rmoOut.prgnGet(), erclDest, CLIP_FORCE);
  1272. pcoOut = &ecoOut;
  1273. }
  1274. //
  1275. // make sure it doesn't have a empty rectangle
  1276. //
  1277. if ((pcoOut->rclBounds.left < pcoOut->rclBounds.right) &&
  1278. (pcoOut->rclBounds.top < pcoOut->rclBounds.bottom))
  1279. {
  1280. for (LONG yRow = erclTrim.top; yRow < erclTrim.bottom; yRow++)
  1281. {
  1282. pdda->dsX = pdda->ds;
  1283. (*pfnWrite)(prun,
  1284. (*pfnRead)(pdda,
  1285. prun,
  1286. pjSrc,
  1287. pjMask,
  1288. pxloIn,
  1289. erclTrim.left,
  1290. erclTrim.right,
  1291. ptlMask.x),
  1292. pSurfOut,
  1293. pcoOut);
  1294. vAdvYDDA(pdda);
  1295. pjSrc += pSurfIn->lDelta();
  1296. if (pjMask != (BYTE *) NULL)
  1297. {
  1298. pjMask += pSurfMsk->lDelta();
  1299. }
  1300. }
  1301. VFREEMEM(prun);
  1302. //
  1303. // See if we have drawn on the actual output surface.
  1304. //
  1305. if (pSurfOut == pSurfTrg)
  1306. {
  1307. bRet = TRUE;
  1308. }
  1309. else
  1310. {
  1311. BOOL bTmpRet = FALSE;
  1312. //
  1313. // If the source rectangle was reduced, then we have to
  1314. // create a mask for the target, so only the actual pels
  1315. // effected by the PlgBlt will be altered on the target.
  1316. SURFMEM dimoMask;
  1317. SURFACE *pSurfMask;
  1318. if (((prcl->right - prcl->left) == erclTrim.right) &&
  1319. ((prcl->bottom - prcl->top) == erclTrim.bottom) )
  1320. {
  1321. pSurfMask = (SURFACE *) NULL;
  1322. bTmpRet = TRUE;
  1323. }
  1324. else
  1325. {
  1326. DEVBITMAPINFO dbmi;
  1327. dbmi.cxBitmap = erclDev.right + 1;
  1328. dbmi.cyBitmap = erclDev.bottom + 1;
  1329. dbmi.hpal = (HPALETTE) 0;
  1330. dbmi.iFormat = BMF_1BPP;
  1331. dbmi.fl = pSurfTrg->bUMPD() ? UMPD_SURFACE : 0;
  1332. dimoMask.bCreateDIB(&dbmi, (VOID *) NULL);
  1333. if (dimoMask.bValid())
  1334. {
  1335. SURFMEM dimoTrim;
  1336. dbmi.cxBitmap = erclTrim.right;
  1337. dbmi.cyBitmap = erclTrim.bottom;
  1338. dbmi.hpal = (HPALETTE) 0;
  1339. dbmi.iFormat = BMF_1BPP;
  1340. dbmi.fl = pSurfTrg->bUMPD() ? UMPD_SURFACE : 0;
  1341. dimoTrim.bCreateDIB(&dbmi, (VOID *) NULL);
  1342. RGNMEMOBJTMP rmoMask;
  1343. if (dimoTrim.bValid() &&
  1344. rmoMask.bValid() )
  1345. {
  1346. rmoMask.vSet((RECTL *) &erclDev);
  1347. ECLIPOBJ ecoMask(rmoMask.prgnGet(), erclDev, CLIP_FORCE);
  1348. //
  1349. // Initialize the two bitmaps and call EngPlgBlt to create a pel
  1350. // perfect mask for the reduced call.
  1351. //
  1352. if (EngEraseSurface(dimoMask.pSurfobj(),
  1353. &erclDev,
  1354. 0L) &&
  1355. EngEraseSurface(dimoTrim.pSurfobj(),
  1356. &erclTrim,
  1357. (ULONG)~0L) &&
  1358. EngPlgBlt(dimoMask.pSurfobj(),
  1359. dimoTrim.pSurfobj(),
  1360. (SURFOBJ *) NULL,
  1361. &ecoMask,
  1362. NULL,
  1363. (COLORADJUSTMENT *) NULL,
  1364. (POINTL *) NULL,
  1365. pptfxOut,
  1366. prclIn,
  1367. (POINTL *) NULL,
  1368. COLORONCOLOR) )
  1369. {
  1370. pSurfMask = dimoMask.ps;
  1371. bTmpRet = TRUE;
  1372. }
  1373. }
  1374. }
  1375. }
  1376. // If we had to draw the target on a shadow, we need to copy it to the
  1377. // actual surface. Since we don't clip to the shadow buffer, we need
  1378. // to merge the parallelogram into the clipobj and clip against this
  1379. // and call BitBlt.
  1380. PATHMEMOBJ pmo;
  1381. if (bTmpRet &&
  1382. pmo.bValid())
  1383. {
  1384. //
  1385. // Create a parallelogram in drawing order.
  1386. //
  1387. POINTL aptl[4];
  1388. aptl[0].x = pptfx[0].x;
  1389. aptl[0].y = pptfx[0].y;
  1390. aptl[1].x = pptfx[1].x;
  1391. aptl[1].y = pptfx[1].y;
  1392. aptl[2].x = pptfx[1].x + pptfx[2].x - pptfx[0].x;
  1393. aptl[2].y = pptfx[1].y + pptfx[2].y - pptfx[0].y;;
  1394. aptl[3].x = pptfx[2].x;
  1395. aptl[3].y = pptfx[2].y;
  1396. //
  1397. // Construct a path around the parallelogram
  1398. //
  1399. if ( (pmo.bMoveTo((EXFORMOBJ *) NULL, &aptl[0])) &&
  1400. (pmo.bPolyLineTo((EXFORMOBJ *) NULL, &aptl[1], 3)) )
  1401. {
  1402. //
  1403. // Create a regions from it.
  1404. //
  1405. RGNMEMOBJTMP rmo(pmo, ALTERNATE);
  1406. RGNMEMOBJTMP rmoTrg;
  1407. if ( (rmo.bValid()) &&
  1408. (rmoTrg.bValid()) )
  1409. {
  1410. //
  1411. // Merge the region we just constructed with the clip region.
  1412. //
  1413. if ( ((pco == (CLIPOBJ *) NULL) &&
  1414. (rmoTrg.bCopy(rmo))) ||
  1415. ((pco != (CLIPOBJ *) NULL) &&
  1416. (rmoTrg.bMerge(rmo,
  1417. *((ECLIPOBJ *)pco),
  1418. gafjRgnOp[RGN_AND]))) )
  1419. {
  1420. ERECTL ercl;
  1421. rmoTrg.vGet_rcl(&ercl);
  1422. // If we have a clipobj,
  1423. // make sure that the bounds are
  1424. // tight to the destination rectangle
  1425. // and there is intersection.
  1426. if ((pco == NULL) ||
  1427. bIntersect(&ercl, &pco->rclBounds, &ercl))
  1428. {
  1429. ECLIPOBJ eco(rmoTrg.prgnGet(), ercl, CLIP_FORCE);
  1430. if (!eco.erclExclude().bEmpty())
  1431. {
  1432. //
  1433. // Copy from the temporary to the target surface.
  1434. //
  1435. erclDev.left += eptlDev.x;
  1436. erclDev.top += eptlDev.y;
  1437. erclDev.right += eptlDev.x;
  1438. erclDev.bottom += eptlDev.y;
  1439. eptlDev.x = 0;
  1440. eptlDev.y = 0;
  1441. //
  1442. // Inc the target surface uniqueness
  1443. //
  1444. INC_SURF_UNIQ(pSurfTrg);
  1445. if (!bHalftone)
  1446. {
  1447. (*(pSurfTrg->pfnBitBlt()))(
  1448. pSurfTrg->pSurfobj(),
  1449. dimoOut.pSurfobj(),
  1450. pSurfMask->pSurfobj(),
  1451. &eco,
  1452. pxloOut,
  1453. &erclDev,
  1454. &eptlDev,
  1455. &eptlDev,
  1456. (BRUSHOBJ *) NULL,
  1457. (POINTL *) NULL,
  1458. pSurfMask == (SURFACE *) NULL ? 0x0000CCCC : 0x0000AACC);
  1459. }
  1460. else
  1461. {
  1462. POINTL ptlBrushOrg;
  1463. ERECTL erclSrc(0, 0,
  1464. erclDev.right-erclDev.left,
  1465. erclDev.bottom-erclDev.top);
  1466. ptlBrushOrg.x=0; ptlBrushOrg.y=0;
  1467. (*PPFNGET(pdoTrg, StretchBlt, pSurfTrg->flags()))(
  1468. pSurfTrg->pSurfobj(),
  1469. dimoOut.pSurfobj(),
  1470. pSurfMask->pSurfobj(),
  1471. &eco,
  1472. pxloOut,
  1473. NULL,
  1474. &ptlBrushOrg,
  1475. &erclDev,
  1476. &erclSrc,
  1477. &eptlDev,
  1478. HALFTONE);
  1479. }
  1480. }
  1481. }
  1482. bRet = TRUE;
  1483. }
  1484. }
  1485. }
  1486. }
  1487. }
  1488. }
  1489. else
  1490. {
  1491. VFREEMEM(prun);
  1492. }
  1493. }
  1494. }
  1495. VFREEMEM(pdda);
  1496. }
  1497. }
  1498. exit:
  1499. if(pdoTrg.bValid() && pdoTrg.bDisplayPDEV())
  1500. GreResumeWatch(pdoTrg.ppdev, WD_DEVLOCK);
  1501. if(pdoSrc.bValid() && pdoSrc.bDisplayPDEV())
  1502. GreResumeWatch(pdoSrc.ppdev, WD_DEVLOCK);
  1503. return bRet;
  1504. }