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.

1291 lines
32 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name:
  4. str.c
  5. Abstract:
  6. stretch blt routines
  7. Author:
  8. Mark Enstrom (marke)
  9. Environment:
  10. C
  11. Revision History:
  12. 08-26-92 Initial version
  13. --*/
  14. #include "precomp.hxx"
  15. #include "stretch.hxx"
  16. #define STRETCH_MAX_WIDTH 32767
  17. #ifdef DBG_STRDIR
  18. ULONG DbgStrBlt=0;
  19. #endif
  20. PFN_DIRSTRETCH
  21. pfnStrArray[] = {
  22. vDirectStretchError, // 0
  23. vDirectStretchError, // 1
  24. vDirectStretchError, // 4
  25. vDirectStretch8, // 8
  26. vDirectStretch16, // 16
  27. vDirectStretchError, // 24
  28. vDirectStretch32, // 32
  29. vDirectStretchError, // 0 Narrow
  30. vDirectStretchError, // 0 Narrow
  31. vDirectStretchError, // 1 Narrow
  32. vDirectStretchError, // 4 Narrow
  33. vDirectStretch8Narrow, // 8 Narrow
  34. vDirectStretch16, // 16 Narrow
  35. vDirectStretchError, // 24 Narrow
  36. vDirectStretch32, // 32 Narrow
  37. vDirectStretchError // 0 Narrow
  38. };
  39. /******************************Public*Routine******************************\
  40. *
  41. * Routine Description:
  42. *
  43. * StretchBlt using integer math. Must be from one surface to another
  44. * surface of the same format. Currently only 8,16 and 32 bit per pixel
  45. * are supported
  46. *
  47. * Arguments:
  48. *
  49. * pvDst - Pointer to start of dst bitmap
  50. * lDeltaDst - Bytes from start of dst scan line to start of next
  51. * DstCx - Width of Dst Bitmap in pixels
  52. * DstCy - Height of Dst Bitmap in pixels
  53. * prclDst - Pointer to rectangle of Dst extents
  54. * pvSrc - Pointer to start of Src bitmap
  55. * lDeltaSrc - Bytes from start of Src scan line to start of next
  56. * SrcCx - Width of Src Bitmap in pixels
  57. * SrcCy - Height of Src Bitmap in pixels
  58. * prclSrc - Pointer to rectangle of Src extents
  59. * prclTrim - Return dst extents trimmed by clipping in this rect
  60. * prclSClip - Clip Dest to this rect
  61. * iBitmapFormat - Format of Src and Dst bitmaps
  62. *
  63. * Return Value:
  64. *
  65. * Status
  66. *
  67. * Revision History:
  68. *
  69. * 10-07-94 Initial code
  70. *
  71. \**************************************************************************/
  72. BOOL
  73. StretchDIBDirect(
  74. PVOID pvDst,
  75. LONG lDeltaDst,
  76. ULONG DstCx,
  77. ULONG DstCy,
  78. PRECTL prclDst,
  79. PVOID pvSrc,
  80. LONG lDeltaSrc,
  81. ULONG SrcCx,
  82. ULONG SrcCy,
  83. PRECTL prclSrc,
  84. PRECTL prclTrim,
  85. PRECTL prclClip,
  86. ULONG iBitmapFormat
  87. )
  88. {
  89. //
  90. // validate parameters, then determine src to dst mapping
  91. //
  92. ASSERTGDI(pvDst != (PVOID)NULL,"Bad destination bitmap pointer");
  93. ASSERTGDI(pvSrc != (PVOID)NULL,"Bad source bitmap pointer");
  94. ASSERTGDI(prclDst != (PRECTL)NULL,"Bad destination rectangle");
  95. ASSERTGDI(prclSrc != (PRECTL)NULL,"Bad source rectangle");
  96. STR_BLT StrBlt;
  97. #ifdef DBG_STRDIR
  98. if (DbgStrBlt >= 3) {
  99. DbgPrint("\n-----------------------------------------------------------");
  100. DbgPrint("StretchBlt\n");
  101. DbgPrint("rclDst = [0x%8lx,0x%8lx] to [0x%8lx,0x%8lx]\n",prclDst->left,prclDst->top,prclDst->right,prclDst->bottom);
  102. DbgPrint("rclSrc = [0x%8lx,0x%8lx] to [0x%8lx,0x%8lx]\n",prclSrc->left,prclSrc->top,prclSrc->right,prclSrc->bottom);
  103. }
  104. #endif
  105. LONG WidthDst = prclDst->right - prclDst->left;
  106. LONG HeightDst = prclDst->bottom - prclDst->top;
  107. LONG WidthSrc = prclSrc->right - prclSrc->left;
  108. LONG HeightSrc = prclSrc->bottom - prclSrc->top;
  109. ULONG XSrcToDstIntFloor;
  110. ULONG XSrcToDstFracFloor;
  111. ULONG ulXDstToSrcIntCeil;
  112. ULONG ulXDstToSrcFracCeil;
  113. ULONG YSrcToDstIntFloor;
  114. ULONG YSrcToDstFracFloor;
  115. ULONG ulYDstToSrcIntCeil;
  116. ULONG ulYDstToSrcFracCeil;
  117. LONG SrcIntScan;
  118. LONG DstDeltaScanEnd;
  119. //
  120. // calculate EXCLUSIVE start and end points
  121. //
  122. LONG XSrcStart = prclSrc->left;
  123. LONG XSrcEnd = prclSrc->right;
  124. LONG XDstStart = prclDst->left;
  125. LONG XDstEnd = prclDst->right;
  126. LONG YSrcStart = prclSrc->top;
  127. LONG YSrcEnd = prclSrc->bottom;
  128. LONG YDstStart = prclDst->top;
  129. LONG YDstEnd = prclDst->bottom;
  130. ULONG ulXFracAccumulator;
  131. ULONG ulYFracAccumulator;
  132. BOOL bXSrcClipped = FALSE;
  133. BOOL bYSrcClipped = FALSE;
  134. RECTL rclDefClip;
  135. PRECTL prclBounds = prclClip;
  136. LONG LeftClipDistance;
  137. LONG TopClipDistance;
  138. PFN_DIRSTRETCH pfnStr;
  139. //
  140. // check for quick-out NULL RECTs. SrcWidth and SrcHeight must be
  141. // positive here. Mirroring is taken care of earlier.
  142. //
  143. if (
  144. (WidthDst <= 0) ||
  145. (HeightDst <= 0) ||
  146. (WidthSrc <= 0) ||
  147. (HeightSrc <= 0)
  148. )
  149. {
  150. return(TRUE);
  151. }
  152. //
  153. // make sure extents fit with the limits of 32 bit integer
  154. // arithmatic
  155. //
  156. if (
  157. (WidthDst > STRETCH_MAX_WIDTH) ||
  158. (HeightDst > STRETCH_MAX_WIDTH) ||
  159. (WidthSrc > STRETCH_MAX_WIDTH) ||
  160. (HeightSrc > STRETCH_MAX_WIDTH)
  161. )
  162. {
  163. return(FALSE);
  164. }
  165. //
  166. // if prclClip is null, then make bounds point to a
  167. // default clip region of the entire dst rect
  168. //
  169. if (prclClip == (PRECTL)NULL) {
  170. prclBounds = &rclDefClip;
  171. rclDefClip.left = 0;
  172. rclDefClip.right = DstCx;
  173. rclDefClip.top = 0;
  174. rclDefClip.bottom = DstCy;
  175. }
  176. //
  177. // Calculate X Dst to Src mapping
  178. //
  179. //
  180. // dst->src = ( CEIL( (2k*WidthSrc)/WidthDst) ) / 2k
  181. //
  182. // = ( FLOOR( (2k*WidthSrc -1) / WidthDst) + 1) / 2k
  183. //
  184. // where 2k = 2 ^ 32
  185. //
  186. {
  187. LARGE_INTEGER liWidthSrc;
  188. LARGE_INTEGER liQuo;
  189. ULONG ulTemp;
  190. liWidthSrc.LowPart = (ULONG)-1;
  191. liWidthSrc.HighPart = WidthSrc-1;
  192. liQuo = RtlExtendedLargeIntegerDivide(liWidthSrc,(ULONG)WidthDst,(PULONG)NULL);
  193. ulXDstToSrcIntCeil = liQuo.HighPart;
  194. ulXDstToSrcFracCeil = liQuo.LowPart;
  195. //
  196. // now add 1, use fake carry
  197. //
  198. ulTemp = ulXDstToSrcFracCeil + 1;
  199. ulXDstToSrcIntCeil += (ulTemp < ulXDstToSrcFracCeil);
  200. ulXDstToSrcFracCeil = ulTemp;
  201. }
  202. //
  203. // Calculate Y Dst to Src mapping
  204. //
  205. //
  206. // dst->src = ( CEIL( (2k*HeightSrc)/HeightDst) ) / 2k
  207. //
  208. // = ( FLOOR( (2k*HeightSrc -1) / HeightDst) + 1) / 2k
  209. //
  210. // where 2k = 2 ^ 32
  211. //
  212. {
  213. LARGE_INTEGER liHeightSrc;
  214. LARGE_INTEGER liQuo;
  215. ULONG ulTemp;
  216. liHeightSrc.LowPart = (ULONG) -1;
  217. liHeightSrc.HighPart = HeightSrc-1;
  218. liQuo = RtlExtendedLargeIntegerDivide(liHeightSrc,HeightDst,NULL);
  219. ulYDstToSrcIntCeil = (ULONG)liQuo.HighPart;
  220. ulYDstToSrcFracCeil = liQuo.LowPart;
  221. //
  222. // now add 1, use fake carry
  223. //
  224. ulTemp = ulYDstToSrcFracCeil + 1;
  225. ulYDstToSrcIntCeil += (ulTemp < ulYDstToSrcFracCeil);
  226. ulYDstToSrcFracCeil = ulTemp;
  227. }
  228. //
  229. // Check for a x clipped src
  230. //
  231. if ((XSrcStart < 0) || (XSrcEnd > (LONG)SrcCx)) {
  232. bXSrcClipped = TRUE;
  233. //
  234. // src is x clipped.
  235. // calculate Src to Dst mapping, then calculate
  236. // new XDstStart and/or XDstEnd based on clipped src
  237. //
  238. // Calculate X Src to Dst mapping
  239. //
  240. // Src->Dst = ( FLOOR( (2k*WidthDst)/WidthSrc) ) / 2k
  241. //
  242. // where 2k = 2 ^ 32
  243. //
  244. LARGE_INTEGER liHalfk = {0x7fffffff,0x00000000};
  245. LARGE_INTEGER liWidthDst;
  246. LARGE_INTEGER liQuo;
  247. ULONG ulTemp;
  248. bXSrcClipped = TRUE;
  249. liWidthDst.HighPart = WidthDst;;
  250. liWidthDst.LowPart = 0;
  251. liQuo = RtlExtendedLargeIntegerDivide(liWidthDst,(ULONG)WidthSrc,(PULONG)NULL);
  252. XSrcToDstIntFloor = (ULONG)liQuo.HighPart;
  253. XSrcToDstFracFloor = liQuo.LowPart;
  254. //
  255. // is src left clipped
  256. //
  257. if (XSrcStart < 0)
  258. {
  259. //
  260. // clip left Ad = FLOOR[ N * As + (2^(k-1) -1)]/2^k
  261. //
  262. LONG SrcClipped = -(LONG)XSrcStart;
  263. ULONG DeltaDstInt;
  264. LARGE_INTEGER liDeltaDstFrac;
  265. LONG NewWidthSrc = WidthSrc;
  266. NewWidthSrc -= SrcClipped;
  267. if (NewWidthSrc <= 0)
  268. {
  269. return(TRUE);
  270. }
  271. //
  272. // calc fraction N * As
  273. //
  274. DeltaDstInt = (ULONG)SrcClipped * XSrcToDstIntFloor;
  275. liDeltaDstFrac = RtlEnlargedUnsignedMultiply((ULONG)SrcClipped,XSrcToDstFracFloor);
  276. liDeltaDstFrac.HighPart += (LONG)DeltaDstInt;
  277. //
  278. // add in 2^(k-1) - 1 = 0x00000000 0x7fffffff
  279. //
  280. liDeltaDstFrac = RtlLargeIntegerAdd(liDeltaDstFrac,liHalfk);
  281. XSrcStart = 0;
  282. XDstStart += liDeltaDstFrac.HighPart;
  283. }
  284. if (XSrcEnd > (LONG)SrcCx)
  285. {
  286. //
  287. // clip right edge, calc src offset from XSrcStart (SrcClipped)
  288. //
  289. // clip left Bd = FLOOR[ N * Bs + (2^(k-1) -1)]/2^k
  290. //
  291. // Note: use original value of WidthSrc, not value reduced by
  292. // left clipping.
  293. //
  294. LONG SrcClipped = XSrcEnd - SrcCx;
  295. ULONG DeltaDstInt;
  296. LARGE_INTEGER liDstWidth;
  297. WidthSrc = WidthSrc - SrcClipped;
  298. //
  299. // check for totally src clipped
  300. //
  301. if (WidthSrc <= 0)
  302. {
  303. return(TRUE);
  304. }
  305. //
  306. // calc N * Bs
  307. //
  308. DeltaDstInt = (ULONG)WidthSrc * (ULONG)XSrcToDstIntFloor;
  309. liDstWidth = RtlEnlargedUnsignedMultiply((ULONG)WidthSrc,XSrcToDstFracFloor);
  310. liDstWidth.HighPart += (LONG)DeltaDstInt;
  311. //
  312. // add in (2^(k-1) -1)
  313. //
  314. liDstWidth = RtlLargeIntegerAdd(liDstWidth,liHalfk);
  315. XSrcEnd = SrcCx;
  316. XDstEnd = prclDst->left + liDstWidth.HighPart;
  317. }
  318. }
  319. //
  320. // Now clip Dst in X, and/or calc src clipping effect on dst
  321. //
  322. // adjust left and right edges if needed, record
  323. // distance adjusted for fixing the src
  324. //
  325. if (XDstStart < prclBounds->left)
  326. {
  327. XDstStart = prclBounds->left;
  328. }
  329. if (XDstEnd > prclBounds->right)
  330. {
  331. XDstEnd = prclBounds->right;
  332. }
  333. //
  334. // check for totally clipped out dst
  335. //
  336. if (XDstEnd <= XDstStart)
  337. {
  338. return(TRUE);
  339. }
  340. LeftClipDistance = XDstStart - prclDst->left;
  341. if (!bXSrcClipped && (LeftClipDistance == 0))
  342. {
  343. ULONG ulTempInt,ulTempFrac;
  344. //
  345. // calc displacement for .5 in dst and add
  346. //
  347. ulTempFrac = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
  348. ulTempInt = ulXDstToSrcIntCeil >> 1;
  349. XSrcStart += (LONG)ulTempInt;
  350. ulXFracAccumulator = ulTempFrac;
  351. } else {
  352. //
  353. // calc new src start
  354. //
  355. LARGE_INTEGER liMulResult;
  356. LARGE_INTEGER liHalfDest;
  357. ULONG ulIntResult;
  358. //
  359. // calculate starting XSrc based on LeftClipDistance.
  360. //
  361. liMulResult = RtlEnlargedUnsignedMultiply((ULONG)LeftClipDistance,ulXDstToSrcIntCeil);
  362. ulIntResult = liMulResult.LowPart;
  363. liMulResult = RtlEnlargedUnsignedMultiply((ULONG)LeftClipDistance,ulXDstToSrcFracCeil);
  364. liMulResult.HighPart += ulIntResult;
  365. //
  366. // calculate change in Src for .5 change in dst. This is just 1/2 INT:FRAC
  367. //
  368. liHalfDest.LowPart = (ulXDstToSrcFracCeil >> 1) | (ulXDstToSrcIntCeil << 31);
  369. liHalfDest.HighPart = ulXDstToSrcIntCeil >> 1;
  370. //
  371. // add changed together for final XSrcStart
  372. //
  373. liMulResult = RtlLargeIntegerAdd(liMulResult,liHalfDest);
  374. //
  375. // separate int portion and fractional portion
  376. //
  377. XSrcStart = prclSrc->left + liMulResult.HighPart;
  378. ulXFracAccumulator = liMulResult.LowPart;
  379. }
  380. //
  381. // now check for src and dst clipping in Y
  382. //
  383. // Check for a Y clipped src
  384. //
  385. if ((YSrcStart < 0) || (YSrcEnd > (LONG)SrcCy))
  386. {
  387. bYSrcClipped = TRUE;
  388. //
  389. // src is y clipped.
  390. // calculate Src to Dst mapping, then calculate
  391. // new YDstStart and/or YDstEnd based on clipped src
  392. //
  393. // Calculate Y Src to Dst mapping
  394. //
  395. // Src->Dst = ( FLOOR( (2k*HeightDst)/HeightSrc) ) / 2k
  396. //
  397. // where 2k = 2 ^ 32
  398. //
  399. LARGE_INTEGER liHalfk = {0x7fffffff,0x00000000};
  400. LARGE_INTEGER liHeightDst;
  401. LARGE_INTEGER liQuo;
  402. ULONG ulTemp;
  403. bYSrcClipped = TRUE;
  404. liHeightDst.HighPart = HeightDst;
  405. liHeightDst.LowPart = 0;
  406. liQuo = RtlExtendedLargeIntegerDivide(liHeightDst,(LONG)HeightSrc,(PULONG)NULL);
  407. YSrcToDstIntFloor = (ULONG)liQuo.HighPart;
  408. YSrcToDstFracFloor = liQuo.LowPart;
  409. //
  410. // is src top clipped
  411. //
  412. if (YSrcStart < 0)
  413. {
  414. //
  415. // clip top
  416. // clip left Ad = FLOOR[ d/s * As - liHalfK] + 1
  417. //
  418. LONG SrcClipped = -(LONG)YSrcStart;
  419. LONG DeltaDstInt;
  420. LARGE_INTEGER liDeltaDst;
  421. LONG NewHeightSrc = HeightSrc;
  422. NewHeightSrc -= SrcClipped;
  423. if (NewHeightSrc <= 0)
  424. {
  425. return(TRUE);
  426. }
  427. DeltaDstInt = SrcClipped * (LONG)YSrcToDstIntFloor;
  428. liDeltaDst = RtlEnlargedUnsignedMultiply((ULONG)SrcClipped,YSrcToDstFracFloor);
  429. liDeltaDst.HighPart += DeltaDstInt;
  430. //
  431. // add in (2^(k-1) -1) "liHalfk"
  432. //
  433. liDeltaDst = RtlLargeIntegerAdd(liDeltaDst,liHalfk);
  434. YSrcStart = 0;
  435. YDstStart += liDeltaDst.HighPart;
  436. }
  437. if (YSrcEnd > (LONG)SrcCy)
  438. {
  439. //
  440. // clip bottom edge, calc src offset from YSrcStart (SrcClipped)
  441. // clip left Bd = FLOOR[ d/s * Bs + liHalfK]
  442. //
  443. // Note: use original value of HeightSrc, not value reduced
  444. // by top clipping
  445. //
  446. LONG SrcClipped = YSrcEnd - SrcCy;
  447. ULONG DeltaDstInt;
  448. LARGE_INTEGER liDeltaDstFrac;
  449. HeightSrc = HeightSrc - SrcClipped;
  450. //
  451. // check for totally src clipped
  452. //
  453. if (HeightSrc <= 0)
  454. {
  455. return(TRUE);
  456. }
  457. DeltaDstInt = (ULONG)HeightSrc * YSrcToDstIntFloor;
  458. liDeltaDstFrac = RtlEnlargedUnsignedMultiply(HeightSrc,YSrcToDstFracFloor);
  459. liDeltaDstFrac.HighPart += DeltaDstInt;
  460. //
  461. // add in (2^(k-1) -1) "liHalfk"
  462. //
  463. liDeltaDstFrac = RtlLargeIntegerAdd(liDeltaDstFrac,liHalfk);
  464. YSrcEnd = SrcCy;
  465. YDstEnd = prclDst->top + liDeltaDstFrac.HighPart;
  466. }
  467. }
  468. //
  469. // Now clip Dst in Y, and/or calc src clipping effect on dst
  470. //
  471. // adjust top and bottom edges if needed, record
  472. // distance adjusted for fixing the src
  473. //
  474. if (YDstStart < prclBounds->top)
  475. {
  476. YDstStart = prclBounds->top;
  477. }
  478. if (YDstEnd > prclBounds->bottom)
  479. {
  480. YDstEnd = prclBounds->bottom;
  481. }
  482. //
  483. // check for totally clipped out dst
  484. //
  485. if (YDstEnd <= YDstStart)
  486. {
  487. return(TRUE);
  488. }
  489. TopClipDistance = YDstStart - prclDst->top;
  490. if (!bYSrcClipped && (TopClipDistance == 0))
  491. {
  492. ULONG ulTempInt,ulTempFrac;
  493. //
  494. // calc displacement for .5 in dst and add
  495. //
  496. ulTempFrac = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
  497. ulTempInt = ulYDstToSrcIntCeil >> 1;
  498. YSrcStart += (LONG)ulTempInt;
  499. ulYFracAccumulator = ulTempFrac;
  500. } else {
  501. //
  502. // calc new src start
  503. //
  504. LARGE_INTEGER liMulResult;
  505. LARGE_INTEGER liHalfDest;
  506. ULONG ulIntResult;
  507. //
  508. // calculate Src offset for clipping offset in Dst
  509. //
  510. liMulResult = RtlEnlargedUnsignedMultiply((ULONG)TopClipDistance,ulYDstToSrcIntCeil);
  511. ulIntResult = liMulResult.LowPart;
  512. liMulResult = RtlEnlargedUnsignedMultiply(TopClipDistance,ulYDstToSrcFracCeil);
  513. liMulResult.HighPart += ulIntResult;
  514. //
  515. // calculate change in Src for .5 change in dst. This is just 1/2 INT:FRAC
  516. //
  517. liHalfDest.LowPart = (ulYDstToSrcFracCeil >> 1) | (ulYDstToSrcIntCeil << 31);
  518. liHalfDest.HighPart = ulYDstToSrcIntCeil >> 1;
  519. //
  520. // add changed together for final YSrcStart
  521. //
  522. liMulResult = RtlLargeIntegerAdd(liMulResult,liHalfDest);
  523. //
  524. // separate int and frac portions
  525. //
  526. YSrcStart = prclSrc->top + liMulResult.HighPart;
  527. ulYFracAccumulator = liMulResult.LowPart;
  528. }
  529. //
  530. // fill out blt structure, then call format specific stretch code
  531. //
  532. #ifdef DBG_STRDIR
  533. if (DbgStrBlt >= 2) {
  534. DbgPrint("StretchBlt:\n");
  535. DbgPrint("XSrcStart = %li\n",XSrcStart);
  536. DbgPrint("YSrcStart = %li\n",YSrcStart);
  537. DbgPrint("XDstStart,XDstEnd = %li to %li\n",XDstStart,XDstEnd);
  538. DbgPrint("YDstStart,YDstEnd = %li to %li\n",YDstStart,YDstEnd);
  539. }
  540. #endif
  541. //
  542. // caclulate starting scan line address, since the inner loop
  543. // routines are format dependent, they must add XDstStart/XSrcStart
  544. // to pjDstScan/pjSrcScan to get the actual starting pixel address
  545. //
  546. StrBlt.pjSrcScan = (PBYTE)pvSrc + (YSrcStart * lDeltaSrc);
  547. StrBlt.pjDstScan = (PBYTE)pvDst + (YDstStart * lDeltaDst);
  548. StrBlt.lDeltaSrc = lDeltaSrc;
  549. StrBlt.XSrcStart = XSrcStart;
  550. StrBlt.XDstStart = XDstStart;
  551. StrBlt.lDeltaDst = lDeltaDst;
  552. StrBlt.XDstEnd = XDstEnd;
  553. StrBlt.YDstCount = YDstEnd - YDstStart;
  554. StrBlt.ulXDstToSrcIntCeil = ulXDstToSrcIntCeil;
  555. StrBlt.ulXDstToSrcFracCeil = ulXDstToSrcFracCeil;
  556. StrBlt.ulYDstToSrcIntCeil = ulYDstToSrcIntCeil;
  557. StrBlt.ulYDstToSrcFracCeil = ulYDstToSrcFracCeil;
  558. StrBlt.ulXFracAccumulator = ulXFracAccumulator;
  559. StrBlt.ulYFracAccumulator = ulYFracAccumulator;
  560. pfnStr = pfnStrArray[ (((XDstEnd - XDstStart) < 7) << 3) | iBitmapFormat];
  561. (*pfnStr)(&StrBlt);
  562. //
  563. // save clipped dst in prclTrim
  564. //
  565. prclTrim->left = XDstStart;
  566. prclTrim->right = XDstEnd;
  567. prclTrim->top = YDstStart;
  568. prclTrim->bottom = YDstEnd;
  569. return(TRUE);
  570. }
  571. #if !defined (_MIPS_)
  572. #if !defined (_X86_)
  573. /******************************Public*Routine******************************\
  574. *
  575. * Routine Name
  576. *
  577. * vDirectStretch8
  578. *
  579. * Routine Description:
  580. *
  581. * Stretch blt 8->8
  582. *
  583. * Arguments:
  584. *
  585. * pStrBlt - contains all params for blt
  586. *
  587. * Return Value:
  588. *
  589. * VOID
  590. *
  591. \**************************************************************************/
  592. VOID
  593. vDirectStretch8(
  594. PSTR_BLT pStrBlt
  595. )
  596. {
  597. LONG xDst = pStrBlt->XDstStart;
  598. LONG xSrc = pStrBlt->XSrcStart;
  599. PBYTE pjSrcScan = pStrBlt->pjSrcScan + xSrc;
  600. PBYTE pjSrc;
  601. PBYTE pjDst = pStrBlt->pjDstScan + xDst;
  602. PBYTE pjDstEnd;
  603. LONG yCount = pStrBlt->YDstCount;
  604. ULONG StartAln = (ULONG)((ULONG_PTR)pjDst & 0x03);
  605. LONG WidthX = pStrBlt->XDstEnd - xDst;
  606. LONG WidthXAln;
  607. ULONG EndAln = (ULONG)((ULONG_PTR)(pjDst + WidthX) & 0x03);
  608. ULONG ulDst;
  609. BOOL bExpand = (pStrBlt->ulYDstToSrcIntCeil == 0);
  610. ULONG xAccum;
  611. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  612. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  613. ULONG xTmp;
  614. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  615. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  616. LONG yInt = 0;
  617. ULONG yTmp;
  618. LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
  619. WidthXAln = WidthX - EndAln - ((4-StartAln) & 0x03);
  620. if (yCount <= 0)
  621. {
  622. return;
  623. }
  624. //
  625. // if this is a shrinking blt, calc src scan line stride
  626. //
  627. if (!bExpand)
  628. {
  629. yInt = pStrBlt->lDeltaSrc * (LONG)pStrBlt->ulYDstToSrcIntCeil;
  630. }
  631. //
  632. // loop drawing each scan line
  633. //
  634. //
  635. // at least 7 wide (DST) blt
  636. //
  637. do {
  638. BYTE jSrc0,jSrc1,jSrc2,jSrc3;
  639. ULONG yTmp = yAccum + yFrac;
  640. pjSrc = pjSrcScan;
  641. xAccum = pStrBlt->ulXFracAccumulator;
  642. //
  643. // a single src scan line is being written
  644. //
  645. switch (StartAln) {
  646. case 1:
  647. jSrc0 = *pjSrc;
  648. xTmp = xAccum + xFrac;
  649. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  650. *pjDst++ = jSrc0;
  651. xAccum = xTmp;
  652. case 2:
  653. jSrc0 = *pjSrc;
  654. xTmp = xAccum + xFrac;
  655. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  656. *pjDst++ = jSrc0;
  657. xAccum = xTmp;
  658. case 3:
  659. jSrc0 = *pjSrc;
  660. xTmp = xAccum + xFrac;
  661. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  662. *pjDst++ = jSrc0;
  663. xAccum = xTmp;
  664. }
  665. pjDstEnd = pjDst + WidthXAln;
  666. while (pjDst != pjDstEnd)
  667. {
  668. jSrc0 = *pjSrc;
  669. xTmp = xAccum + xFrac;
  670. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  671. jSrc1 = *pjSrc;
  672. xAccum = xTmp + xFrac;
  673. pjSrc = pjSrc + xInt + (xAccum < xTmp);
  674. jSrc2 = *pjSrc;
  675. xTmp = xAccum + xFrac;
  676. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  677. jSrc3 = *pjSrc;
  678. xAccum = xTmp + xFrac;
  679. pjSrc = pjSrc + xInt + (xAccum < xTmp);
  680. ulDst = (jSrc3 << 24) | (jSrc2 << 16) | (jSrc1 << 8) | jSrc0;
  681. *(PULONG)pjDst = ulDst;
  682. pjDst += 4;
  683. }
  684. switch (EndAln) {
  685. case 3:
  686. jSrc0 = *pjSrc;
  687. xTmp = xAccum + xFrac;
  688. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  689. *pjDst++ = jSrc0;
  690. xAccum = xTmp;
  691. case 2:
  692. jSrc0 = *pjSrc;
  693. xTmp = xAccum + xFrac;
  694. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  695. *pjDst++ = jSrc0;
  696. xAccum = xTmp;
  697. case 1:
  698. jSrc0 = *pjSrc;
  699. xTmp = xAccum + xFrac;
  700. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  701. *pjDst++ = jSrc0;
  702. }
  703. pjSrcScan += yInt;
  704. if (yTmp < yAccum)
  705. {
  706. pjSrcScan += pStrBlt->lDeltaSrc;
  707. }
  708. yAccum = yTmp;
  709. pjDst += lDstStride;
  710. } while (--yCount);
  711. }
  712. #endif
  713. #endif
  714. /******************************Public*Routine******************************\
  715. *
  716. * Routine Name
  717. *
  718. * vDirectStretch8Narrow
  719. *
  720. * Routine Description:
  721. *
  722. * Stretch blt 8->8 when the width is 7 or less
  723. *
  724. * Arguments:
  725. *
  726. * pStrBlt - contains all params for blt
  727. *
  728. * Return Value:
  729. *
  730. * VOID
  731. *
  732. \**************************************************************************/
  733. VOID
  734. vDirectStretch8Narrow(
  735. PSTR_BLT pStrBlt
  736. )
  737. {
  738. LONG xDst = pStrBlt->XDstStart;
  739. LONG xSrc = pStrBlt->XSrcStart;
  740. PBYTE pjSrcScan = pStrBlt->pjSrcScan + xSrc;
  741. PBYTE pjSrc;
  742. PBYTE pjDst = pStrBlt->pjDstScan + xDst;
  743. PBYTE pjDstEnd;
  744. LONG yCount = pStrBlt->YDstCount;
  745. LONG WidthX = pStrBlt->XDstEnd - xDst;
  746. ULONG ulDst;
  747. ULONG xAccum;
  748. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  749. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  750. ULONG xTmp;
  751. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  752. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  753. LONG yInt = 0;
  754. ULONG yTmp;
  755. LONG lDstStride = pStrBlt->lDeltaDst - WidthX;
  756. if (yCount <= 0)
  757. {
  758. return;
  759. }
  760. yInt = pStrBlt->lDeltaSrc * (LONG)pStrBlt->ulYDstToSrcIntCeil;
  761. //
  762. // Narrow blt
  763. //
  764. do {
  765. ULONG yTmp = yAccum + yFrac;
  766. BYTE jSrc0;
  767. PBYTE pjDstEndNarrow = pjDst + WidthX;
  768. pjSrc = pjSrcScan;
  769. xAccum = pStrBlt->ulXFracAccumulator;
  770. do {
  771. jSrc0 = *pjSrc;
  772. xTmp = xAccum + xFrac;
  773. pjSrc = pjSrc + xInt + (xTmp < xAccum);
  774. *pjDst++ = jSrc0;
  775. xAccum = xTmp;
  776. } while (pjDst != pjDstEndNarrow);
  777. pjSrcScan += yInt;
  778. if (yTmp < yAccum)
  779. {
  780. pjSrcScan += pStrBlt->lDeltaSrc;
  781. }
  782. yAccum = yTmp;
  783. pjDst += lDstStride;
  784. } while (--yCount);
  785. }
  786. /******************************Public*Routine******************************\
  787. *
  788. * Routine Name
  789. *
  790. * vDirectStretch16
  791. *
  792. * Routine Description:
  793. *
  794. * Stretch blt 16->16
  795. *
  796. * Arguments:
  797. *
  798. * pStrBlt - contains all params for blt
  799. *
  800. * Return Value:
  801. *
  802. * VOID
  803. *
  804. \**************************************************************************/
  805. VOID
  806. vDirectStretch16(
  807. PSTR_BLT pStrBlt
  808. )
  809. {
  810. LONG xDst = pStrBlt->XDstStart;
  811. LONG xSrc = pStrBlt->XSrcStart;
  812. PUSHORT pusSrcScan = (PUSHORT)(pStrBlt->pjSrcScan) + xSrc;
  813. PUSHORT pusSrc;
  814. PUSHORT pusDst = (PUSHORT)(pStrBlt->pjDstScan) + xDst;
  815. PUSHORT pusDstEnd;
  816. LONG yCount = pStrBlt->YDstCount;
  817. ULONG StartAln = ((ULONG)(ULONG_PTR)pusDst & 0x02) >> 1;
  818. LONG WidthX = pStrBlt->XDstEnd - xDst;
  819. LONG WidthXAln;
  820. ULONG EndAln = ((ULONG)(ULONG_PTR)(pusDst + WidthX) & 0x02) >> 1;
  821. ULONG ulDst;
  822. BOOL bExpand = (pStrBlt->ulYDstToSrcIntCeil == 0);
  823. ULONG xAccum;
  824. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  825. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  826. ULONG xTmp;
  827. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  828. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  829. LONG yInt = 0;
  830. ULONG yTmp;
  831. LONG lDstStride = pStrBlt->lDeltaDst - 2*WidthX;
  832. WidthXAln = WidthX - EndAln - StartAln;
  833. if (yCount <= 0)
  834. {
  835. return;
  836. }
  837. //
  838. // if this is a shrinking blt, calc src scan line stride
  839. //
  840. if (!bExpand)
  841. {
  842. yInt = pStrBlt->lDeltaSrc * (LONG)pStrBlt->ulYDstToSrcIntCeil;
  843. }
  844. //
  845. // Loop stretching each scan line
  846. //
  847. do {
  848. USHORT usSrc0,usSrc1;
  849. ULONG yTmp = yAccum + yFrac;
  850. pusSrc = pusSrcScan;
  851. xAccum = pStrBlt->ulXFracAccumulator;
  852. //
  853. // a single src scan line is being written
  854. //
  855. if (StartAln)
  856. {
  857. usSrc0 = *pusSrc;
  858. xTmp = xAccum + xFrac;
  859. pusSrc = pusSrc + xInt + (xTmp < xAccum);
  860. *pusDst++ = usSrc0;
  861. xAccum = xTmp;
  862. }
  863. pusDstEnd = pusDst + WidthXAln;
  864. while (pusDst != pusDstEnd)
  865. {
  866. usSrc0 = *pusSrc;
  867. xTmp = xAccum + xFrac;
  868. pusSrc = pusSrc + xInt + (xTmp < xAccum);
  869. usSrc1 = *pusSrc;
  870. xAccum = xTmp + xFrac;
  871. pusSrc = pusSrc + xInt + (xAccum < xTmp);
  872. ulDst = (ULONG)((usSrc1 << 16) | usSrc0);
  873. *(PULONG)pusDst = ulDst;
  874. pusDst+=2;
  875. }
  876. if (EndAln)
  877. {
  878. usSrc0 = *pusSrc;
  879. xTmp = xAccum + xFrac;
  880. pusSrc = pusSrc + xInt + (xTmp < xAccum);
  881. *pusDst++ = usSrc0;
  882. }
  883. pusSrcScan = (PUSHORT)((PBYTE)pusSrcScan + yInt);
  884. if (yTmp < yAccum)
  885. {
  886. pusSrcScan = (PUSHORT)((PBYTE)pusSrcScan + pStrBlt->lDeltaSrc);
  887. }
  888. yAccum = yTmp;
  889. pusDst = (PUSHORT)((PBYTE)pusDst + lDstStride);
  890. } while (--yCount);
  891. }
  892. /******************************Public*Routine******************************\
  893. *
  894. * Routine Name
  895. *
  896. * vDirectStretch32
  897. *
  898. * Routine Description:
  899. *
  900. * Stretch blt 32->32
  901. *
  902. * Arguments:
  903. *
  904. * pStrBlt - contains all params for blt
  905. *
  906. * Return Value:
  907. *
  908. * VOID
  909. *
  910. \**************************************************************************/
  911. VOID
  912. vDirectStretch32(
  913. PSTR_BLT pStrBlt
  914. )
  915. {
  916. LONG xDst = pStrBlt->XDstStart;
  917. LONG xSrc = pStrBlt->XSrcStart;
  918. PULONG pulSrcScan = (PULONG)(pStrBlt->pjSrcScan) + xSrc;
  919. PULONG pulSrc;
  920. PULONG pulDst = (PULONG)(pStrBlt->pjDstScan) + xDst;
  921. PULONG pulDstEnd;
  922. LONG yCount = pStrBlt->YDstCount;
  923. LONG WidthX = pStrBlt->XDstEnd - xDst;
  924. ULONG ulDst;
  925. BOOL bExpand = (pStrBlt->ulYDstToSrcIntCeil == 0);
  926. ULONG xAccum;
  927. ULONG xInt = pStrBlt->ulXDstToSrcIntCeil;
  928. ULONG xFrac = pStrBlt->ulXDstToSrcFracCeil;
  929. ULONG xTmp;
  930. ULONG yAccum = pStrBlt->ulYFracAccumulator;
  931. ULONG yFrac = pStrBlt->ulYDstToSrcFracCeil;
  932. LONG yInt = 0;
  933. ULONG yTmp;
  934. LONG lDstStride = pStrBlt->lDeltaDst - 4*WidthX;
  935. if (yCount <= 0)
  936. {
  937. return;
  938. }
  939. //
  940. // if this is a shrinking blt, calc src scan line stride
  941. //
  942. if (!bExpand)
  943. {
  944. yInt = pStrBlt->lDeltaSrc * (LONG)pStrBlt->ulYDstToSrcIntCeil;
  945. }
  946. //
  947. // general
  948. //
  949. do {
  950. ULONG ulSrc;
  951. ULONG yTmp = yAccum + yFrac;
  952. pulSrc = pulSrcScan;
  953. xAccum = pStrBlt->ulXFracAccumulator;
  954. //
  955. // a single src scan line is being written
  956. //
  957. pulDstEnd = pulDst + WidthX;
  958. while (pulDst != pulDstEnd)
  959. {
  960. ulSrc = *pulSrc;
  961. xTmp = xAccum + xFrac;
  962. pulSrc = pulSrc + xInt + (xTmp < xAccum);
  963. *(PULONG)pulDst = ulSrc;
  964. pulDst++;
  965. xAccum = xTmp;
  966. }
  967. pulSrcScan = (PULONG)((PBYTE)pulSrcScan + yInt);
  968. if (yTmp < yAccum)
  969. {
  970. pulSrcScan = (PULONG)((PBYTE)pulSrcScan + pStrBlt->lDeltaSrc);
  971. }
  972. yAccum = yTmp;
  973. pulDst = (PULONG)((PBYTE)pulDst + lDstStride);
  974. } while (--yCount);
  975. }
  976. VOID vDirectStretchError(
  977. PSTR_BLT pstr
  978. )
  979. {
  980. #ifdef DBG_STRDIR
  981. DbgPrint("Illegal stretch blt acceleration called\n");
  982. #endif
  983. }