Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

786 lines
22 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: stretch.c
  3. *
  4. * Copyright (c) 1993-1995 Microsoft Corporation
  5. \**************************************************************************/
  6. #include "precomp.h"
  7. #define STRETCH_MAX_EXTENT 32767
  8. typedef DWORDLONG ULONGLONG;
  9. /******************************Public*Routine******************************\
  10. *
  11. * Routine Name
  12. *
  13. * vDirectStretch8Narrow
  14. *
  15. * Routine Description:
  16. *
  17. * Stretch blt 8->8 when the width is 7 or less
  18. *
  19. * Arguments:
  20. *
  21. * pStrBlt - contains all params for blt
  22. *
  23. * Return Value:
  24. *
  25. * VOID
  26. *
  27. \**************************************************************************/
  28. VOID vDirectStretch8Narrow(
  29. STR_BLT* pStrBlt)
  30. {
  31. BYTE* pjSrc;
  32. BYTE* pjDstEnd;
  33. ULONG ulDst;
  34. ULONG xAccum;
  35. ULONG xTmp;
  36. ULONG yTmp;
  37. LONG xDst = pStrBlt->XDstStart;
  38. LONG xSrc = pStrBlt->XSrcStart;
  39. BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc;
  40. BYTE* pjDst = pStrBlt->pjDstScan + xDst;
  41. LONG yCount = pStrBlt->YDstCount;
  42. LONG WidthX = pStrBlt->XDstEnd - xDst;
  43. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  44. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  45. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  46. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  47. LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
  48. ULONG yInt = 0;
  49. yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
  50. //
  51. // Narrow blt
  52. //
  53. do {
  54. ULONG yTmp = yAccum + yFrac;
  55. BYTE jSrc0;
  56. BYTE* pjDstEndNarrow = pjDst + WidthX;
  57. pjSrc = pjSrcScan;
  58. xAccum = pStrBlt->ulXFracAccumulator;
  59. do {
  60. jSrc0 = *pjSrc;
  61. xTmp = xAccum + xFrac;
  62. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  63. *pjDst++ = jSrc0;
  64. xAccum = xTmp;
  65. } while (pjDst != pjDstEndNarrow);
  66. pjSrcScan += yInt;
  67. if (yTmp < yAccum)
  68. {
  69. pjSrcScan += pStrBlt->lDeltaSrc;
  70. }
  71. yAccum = yTmp;
  72. pjDst += lDstStride;
  73. } while (--yCount);
  74. }
  75. /******************************Public*Routine******************************\
  76. *
  77. * Routine Name
  78. *
  79. * vDirectStretch32
  80. *
  81. * Routine Description:
  82. *
  83. * Stretch blt 32->32
  84. *
  85. * Arguments:
  86. *
  87. * pStrBlt - contains all params for blt
  88. *
  89. * Return Value:
  90. *
  91. * VOID
  92. *
  93. \**************************************************************************/
  94. VOID vDirectStretch32(
  95. STR_BLT* pStrBlt)
  96. {
  97. BYTE* pjOldScan;
  98. ULONG* pulSrc;
  99. ULONG* pulDstEnd;
  100. ULONG ulDst;
  101. ULONG xAccum;
  102. ULONG xTmp;
  103. ULONG yTmp;
  104. LONG cyDuplicate;
  105. BYTE* pjBase;
  106. PDEV* ppdev = pStrBlt->ppdev;
  107. LONG xDst = pStrBlt->XDstStart;
  108. LONG xSrc = pStrBlt->XSrcStart;
  109. BYTE* pjSrcScan = pStrBlt->pjSrcScan + xSrc * 4;
  110. ULONG* pulDst = (ULONG*)(pStrBlt->pjDstScan) + xDst;
  111. LONG yDst = pStrBlt->YDstStart;
  112. LONG yCount = pStrBlt->YDstCount;
  113. LONG WidthX = pStrBlt->XDstEnd - xDst;
  114. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  115. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  116. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  117. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  118. LONG lDstStride = pStrBlt->lDeltaDst - 4*WidthX;
  119. ULONG yInt = 0;
  120. pjBase = ppdev->pjBase;
  121. //
  122. // if this is a shrinking blt, calc src scan line stride
  123. //
  124. if (pStrBlt->ulYDstToSrcIntCeil != 0)
  125. {
  126. yInt = pStrBlt->lDeltaSrc * pStrBlt->ulYDstToSrcIntCeil;
  127. }
  128. do {
  129. ULONG ulSrc;
  130. ULONG yTmp;
  131. pulSrc = (ULONG*) pjSrcScan;
  132. xAccum = pStrBlt->ulXFracAccumulator;
  133. //
  134. // a single src scan line is being written
  135. //
  136. pulDstEnd = pulDst + WidthX;
  137. while (pulDst != pulDstEnd)
  138. {
  139. ulSrc = *pulSrc;
  140. xTmp = xAccum + xFrac;
  141. pulSrc = pulSrc + xInt + (xTmp < xAccum);
  142. *(ULONG*)pulDst = ulSrc;
  143. pulDst++;
  144. xAccum = xTmp;
  145. }
  146. pjOldScan = pjSrcScan;
  147. pjSrcScan += yInt;
  148. yTmp = yAccum + yFrac;
  149. if (yTmp < yAccum)
  150. {
  151. pjSrcScan += pStrBlt->lDeltaSrc;
  152. }
  153. yAccum = yTmp;
  154. pulDst = (ULONG*) ((BYTE*) pulDst + lDstStride);
  155. yDst++;
  156. yCount--;
  157. if ((yCount != 0) && (pjSrcScan == pjOldScan))
  158. {
  159. // It's an expanding stretch in 'y'; the scan we just laid down
  160. // will be copied at least once using the hardware:
  161. cyDuplicate = 0;
  162. do {
  163. cyDuplicate++;
  164. pjSrcScan += yInt;
  165. yTmp = yAccum + yFrac;
  166. if (yTmp < yAccum)
  167. {
  168. pjSrcScan += pStrBlt->lDeltaSrc;
  169. }
  170. yAccum = yTmp;
  171. pulDst = (ULONG*) ((BYTE*) pulDst + pStrBlt->lDeltaDst);
  172. yCount--;
  173. } while ((yCount != 0) && (pjSrcScan == pjOldScan));
  174. // The scan is to be copied 'cyDuplicate' times using the
  175. // hardware.
  176. do {
  177. CP_Y0(ppdev, pjBase, yDst - 1);
  178. CP_Y1(ppdev, pjBase, yDst - 1);
  179. CP_Y2(ppdev, pjBase, yDst);
  180. CP_Y3(ppdev, pjBase, yDst);
  181. yDst++;
  182. CP_START_BLT_WAIT(ppdev, pjBase);
  183. } while (--cyDuplicate != 0);
  184. }
  185. } while (yCount != 0);
  186. }
  187. /******************************Public*Routine******************************\
  188. *
  189. * Routine Description:
  190. *
  191. * StretchBlt using integer math. Must be from one surface to another
  192. * surface of the same format.
  193. *
  194. * Arguments:
  195. *
  196. * ppdev - PDEV for device
  197. * pvDst - Pointer to start of dst bitmap
  198. * lDeltaDst - Bytes from start of dst scan line to start of next
  199. * DstCx - Width of Dst Bitmap in pixels
  200. * DstCy - Height of Dst Bitmap in pixels
  201. * prclDst - Pointer to rectangle of Dst extents
  202. * pvSrc - Pointer to start of Src bitmap
  203. * lDeltaSrc - Bytes from start of Src scan line to start of next
  204. * SrcCx - Width of Src Bitmap in pixels
  205. * SrcCy - Height of Src Bitmap in pixels
  206. * prclSrc - Pointer to rectangle of Src extents
  207. * prclSClip - Clip Dest to this rect
  208. *
  209. * Return Value:
  210. *
  211. * Status
  212. *
  213. \**************************************************************************/
  214. BOOL bStretchDIBDirect(
  215. PDEV* ppdev,
  216. VOID* pvDst,
  217. LONG lDeltaDst,
  218. RECTL* prclDst,
  219. VOID* pvSrc,
  220. LONG lDeltaSrc,
  221. RECTL* prclSrc,
  222. RECTL* prclClip)
  223. {
  224. STR_BLT StrBlt;
  225. ULONG XSrcToDstIntFloor;
  226. ULONG XSrcToDstFracFloor;
  227. ULONG ulXDstToSrcIntCeil;
  228. ULONG ulXDstToSrcFracCeil;
  229. ULONG YSrcToDstIntFloor;
  230. ULONG YSrcToDstFracFloor;
  231. ULONG ulYDstToSrcIntCeil;
  232. ULONG ulYDstToSrcFracCeil;
  233. LONG SrcIntScan;
  234. LONG DstDeltaScanEnd;
  235. ULONG ulXFracAccumulator;
  236. ULONG ulYFracAccumulator;
  237. LONG LeftClipDistance;
  238. LONG TopClipDistance;
  239. BOOL bStretch;
  240. union {
  241. LARGE_INTEGER large;
  242. ULONGLONG li;
  243. } liInit;
  244. PFN_DIRSTRETCH pfnStr;
  245. //
  246. // Calculate exclusive start and end points:
  247. //
  248. LONG WidthDst = prclDst->right - prclDst->left;
  249. LONG HeightDst = prclDst->bottom - prclDst->top;
  250. LONG WidthSrc = prclSrc->right - prclSrc->left;
  251. LONG HeightSrc = prclSrc->bottom - prclSrc->top;
  252. LONG XSrcStart = prclSrc->left;
  253. LONG XSrcEnd = prclSrc->right;
  254. LONG XDstStart = prclDst->left;
  255. LONG XDstEnd = prclDst->right;
  256. LONG YSrcStart = prclSrc->top;
  257. LONG YSrcEnd = prclSrc->bottom;
  258. LONG YDstStart = prclDst->top;
  259. LONG YDstEnd = prclDst->bottom;
  260. //
  261. // Validate parameters:
  262. //
  263. ASSERTDD(pvDst != (VOID*)NULL, "Bad destination bitmap pointer");
  264. ASSERTDD(pvSrc != (VOID*)NULL, "Bad source bitmap pointer");
  265. ASSERTDD(prclDst != (RECTL*)NULL, "Bad destination rectangle");
  266. ASSERTDD(prclSrc != (RECTL*)NULL, "Bad source rectangle");
  267. ASSERTDD((WidthDst > 0) && (HeightDst > 0) &&
  268. (WidthSrc > 0) && (HeightSrc > 0),
  269. "Can't do mirroring or empty rectangles here");
  270. ASSERTDD((WidthDst <= STRETCH_MAX_EXTENT) &&
  271. (HeightDst <= STRETCH_MAX_EXTENT) &&
  272. (WidthSrc <= STRETCH_MAX_EXTENT) &&
  273. (HeightSrc <= STRETCH_MAX_EXTENT), "Stretch exceeds limits");
  274. ASSERTDD(prclClip != NULL, "Bad clip rectangle");
  275. //
  276. // Calculate X Dst to Src mapping
  277. //
  278. //
  279. // dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
  280. //
  281. // = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
  282. //
  283. // where 2k = 2 ^ 32
  284. //
  285. {
  286. ULONGLONG liWidthSrc;
  287. ULONGLONG liQuo;
  288. ULONG ulTemp;
  289. //
  290. // Work around a compiler bug dealing with the assignment
  291. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  292. //
  293. liInit.large.LowPart = (ULONG) -1;
  294. liInit.large.HighPart = WidthSrc - 1;
  295. liWidthSrc = liInit.li;
  296. liQuo = liWidthSrc / (ULONGLONG) WidthDst;
  297. ulXDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  298. ulXDstToSrcFracCeil = (ULONG)liQuo;
  299. //
  300. // Now add 1, use fake carry:
  301. //
  302. ulTemp = ulXDstToSrcFracCeil + 1;
  303. ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
  304. ulXDstToSrcFracCeil = ulTemp;
  305. }
  306. //
  307. // Calculate Y Dst to Src mapping
  308. //
  309. //
  310. // dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
  311. //
  312. // = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
  313. //
  314. // where 2k = 2 ^ 32
  315. //
  316. {
  317. ULONGLONG liHeightSrc;
  318. ULONGLONG liQuo;
  319. ULONG ulTemp;
  320. //
  321. // Work around a compiler bug dealing with the assignment
  322. // 'liHeightSrc = (((LONGLONG)HeightSrc) << 32) - 1':
  323. //
  324. liInit.large.LowPart = (ULONG) -1;
  325. liInit.large.HighPart = HeightSrc - 1;
  326. liHeightSrc = liInit.li;
  327. liQuo = liHeightSrc / (ULONGLONG) HeightDst;
  328. ulYDstToSrcIntCeil = (ULONG)(liQuo >> 32);
  329. ulYDstToSrcFracCeil = (ULONG)liQuo;
  330. //
  331. // Now add 1, use fake carry:
  332. //
  333. ulTemp = ulYDstToSrcFracCeil + 1;
  334. ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
  335. ulYDstToSrcFracCeil = ulTemp;
  336. }
  337. //
  338. // Now clip Dst in X, and/or calc src clipping effect on dst
  339. //
  340. // adjust left and right edges if needed, record
  341. // distance adjusted for fixing the src
  342. //
  343. if (XDstStart < prclClip->left)
  344. {
  345. XDstStart = prclClip->left;
  346. }
  347. if (XDstEnd > prclClip->right)
  348. {
  349. XDstEnd = prclClip->right;
  350. }
  351. //
  352. // Check for totally clipped out destination:
  353. //
  354. if (XDstEnd <= XDstStart)
  355. {
  356. return(TRUE);
  357. }
  358. LeftClipDistance = XDstStart - prclDst->left;
  359. {
  360. ULONG ulTempInt;
  361. ULONG ulTempFrac;
  362. //
  363. // Calculate displacement for .5 in destination and add:
  364. //
  365. ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
  366. ulTempInt = (ulXDstToSrcIntCeil >> 1);
  367. XSrcStart += ulTempInt;
  368. ulXFracAccumulator = ulTempFrac;
  369. if (LeftClipDistance != 0)
  370. {
  371. ULONGLONG ullFraction;
  372. ULONG ulTmp;
  373. ullFraction = UInt32x32To64(ulXDstToSrcFracCeil, LeftClipDistance);
  374. ulTmp = ulXFracAccumulator;
  375. ulXFracAccumulator += (ULONG) (ullFraction);
  376. if (ulXFracAccumulator < ulTmp)
  377. XSrcStart++;
  378. XSrcStart += (ulXDstToSrcIntCeil * LeftClipDistance)
  379. + (ULONG) (ullFraction >> 32);
  380. }
  381. }
  382. //
  383. // Now clip Dst in Y, and/or calc src clipping effect on dst
  384. //
  385. // adjust top and bottom edges if needed, record
  386. // distance adjusted for fixing the src
  387. //
  388. if (YDstStart < prclClip->top)
  389. {
  390. YDstStart = prclClip->top;
  391. }
  392. if (YDstEnd > prclClip->bottom)
  393. {
  394. YDstEnd = prclClip->bottom;
  395. }
  396. //
  397. // Check for totally clipped out destination:
  398. //
  399. if (YDstEnd <= YDstStart)
  400. {
  401. return(TRUE);
  402. }
  403. TopClipDistance = YDstStart - prclDst->top;
  404. {
  405. ULONG ulTempInt;
  406. ULONG ulTempFrac;
  407. //
  408. // Calculate displacement for .5 in destination and add:
  409. //
  410. ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
  411. ulTempInt = ulYDstToSrcIntCeil >> 1;
  412. YSrcStart += (LONG)ulTempInt;
  413. ulYFracAccumulator = ulTempFrac;
  414. if (TopClipDistance != 0)
  415. {
  416. ULONGLONG ullFraction;
  417. ULONG ulTmp;
  418. ullFraction = UInt32x32To64(ulYDstToSrcFracCeil, TopClipDistance);
  419. ulTmp = ulYFracAccumulator;
  420. ulYFracAccumulator += (ULONG) (ullFraction);
  421. if (ulYFracAccumulator < ulTmp)
  422. YSrcStart++;
  423. YSrcStart += (ulYDstToSrcIntCeil * TopClipDistance)
  424. + (ULONG) (ullFraction >> 32);
  425. }
  426. }
  427. //
  428. // Warm up the hardware if doing an expanding stretch in 'y':
  429. //
  430. bStretch = (HeightDst > HeightSrc);
  431. if (bStretch)
  432. {
  433. LONG cjPel = ppdev->cjPel;
  434. BYTE* pjBase = ppdev->pjBase;
  435. LONG x;
  436. CP_WAIT(ppdev, pjBase);
  437. CP_RASTER(ppdev, pjBase, P9000(ppdev) ? P9000_S : P9100_S);
  438. //
  439. // Set up the left and right blt edges, since they never change
  440. // during the StretchBlt
  441. //
  442. x = (XDstStart + ppdev->xOffset) * cjPel;
  443. CP_ABS_X0(ppdev, pjBase, x);
  444. CP_ABS_X2(ppdev, pjBase, x);
  445. x = (XDstEnd + ppdev->xOffset) * cjPel - 1;
  446. CP_ABS_X1(ppdev, pjBase, x);
  447. CP_ABS_X3(ppdev, pjBase, x);
  448. }
  449. //
  450. // Fill out blt structure, then call format-specific stretch code
  451. //
  452. StrBlt.ppdev = ppdev;
  453. StrBlt.XDstEnd = XDstEnd;
  454. StrBlt.YDstStart = YDstStart;
  455. StrBlt.YDstCount = YDstEnd - YDstStart;
  456. if (StrBlt.YDstCount > 0)
  457. {
  458. //
  459. // Caclulate starting scan line address. Since the inner loop
  460. // routines are format dependent, they must add XDstStart/XSrcStart
  461. // to pjDstScan/pjSrcScan to get the actual starting pixel address.
  462. //
  463. StrBlt.pjSrcScan = (BYTE*) pvSrc + (YSrcStart * lDeltaSrc);
  464. StrBlt.pjDstScan = (BYTE*) pvDst + (YDstStart * lDeltaDst);
  465. StrBlt.lDeltaSrc = lDeltaSrc;
  466. StrBlt.XSrcStart = XSrcStart;
  467. StrBlt.XDstStart = XDstStart;
  468. StrBlt.lDeltaDst = lDeltaDst;
  469. StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
  470. StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
  471. StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
  472. StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
  473. StrBlt.ulXFracAccumulator = ulXFracAccumulator;
  474. StrBlt.ulYFracAccumulator = ulYFracAccumulator;
  475. if (ppdev->iBitmapFormat == BMF_8BPP)
  476. {
  477. if ((XDstEnd - XDstStart) < 7)
  478. pfnStr = vDirectStretch8Narrow;
  479. else
  480. pfnStr = vDirectStretch8;
  481. }
  482. else if (ppdev->iBitmapFormat == BMF_16BPP)
  483. {
  484. pfnStr = vDirectStretch16;
  485. }
  486. else
  487. {
  488. ASSERTDD(ppdev->iBitmapFormat == BMF_32BPP,
  489. "Only handle stretchs at 8, 16 and 32bpp");
  490. pfnStr = vDirectStretch32;
  491. }
  492. (*pfnStr)(&StrBlt);
  493. }
  494. return(TRUE);
  495. }
  496. /******************************Public*Routine******************************\
  497. * BOOL DrvStretchBlt
  498. *
  499. \**************************************************************************/
  500. BOOL DrvStretchBlt(
  501. SURFOBJ* psoDst,
  502. SURFOBJ* psoSrc,
  503. SURFOBJ* psoMsk,
  504. CLIPOBJ* pco,
  505. XLATEOBJ* pxlo,
  506. COLORADJUSTMENT* pca,
  507. POINTL* pptlHTOrg,
  508. RECTL* prclDst,
  509. RECTL* prclSrc,
  510. POINTL* pptlMsk,
  511. ULONG iMode)
  512. {
  513. DSURF* pdsurfSrc;
  514. DSURF* pdsurfDst;
  515. PDEV* ppdev;
  516. OH* poh;
  517. // GDI guarantees us that for a StretchBlt the destination surface
  518. // will always be a device surface, and not a DIB:
  519. ppdev = (PDEV*) psoDst->dhpdev;
  520. // It's quicker for GDI to do a StretchBlt when the source surface
  521. // is not a device-managed surface, because then it can directly
  522. // read the source bits without having to allocate a temporary
  523. // buffer and call DrvCopyBits to get a copy that it can use.
  524. //
  525. // So if the source is one of our off-screen DFBs, we'll immediately
  526. // and permanently convert it to a DIB:
  527. if (psoSrc->iType == STYPE_DEVBITMAP)
  528. {
  529. pdsurfSrc = (DSURF*) psoSrc->dhsurf;
  530. if (pdsurfSrc->dt == DT_SCREEN)
  531. {
  532. if (!pohMoveOffscreenDfbToDib(ppdev, pdsurfSrc->poh))
  533. return(FALSE);
  534. }
  535. ASSERTDD(pdsurfSrc->dt == DT_DIB, "Can only handle DIB DFBs here");
  536. psoSrc = pdsurfSrc->pso;
  537. }
  538. pdsurfDst = (DSURF*) psoDst->dhsurf;
  539. if (pdsurfDst->dt == DT_DIB)
  540. {
  541. // The destination was a device bitmap that we just converted
  542. // to a DIB:
  543. psoDst = pdsurfDst->pso;
  544. goto Punt_It;
  545. }
  546. poh = pdsurfDst->poh;
  547. psoDst = ppdev->psoPunt;
  548. ppdev->xOffset = poh->x;
  549. ppdev->yOffset = poh->y;
  550. psoDst->pvScan0 = poh->pvScan0;
  551. // NOTE: The P9000 is allowed down here, too
  552. {
  553. RECTL rclClip;
  554. RECTL* prclClip;
  555. ULONG cxDst;
  556. ULONG cyDst;
  557. ULONG cxSrc;
  558. ULONG cySrc;
  559. BOOL bMore;
  560. CLIPENUM ce;
  561. LONG c;
  562. LONG i;
  563. if ((psoSrc->iType == STYPE_BITMAP) &&
  564. (psoMsk == NULL) &&
  565. ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)) &&
  566. ((psoSrc->iBitmapFormat == ppdev->iBitmapFormat)) &&
  567. (ppdev->iBitmapFormat != BMF_24BPP))
  568. {
  569. cxDst = prclDst->right - prclDst->left;
  570. cyDst = prclDst->bottom - prclDst->top;
  571. cxSrc = prclSrc->right - prclSrc->left;
  572. cySrc = prclSrc->bottom - prclSrc->top;
  573. // Our 'bStretchDIBDirect' routine requires that the stretch be
  574. // non-inverting, within a certain size, to have no source
  575. // clipping, and to have no empty rectangles (the latter is the
  576. // reason for the '- 1' on the unsigned compare here):
  577. if (((cxSrc - 1) < STRETCH_MAX_EXTENT) &&
  578. ((cySrc - 1) < STRETCH_MAX_EXTENT) &&
  579. ((cxDst - 1) < STRETCH_MAX_EXTENT) &&
  580. ((cyDst - 1) < STRETCH_MAX_EXTENT) &&
  581. (prclSrc->left >= 0) &&
  582. (prclSrc->top >= 0) &&
  583. (prclSrc->right <= psoSrc->sizlBitmap.cx) &&
  584. (prclSrc->bottom <= psoSrc->sizlBitmap.cy))
  585. {
  586. // Our snazzy routine only does COLORONCOLOR. But for
  587. // stretching blts, BLACKONWHITE and WHITEONBLACK are also
  588. // equivalent to COLORONCOLOR:
  589. if ((iMode == COLORONCOLOR) ||
  590. ((iMode < COLORONCOLOR) && (cxSrc <= cxDst) && (cySrc <= cyDst)))
  591. {
  592. if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL))
  593. {
  594. rclClip.left = LONG_MIN;
  595. rclClip.top = LONG_MIN;
  596. rclClip.right = LONG_MAX;
  597. rclClip.bottom = LONG_MAX;
  598. prclClip = &rclClip;
  599. StretchSingleClipRect:
  600. if (bStretchDIBDirect(ppdev,
  601. poh->pvScan0,
  602. ppdev->lDelta,
  603. prclDst,
  604. psoSrc->pvScan0,
  605. psoSrc->lDelta,
  606. prclSrc,
  607. prclClip))
  608. {
  609. return(TRUE);
  610. }
  611. }
  612. else if (pco->iDComplexity == DC_RECT)
  613. {
  614. prclClip = &pco->rclBounds;
  615. goto StretchSingleClipRect;
  616. }
  617. else
  618. {
  619. CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
  620. do {
  621. bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG*) &ce);
  622. c = cIntersect(prclDst, ce.arcl, ce.c);
  623. if (c != 0)
  624. {
  625. for (i = 0; i < c; i++)
  626. {
  627. if (!bStretchDIBDirect(ppdev,
  628. poh->pvScan0,
  629. ppdev->lDelta,
  630. prclDst,
  631. psoSrc->pvScan0,
  632. psoSrc->lDelta,
  633. prclSrc,
  634. &ce.arcl[i]))
  635. {
  636. goto Punt_It;
  637. }
  638. }
  639. }
  640. } while (bMore);
  641. return(TRUE);
  642. }
  643. }
  644. }
  645. }
  646. }
  647. Punt_It:
  648. return(EngStretchBlt(psoDst, psoSrc, psoMsk, pco, pxlo, pca, pptlHTOrg,
  649. prclDst, prclSrc, pptlMsk, iMode));
  650. }