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.

2709 lines
78 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: strchblt.cxx
  3. *
  4. * This contains the API and DDI entry points to the graphics engine
  5. * for StretchBlt and EngStretchBlt.
  6. *
  7. * Created: 04-Apr-1991 10:57:37
  8. * Author: Patrick Haluptzok patrickh
  9. *
  10. * Copyright (c) 1990-1999 Microsoft Corporation
  11. \**************************************************************************/
  12. #include "precomp.hxx"
  13. #include "stretch.hxx"
  14. //the limit of our coordinate systems (2^27)
  15. #define MAX_STRETCH_COOR 128000000L
  16. ULONG gaulMonoExpand[] = {
  17. 0x00000000, //
  18. 0x00000001, // BMF_1BPP
  19. 0x0000000F, // BMF_4BPP
  20. 0x000000FF, // BMF_8BPP
  21. 0x0000FFFF, // BMF_16BPP
  22. 0x00FFFFFF, // BMF_24BPP
  23. 0xFFFFFFFF // BMF_32BPP
  24. };
  25. /******************************Public*Routine******************************\
  26. * GreStretchBlt
  27. *
  28. * Stretches the source image to the destination.
  29. *
  30. * Returns: TRUE if successful, FALSE for failure.
  31. *
  32. * History:
  33. * Thu Mar-05-1998 -by- Samer Arafeh [samera]
  34. * Support LAYOUT_BITMAPORIENTATIONPRESERVED. Make sure
  35. * to exit thru one of the RETURN_XXX labels if you are writing
  36. * code past the layout code (see comments below).
  37. *
  38. * Tue 02-Jun-1992 -by- Patrick Haluptzok [patrickh]
  39. * Fix clipping bugs
  40. *
  41. * 21-Mar-1992 -by- Donald Sidoroff [donalds]
  42. * Rewrote it.
  43. *
  44. * 15-Jan-1992 -by- Patrick Haluptzok patrickh
  45. * add mask support
  46. *
  47. * Thu 19-Sep-1991 -by- Patrick Haluptzok [patrickh]
  48. * add support for rops
  49. *
  50. * 07-Nov-1990 -by- Patrick Haluptzok patrickh
  51. * Wrote it.
  52. \**************************************************************************/
  53. BOOL GreStretchBlt(
  54. HDC hdcTrg,
  55. int x,
  56. int y,
  57. int cx,
  58. int cy,
  59. HDC hdcSrc,
  60. int xSrc,
  61. int ySrc,
  62. int cxSrc,
  63. int cySrc,
  64. DWORD rop4,
  65. DWORD crBackColor
  66. )
  67. {
  68. GDITraceHandle2(GreStretchBlt, "(%X, %d, %d, %d, %d, %X, %d, %d, %d, %d, %X, %X)\n", (va_list)&hdcTrg, hdcTrg, hdcSrc);
  69. return (GreStretchBltInternal(
  70. hdcTrg, x, y, cx, cy,
  71. hdcSrc, xSrc, ySrc, cxSrc, cySrc,
  72. rop4, crBackColor, 0));
  73. }
  74. BOOL GreStretchBltInternal(
  75. HDC hdcTrg,
  76. int x,
  77. int y,
  78. int cx,
  79. int cy,
  80. HDC hdcSrc,
  81. int xSrc,
  82. int ySrc,
  83. int cxSrc,
  84. int cySrc,
  85. DWORD rop4,
  86. DWORD crBackColor,
  87. FLONG ulFlags
  88. )
  89. {
  90. BLTRECORD blt;
  91. BOOL bRet;
  92. POINTL ptOrgDst;
  93. DWORD OrgRop4 = rop4, dwOldLayout;
  94. rop4 = rop4 & ~NOMIRRORBITMAP;
  95. // [Bug #278291] - CAPTUREBLT
  96. // The CAPTUREBLT rop flag is used for screen capture. When it's set, we bypass
  97. // the sprite code which normally hides the sprites, so that the caller gets
  98. // an exact copy of what's on the screen (except for the cursor).
  99. BOOL bCaptureBlt = 0;
  100. if (rop4 & CAPTUREBLT)
  101. {
  102. bCaptureBlt = 1;
  103. rop4 = rop4 & ~CAPTUREBLT;
  104. }
  105. // Initialize the blt record
  106. blt.rop((rop4 | (rop4 & 0x00ff0000) << 8) >> 16);
  107. // Convert the rop into something useful.
  108. ULONG ulAvec = ((ULONG) gajRop3[blt.ropFore()]) |
  109. ((ULONG) gajRop3[blt.ropBack()]);
  110. // See if we can special case this operation
  111. if (!(ulAvec & AVEC_NEED_SOURCE))
  112. {
  113. // We can't require a mask, since one can't be passed.
  114. if (blt.ropFore() == blt.ropBack())
  115. return(NtGdiPatBlt(hdcTrg, x, y, cx, cy, rop4));
  116. }
  117. // Lock the DC's, no optimization is made for same surface
  118. DCOBJ dcoTrg(hdcTrg);
  119. DCOBJ dcoSrc(hdcSrc);
  120. if (dcoTrg.bValid() && !dcoTrg.bStockBitmap())
  121. {
  122. ULONG ulDirty = dcoTrg.pdc->ulDirty();
  123. if ( ulDirty & DC_BRUSH_DIRTY)
  124. {
  125. GreDCSelectBrush (dcoTrg.pdc, dcoTrg.pdc->hbrush());
  126. }
  127. }
  128. if (!dcoTrg.bValid() ||
  129. dcoTrg.bStockBitmap() ||
  130. (!dcoSrc.bValid() && (ulAvec & AVEC_NEED_SOURCE)))
  131. {
  132. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  133. return(!(ulAvec & AVEC_NEED_SOURCE) || dcoSrc.bValid());
  134. }
  135. // Lock the relevant surfaces
  136. DEVLOCKBLTOBJ dlo;
  137. if (ulAvec & AVEC_NEED_SOURCE)
  138. dlo.bLock(dcoTrg, dcoSrc);
  139. else
  140. dlo.bLock(dcoTrg);
  141. if (!dlo.bValid())
  142. {
  143. return(dcoTrg.bFullScreen());
  144. }
  145. if (!dcoTrg.bValidSurf() || !dcoSrc.bValidSurf() || !dcoSrc.pSurface()->bReadable())
  146. {
  147. if ((dcoTrg.dctp() == DCTYPE_INFO) || !dcoSrc.bValidSurf())
  148. {
  149. if (dcoTrg.fjAccum())
  150. {
  151. EXFORMOBJ exo(dcoTrg, WORLD_TO_DEVICE);
  152. ERECTL ercl(x, y, x + cx, y + cy);
  153. if (exo.bXform(ercl))
  154. {
  155. ercl.vOrder();
  156. dcoTrg.vAccumulate(ercl);
  157. }
  158. }
  159. // if we need a source and the source isn't valid, return failure
  160. return(TRUE);
  161. }
  162. // Do the security test on SCREEN to MEMORY blits.
  163. if (dcoSrc.bDisplay() && !dcoTrg.bDisplay())
  164. {
  165. if (!UserScreenAccessCheck())
  166. {
  167. SAVE_ERROR_CODE(ERROR_ACCESS_DENIED);
  168. return(FALSE);
  169. }
  170. }
  171. // If the source isn't a DISPLAY we should exit
  172. if (!dcoSrc.bDisplay())
  173. return(FALSE);
  174. }
  175. if(dcoTrg.bDisplay() && !dcoTrg.bRedirection() && dcoSrc.bValidSurf() && !dcoSrc.bDisplay() && !UserScreenAccessCheck())
  176. {
  177. SAVE_ERROR_CODE(ERROR_ACCESS_DENIED);
  178. return(FALSE);
  179. }
  180. // We can't require a mask, since one can't be passed.
  181. if (blt.ropFore() != blt.ropBack())
  182. {
  183. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  184. return(FALSE);
  185. }
  186. // ATTENTION: Please pay attention here
  187. //
  188. // Any code you are going to write past the following
  189. // section of code (mirroring code below that changes the
  190. // windows origin of the DC) should exit (return) -if it needs-
  191. // through either RETURN_FAIL, RETURN_FAIL_ONLY or RETURN_STATUS
  192. // labels by doing a goto statement to them. The reason for this
  193. // is to restore the DC's window origin by executing
  194. // the code located at the RETURN_STATUS label (see end of fn). [samera]
  195. //
  196. // Let's preserve the bitmap shape if the target DC
  197. // is a mirrored one. [samera]
  198. //
  199. if ( (((OrgRop4 & NOMIRRORBITMAP) && MIRRORED_DC(dcoTrg.pdc) ) ||
  200. MIRRORED_DC_NO_BITMAP_FLIP(dcoTrg.pdc)) &&
  201. (hdcSrc != hdcTrg) ) {
  202. dcoTrg.pdc->vGet_ptlWindowOrg( &ptOrgDst );
  203. dwOldLayout = dcoTrg.pdc->dwSetLayout(-1, 0);
  204. x = ptOrgDst.x - x - cx;
  205. // Restore the DC if the flag is in the DC and not part
  206. // of the Rops. [samera]
  207. //
  208. OrgRop4 = NOMIRRORBITMAP;
  209. } else {
  210. OrgRop4 = 0;
  211. }
  212. HANDLE hcmXform = NULL;
  213. // Don't put any goto's before here.
  214. //
  215. // [Bug #278291] - CAPTUREBLT
  216. // If we're doing a screen capture, hide the cursor, and set a
  217. // flag in the destination surface, to notify the sprite code.
  218. SURFACE *pSurfTrg = dcoTrg.pSurfaceEff();
  219. SURFACE *pSurfSrc = dcoSrc.pSurfaceEff();
  220. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  221. POINTL pointerPos;
  222. if (bCaptureBlt)
  223. {
  224. if (dcoSrc.bDisplay() &&
  225. !dcoSrc.bPrinter() &&
  226. (dcoSrc.hdev() == dcoTrg.hdev()))
  227. {
  228. ASSERTGDI(pSurfTrg, "Null destination surface");
  229. ASSERTGDI(pSurfSrc, "Null source surface");
  230. // Because the sprites are going to be visible, we must explicitly
  231. // hide the cursor (since it may be a sprite).
  232. // Grab the pointer semaphore to ensure that no-one else moves
  233. // the pointer until we restore it.
  234. GreAcquireSemaphoreEx(pdoSrc.hsemPointer(), SEMORDER_POINTER, dcoSrc.hsemDcDevLock());
  235. pointerPos = pdoSrc.ptlPointer();
  236. //
  237. // Don't make this a procedural mouse move for TS otherwise during
  238. // scenarios like magnifier with a lot of stretchblits the client
  239. // gets repeated programmatic mouse moves (with delay) that cause
  240. // it to get a jerky mouse. See bug#450927
  241. //
  242. GreMovePointer(pSurfSrc->hdev(), -1, -1, MP_NORMAL);
  243. // Set the 'IncludeSprites' flag in the destination surface. This tells
  244. // bSpBltFromScreen to include the sprites.
  245. pSurfTrg->vSetIncludeSprites();
  246. }
  247. else
  248. {
  249. // Clear bCaptureBlt, to bypass the cleanup code at the end.
  250. bCaptureBlt = 0;
  251. }
  252. }
  253. // Fill the BLTRECORD
  254. blt.pxoTrg()->vInit(dcoTrg,WORLD_TO_DEVICE);
  255. blt.pSurfTrg(dcoTrg.pSurfaceEff());
  256. blt.ppoTrg()->ppalSet(blt.pSurfTrg()->ppal());
  257. blt.ppoTrgDC()->ppalSet(dcoTrg.ppal());
  258. blt.pxoSrc()->vInit(dcoSrc,WORLD_TO_DEVICE);
  259. blt.pSurfSrc(dcoSrc.pSurfaceEff());
  260. blt.ppoSrc()->ppalSet(blt.pSurfSrc()->ppal());
  261. blt.ppoSrcDC()->ppalSet(dcoSrc.ppal());
  262. if (crBackColor == (COLORREF)-1)
  263. crBackColor = dcoSrc.pdc->ulBackClr();
  264. // Initialize the color translation object.
  265. //
  266. // No ICM with StretchBlt() so pass NULL color transform to XLATEOBJ.
  267. if (ulFlags & STRETCHBLT_ENABLE_ICM)
  268. {
  269. hcmXform = dcoTrg.pdc->hcmXform();
  270. }
  271. if (!blt.pexlo()->bInitXlateObj(hcmXform, // hColorTransform
  272. dcoTrg.pdc->lIcmMode(), // ICM mode
  273. *blt.ppoSrc(),
  274. *blt.ppoTrg(),
  275. *blt.ppoSrcDC(),
  276. *blt.ppoTrgDC(),
  277. dcoTrg.pdc->crTextClr(),
  278. dcoTrg.pdc->crBackClr(),
  279. crBackColor))
  280. {
  281. WARNING("bInitXlateObj failed in StretchBlt\n");
  282. goto RETURN_FAIL_ONLY;
  283. }
  284. blt.flSet(BLTREC_PXLO);
  285. if (ulAvec & AVEC_NEED_PATTERN)
  286. {
  287. // Set up the brush if necesary.
  288. blt.pbo(dcoTrg.peboFill());
  289. if ((dcoTrg.ulDirty() & DIRTY_FILL) || (dcoTrg.pdc->flbrush() & DIRTY_FILL))
  290. {
  291. dcoTrg.ulDirtySub(DIRTY_FILL);
  292. dcoTrg.pdc->flbrushSub(DIRTY_FILL);
  293. blt.pbo()->vInitBrush(
  294. dcoTrg.pdc,
  295. dcoTrg.pdc->pbrushFill(),
  296. *((XEPALOBJ *) blt.ppoTrgDC()),
  297. *((XEPALOBJ *) blt.ppoTrg()),
  298. blt.pSurfTrg());
  299. }
  300. blt.Brush(dcoTrg.pdc->ptlFillOrigin());
  301. }
  302. else
  303. {
  304. blt.pbo (NULL);
  305. }
  306. // Initialize some stuff for DDI.
  307. blt.pSurfMsk((SURFACE *) NULL);
  308. // Set the source rectangle
  309. if (blt.pxoSrc()->bRotation() || !blt.Src(xSrc, ySrc, cxSrc, cySrc))
  310. {
  311. goto RETURN_FAIL;
  312. }
  313. // Don't call the driver with an empty source rectangle.
  314. if((ulAvec & AVEC_NEED_SOURCE) &&
  315. (blt.perclSrc()->bEmpty()))
  316. {
  317. // We really should fail here, but return TRUE in order to maintain
  318. // backward compatibility.
  319. bRet = TRUE;
  320. goto RETURN_STATUS;
  321. }
  322. // Now all the essential information has been collected. We now
  323. // need to check for promotion or demotion and call the appropriate
  324. // method to finish the blt. If we rotate we must send the call away.
  325. if (blt.pxoTrg()->bRotation())
  326. {
  327. blt.TrgPlg(x, y, cx, cy);
  328. bRet = blt.bRotate(dcoTrg, dcoSrc, ulAvec, dcoTrg.pdc->jStretchBltMode());
  329. goto RETURN_STATUS;
  330. }
  331. // We can now set the target rectangle
  332. if (!blt.Trg(x, y, cx, cy))
  333. {
  334. goto RETURN_FAIL;
  335. }
  336. // If we are halftoning or the extents aren't equal, call bStretch
  337. if (( dcoTrg.pdc->jStretchBltMode() == HALFTONE) || !blt.bEqualExtents()) {
  338. bRet = blt.bStretch(dcoTrg, dcoSrc, ulAvec, dcoTrg.pdc->jStretchBltMode() );
  339. goto RETURN_STATUS;
  340. }
  341. // Since there can't be a mask, call bBitBlt.
  342. bRet = blt.bBitBlt(dcoTrg, dcoSrc, ulAvec);
  343. goto RETURN_STATUS;
  344. RETURN_FAIL:
  345. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  346. RETURN_FAIL_ONLY:
  347. bRet = FALSE;
  348. RETURN_STATUS:
  349. if (OrgRop4 & NOMIRRORBITMAP) {
  350. dcoTrg.pdc->dwSetLayout(-1, dwOldLayout);
  351. }
  352. // [Bug #278291] - CAPTUREBLT
  353. // Undo what was done above
  354. if (bCaptureBlt)
  355. {
  356. // Clear the flag
  357. pSurfTrg->vClearIncludeSprites();
  358. // Restore the cursor
  359. GreMovePointer(pSurfSrc->hdev(),
  360. pointerPos.x,
  361. pointerPos.y,
  362. MP_NORMAL);
  363. GreReleaseSemaphoreEx(pdoSrc.hsemPointer());
  364. }
  365. return bRet;
  366. }
  367. /******************************Public*Routine******************************\
  368. * BOOL BLTRECORD::bStretch(dcoTrg, dcoSrc, ulAvec, jMode)
  369. *
  370. * Do a stretch blt from the blt record
  371. *
  372. * History:
  373. * 21-Mar-1992 -by- Donald Sidoroff [donalds]
  374. * Rewrote it.
  375. \**************************************************************************/
  376. BOOL BLTRECORD::bStretch(
  377. DCOBJ& dcoTrg,
  378. DCOBJ& dcoSrc,
  379. ULONG ulAvec,
  380. BYTE jMode)
  381. {
  382. // Make the target rectangle well ordered and remember flips.
  383. vOrderStupid(perclTrg());
  384. // before we do a pattern only blt. The mask will be replaced in the
  385. // BLTRECORD and its offset correctly adjusted.
  386. if (!(ulAvec & AVEC_NEED_SOURCE))
  387. {
  388. vOrderStupid(perclMask());
  389. // Before we call to the driver, validate that the mask will actually
  390. // cover the entire target.
  391. if (pSurfMskOut() != (SURFACE *) NULL)
  392. {
  393. if ((aptlMask[0].x < 0) ||
  394. (aptlMask[0].y < 0) ||
  395. (aptlMask[1].x > pSurfMsk()->sizl().cx) ||
  396. (aptlMask[1].y > pSurfMsk()->sizl().cy))
  397. {
  398. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  399. return(FALSE);
  400. }
  401. }
  402. SURFMEM dimoMask;
  403. if ((ulAvec & AVEC_NEED_MASK) && !bStretch(dimoMask, (ULONG) jMode))
  404. return(FALSE);
  405. // Now, we need to fake out the source extents for the mask
  406. aptlSrc[1].x = aptlSrc[0].x + (aptlTrg[1].x - aptlTrg[0].x);
  407. aptlSrc[1].y = aptlSrc[0].y + (aptlTrg[1].y - aptlTrg[0].y);
  408. return(bBitBlt(dcoTrg, dcoTrg, ulAvec));
  409. }
  410. PDEVOBJ pdoTrg(pSurfTrg()->hdev());
  411. // WINBUG #298689 4-4-2001 jasonha Handle any device stretch to Meta
  412. BOOL bTrgMetaDriver = (dcoTrg.bSynchronizeAccess() && pdoTrg.bValid() && pdoTrg.bMetaDriver());
  413. // If the devices are on different PDEV's and we are not targeting a meta driver
  414. // we can only call driver if the Engine manages one or both of the surfaces.
  415. // Check for this.
  416. // WINBUG #256643 12-13-2000 bhouse Need to review handling of cross device operatons
  417. // We need to review this logic. This check and others like it are spread
  418. // throughout GDI and are in some cases now outdated. For example, there
  419. // is no reason not to call the multi-mon driver as a target.
  420. // We are fixing this case now but we should examine this check in light
  421. // of other possible cases.
  422. if (dcoTrg.hdev() != dcoSrc.hdev())
  423. {
  424. if (!bTrgMetaDriver)
  425. {
  426. if(((dcoTrg.pSurfaceEff()->iType() != STYPE_BITMAP)
  427. || (dcoTrg.pSurfaceEff()->dhsurf() != NULL)) &&
  428. ((dcoSrc.pSurfaceEff()->iType() != STYPE_BITMAP)
  429. || (dcoSrc.pSurfaceEff()->dhsurf() != NULL)))
  430. {
  431. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  432. return (FALSE);
  433. }
  434. }
  435. }
  436. // Before we get too involved, validate that the mask will actually
  437. // cover the entire source.
  438. if (pSurfMskOut() != (SURFACE *) NULL)
  439. {
  440. if ((aptlMask[0].x < 0) ||
  441. (aptlMask[0].y < 0) ||
  442. (aptlMask[1].x > pSurfMsk()->sizl().cx) ||
  443. (aptlMask[1].y > pSurfMsk()->sizl().cy))
  444. {
  445. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  446. return(FALSE);
  447. }
  448. }
  449. // Make the source rectangle well ordered and remember flips.
  450. vOrderStupid(perclSrc());
  451. vOrderAmnesia(perclMask());
  452. // Win 3.1 has a lovely little 'feature' where they decide
  453. // you called StretchBlt but you really didn't mean it. This
  454. // ludicrous behaviour needs to be supported forever because
  455. // some pinhead applications have grown to rely on this act
  456. // of insanity. Flips cancel this, since EngBitBlt can't
  457. // handle negative extents. Also note that we can't fail to
  458. // call DanielC if HALFTONE has been requested. [donalds]
  459. if ((jMode != HALFTONE) &&
  460. (dcoTrg.pdc->iGraphicsMode() != GM_ADVANCED) &&
  461. (pSurfMskOut() == (SURFACE *) NULL) &&
  462. !(flState & (BLTREC_MIRROR_X | BLTREC_MIRROR_Y)))
  463. {
  464. LONG lHStr = (perclTrg()->right - perclTrg()->left) -
  465. (perclSrc()->right - perclSrc()->left);
  466. LONG lVStr = (perclTrg()->bottom - perclTrg()->top) -
  467. (perclSrc()->bottom - perclSrc()->top);
  468. if ((lHStr >= -1) && (lHStr <= 1) &&
  469. (lVStr >= -1) && (lVStr <= 1))
  470. return(bBitBlt(dcoTrg, dcoSrc, ulAvec, lHStr, lVStr));
  471. }
  472. // Accumulate bounds. We can do this before knowing if the operation is
  473. // successful because bounds can be loose.
  474. if (dcoTrg.fjAccum())
  475. dcoTrg.vAccumulate(*perclTrg());
  476. // With a fixed DC origin we can change the rectangles to SCREEN coordinates.
  477. *perclTrg() += dcoTrg.eptlOrigin();
  478. *perclSrc() += dcoSrc.eptlOrigin();
  479. // Compute the clipping complexity and maybe reduce the exclusion rectangle.
  480. ECLIPOBJ eco(dcoTrg.prgnEffRao(), *perclTrg());
  481. // Check the destination which is reduced by clipping.
  482. if (eco.erclExclude().bEmpty())
  483. return(TRUE);
  484. // Compute the exclusion rectangle.
  485. ERECTL erclExclude = eco.erclExclude();
  486. // If we are going to the same source, prevent bad overlap situations
  487. if (dcoSrc.pSurface() == dcoTrg.pSurface())
  488. {
  489. if (perclSrc()->left < erclExclude.left)
  490. erclExclude.left = perclSrc()->left;
  491. if (perclSrc()->top < erclExclude.top)
  492. erclExclude.top = perclSrc()->top;
  493. if (perclSrc()->right > erclExclude.right)
  494. erclExclude.right = perclSrc()->right;
  495. if (perclSrc()->bottom > erclExclude.bottom)
  496. erclExclude.bottom = perclSrc()->bottom;
  497. }
  498. // We might have to exclude the source or the target, get ready to do either.
  499. DEVEXCLUDEOBJ dxo;
  500. PDEVOBJ pdoSrc(pSurfSrc()->hdev());
  501. // They can't both be display
  502. if (dcoSrc.bDisplay())
  503. {
  504. ERECTL ercl(0,0,pSurfSrc()->sizl().cx,pSurfSrc()->sizl().cy);
  505. if (dcoSrc.pSurface() == dcoTrg.pSurface())
  506. ercl *= erclExclude;
  507. else
  508. ercl *= *perclSrc();
  509. dxo.vExclude(dcoSrc.hdev(),&ercl,NULL);
  510. }
  511. else if (dcoTrg.bDisplay())
  512. dxo.vExclude(dcoTrg.hdev(),&erclExclude,&eco);
  513. // Dispatch the call.
  514. PFN_DrvStretchBltROP pfn = PPFNGET(pdoTrg, StretchBltROP, pSurfTrg()->flags());
  515. if (!bTrgMetaDriver)
  516. {
  517. if (jMode == HALFTONE)
  518. {
  519. // Don't call the driver if it doesn't do halftone.
  520. if (!(pdoTrg.flGraphicsCapsNotDynamic() & GCAPS_HALFTONE))
  521. pfn = (PFN_DrvStretchBltROP)EngStretchBltROP;
  522. }
  523. // WINBUG #95246 3-17-2000 jasonha GDI: StretchBlt optimizations: Let drivers handle more cases
  524. // Don't call the driver if the source rectangle exceeds the source
  525. // surface. Some drivers punt using a duplicate of the source
  526. // SURFOBJ, but without preserving its sizlBitmap member.
  527. BOOL bSrcExceeds = FALSE;
  528. if(pSurfSrc()->iType() == STYPE_DEVICE && pdoSrc.bValid() && pdoSrc.bMetaDriver())
  529. {
  530. if((perclSrc()->left < pdoSrc.pptlOrigin()->x ) ||
  531. (perclSrc()->top < pdoSrc.pptlOrigin()->y ) ||
  532. (perclSrc()->right > pdoSrc.pptlOrigin()->x + pSurfSrc()->sizl().cx) ||
  533. (perclSrc()->bottom > pdoSrc.pptlOrigin()->y + pSurfSrc()->sizl().cy))
  534. {
  535. bSrcExceeds = TRUE;
  536. }
  537. }
  538. else
  539. {
  540. if((perclSrc()->left < 0) ||
  541. (perclSrc()->top < 0) ||
  542. (perclSrc()->right > pSurfSrc()->sizl().cx) ||
  543. (perclSrc()->bottom > pSurfSrc()->sizl().cy))
  544. {
  545. bSrcExceeds = TRUE;
  546. }
  547. }
  548. if( bSrcExceeds )
  549. {
  550. pfn = (PFN_DrvStretchBltROP)EngStretchBltROP;
  551. }
  552. // WINBUG #95246 3-17-2000 jasonha GDI: StretchBlt optimizations: Let drivers handle more cases
  553. // Don't call the driver if the source overlaps the destination.
  554. // Some drivers don't handle this case.
  555. if ((pSurfTrg() == pSurfSrc()) &&
  556. bIntersect(perclSrc(), perclTrg()))
  557. {
  558. pfn = (PFN_DrvStretchBltROP)EngStretchBltROP;
  559. }
  560. }
  561. // Deal with target mirroring
  562. vMirror(perclTrg());
  563. // Inc the target surface uniqueness
  564. INC_SURF_UNIQ(pSurfTrg());
  565. return((*pfn)(pSurfTrg()->pSurfobj(),
  566. pSurfSrc()->pSurfobj(),
  567. (rop4 == 0x0000CCCC) ? (SURFOBJ *) NULL : pSurfMskOut()->pSurfobj(),
  568. &eco,
  569. pexlo()->pxlo(),
  570. (dcoTrg.pColorAdjustment()->caFlags & CA_DEFAULT) ?
  571. (PCOLORADJUSTMENT)NULL : dcoTrg.pColorAdjustment(),
  572. &dcoTrg.pdc->ptlFillOrigin(),
  573. perclTrg(),
  574. perclSrc(),
  575. aptlMask,
  576. jMode,
  577. pbo(),
  578. rop4));
  579. }
  580. /******************************Public*Routine******************************\
  581. * BOOL BLTRECORD::bStretch(dimo, iMode)
  582. *
  583. * Stretch just the mask.
  584. *
  585. * History:
  586. * 23-Mar-1992 -by- Donald Sidoroff [donalds]
  587. * Wrote it.
  588. \**************************************************************************/
  589. BOOL BLTRECORD::bStretch(
  590. SURFMEM& dimo,
  591. ULONG iMode)
  592. {
  593. // Use the ordered target extents for the size
  594. DEVBITMAPINFO dbmi;
  595. dbmi.iFormat = BMF_1BPP;
  596. dbmi.cxBitmap = aptlTrg[1].x - aptlTrg[0].x;
  597. dbmi.cyBitmap = aptlTrg[1].y - aptlTrg[0].y;
  598. dbmi.hpal = (HPALETTE) 0;
  599. dbmi.fl = pSurfMskOut()->bUMPD() ? UMPD_SURFACE : 0;
  600. // Build a shadow rectangle.
  601. ERECTL erclTrg(0, 0, dbmi.cxBitmap, dbmi.cyBitmap);
  602. // Take care of mirroring.
  603. vMirror(&erclTrg);
  604. dimo.bCreateDIB(&dbmi, (VOID *) NULL);
  605. if (!dimo.bValid())
  606. return(FALSE);
  607. // Call EngStretchBlt to stretch the mask.
  608. EPOINTL ptl(0,0);
  609. if (!EngStretchBlt(dimo.pSurfobj(),
  610. pSurfMskOut()->pSurfobj(),
  611. (SURFOBJ *) NULL,
  612. (CLIPOBJ *) NULL,
  613. NULL,
  614. NULL,
  615. (POINTL *)&ptl,
  616. &erclTrg,
  617. perclMask(),
  618. (POINTL *) NULL,
  619. iMode))
  620. {
  621. return(FALSE);
  622. }
  623. // Adjust the mask origin.
  624. aptlMask[0].x = 0;
  625. aptlMask[0].y = 0;
  626. // Release the previous pSurfMask, tell ~BLTRECORD its gone and put the
  627. // new DIB in its place.
  628. flState &= ~BLTREC_MASK_LOCKED;
  629. pSurfMsk()->vAltUnlockFast();
  630. pSurfMsk((SURFACE *) dimo.ps);
  631. return(TRUE);
  632. }
  633. /******************************Public*Routine******************************\
  634. * BOOL BLTRECORD::bStretch(dcoSrc, dimoShadow, dimoMask, ulAvec)
  635. *
  636. * Stretch the shadow and mask.
  637. *
  638. * History:
  639. * 24-Mar-1992 -by- Donald Sidoroff [donalds]
  640. * Wrote it.
  641. \**************************************************************************/
  642. BOOL BLTRECORD::bStretch(
  643. DCOBJ& dcoSrc,
  644. SURFMEM& dimoShadow,
  645. SURFMEM& dimoMask,
  646. ULONG ulAvec,
  647. ULONG iMode)
  648. {
  649. // If there is a mask, stretch it.
  650. if ((ulAvec & AVEC_NEED_MASK) && !bStretch(dimoMask, iMode))
  651. return(FALSE);
  652. // Use the ordered target extents for the size
  653. DEVBITMAPINFO dbmi;
  654. dbmi.cxBitmap = aptlTrg[1].x - aptlTrg[0].x;
  655. dbmi.cyBitmap = aptlTrg[1].y - aptlTrg[0].y;
  656. dbmi.hpal = 0;
  657. dbmi.iFormat = pSurfSrc()->iFormat();
  658. dbmi.fl = pSurfSrc()->bUMPD() ? UMPD_SURFACE : 0;
  659. // Build a shadow rectangle.
  660. ERECTL erclTrg(0, 0, dbmi.cxBitmap, dbmi.cyBitmap);
  661. // Take care of mirroring.
  662. vMirror(&erclTrg);
  663. dimoShadow.bCreateDIB(&dbmi, (VOID *) NULL);
  664. if (!dimoShadow.bValid())
  665. return(FALSE);
  666. // Now comes the tricky part. The source may be a display. While it may
  667. // be somewhat faster to assume it isn't, code would be much more complex.
  668. {
  669. // Adjust the source rectangle.
  670. *perclSrc() += dcoSrc.eptlOrigin();
  671. // Exclude the pointer.
  672. ERECTL ercl(0,0,pSurfSrc()->sizl().cx,pSurfSrc()->sizl().cy);
  673. ercl *= *perclSrc();
  674. DEVEXCLUDEOBJ dxo(dcoSrc, &ercl);
  675. EPOINTL ptl(0,0);
  676. // Stretch the bits to the DIB.
  677. if (!EngStretchBlt(dimoShadow.pSurfobj(),
  678. pSurfSrc()->pSurfobj(),
  679. (SURFOBJ *) NULL,
  680. (CLIPOBJ *) NULL,
  681. NULL,
  682. NULL,
  683. (POINTL *)&ptl,
  684. &erclTrg,
  685. perclSrc(),
  686. (POINTL *) NULL,
  687. iMode))
  688. {
  689. return(FALSE);
  690. }
  691. // Update the source surface and origin.
  692. pSurfSrc((SURFACE *) dimoShadow.ps);
  693. perclSrc()->left = -dcoSrc.eptlOrigin().x;
  694. perclSrc()->top = -dcoSrc.eptlOrigin().y;
  695. perclSrc()->right = dbmi.cxBitmap - dcoSrc.eptlOrigin().x;
  696. perclSrc()->bottom = dbmi.cyBitmap - dcoSrc.eptlOrigin().y;
  697. }
  698. return(TRUE);
  699. }
  700. /******************************Public*Routine******************************\
  701. * VOID BLTRECORD::vOrder(percl)
  702. *
  703. * Make the rectangle well ordered, remembering how we flipped.
  704. *
  705. * History:
  706. * 23-Mar-1992 -by- Donald Sidoroff [donalds]
  707. * Wrote it.
  708. \**************************************************************************/
  709. VOID BLTRECORD::vOrder(ERECTL *percl)
  710. {
  711. LONG l;
  712. if (percl->left > percl->right)
  713. {
  714. l = percl->left, percl->left = percl->right, percl->right = l;
  715. flState ^= BLTREC_MIRROR_X;
  716. }
  717. if (percl->top > percl->bottom)
  718. {
  719. l = percl->top, percl->top = percl->bottom, percl->bottom = l;
  720. flState ^= BLTREC_MIRROR_Y;
  721. }
  722. }
  723. /******************************Public*Routine******************************\
  724. * VOID BLTRECORD::vOrderStupid(percl)
  725. *
  726. * Make the rectangle well ordered, remembering how we flipped. Uses the
  727. * Win3.1 compatible swap method.
  728. *
  729. * History:
  730. * 23-Mar-1992 -by- Donald Sidoroff [donalds]
  731. * Wrote it.
  732. \**************************************************************************/
  733. VOID BLTRECORD::vOrderStupid(ERECTL *percl)
  734. {
  735. LONG l;
  736. if (percl->left > percl->right)
  737. {
  738. l = percl->left, percl->left = percl->right, percl->right = l;
  739. percl->left++;
  740. percl->right++;
  741. flState ^= BLTREC_MIRROR_X;
  742. }
  743. if (percl->top > percl->bottom)
  744. {
  745. l = percl->top, percl->top = percl->bottom, percl->bottom = l;
  746. percl->top++;
  747. percl->bottom++;
  748. flState ^= BLTREC_MIRROR_Y;
  749. }
  750. }
  751. /******************************Public*Routine******************************\
  752. * VOID BLTRECORD::vOrderAmnesia(percl)
  753. *
  754. * Make the rectangle well ordered. Uses the Win 3.1 compatible swap
  755. * method.
  756. *
  757. * History:
  758. * 23-Mar-1992 -by- Donald Sidoroff [donalds]
  759. * Wrote it.
  760. \**************************************************************************/
  761. VOID BLTRECORD::vOrderAmnesia(ERECTL *percl)
  762. {
  763. LONG l;
  764. if (percl->left > percl->right)
  765. {
  766. l = percl->left, percl->left = percl->right, percl->right = l;
  767. percl->left++;
  768. percl->right++;
  769. }
  770. if (percl->top > percl->bottom)
  771. {
  772. l = percl->top, percl->top = percl->bottom, percl->bottom = l;
  773. percl->top++;
  774. percl->bottom++;
  775. }
  776. }
  777. /******************************Public*Routine******************************\
  778. * VOID BLTRECORD::vMirror(percl)
  779. *
  780. * Flip the rectangle according to the mirroring flags
  781. *
  782. * History:
  783. * 24-Mar-1992 -by- Donald Sidoroff [donalds]
  784. * Wrote it.
  785. \**************************************************************************/
  786. VOID BLTRECORD::vMirror(ERECTL *percl)
  787. {
  788. LONG l;
  789. if (flState & BLTREC_MIRROR_X)
  790. l = percl->left, percl->left = percl->right, percl->right = l;
  791. if (flState & BLTREC_MIRROR_Y)
  792. l = percl->top, percl->top = percl->bottom, percl->bottom = l;
  793. }
  794. /******************************Public*Routine******************************\
  795. * VOID BLTRECORD::bBitBlt(dcoTrg, dcoSrc, ul, lH, lV)
  796. *
  797. * Do a near-miss ???BitBlt instead of ???StretchBlt.
  798. *
  799. * History:
  800. * 12-Apr-1993 -by- Donald Sidoroff [donalds]
  801. * Wrote it.
  802. \**************************************************************************/
  803. #define PUT_RECTS erclTrg = *perclTrg(); erclSrc = *perclSrc()
  804. #define GET_RECTS *perclSrc() = erclSrc; *perclTrg() = erclTrg
  805. BOOL BLTRECORD::bBitBlt(
  806. DCOBJ& dcoTrg,
  807. DCOBJ& dcoSrc,
  808. ULONG ulAvec,
  809. LONG lHStr,
  810. LONG lVStr)
  811. {
  812. ERECTL erclTrg;
  813. ERECTL erclSrc;
  814. BOOL bHack;
  815. switch (lHStr)
  816. {
  817. case -1:
  818. perclSrc()->right--;
  819. if (lVStr == 1)
  820. {
  821. perclTrg()->bottom--;
  822. PUT_RECTS;
  823. bHack = bBitBlt(dcoTrg, dcoSrc, ulAvec);
  824. GET_RECTS;
  825. perclTrg()->top = perclTrg()->bottom;
  826. perclTrg()->bottom++;
  827. perclSrc()->top = perclSrc()->bottom - 1;
  828. return(bHack & bBitBlt(dcoTrg, dcoSrc, ulAvec));
  829. }
  830. else
  831. {
  832. perclSrc()->bottom += lVStr;
  833. return(bBitBlt(dcoTrg, dcoSrc, ulAvec));
  834. }
  835. break;
  836. case 0:
  837. if (lVStr == 1)
  838. {
  839. perclTrg()->bottom--;
  840. PUT_RECTS;
  841. bHack = bBitBlt(dcoTrg, dcoSrc, ulAvec);
  842. GET_RECTS;
  843. perclTrg()->top = perclTrg()->bottom;
  844. perclTrg()->bottom++;
  845. perclSrc()->top = perclSrc()->bottom - 1;
  846. return(bHack & bBitBlt(dcoTrg, dcoSrc, ulAvec));
  847. }
  848. else
  849. {
  850. perclSrc()->bottom += lVStr;
  851. return(bBitBlt(dcoTrg, dcoSrc, ulAvec));
  852. }
  853. break;
  854. case 1:
  855. perclTrg()->right--;
  856. if (lVStr == 1)
  857. {
  858. perclTrg()->bottom--;
  859. PUT_RECTS;
  860. bHack = bBitBlt(dcoTrg, dcoSrc, ulAvec);
  861. GET_RECTS;
  862. perclTrg()->left = perclTrg()->right;
  863. perclTrg()->right++;
  864. perclSrc()->left = perclSrc()->right - 1;
  865. bHack &= bBitBlt(dcoTrg, dcoSrc, ulAvec);
  866. GET_RECTS;
  867. perclTrg()->top = perclTrg()->bottom;
  868. perclTrg()->bottom++;
  869. perclSrc()->top = perclSrc()->bottom - 1;
  870. bHack &= bBitBlt(dcoTrg, dcoSrc, ulAvec);
  871. GET_RECTS;
  872. perclTrg()->top = perclTrg()->bottom;
  873. perclTrg()->bottom++;
  874. perclSrc()->top = perclSrc()->bottom - 1;
  875. perclTrg()->left = perclTrg()->right;
  876. perclTrg()->right++;
  877. perclSrc()->left = perclSrc()->right - 1;
  878. return(bHack & bBitBlt(dcoTrg, dcoSrc, ulAvec));
  879. }
  880. else
  881. {
  882. perclSrc()->bottom += lVStr;
  883. PUT_RECTS;
  884. bHack = bBitBlt(dcoTrg, dcoSrc, ulAvec);
  885. GET_RECTS;
  886. perclTrg()->left = perclTrg()->right;
  887. perclTrg()->right++;
  888. perclSrc()->left = perclSrc()->right - 1;
  889. return(bHack & bBitBlt(dcoTrg, dcoSrc, ulAvec));
  890. }
  891. break;
  892. default:
  893. break;
  894. }
  895. return FALSE;
  896. }
  897. #ifdef DBG_STRBLT
  898. LONG gflStrBlt = 0;
  899. VOID vShowRect(
  900. CHAR *psz,
  901. RECTL *prcl)
  902. {
  903. if (gflStrBlt & STRBLT_RECTS)
  904. DbgPrint("%s [(%ld,%ld) (%ld,%ld)]\n",
  905. psz, prcl->left, prcl->top, prcl->right, prcl->bottom);
  906. }
  907. #endif
  908. /******************************Public*Routine******************************\
  909. * EngStretchBlt
  910. *
  911. * This does stretched bltting. The source rectangle is stretched to fit
  912. * the target rectangle.
  913. *
  914. * NOTE! The source rectangle MUST BE WELL ORDERED IN DEVICE SPACE.
  915. *
  916. * This call returns TRUE for success, FALSE for ERROR.
  917. *
  918. * History:
  919. * 16-Feb-1993 -by- Donald Sidoroff [donalds]
  920. * Wrote.
  921. \**************************************************************************/
  922. BOOL EngStretchBlt(
  923. SURFOBJ *psoTrg,
  924. SURFOBJ *psoSrc,
  925. SURFOBJ *psoMask,
  926. CLIPOBJ *pco,
  927. XLATEOBJ *pxlo,
  928. COLORADJUSTMENT *pca,
  929. POINTL *pptlBrushOrg,
  930. RECTL *prclTrg,
  931. RECTL *prclSrc,
  932. POINTL *pptlMask,
  933. ULONG iMode)
  934. {
  935. //
  936. // Prevent bad driver call backs
  937. //
  938. if ((iMode == 0) || (iMode > MAXSTRETCHBLTMODE))
  939. {
  940. WARNING1("EngStretchBlt: Unsupported iMode\n");
  941. return(FALSE);
  942. }
  943. PSURFACE pSurfTrg = SURFOBJ_TO_SURFACE(psoTrg);
  944. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  945. PSURFACE pSurfMask = SURFOBJ_TO_SURFACE(psoMask);
  946. //
  947. // Can't StretchBlt to an RLE
  948. // Can't StretchBlt to/from a JPEG or PNG
  949. //
  950. if ((pSurfTrg->iFormat() == BMF_4RLE) ||
  951. (pSurfTrg->iFormat() == BMF_8RLE) ||
  952. (pSurfTrg->iFormat() == BMF_JPEG) ||
  953. (pSurfSrc->iFormat() == BMF_JPEG) ||
  954. (pSurfTrg->iFormat() == BMF_PNG ) ||
  955. (pSurfSrc->iFormat() == BMF_PNG ))
  956. {
  957. WARNING1("EngStretchBlt: Unsupported source/target\n");
  958. return(FALSE);
  959. }
  960. //
  961. // If the source or target rectangles are empty, don't bother.
  962. //
  963. if ((prclSrc->left == prclSrc->right) || (prclSrc->top == prclSrc->bottom) ||
  964. (prclTrg->left == prclTrg->right) || (prclTrg->top == prclTrg->bottom))
  965. return(TRUE);
  966. //
  967. // Get the LDEV for the target and source surfaces
  968. //
  969. PDEVOBJ pdoTrg( pSurfTrg->hdev());
  970. PDEVOBJ pdoSrc( pSurfSrc->hdev());
  971. //
  972. // We should have gone to the Mul layer if the destination
  973. // is a meta.
  974. //
  975. ASSERTGDI( !( psoTrg->iType != STYPE_BITMAP && pdoTrg.bValid()
  976. && pdoTrg.bMetaDriver()),
  977. "EngStretchBlt called with a destination meta device" );
  978. //
  979. // We cannot handle cases where the source is a meta,
  980. // so make a copy in this case.
  981. //
  982. SURFMEM srcCopy;
  983. RECTL rclCopy = *prclSrc;
  984. if( psoSrc->iType == STYPE_DEVICE && pdoSrc.bValid() &&
  985. pdoSrc.bMetaDriver())
  986. {
  987. if(!MulCopyDeviceToDIB( psoSrc, &srcCopy, &rclCopy ))
  988. return FALSE;
  989. if(srcCopy.ps == NULL )
  990. {
  991. // We didn't get to the point of creating the surface
  992. // becasue the rect was out of bounds.
  993. return TRUE;
  994. }
  995. prclSrc = &rclCopy;
  996. psoSrc = srcCopy.pSurfobj();
  997. pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  998. pdoSrc.vInit(pSurfSrc->hdev());
  999. }
  1000. //
  1001. // CMYK based source bitmap support.
  1002. //
  1003. // limilation:
  1004. // - Source surface must be STYPE_BITMAP, since we can't read CMYK surface from device.
  1005. // - Target surface must be STYPE_DEVICE, since other Eng function can't handle.
  1006. // - Source surface must not be same as target surface.
  1007. // - No mask surface.
  1008. // - No halftone mode, since EngHTBlt can't handle.
  1009. //
  1010. BOOL bSrcCMYKColor = (pxlo && (pxlo->flXlate & XO_FROM_CMYK)) ? TRUE : FALSE;
  1011. if (bSrcCMYKColor)
  1012. {
  1013. WARNING("EngStretchBlt called with XO_FROM_CMYK - limited support");
  1014. // source surface must be STYPE_BITMAP.
  1015. // target surface must be STYPE_DEVICE.
  1016. // Must be no mask
  1017. if ((psoSrc->iType != STYPE_BITMAP) ||
  1018. (psoTrg->iType != STYPE_DEVICE) ||
  1019. (psoMask != NULL))
  1020. {
  1021. return (FALSE);
  1022. }
  1023. }
  1024. //
  1025. // Send Halftoning to DanielC.
  1026. //
  1027. if (iMode == HALFTONE)
  1028. {
  1029. //
  1030. // If source bitmap is CMYK, EngHTBlt can't handle.
  1031. //
  1032. if (bSrcCMYKColor)
  1033. {
  1034. return (FALSE);
  1035. }
  1036. int iRet = EngHTBlt(psoTrg,
  1037. psoSrc,
  1038. psoMask,
  1039. pco,
  1040. pxlo,
  1041. pca,
  1042. pptlBrushOrg,
  1043. prclTrg,
  1044. prclSrc,
  1045. pptlMask,
  1046. 0,
  1047. NULL);
  1048. switch (iRet)
  1049. {
  1050. case HTBLT_ERROR:
  1051. return(FALSE);
  1052. case HTBLT_SUCCESS:
  1053. return(TRUE);
  1054. case HTBLT_NOTSUPPORTED:
  1055. iMode = COLORONCOLOR;
  1056. break;
  1057. };
  1058. }
  1059. #ifdef DBG_STRBLT
  1060. if (!(gflStrBlt & STRBLT_ENABLE))
  1061. {
  1062. POINTFIX aptfx[3];
  1063. aptfx[0].x = FIX_FROM_LONG(prclTrg->left);
  1064. aptfx[0].y = FIX_FROM_LONG(prclTrg->top);
  1065. aptfx[1].x = FIX_FROM_LONG(prclTrg->right);
  1066. aptfx[1].y = FIX_FROM_LONG(prclTrg->top);
  1067. aptfx[2].x = FIX_FROM_LONG(prclTrg->left);
  1068. aptfx[2].y = FIX_FROM_LONG(prclTrg->bottom);
  1069. return(EngPlgBlt(psoTrg,
  1070. psoSrc,
  1071. psoMask,
  1072. pco,
  1073. pxlo,
  1074. pca,
  1075. pptlBrushOrg,
  1076. aptfx,
  1077. prclSrc,
  1078. pptlMask,
  1079. iMode));
  1080. }
  1081. if (gflStrBlt & STRBLT_FORMAT)
  1082. {
  1083. LONG foo[] = { 0, 1, 4, 8, 16, 24, 32 };
  1084. DbgPrint("Target = %2ldBPP, Source = %2ldBPP\n",
  1085. foo[pSurfTrg->iFormat()],
  1086. foo[pSurfSrc->iFormat()]);
  1087. }
  1088. #endif
  1089. //
  1090. // We may have to 'mirror'.
  1091. //
  1092. FLONG flMirror = 0;
  1093. if (prclTrg->bottom < prclTrg->top)
  1094. {
  1095. LONG lTemp = prclTrg->top;
  1096. prclTrg->top = prclTrg->bottom;
  1097. prclTrg->bottom = lTemp;
  1098. flMirror |= STRBLT_MIRROR_Y;
  1099. }
  1100. if (prclTrg->right < prclTrg->left)
  1101. {
  1102. LONG lTemp = prclTrg->left;
  1103. prclTrg->left = prclTrg->right;
  1104. prclTrg->right = lTemp;
  1105. flMirror |= STRBLT_MIRROR_X;
  1106. }
  1107. //
  1108. // We may need to do a WHITEONBLACK or BLACKONWHITE from a monochrome source.
  1109. // Find out and set the bogusity flag.
  1110. //
  1111. BOOL bBogus = ((iMode < COLORONCOLOR) &&
  1112. (pSurfMask == (SURFACE *) NULL));
  1113. //
  1114. // Bogusity mode only applies on shrinking blts. Test the dx/dy for source
  1115. // and targets and see if it still applies.
  1116. //
  1117. if (bBogus)
  1118. {
  1119. if (((prclTrg->right - prclTrg->left) >= (prclSrc->right - prclSrc->left)) &&
  1120. ((prclTrg->bottom - prclTrg->top) >= (prclSrc->bottom - prclSrc->top)))
  1121. bBogus = FALSE;
  1122. }
  1123. //
  1124. // If we don't need bogusity, eliminate it.
  1125. //
  1126. if ((!bBogus) && (iMode < COLORONCOLOR))
  1127. iMode = COLORONCOLOR;
  1128. //
  1129. // Many display drivers have fast-paths for stretches that handle only
  1130. // source formats that are the same as the destination format, and only
  1131. // with identity translates. They also typically handle only STYPE_BITMAP
  1132. // formats.
  1133. //
  1134. // So we will consider making a copy of the source bitmap up-front to
  1135. // remove any translations and also to convert non-STYPE_BITMAP formats.
  1136. //
  1137. // Note that this isn't terribly efficient when clipping is involved,
  1138. // but that will be a later optimization...
  1139. //
  1140. if (!pSurfTrg->bUMPD() &&
  1141. (((pxlo != NULL) && !(pxlo->flXlate & XO_TRIVIAL)) ||
  1142. (psoSrc->iType != STYPE_BITMAP)))
  1143. {
  1144. //
  1145. // To go any further, the driver must of course hook StretchBlt.
  1146. //
  1147. // In addition, we'll add some further restrictions here to make
  1148. // our life easier. The driver's fast paths typically handle only
  1149. // stretches that are non-inverting, don't involve a mask, and don't
  1150. // have source clipping, and we'll do the same (otherwise we'd have
  1151. // to add more code):
  1152. //
  1153. // Note that some drivers (specifically the Weitek driver) have a
  1154. // bug where they set "psoDst = ppdev->psoPunt" and then call
  1155. // EngStretchBlt on that. This would work fine, except that they
  1156. // had also called EngAssociateSurface on the surface and said they
  1157. // hooked STRETCHBLT for that punt surface -- which is a lie because
  1158. // they fall over if we call DrvStretchBlt on that punt surface!
  1159. // (They don't really expect their DrvStretchBlt routine to be called
  1160. // for an engine-managed surface, even though that's what they're
  1161. // saying they support via the EngAssociateSurface call.) So
  1162. // we add a (pSurfTrg->iType() != STYPE_BITMAP) check and don't
  1163. // execute this fast-path at all for engine-managed surfaces, and
  1164. // thus we avoid driver bugs like the Weitek's.
  1165. //
  1166. //
  1167. // WINBUG #95246 3-17-2000 jasonha GDI: StretchBlt optimizations: Let drivers handle more cases
  1168. //
  1169. // Actually, we must NEVER call the driver if there is source
  1170. // clipping. Some drivers punt using a duplicate of the source
  1171. // SURFOBJ, but without preserving its sizlBitmap member.
  1172. //
  1173. if ((pSurfTrg->iType() != STYPE_BITMAP) &&
  1174. (pSurfTrg->flags() & HOOK_STRETCHBLT) &&
  1175. (flMirror == 0) &&
  1176. (psoMask == NULL) &&
  1177. (prclSrc->left >= 0) &&
  1178. (prclSrc->top >= 0) &&
  1179. (prclSrc->right <= psoSrc->sizlBitmap.cx) &&
  1180. (prclSrc->bottom <= psoSrc->sizlBitmap.cy))
  1181. {
  1182. SIZEL sizlNewSrc;
  1183. HSURF hsurfNewSrc;
  1184. SURFOBJ *psoNewSrc;
  1185. RECTL rclNew;
  1186. BOOL bRet;
  1187. sizlNewSrc.cx = prclSrc->right - prclSrc->left;
  1188. sizlNewSrc.cy = prclSrc->bottom - prclSrc->top;
  1189. if ((sizlNewSrc.cx <= (prclTrg->right - prclTrg->left)) &&
  1190. (sizlNewSrc.cy <= (prclTrg->bottom - prclTrg->top)))
  1191. {
  1192. hsurfNewSrc = (HSURF) EngCreateBitmap(sizlNewSrc,
  1193. 0,
  1194. psoTrg->iBitmapFormat,
  1195. 0,
  1196. NULL);
  1197. psoNewSrc = EngLockSurface(hsurfNewSrc);
  1198. if (psoNewSrc)
  1199. {
  1200. //
  1201. // Bug #69739
  1202. //
  1203. // Set uniqueness to zero so that the driver does not bother
  1204. // trying to cache the temporary bitmap.
  1205. //
  1206. psoNewSrc->iUniq = 0;
  1207. rclNew.left = 0;
  1208. rclNew.top = 0;
  1209. rclNew.right = sizlNewSrc.cx;
  1210. rclNew.bottom = sizlNewSrc.cy;
  1211. bRet = (PPFNGET(pdoSrc, CopyBits, pSurfSrc->flags())
  1212. (psoNewSrc,
  1213. psoSrc,
  1214. NULL,
  1215. pxlo,
  1216. &rclNew,
  1217. (POINTL*) prclSrc))
  1218. && (PPFNDRV(pdoTrg, StretchBlt)(psoTrg,
  1219. psoNewSrc,
  1220. psoMask,
  1221. pco,
  1222. NULL,
  1223. pca,
  1224. pptlBrushOrg,
  1225. prclTrg,
  1226. &rclNew,
  1227. pptlMask,
  1228. iMode));
  1229. EngUnlockSurface(psoNewSrc);
  1230. EngDeleteSurface(hsurfNewSrc);
  1231. return(bRet);
  1232. }
  1233. }
  1234. }
  1235. }
  1236. //
  1237. // Set up frame variables for possible switch to temporary output surface
  1238. //
  1239. SURFMEM dimoOut;
  1240. SURFACE *pSurfOut;
  1241. RECTL rclOut;
  1242. RECTL *prclOut;
  1243. ECLIPOBJ ecoOut;
  1244. CLIPOBJ *pcoOut;
  1245. ERECTL erclDev;
  1246. EPOINTL eptlDev;
  1247. ERECTL erclTrim(0, 0, pSurfSrc->sizl().cx, pSurfSrc->sizl().cy);
  1248. RECTL rclTrim;
  1249. RGNMEMOBJTMP rmoOut;
  1250. //
  1251. // If the target is not a DIB, or the target and source are on the same
  1252. // surface and the extents overlap, create a target DIB of the needed
  1253. // size and format.
  1254. //
  1255. if ((pSurfTrg->iType() == STYPE_BITMAP) &&
  1256. (pSurfTrg->hsurf() != pSurfSrc->hsurf()))
  1257. {
  1258. pSurfOut = pSurfTrg;
  1259. prclOut = prclTrg;
  1260. pcoOut = pco;
  1261. }
  1262. else
  1263. {
  1264. rclOut = *prclTrg;
  1265. erclDev.left = rclOut.left - 1;
  1266. erclDev.top = rclOut.top - 1;
  1267. erclDev.right = rclOut.right + 1;
  1268. erclDev.bottom = rclOut.bottom + 1;
  1269. //
  1270. // Trim to the target surface.
  1271. //
  1272. ERECTL erclTrg(0, 0, pSurfTrg->sizl().cx, pSurfTrg->sizl().cy);
  1273. #ifdef DBG_STRBLT
  1274. vShowRect("Trg Rect", (RECTL *) &erclDev);
  1275. vShowRect("Trg Surf", (RECTL *) &erclTrg);
  1276. #endif
  1277. erclDev *= erclTrg;
  1278. //
  1279. // If we have nothing left, we're done.
  1280. //
  1281. if (erclDev.bEmpty())
  1282. return(TRUE);
  1283. #ifdef DBG_STRBLT
  1284. vShowRect("Trg Surf & Rect", (RECTL *) &erclDev);
  1285. #endif
  1286. //
  1287. // If we are only here on possible overlap, test for misses
  1288. //
  1289. if (( pSurfTrg->iType() == STYPE_BITMAP) &&
  1290. ((erclDev.left > prclSrc->right) || (erclDev.right < prclSrc->left) ||
  1291. (erclDev.top > prclSrc->bottom) || (erclDev.bottom < prclSrc->top)))
  1292. {
  1293. pSurfOut = pSurfTrg;
  1294. prclOut = prclTrg;
  1295. pcoOut = pco;
  1296. }
  1297. else
  1298. {
  1299. //
  1300. // Compute the adjusted rectangle in the temporary surface.
  1301. //
  1302. rclOut.left -= erclDev.left;
  1303. rclOut.top -= erclDev.top;
  1304. rclOut.right -= erclDev.left;
  1305. rclOut.bottom -= erclDev.top;
  1306. DEVBITMAPINFO dbmi;
  1307. dbmi.cxBitmap = erclDev.right - erclDev.left + 1;
  1308. dbmi.cyBitmap = erclDev.bottom - erclDev.top + 1;
  1309. dbmi.hpal = (HPALETTE) 0;
  1310. if (bSrcCMYKColor)
  1311. {
  1312. //
  1313. // On CMYK color mode, create temporary surface based on source surface.
  1314. //
  1315. dbmi.iFormat = pSurfSrc->iFormat();
  1316. }
  1317. else
  1318. {
  1319. dbmi.iFormat = pSurfTrg->iFormat();
  1320. }
  1321. dbmi.fl = pSurfTrg->bUMPD() ? UMPD_SURFACE : 0;
  1322. #ifdef DBG_STRBLT
  1323. if (gflStrBlt & STRBLT_ALLOC)
  1324. {
  1325. DbgPrint("Allocating temporary target\n");
  1326. DbgPrint("Size (%lx, %lx)\n", dbmi.cxBitmap, dbmi.cyBitmap);
  1327. DbgPrint("Format = %lx\n", dbmi.iFormat);
  1328. }
  1329. #endif
  1330. dimoOut.bCreateDIB(&dbmi, (VOID *) NULL);
  1331. if (!dimoOut.bValid())
  1332. return(FALSE);
  1333. //
  1334. // What point in the target surface is 0,0 in temporary surface.
  1335. //
  1336. eptlDev = *((EPOINTL *) &erclDev);
  1337. //
  1338. // Build a CLIPOBJ for the new surface.
  1339. //
  1340. if (!rmoOut.bValid())
  1341. return(FALSE);
  1342. erclDev.left = 0;
  1343. erclDev.top = 0;
  1344. erclDev.right -= eptlDev.x;
  1345. erclDev.bottom -= eptlDev.y;
  1346. #ifdef DBG_STRBLT
  1347. vShowRect("Trg Clip", (RECTL *) &erclDev);
  1348. #endif
  1349. rmoOut.vSet((RECTL *) &erclDev);
  1350. ecoOut.vSetup(rmoOut.prgnGet(), erclDev, CLIP_FORCE);
  1351. //
  1352. // Synchronize with the device driver before touching the device surface.
  1353. //
  1354. {
  1355. PDEVOBJ po( pSurfTrg->hdev());
  1356. po.vSync(pSurfTrg->pSurfobj(),NULL,0);
  1357. }
  1358. //
  1359. // If there is a mask, copy the actual target to the temporary.
  1360. //
  1361. if (pSurfMask != (SURFACE *) NULL)
  1362. {
  1363. (*PPFNGET(pdoTrg,CopyBits, pSurfTrg->flags()))(
  1364. dimoOut.pSurfobj(),
  1365. pSurfTrg->pSurfobj(),
  1366. (CLIPOBJ *) NULL,
  1367. &xloIdent,
  1368. &erclDev,
  1369. &eptlDev);
  1370. }
  1371. //
  1372. // Point to the new target.
  1373. //
  1374. pSurfOut = dimoOut.ps;
  1375. prclOut = &rclOut;
  1376. pcoOut = &ecoOut;
  1377. }
  1378. }
  1379. //
  1380. // Synchronize with the device driver before touching the device surface.
  1381. //
  1382. {
  1383. PDEVOBJ po( pSurfSrc->hdev());
  1384. po.vSync(psoSrc,NULL,0);
  1385. }
  1386. //
  1387. // Compute what area of the source surface will actually be used. We do
  1388. // this so we never read off the end of the surface and fault or worse,
  1389. // write bad pixels onto the target. Trim the source rectangle to the
  1390. // source surface.
  1391. //
  1392. #ifdef DBG_STRBLT
  1393. vShowRect("Src Surf", (RECTL *) &erclTrim);
  1394. vShowRect("Src Rect", prclSrc);
  1395. #endif
  1396. erclTrim *= *prclSrc;
  1397. #ifdef DBG_STRBLT
  1398. vShowRect("Src Surf & Src Rect", (RECTL *) &erclTrim);
  1399. #endif
  1400. //
  1401. // If we have nothing left, we're done.
  1402. //
  1403. if (erclTrim.bEmpty())
  1404. return(TRUE);
  1405. //
  1406. // Now we must worry about the source surface. Its possible we are blitting
  1407. // from an RLE to the VGA for instance. We convert the surface to the same
  1408. // bitmap format as the target for convience.
  1409. //
  1410. SURFMEM dimoIn;
  1411. SURFACE *pSurfIn;
  1412. RECTL rclIn;
  1413. RECTL *prclIn;
  1414. XLATEOBJ *pxloIn;
  1415. if ((flMirror == 0) &&
  1416. ( pSurfSrc->iType() == STYPE_BITMAP) &&
  1417. ( pSurfSrc->iFormat() != BMF_4RLE) &&
  1418. ( pSurfSrc->iFormat() != BMF_8RLE))
  1419. {
  1420. pSurfIn = pSurfSrc;
  1421. if (bSrcCMYKColor)
  1422. {
  1423. //
  1424. // The surface will be kept as compatible as source, so no translation at this point.
  1425. //
  1426. pxloIn = NULL;
  1427. }
  1428. else
  1429. {
  1430. pxloIn = pxlo;
  1431. }
  1432. prclIn = prclSrc;
  1433. }
  1434. else
  1435. {
  1436. DEVBITMAPINFO dbmi;
  1437. dbmi.cxBitmap = erclTrim.right - erclTrim.left;
  1438. dbmi.cyBitmap = erclTrim.bottom - erclTrim.top;
  1439. dbmi.hpal = (HPALETTE) 0;
  1440. if (bSrcCMYKColor)
  1441. {
  1442. //
  1443. // On CMYK color mode, create temporary surface based on source surface.
  1444. //
  1445. dbmi.iFormat = pSurfSrc->iFormat();
  1446. }
  1447. else
  1448. {
  1449. dbmi.iFormat = pSurfOut->iFormat();
  1450. }
  1451. dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
  1452. #ifdef DBG_STRBLT
  1453. if (gflStrBlt & STRBLT_ALLOC)
  1454. {
  1455. DbgPrint("Allocating temporary source\n");
  1456. DbgPrint("Size (%lx, %lx)\n", dbmi.cxBitmap, dbmi.cyBitmap);
  1457. DbgPrint("Format = %lx\n", dbmi.iFormat);
  1458. }
  1459. #endif
  1460. dimoIn.bCreateDIB(&dbmi, (VOID *) NULL);
  1461. if (!dimoIn.bValid())
  1462. return(FALSE);
  1463. //
  1464. // The cursor should already be excluded at this point, so just copy
  1465. // to the DIB.
  1466. //
  1467. rclIn.left = 0;
  1468. rclIn.top = 0;
  1469. rclIn.right = erclTrim.right - erclTrim.left;
  1470. rclIn.bottom = erclTrim.bottom - erclTrim.top;
  1471. (*PPFNGET(pdoSrc,CopyBits, pSurfSrc->flags()))(
  1472. dimoIn.pSurfobj(),
  1473. pSurfSrc->pSurfobj(),
  1474. (CLIPOBJ *) NULL,
  1475. (bSrcCMYKColor ? NULL : pxlo),
  1476. &rclIn,
  1477. (POINTL *) &erclTrim);
  1478. //
  1479. // Point at the new source
  1480. //
  1481. rclIn.left = prclSrc->left - erclTrim.left;
  1482. rclIn.top = prclSrc->top - erclTrim.top;
  1483. rclIn.right = prclSrc->right - erclTrim.left;
  1484. rclIn.bottom = prclSrc->bottom - erclTrim.top;
  1485. pSurfIn = dimoIn.ps;
  1486. prclIn = &rclIn;
  1487. pxloIn = NULL;
  1488. //
  1489. // Adjust the trimmed source origin and extent
  1490. //
  1491. erclTrim.right -= erclTrim.left;
  1492. erclTrim.bottom -= erclTrim.top;
  1493. erclTrim.left = 0;
  1494. erclTrim.top = 0;
  1495. //
  1496. // If we needed to, do mirroring. Y mirroring is easy.
  1497. //
  1498. if (flMirror & STRBLT_MIRROR_Y)
  1499. {
  1500. if (dimoIn.ps->lDelta() > 0)
  1501. dimoIn.ps->pvScan0(((BYTE *) dimoIn.ps->pvBits()) + dimoIn.ps->lDelta() * (erclTrim.bottom - 1));
  1502. else
  1503. dimoIn.ps->pvScan0(dimoIn.ps->pvBits());
  1504. dimoIn.ps->lDelta(-dimoIn.ps->lDelta());
  1505. }
  1506. //
  1507. // X mirroring is not.
  1508. //
  1509. if (flMirror & STRBLT_MIRROR_X)
  1510. (*apfnMirror[dimoIn.ps->iFormat()])(dimoIn.ps);
  1511. }
  1512. //
  1513. // Synchronize with the device driver before touching the device surface.
  1514. //
  1515. {
  1516. PDEVOBJ po( pSurfOut->hdev());
  1517. po.vSync(pSurfOut->pSurfobj(),NULL, 0);
  1518. }
  1519. //
  1520. // Compute the space needed for the DDA to see if we can do it on the frame.
  1521. // Clip it to the limit of our coordinate systems (2^27) to avoid math
  1522. // overflow in the subsequent calculations.
  1523. //
  1524. if (((prclIn->right - prclIn->left) >= MAX_STRETCH_COOR) ||
  1525. ((prclIn->bottom - prclIn->top) >= MAX_STRETCH_COOR))
  1526. {
  1527. return(FALSE);
  1528. }
  1529. if (((prclOut->right - prclOut->left) >= MAX_STRETCH_COOR) ||
  1530. ((prclOut->bottom - prclOut->top) >= MAX_STRETCH_COOR) ||
  1531. ((prclOut->right - prclOut->left) <= -MAX_STRETCH_COOR) ||
  1532. ((prclOut->bottom - prclOut->top) <= -MAX_STRETCH_COOR))
  1533. {
  1534. return(FALSE);
  1535. }
  1536. //
  1537. // Special acceleration case:
  1538. //
  1539. // SrcFormat and Destination format are the same
  1540. // Color translation is NULL
  1541. // Src width and height and less than 2 ^ 30
  1542. //
  1543. if (
  1544. (iMode == COLORONCOLOR) &&
  1545. (psoMask == (SURFOBJ *) NULL) &&
  1546. ((pxloIn == (XLATEOBJ *)NULL) || ((XLATE *)pxloIn)->bIsIdentity()) &&
  1547. (pSurfOut->iFormat() == pSurfIn->iFormat()) &&
  1548. (
  1549. (pSurfIn->iFormat() == BMF_8BPP) ||
  1550. (pSurfIn->iFormat() == BMF_16BPP) ||
  1551. (pSurfIn->iFormat() == BMF_32BPP)
  1552. )
  1553. )
  1554. {
  1555. if((pcoOut == (CLIPOBJ *)NULL) ||
  1556. (pcoOut->iDComplexity != DC_COMPLEX))
  1557. {
  1558. //
  1559. // Case for no clip region (DC_TRIVIAL) or single rectangle
  1560. // clipping (DC_RECT).
  1561. //
  1562. //
  1563. // set clipping for DC_RECT case only, otherwise
  1564. // use dst rectangle
  1565. //
  1566. PRECTL prclClipOut = prclOut;
  1567. //
  1568. // StretchDIBDirect has early out cases which leave erclTrim
  1569. // uninitialized. This line of code is left commented out because
  1570. // nobody has found a bug caused by this.
  1571. //
  1572. // erclTrim.left = erclTrim.right = erclTrim.top = erclTrim.bottom = 0;
  1573. //
  1574. if ((pcoOut != (CLIPOBJ *)NULL) &&
  1575. (pcoOut->iDComplexity == DC_RECT))
  1576. {
  1577. prclClipOut = &(pcoOut->rclBounds);
  1578. }
  1579. //
  1580. // call stretch blt accelerator
  1581. //
  1582. StretchDIBDirect(
  1583. pSurfOut->pvScan0(),
  1584. pSurfOut->lDelta(),
  1585. pSurfOut->sizl().cx,
  1586. pSurfOut->sizl().cy,
  1587. prclOut,
  1588. pSurfIn->pvScan0(),
  1589. pSurfIn->lDelta(),
  1590. pSurfIn->sizl().cx,
  1591. pSurfIn->sizl().cy,
  1592. prclIn,
  1593. &erclTrim,
  1594. prclClipOut,
  1595. pSurfOut->iFormat()
  1596. );
  1597. }
  1598. else
  1599. {
  1600. //
  1601. // Handle the complex CLIPOBJ case (DC_COMPLEX)
  1602. //
  1603. //
  1604. // Temp storage for individual trim sub-rectangles
  1605. //
  1606. ERECTL erclTrimTmp(0,0,0,0);
  1607. //
  1608. // Initialize erclTrim for accumulation using the += operator below
  1609. // Setting everything to zero ensures the first RECTL is copied.
  1610. // Theoretically we could just set left=right for this to work.
  1611. //
  1612. erclTrim.left = erclTrim.right = erclTrim.top = erclTrim.bottom = 0;
  1613. BOOL bMore;
  1614. ENUMRECTS arclComplexEnum;
  1615. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  1616. //
  1617. // Point this at the RECTL location and then the loop code below
  1618. // will slide each successive RECTL under this pointer.
  1619. //
  1620. PRECTL prclClipOut=&arclComplexEnum.arcl[0];
  1621. do {
  1622. //
  1623. // Enumerate each rectangle one-by-one in any order.
  1624. //
  1625. bMore = CLIPOBJ_bEnum(pco, sizeof(arclComplexEnum), (ULONG*) &arclComplexEnum);
  1626. //
  1627. // Call the stretch blt accelerator for this RECTL
  1628. //
  1629. if(arclComplexEnum.c > 0)
  1630. {
  1631. StretchDIBDirect(
  1632. pSurfOut->pvScan0(),
  1633. pSurfOut->lDelta(),
  1634. pSurfOut->sizl().cx,
  1635. pSurfOut->sizl().cy,
  1636. prclOut,
  1637. pSurfIn->pvScan0(),
  1638. pSurfIn->lDelta(),
  1639. pSurfIn->sizl().cx,
  1640. pSurfIn->sizl().cy,
  1641. prclIn,
  1642. &erclTrimTmp,
  1643. prclClipOut,
  1644. pSurfOut->iFormat()
  1645. );
  1646. //
  1647. // Accumulate the Trim rectangle
  1648. //
  1649. erclTrim += erclTrimTmp;
  1650. }
  1651. } while (bMore);
  1652. }
  1653. //
  1654. // save reduced target rectangle for use in CopyBits
  1655. // to write a temp DIB to the target
  1656. //
  1657. rclTrim.left = erclTrim.left;
  1658. rclTrim.right = erclTrim.right;
  1659. rclTrim.top = erclTrim.top;
  1660. rclTrim.bottom = erclTrim.bottom;
  1661. }
  1662. else
  1663. {
  1664. //
  1665. // Initialize the DDA
  1666. //
  1667. STRDDA *pdda;
  1668. LONG cjSpace = sizeof(STRDDA) +
  1669. (sizeof(LONG) * (prclIn->right - prclIn->left +
  1670. prclIn->bottom - prclIn->top));
  1671. pdda = (STRDDA *) PALLOCNOZ(cjSpace, 'htsG');
  1672. if (pdda == (STRDDA *) NULL)
  1673. {
  1674. return(FALSE);
  1675. }
  1676. #ifdef DBG_STRBLT
  1677. if (gflStrBlt & STRBLT_ALLOC)
  1678. {
  1679. DbgPrint("Need %ld bytes for DDA\n", cjSpace);
  1680. DbgPrint("DDA @%08lx\n", (ULONG) pdda);
  1681. }
  1682. #endif
  1683. vInitStrDDA(pdda, (RECTL *) &erclTrim, prclIn, prclOut);
  1684. //
  1685. // Save the reduced target rectangle.
  1686. //
  1687. rclTrim = pdda->rcl;
  1688. //
  1689. // See if we can accelerate anything.
  1690. //
  1691. if ((pxloIn != NULL) && (pxloIn->flXlate & XO_TRIVIAL))
  1692. {
  1693. pxloIn = NULL;
  1694. }
  1695. if ((pcoOut != (CLIPOBJ *) NULL) &&
  1696. (pcoOut->iDComplexity == DC_TRIVIAL))
  1697. {
  1698. pcoOut = (CLIPOBJ *) NULL;
  1699. }
  1700. PFN_STRREAD pfnRead;
  1701. PFN_STRWRITE pfnWrite = apfnWrite[pSurfOut->iFormat()];
  1702. if (bBogus)
  1703. {
  1704. pdda->iColor = (iMode == BLACKONWHITE) ? ~0L : 0L;
  1705. }
  1706. pfnRead = apfnRead[pSurfIn->iFormat()][iMode - BLACKONWHITE];
  1707. STRRUN *prun;
  1708. //
  1709. // Now compute the space needed for the stretch buffers
  1710. //
  1711. if ((prclIn->right - prclIn->left) > (prclOut->right - prclOut->left))
  1712. {
  1713. //
  1714. // Shrink case -- even though shrinking the mask may cause
  1715. // separate runs to merge together, the low-level stretch code
  1716. // does not handle this. Therefore, may have a run for every
  1717. // single pixel.
  1718. //
  1719. cjSpace = sizeof(STRRUN) +
  1720. (sizeof(XRUNLEN) * (rclTrim.right - rclTrim.left)) +
  1721. sizeof(DWORD);
  1722. }
  1723. else
  1724. {
  1725. //
  1726. // Stretch case -- worse case: every other pixel is masked, so
  1727. // number of runs is 1/2 the number of pixels.
  1728. //
  1729. cjSpace = sizeof(STRRUN) + sizeof(XRUNLEN) *
  1730. ((rclTrim.right - rclTrim.left + 3) / 2) + sizeof(DWORD);
  1731. }
  1732. if ( ((rclTrim.right - rclTrim.left) > 100000000L) ||
  1733. ((prun = (STRRUN *) AllocFreeTmpBuffer(cjSpace)) == NULL) )
  1734. {
  1735. VFREEMEM(pdda);
  1736. return(FALSE);
  1737. }
  1738. #ifdef DBG_STRBLT
  1739. if (gflStrBlt & STRBLT_ALLOC)
  1740. {
  1741. DbgPrint("Need %ld bytes for buffer\n", cjSpace);
  1742. DbgPrint("Buffer @%08lx\n", (ULONG) prun);
  1743. }
  1744. #endif
  1745. BYTE *pjSrc = (BYTE *) pSurfIn->pvScan0() + pSurfIn->lDelta() * erclTrim.top;
  1746. BYTE *pjMask;
  1747. POINTL ptlMask;
  1748. LONG yRow;
  1749. LONG yCnt;
  1750. if (psoMask == (SURFOBJ *) NULL)
  1751. {
  1752. pjMask = (BYTE *) NULL;
  1753. }
  1754. else
  1755. {
  1756. ptlMask.x = erclTrim.left - prclIn->left + pptlMask->x;
  1757. ptlMask.y = erclTrim.top - prclIn->top + pptlMask->y;
  1758. pjMask = (BYTE *) pSurfMask->pvScan0() + pSurfMask->lDelta() * ptlMask.y;
  1759. }
  1760. //
  1761. // If we are in bogus mode, initialize the buffer
  1762. //
  1763. ULONG iOver;
  1764. if (bBogus)
  1765. {
  1766. iOver = (iMode == BLACKONWHITE) ? -1 : 0;
  1767. vInitBuffer(prun, &rclTrim, iOver);
  1768. }
  1769. prun->yPos = pdda->rcl.top;
  1770. SUSPENDWATCH sw(pdoTrg);
  1771. for (yRow = erclTrim.top, yCnt = 0; yRow < erclTrim.bottom; yRow++, yCnt++)
  1772. {
  1773. prun->cRep = pdda->plYStep[yCnt];
  1774. if (prun->cRep)
  1775. {
  1776. (*pfnWrite)(prun,
  1777. (*pfnRead)(pdda,
  1778. prun,
  1779. pjSrc,
  1780. pjMask,
  1781. pxloIn,
  1782. erclTrim.left,
  1783. erclTrim.right,
  1784. ptlMask.x),
  1785. pSurfOut,
  1786. pcoOut);
  1787. //
  1788. // If we are in bogus mode, reinitialize the buffer
  1789. //
  1790. if (bBogus)
  1791. vInitBuffer(prun, &rclTrim, iOver);
  1792. }
  1793. else
  1794. {
  1795. //
  1796. // If we are in BLACKONWHITE or WHITEONBLACK mode, we need to read
  1797. // the scan and mix it with the current buffer.
  1798. //
  1799. if (bBogus)
  1800. {
  1801. (*pfnRead)(pdda,
  1802. prun,
  1803. pjSrc,
  1804. (BYTE *) NULL,
  1805. pxloIn,
  1806. erclTrim.left,
  1807. erclTrim.right,
  1808. 0);
  1809. }
  1810. }
  1811. pjSrc += pSurfIn->lDelta();
  1812. prun->yPos += prun->cRep;
  1813. if (pjMask != (BYTE *) NULL)
  1814. {
  1815. pjMask += pSurfMask->lDelta();
  1816. }
  1817. }
  1818. sw.Resume();
  1819. //
  1820. // Free up the work buffers.
  1821. //
  1822. FreeTmpBuffer(prun);
  1823. VFREEMEM(pdda);
  1824. }
  1825. //
  1826. // See if we have drawn on the actual output surface.
  1827. //
  1828. if (pSurfOut == pSurfTrg)
  1829. #ifndef DBG_STRBLT
  1830. return(TRUE);
  1831. #else
  1832. {
  1833. if (gflStrBlt & STRBLT_FORMAT)
  1834. DbgBreakPoint();
  1835. return(TRUE);
  1836. }
  1837. #endif
  1838. //
  1839. // We need to build a clipping region equal to the trimmed target.
  1840. //
  1841. rclTrim.left += eptlDev.x;
  1842. rclTrim.top += eptlDev.y;
  1843. rclTrim.right += eptlDev.x;
  1844. rclTrim.bottom += eptlDev.y;
  1845. RGNMEMOBJTMP rmo;
  1846. if (!rmo.bValid())
  1847. return(FALSE);
  1848. if (pco == (CLIPOBJ *) NULL)
  1849. rmo.vSet(&rclTrim);
  1850. else
  1851. {
  1852. RGNMEMOBJTMP rmoTmp;
  1853. if (!rmoTmp.bValid())
  1854. return(FALSE);
  1855. rmoTmp.vSet(&rclTrim);
  1856. if (!rmo.bMerge(rmoTmp, *((ECLIPOBJ *)pco), gafjRgnOp[RGN_AND]))
  1857. return(FALSE);
  1858. }
  1859. ERECTL ercl;
  1860. rmo.vGet_rcl(&ercl);
  1861. if (pco != NULL)
  1862. {
  1863. //
  1864. // Make sure that the bounds are tight to the destination rectangle.
  1865. //
  1866. if (!bIntersect(&ercl, &pco->rclBounds, &ercl))
  1867. {
  1868. return(TRUE);
  1869. }
  1870. }
  1871. ECLIPOBJ eco(rmo.prgnGet(), ercl, CLIP_FORCE);
  1872. if (eco.erclExclude().bEmpty())
  1873. return(TRUE);
  1874. //
  1875. // Copy from the temporary to the target surface.
  1876. //
  1877. erclDev.left += eptlDev.x;
  1878. erclDev.top += eptlDev.y;
  1879. erclDev.right += eptlDev.x;
  1880. erclDev.bottom += eptlDev.y;
  1881. eptlDev.x = 0;
  1882. eptlDev.y = 0;
  1883. #ifdef DBG_STRBLT
  1884. vShowRect("Trg Out", (RECTL *) &erclDev);
  1885. #endif
  1886. //
  1887. // With CMYK color, temp surface is based on source, while non-CMYK
  1888. // case it's target. So we need xlateobj for CMYK color case, but
  1889. // don't need for non-CMYK case.
  1890. //
  1891. (*PPFNGET(pdoTrg,CopyBits, pSurfTrg->flags())) (pSurfTrg->pSurfobj(),
  1892. dimoOut.pSurfobj(),
  1893. &eco,
  1894. (bSrcCMYKColor ? pxlo : NULL),
  1895. &erclDev,
  1896. &eptlDev);
  1897. #ifdef DBG_STRBLT
  1898. if (gflStrBlt & STRBLT_FORMAT)
  1899. DbgBreakPoint();
  1900. #endif
  1901. return(TRUE);
  1902. }
  1903. /******************************Public*Routine******************************\
  1904. * EngStretchBltROP
  1905. *
  1906. * This does stretched bltting with a rop.
  1907. *
  1908. * This call returns TRUE for success, FALSE for ERROR.
  1909. *
  1910. * History:
  1911. * 24-Sept-1996 -by- Lingyun Wang [lingyunw]
  1912. * Wrote it.
  1913. \**************************************************************************/
  1914. BOOL EngStretchBltROP(
  1915. SURFOBJ *psoTrg,
  1916. SURFOBJ *psoSrc,
  1917. SURFOBJ *psoMask,
  1918. CLIPOBJ *pco,
  1919. XLATEOBJ *pxlo,
  1920. COLORADJUSTMENT *pca,
  1921. POINTL *pptlBrushOrg,
  1922. RECTL *prclTrg,
  1923. RECTL *prclSrc,
  1924. POINTL *pptlMask,
  1925. ULONG iMode,
  1926. BRUSHOBJ *pbo,
  1927. ROP4 rop4)
  1928. {
  1929. GDIFunctionID(EngStretchBltROP);
  1930. ASSERTGDI(psoTrg != (SURFOBJ *) NULL, "psoTrg == NULL\n");
  1931. ASSERTGDI(prclTrg != (PRECTL) NULL, "dst rectangle is NULL\n");
  1932. PSURFACE pSurfTrg = SURFOBJ_TO_SURFACE(psoTrg);
  1933. PSURFACE pSurfSrc = SURFOBJ_TO_SURFACE(psoSrc);
  1934. ASSERTGDI(rop4, "rop4 == NULL\n");
  1935. ASSERTGDI(pSurfTrg->iFormat() != BMF_JPEG,
  1936. "dst BMF_JPEG not supported\n");
  1937. ASSERTGDI(pSurfTrg->iFormat() != BMF_PNG,
  1938. "dst BMF_PNG not supported\n");
  1939. ASSERTGDI(!(ROP4NEEDSRC(rop4) && (psoSrc == (SURFOBJ *) NULL)),
  1940. "psoSrc == NULL\n");
  1941. ASSERTGDI(!(ROP4NEEDSRC(rop4) && (prclSrc == (PRECTL) NULL)),
  1942. "src rectangle is NULL\n");
  1943. ASSERTGDI(!(ROP4NEEDSRC(rop4) && (pSurfSrc->iFormat() == BMF_JPEG)),
  1944. "src BMF_JPEG not supported\n");
  1945. ASSERTGDI(!(ROP4NEEDSRC(rop4) && (pSurfSrc->iFormat() == BMF_PNG)),
  1946. "src BMF_PNG not supported\n");
  1947. ASSERTGDI(!(ROP4NEEDPAT(rop4) && (pbo == (BRUSHOBJ *) NULL)),
  1948. "Pattern is NULL\n");
  1949. ASSERTGDI(!(ROP4NEEDPAT(rop4) &&
  1950. (pbo->iSolidColor == 0xFFFFFFFF) &&
  1951. (pptlBrushOrg == (PPOINTL) NULL)),
  1952. "Pattern offset is NULL\n");
  1953. if ((rop4 != 0x0000CCCC) && (rop4 != 0x0000AACC))
  1954. {
  1955. //
  1956. // Dont halftone if we got a weird ROP.
  1957. //
  1958. if (iMode == HALFTONE)
  1959. iMode = COLORONCOLOR;
  1960. LONG l;
  1961. BOOL bFlipX = FALSE;
  1962. BOOL bFlipY = FALSE;
  1963. //
  1964. // order the target extents
  1965. //
  1966. if (prclTrg->left > prclTrg->right)
  1967. {
  1968. l = prclTrg->left, prclTrg->left = prclTrg->right, prclTrg->right = l;
  1969. bFlipX = TRUE;
  1970. }
  1971. if (prclTrg->top > prclTrg->bottom)
  1972. {
  1973. l = prclTrg->top, prclTrg->top = prclTrg->bottom, prclTrg->bottom = l;
  1974. bFlipY = TRUE;
  1975. }
  1976. DEVBITMAPINFO dbmi;
  1977. SURFMEM dimoShadow;
  1978. SURFMEM dimoMask;
  1979. ULONG ulAvec = ((ULONG) gajRop3[rop4 & 0x00ff]) |
  1980. ((ULONG) gajRop3[(rop4 >> 8) & 0x00ff]);
  1981. // The check above does not tell if we need a mask.
  1982. // Check explicitly.
  1983. if (ROP4NEEDMASK(rop4))
  1984. {
  1985. ulAvec |= AVEC_NEED_MASK;
  1986. }
  1987. EPOINTL ptl(0,0);
  1988. //
  1989. // Stretch the Mask
  1990. //
  1991. if (ulAvec & AVEC_NEED_MASK)
  1992. {
  1993. ASSERTGDI (psoMask, "psoMask == NULL\n");
  1994. PSURFACE pSurfMask = SURFOBJ_TO_SURFACE(psoMask);
  1995. //
  1996. // use ordered target extents for the size
  1997. //
  1998. dbmi.iFormat = BMF_1BPP;
  1999. dbmi.cxBitmap = prclTrg->right - prclTrg->left;
  2000. dbmi.cyBitmap = prclTrg->bottom - prclTrg->top;
  2001. dbmi.hpal = (HPALETTE) 0;
  2002. dbmi.fl = pSurfMask->bUMPD() ? UMPD_SURFACE : 0;
  2003. ERECTL erclTrg(0, 0, dbmi.cxBitmap, dbmi.cyBitmap);
  2004. if (bFlipX)
  2005. l = erclTrg.left, erclTrg.left = erclTrg.right, erclTrg.right = l;
  2006. if (bFlipY)
  2007. l = erclTrg.top, erclTrg.top = erclTrg.bottom, erclTrg.bottom = l;
  2008. dimoMask.bCreateDIB(&dbmi, (VOID *) NULL);
  2009. if (!dimoMask.bValid())
  2010. return(FALSE);
  2011. ULONG cx = prclSrc->right - prclSrc->left;
  2012. ULONG cy = prclSrc->bottom - prclSrc->top;
  2013. ERECTL erclMask(pptlMask->x, pptlMask->y, pptlMask->x+cx, pptlMask->y+cy);
  2014. //
  2015. // Call EngStretchBlt to stretch the mask.
  2016. //
  2017. if (!EngStretchBlt(dimoMask.pSurfobj(),
  2018. psoMask,
  2019. (SURFOBJ *) NULL,
  2020. (CLIPOBJ *) NULL,
  2021. NULL,
  2022. NULL,
  2023. (POINTL *)&ptl,
  2024. &erclTrg,
  2025. &erclMask,
  2026. (POINTL *) NULL,
  2027. iMode))
  2028. {
  2029. return(FALSE);
  2030. }
  2031. }
  2032. //
  2033. // Stretch the Src
  2034. //
  2035. if (ulAvec & AVEC_NEED_SOURCE)
  2036. {
  2037. //
  2038. // use ordered target extents for the size
  2039. //
  2040. dbmi.iFormat = pSurfSrc->iFormat();
  2041. dbmi.cxBitmap = prclTrg->right - prclTrg->left;
  2042. dbmi.cyBitmap = prclTrg->bottom - prclTrg->top;
  2043. dbmi.hpal = (HPALETTE) 0;
  2044. dbmi.fl = pSurfSrc->bUMPD() ? UMPD_SURFACE : 0;
  2045. // Build a shadow rectangle.
  2046. ERECTL erclTrg(0, 0, dbmi.cxBitmap, dbmi.cyBitmap);
  2047. if (bFlipX)
  2048. l = erclTrg.left, erclTrg.left = erclTrg.right, erclTrg.right = l;
  2049. if (bFlipY)
  2050. l = erclTrg.top, erclTrg.top = erclTrg.bottom, erclTrg.bottom = l;
  2051. dimoShadow.bCreateDIB(&dbmi, (VOID *) NULL);
  2052. if (!dimoShadow.bValid())
  2053. {
  2054. WARNING("dimoShadow invalid\n");
  2055. return(FALSE);
  2056. }
  2057. //
  2058. // Call EngStretchBlt to stretch the source.
  2059. //
  2060. if (!EngStretchBlt(dimoShadow.pSurfobj(),
  2061. psoSrc,
  2062. (SURFOBJ *) NULL,
  2063. (CLIPOBJ *) NULL,
  2064. NULL,
  2065. NULL,
  2066. (POINTL *)&ptl,
  2067. &erclTrg,
  2068. prclSrc,
  2069. (POINTL *) NULL,
  2070. iMode))
  2071. {
  2072. return(FALSE);
  2073. }
  2074. }
  2075. //
  2076. // Call BitBlt
  2077. //
  2078. return((*(pSurfTrg->pfnBitBlt()))
  2079. ( psoTrg,
  2080. dimoShadow.pSurfobj(),
  2081. dimoMask.pSurfobj(),
  2082. pco,
  2083. pxlo,
  2084. prclTrg,
  2085. (POINTL *)&ptl,
  2086. (POINTL *)&ptl,
  2087. pbo,
  2088. pptlBrushOrg,
  2089. rop4));
  2090. }
  2091. else
  2092. {
  2093. //
  2094. // Just pass it off to EngStretchBlt since it doesn't have a complex ROP
  2095. //
  2096. PDEVOBJ pdoTrg(pSurfTrg->hdev());
  2097. PDEVOBJ pdoSrc(pSurfSrc->hdev());
  2098. // Inc the target surface uniqueness
  2099. INC_SURF_UNIQ(pSurfTrg);
  2100. PFN_DrvStretchBlt pfn = PPFNGET(pdoTrg, StretchBlt, pSurfTrg->flags());
  2101. //
  2102. // There are a bunch of conditions that we don't want to
  2103. // call the driver, so we make pfn point to the Eng
  2104. // function. But if the destination is a meta, we want it
  2105. // to actually call the Mul layer.
  2106. //
  2107. // WINBUG #357937 4-3-2001 jasonha Meta DEVBITMAPs must go thru Mul layer
  2108. // Don't check iType:
  2109. // DEVICE/DEVBITMAP -> MulStretchBlt
  2110. // BITMAP (not hooked) -> EngStretchBlt
  2111. if ((pSurfTrg->flags() & HOOK_StretchBlt) && !pdoTrg.bMetaDriver())
  2112. {
  2113. // Don't call the driver if it doesn't do halftone.
  2114. if (iMode == HALFTONE)
  2115. {
  2116. if (!(pdoTrg.flGraphicsCapsNotDynamic() & GCAPS_HALFTONE))
  2117. pfn = (PFN_DrvStretchBlt)EngStretchBlt;
  2118. }
  2119. // WINBUG #95246 3-17-2000 jasonha GDI: StretchBlt optimizations: Let drivers handle more cases
  2120. // Don't call the driver if the source rectangle exceeds the source
  2121. // surface. Some drivers punt using a duplicate of the source
  2122. // SURFOBJ, but without preserving its sizlBitmap member.
  2123. BOOL bSrcExceeds = FALSE;
  2124. if(pSurfSrc->iType() == STYPE_DEVICE && pdoSrc.bValid() && pdoSrc.bMetaDriver())
  2125. {
  2126. if((prclSrc->left < pdoSrc.pptlOrigin()->x ) ||
  2127. (prclSrc->top < pdoSrc.pptlOrigin()->y ) ||
  2128. (prclSrc->right > pdoSrc.pptlOrigin()->x + pSurfSrc->sizl().cx) ||
  2129. (prclSrc->bottom > pdoSrc.pptlOrigin()->y + pSurfSrc->sizl().cy))
  2130. {
  2131. bSrcExceeds = TRUE;
  2132. }
  2133. }
  2134. else
  2135. {
  2136. if((prclSrc->left < 0) ||
  2137. (prclSrc->top < 0) ||
  2138. (prclSrc->right > pSurfSrc->sizl().cx) ||
  2139. (prclSrc->bottom > pSurfSrc->sizl().cy))
  2140. {
  2141. bSrcExceeds = TRUE;
  2142. }
  2143. }
  2144. if( bSrcExceeds )
  2145. {
  2146. pfn = (PFN_DrvStretchBlt)EngStretchBlt;
  2147. }
  2148. // WINBUG #95246 3-17-2000 jasonha GDI: StretchBlt optimizations: Let drivers handle more cases
  2149. // Don't call the driver if the source overlaps the destination.
  2150. // Some drivers don't handle this case.
  2151. ASSERTGDI((prclSrc->left <= prclSrc->right) &&
  2152. (prclSrc->top <= prclSrc->bottom),
  2153. "Source rectangle not well-ordered\n");
  2154. // Use a well-ordered copy of the destination rectangle to do the
  2155. // intersection test.
  2156. ERECTL rclTrg(*prclTrg);
  2157. rclTrg.vOrder();
  2158. if ((psoSrc == psoTrg) &&
  2159. bIntersect(prclSrc, &rclTrg))
  2160. {
  2161. pfn = (PFN_DrvStretchBlt)EngStretchBlt;
  2162. }
  2163. }
  2164. return ((*pfn)(psoTrg,
  2165. psoSrc,
  2166. (rop4 == 0x0000CCCC) ? (SURFOBJ *) NULL : psoMask,
  2167. pco,
  2168. pxlo,
  2169. pca,
  2170. pptlBrushOrg,
  2171. prclTrg,
  2172. prclSrc,
  2173. pptlMask,
  2174. iMode));
  2175. }
  2176. }