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.

2037 lines
55 KiB

  1. /*****************************************************************************
  2. *
  3. * bitmaps - Entry points for Win32 to Win 16 converter
  4. *
  5. * History:
  6. * Sep 1992 -by- Hock San Lee [hockl]
  7. * Big rewrite.
  8. *
  9. * Copyright 1991 Microsoft Corp
  10. *****************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. HDC hdcMakeCompatibleDC(LPXFORM lpxform);
  14. HBITMAP CreateMonoDib(LPBITMAPINFO pbmi, CONST BYTE * pjBits, UINT iUsage);
  15. BOOL bEmitBitmap(PLOCALDC pLocalDC, HBITMAP hbm,
  16. LONG xDst, LONG yDst, LONG cxDst, LONG cyDst,
  17. LONG xSrc, LONG ySrc, LONG cxSrc, LONG cySrc, DWORD rop);
  18. BOOL WINAPI DoMakeBitmapBottomUp
  19. (
  20. PBITMAPINFO lpBitmapInfo,
  21. DWORD cbBitmapInfo,
  22. LPBYTE lpBits,
  23. DWORD cbBits
  24. );
  25. #define ABS(A) ((A) < 0 ? (-(A)) : (A))
  26. /****************************** Internal Function **************************\
  27. * GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo)
  28. *
  29. * Returns the number of bytes in the color table for the giving info header
  30. *
  31. \***************************************************************************/
  32. WORD GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo)
  33. {
  34. PUTS("GetSizeOfColorTable\n");
  35. ASSERTGDI(!((ULONG_PTR) lpDIBInfo & 0x3), "GetSizeOfColorTable: dword alignment error\n");
  36. if (lpDIBInfo->biBitCount == 16 || lpDIBInfo->biBitCount == 32)
  37. return(3 * sizeof(DWORD));
  38. if (lpDIBInfo->biClrUsed)
  39. return((WORD)lpDIBInfo->biClrUsed * (WORD)sizeof(RGBQUAD));
  40. if (lpDIBInfo->biBitCount < 16)
  41. return((1 << lpDIBInfo->biBitCount) * sizeof(RGBQUAD));
  42. else
  43. return(0);
  44. }
  45. BOOL APIENTRY DoStretchBltAlt
  46. (
  47. PLOCALDC pLocalDC,
  48. LONG xDst,
  49. LONG yDst,
  50. LONG cxDst,
  51. LONG cyDst,
  52. DWORD rop,
  53. LONG xSrc,
  54. LONG ySrc,
  55. LONG cxSrc,
  56. LONG cySrc,
  57. HDC hdcSrc,
  58. HBITMAP hbmSrc,
  59. PXFORM pxformSrc
  60. );
  61. BOOL APIENTRY DoRotatedStretchBlt
  62. (
  63. PLOCALDC pLocalDC,
  64. LONG xDst,
  65. LONG yDst,
  66. LONG cxDst,
  67. LONG cyDst,
  68. DWORD rop,
  69. LONG xSrc,
  70. LONG ySrc,
  71. LONG cxSrc,
  72. LONG cySrc,
  73. PXFORM pxformSrc,
  74. DWORD iUsageSrc,
  75. PBITMAPINFO lpBitmapInfo,
  76. DWORD cbBitmapInfo,
  77. LPBYTE lpBits
  78. );
  79. BOOL APIENTRY DoMaskBltNoSrc
  80. (
  81. PLOCALDC pLocalDC,
  82. LONG xDst,
  83. LONG yDst,
  84. LONG cxDst,
  85. LONG cyDst,
  86. DWORD rop4,
  87. PXFORM pxformSrc,
  88. LONG xMask,
  89. LONG yMask,
  90. DWORD iUsageMask,
  91. PBITMAPINFO lpBitmapInfoMask,
  92. DWORD cbBitmapInfoMask,
  93. LPBYTE lpBitsMask,
  94. DWORD cbBitsMask
  95. );
  96. /***************************************************************************
  97. * SetDIBitsToDevice - Win32 to Win16 Metafile Converter Entry Point
  98. *
  99. * CR2: Notes...
  100. * The xDib, yDib, cxDib, & cyDib are in device units. These must be
  101. * converted to logical units for the stretchblt.
  102. **************************************************************************/
  103. BOOL APIENTRY DoSetDIBitsToDevice
  104. (
  105. PLOCALDC pLocalDC,
  106. LONG xDst,
  107. LONG yDst,
  108. LONG xDib,
  109. LONG yDib,
  110. LONG cxDib,
  111. LONG cyDib,
  112. DWORD iUsage,
  113. DWORD iStartScan,
  114. DWORD cScans,
  115. LPBITMAPINFO lpBitmapInfo,
  116. DWORD cbBitmapInfo,
  117. LPBYTE lpBits,
  118. DWORD cbBits
  119. )
  120. {
  121. BOOL b ;
  122. LPBITMAPINFO pbmi;
  123. POINTL ptlDst ;
  124. RECTL rclDst ;
  125. b = FALSE;
  126. if (!cbBitmapInfo)
  127. return(FALSE);
  128. // Adjust the height of the bitmap we're going to Blt.
  129. pbmi = (LPBITMAPINFO) LocalAlloc(LMEM_FIXED, cbBitmapInfo);
  130. if (pbmi == (LPBITMAPINFO) NULL)
  131. goto dsdbd_exit;
  132. RtlCopyMemory(pbmi, lpBitmapInfo, cbBitmapInfo);
  133. pbmi->bmiHeader.biHeight = cScans;
  134. pbmi->bmiHeader.biSizeImage = cbBits;
  135. // We will convert it into a StretchBlt call. But first we have to
  136. // transform the destination rectangle. In SetDIBitsToDevice, the destination
  137. // rectangle is in device units but in StretchBlt, it is in logical units.
  138. // Transform the destination origin to the device units on the original device.
  139. ptlDst.x = xDst;
  140. ptlDst.y = yDst;
  141. if (!bXformRWorldToRDev(pLocalDC, &ptlDst, 1))
  142. goto dsdbd_exit;
  143. // Transform the destination rectangle to record time world coordinates.
  144. rclDst.left = ptlDst.x;
  145. rclDst.top = ptlDst.y;
  146. rclDst.right = ptlDst.x + cxDib;
  147. rclDst.bottom = ptlDst.y + cyDib;
  148. if (!bXformRDevToRWorld(pLocalDC, (PPOINTL) &rclDst, 2))
  149. goto dsdbd_exit;
  150. b = DoStretchBlt
  151. (
  152. pLocalDC,
  153. rclDst.left,
  154. rclDst.top,
  155. rclDst.right - rclDst.left,
  156. rclDst.bottom - rclDst.top,
  157. SRCCOPY,
  158. xDib,
  159. // dib to bitmap units
  160. ABS(pbmi->bmiHeader.biHeight) - yDib - cyDib + (LONG) iStartScan,
  161. cxDib,
  162. cyDib,
  163. &xformIdentity, // source is in device units
  164. iUsage,
  165. pbmi,
  166. cbBitmapInfo,
  167. lpBits,
  168. cbBits
  169. );
  170. dsdbd_exit:
  171. if (pbmi)
  172. LocalFree(pbmi);
  173. return(b);
  174. }
  175. /***************************************************************************
  176. * StretchDIBits - Win32 to Win16 Metafile Converter Entry Point
  177. **************************************************************************/
  178. BOOL APIENTRY DoStretchDIBits
  179. (
  180. PLOCALDC pLocalDC,
  181. LONG xDst,
  182. LONG yDst,
  183. LONG cxDst,
  184. LONG cyDst,
  185. DWORD rop,
  186. LONG xDib,
  187. LONG yDib,
  188. LONG cxDib,
  189. LONG cyDib,
  190. DWORD iUsage,
  191. LPBITMAPINFO lpBitmapInfo,
  192. DWORD cbBitmapInfo,
  193. LPBYTE lpBits,
  194. DWORD cbBits
  195. )
  196. {
  197. BOOL b ;
  198. b = DoStretchBlt
  199. (
  200. pLocalDC,
  201. xDst,
  202. yDst,
  203. cxDst,
  204. cyDst,
  205. rop,
  206. xDib,
  207. ISSOURCEINROP3(rop)
  208. // dib to bitmap units
  209. ? ABS(lpBitmapInfo->bmiHeader.biHeight) - yDib - cyDib
  210. : 0,
  211. cxDib,
  212. cyDib,
  213. &xformIdentity, // source is in device units
  214. iUsage,
  215. lpBitmapInfo,
  216. cbBitmapInfo,
  217. lpBits,
  218. cbBits
  219. );
  220. return(b) ;
  221. }
  222. /***************************************************************************
  223. * StretchBltAlt
  224. **************************************************************************/
  225. BOOL APIENTRY DoStretchBltAlt
  226. (
  227. PLOCALDC pLocalDC,
  228. LONG xDst,
  229. LONG yDst,
  230. LONG cxDst,
  231. LONG cyDst,
  232. DWORD rop,
  233. LONG xSrc,
  234. LONG ySrc,
  235. LONG cxSrc,
  236. LONG cySrc,
  237. HDC hdcSrc,
  238. HBITMAP hbmSrc,
  239. PXFORM pxformSrc
  240. )
  241. {
  242. BITMAPINFOHEADER bmih;
  243. DWORD cbBitmapInfo;
  244. LPBITMAPINFO lpBitmapInfo;
  245. DWORD cbBits;
  246. LPBYTE lpBits;
  247. BOOL b;
  248. b = FALSE;
  249. // A NOOP ROP do nothing
  250. if (rop == 0x00AA0029)
  251. {
  252. return TRUE;
  253. }
  254. lpBitmapInfo = (LPBITMAPINFO) NULL;
  255. lpBits = (LPBYTE) NULL;
  256. if (!ISSOURCEINROP3(rop))
  257. return
  258. (
  259. DoStretchBlt
  260. (
  261. pLocalDC,
  262. xDst,
  263. yDst,
  264. cxDst,
  265. cyDst,
  266. rop,
  267. 0,
  268. 0,
  269. 0,
  270. 0,
  271. (PXFORM) NULL,
  272. 0,
  273. (PBITMAPINFO) NULL,
  274. 0,
  275. (LPBYTE) NULL,
  276. 0
  277. )
  278. );
  279. bmih.biSize = sizeof(BITMAPINFOHEADER);
  280. bmih.biBitCount = 0; // don't fill in color table
  281. bmih.biCompression = BI_RGB;
  282. if (!GetDIBits(hdcSrc,
  283. hbmSrc,
  284. 0,
  285. 0,
  286. (LPBYTE) NULL,
  287. (LPBITMAPINFO) &bmih,
  288. DIB_RGB_COLORS))
  289. goto dsba_exit;
  290. // Compute size of the bitmap info with color table.
  291. cbBitmapInfo= sizeof(BITMAPINFOHEADER);
  292. if (bmih.biBitCount == 16 || bmih.biBitCount == 32)
  293. cbBitmapInfo += 3 * sizeof(DWORD);
  294. else if (bmih.biClrUsed)
  295. cbBitmapInfo += bmih.biClrUsed * sizeof(RGBQUAD);
  296. else if (bmih.biBitCount < 16)
  297. cbBitmapInfo += (1 << bmih.biBitCount) * sizeof(RGBQUAD);
  298. // Compute size of the buffer required for bitmap bits.
  299. if (bmih.biSizeImage)
  300. cbBits = bmih.biSizeImage;
  301. else
  302. cbBits = CJSCAN(bmih.biWidth,bmih.biPlanes, bmih.biBitCount) *
  303. ABS(bmih.biHeight);
  304. lpBitmapInfo = (LPBITMAPINFO) LocalAlloc(LMEM_FIXED, cbBitmapInfo);
  305. if (lpBitmapInfo == (LPBITMAPINFO) NULL)
  306. goto dsba_exit;
  307. lpBits = (LPBYTE) LocalAlloc(LMEM_FIXED, cbBits);
  308. if (lpBits == (LPBYTE) NULL)
  309. goto dsba_exit;
  310. // Get bitmap info and bits.
  311. *(PBITMAPINFOHEADER) lpBitmapInfo = bmih;
  312. if (!GetDIBits(hdcSrc,
  313. hbmSrc,
  314. 0,
  315. (UINT) ABS(bmih.biHeight),
  316. lpBits,
  317. lpBitmapInfo,
  318. DIB_RGB_COLORS))
  319. goto dsba_exit;
  320. // Call DoStretchBlt.
  321. b = DoStretchBlt
  322. (
  323. pLocalDC,
  324. xDst,
  325. yDst,
  326. cxDst,
  327. cyDst,
  328. rop,
  329. xSrc,
  330. ySrc,
  331. cxSrc,
  332. cySrc,
  333. pxformSrc,
  334. DIB_RGB_COLORS,
  335. lpBitmapInfo,
  336. cbBitmapInfo,
  337. lpBits,
  338. cbBits
  339. );
  340. dsba_exit:
  341. if (lpBitmapInfo)
  342. LocalFree((HANDLE) lpBitmapInfo);
  343. if (lpBits)
  344. LocalFree((HANDLE) lpBits);
  345. return(b);
  346. }
  347. /***************************************************************************
  348. * StretchBlt - Win32 to Win16 Metafile Converter Entry Point
  349. **************************************************************************/
  350. BOOL APIENTRY DoStretchBlt
  351. (
  352. PLOCALDC pLocalDC,
  353. LONG xDst,
  354. LONG yDst,
  355. LONG cxDst,
  356. LONG cyDst,
  357. DWORD rop,
  358. LONG xSrc,
  359. LONG ySrc,
  360. LONG cxSrc,
  361. LONG cySrc,
  362. PXFORM pxformSrc,
  363. DWORD iUsageSrc,
  364. PBITMAPINFO lpBitmapInfo,
  365. DWORD cbBitmapInfo,
  366. LPBYTE lpBits,
  367. DWORD cbBits
  368. )
  369. {
  370. BOOL b;
  371. RECTL rclDst,
  372. rclSrc;
  373. // A NOOP ROP do nothing
  374. if (rop == 0x00AA0029)
  375. {
  376. return TRUE;
  377. }
  378. // Handle strange destination transform separately.
  379. if (pLocalDC->flags & STRANGE_XFORM)
  380. return
  381. (
  382. DoRotatedStretchBlt
  383. (
  384. pLocalDC,
  385. xDst,
  386. yDst,
  387. cxDst,
  388. cyDst,
  389. rop,
  390. xSrc,
  391. ySrc,
  392. cxSrc,
  393. cySrc,
  394. pxformSrc,
  395. iUsageSrc,
  396. lpBitmapInfo,
  397. cbBitmapInfo,
  398. lpBits
  399. )
  400. );
  401. if (pLocalDC->iXORPass != NOTXORPASS)
  402. {
  403. if (rop == SRCCOPY)
  404. {
  405. rop = SRCINVERT;
  406. }
  407. else if (rop == PATCOPY)
  408. {
  409. rop = PATINVERT;
  410. }
  411. else
  412. {
  413. pLocalDC->flags |= ERR_XORCLIPPATH;
  414. return FALSE;
  415. }
  416. }
  417. // Do stretchblt with a simple destination transform.
  418. // Translate the dest rectangle
  419. rclDst.left = xDst;
  420. rclDst.top = yDst;
  421. rclDst.right = xDst + cxDst;
  422. rclDst.bottom = yDst + cyDst;
  423. if (!bXformRWorldToPPage(pLocalDC, (PPOINTL) &rclDst, 2))
  424. return(FALSE);
  425. // Handle stretchblt without source
  426. if (!ISSOURCEINROP3(rop))
  427. {
  428. // Emit the Win16 metafile record.
  429. b = bEmitWin16BitBltNoSrc(pLocalDC,
  430. (SHORT) rclDst.left,
  431. (SHORT) rclDst.top,
  432. (SHORT) (rclDst.right - rclDst.left),
  433. (SHORT) (rclDst.bottom - rclDst.top),
  434. rop);
  435. return(b);
  436. }
  437. // Handle stretchblt with source
  438. // Note: Both Win32 and Win16 DIB Bitmaps are DWord aligned.
  439. // Make sure the source xform is valid.
  440. // The source is not allowed to have a rotation or shear.
  441. if (bRotationTest(pxformSrc) == TRUE)
  442. {
  443. RIPS("MF3216: DoStretchBlt - Invalid source xform\n");
  444. SetLastError(ERROR_INVALID_DATA);
  445. return(FALSE);
  446. }
  447. // Translate the source rectangle. Win3.1 assumes that the
  448. // source rectangle is in bitmap units.
  449. rclSrc.left = xSrc;
  450. rclSrc.top = ySrc;
  451. rclSrc.right = xSrc + cxSrc;
  452. rclSrc.bottom = ySrc + cySrc;
  453. if (!bXformWorkhorse((PPOINTL) &rclSrc, 2, pxformSrc))
  454. return(FALSE);
  455. // The win3.1 StretchBlt metafile record only accepts win3.1 standard
  456. // bitmap with DIB_RGB_COLORS usage. If this is not the case, we have
  457. // to convert it to a standard bitmap.
  458. if (iUsageSrc != DIB_RGB_COLORS
  459. || lpBitmapInfo->bmiHeader.biPlanes != 1
  460. || !(lpBitmapInfo->bmiHeader.biBitCount == 1
  461. || lpBitmapInfo->bmiHeader.biBitCount == 4
  462. || lpBitmapInfo->bmiHeader.biBitCount == 8
  463. || lpBitmapInfo->bmiHeader.biBitCount == 24)
  464. || lpBitmapInfo->bmiHeader.biCompression != BI_RGB )
  465. {
  466. HBITMAP hbmSrc;
  467. DWORD fdwInit;
  468. b = FALSE;
  469. hbmSrc = (HBITMAP) 0;
  470. if( ( lpBitmapInfo->bmiHeader.biCompression == BI_RGB ) ||
  471. ( lpBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS ) )
  472. {
  473. fdwInit = CBM_INIT | CBM_CREATEDIB;
  474. }
  475. else
  476. {
  477. fdwInit = CBM_INIT;
  478. }
  479. // Create the source bitmap.
  480. // Use the helper DC in CreateDIBitmap so that the colors get bind correctly.
  481. if (!(hbmSrc = CreateDIBitmap(
  482. pLocalDC->hdcHelper,
  483. (LPBITMAPINFOHEADER) lpBitmapInfo,
  484. fdwInit,
  485. lpBits,
  486. lpBitmapInfo,
  487. (UINT) iUsageSrc)))
  488. goto dsb_internal_exit;
  489. // Emit the bitmap.
  490. b = bEmitBitmap(pLocalDC,
  491. hbmSrc,
  492. rclDst.left,
  493. rclDst.top,
  494. rclDst.right - rclDst.left,
  495. rclDst.bottom - rclDst.top,
  496. rclSrc.left,
  497. rclSrc.top,
  498. rclSrc.right - rclSrc.left,
  499. rclSrc.bottom - rclSrc.top,
  500. rop);
  501. dsb_internal_exit:
  502. if (hbmSrc)
  503. DeleteObject(hbmSrc);
  504. }
  505. else
  506. {
  507. // Win98 might have added a MAX_PATH in the EMR_STRETCHDIBits
  508. // We need to remove it because WMF don't support it
  509. cbBitmapInfo = lpBitmapInfo->bmiHeader.biSize + GetSizeOfColorTable(&(lpBitmapInfo->bmiHeader));
  510. DoMakeBitmapBottomUp(lpBitmapInfo, cbBitmapInfo, lpBits, cbBits);
  511. // Handle the standard formats.
  512. // Emit a Win16 metafile record.
  513. b = bEmitWin16StretchBlt(pLocalDC,
  514. (SHORT) rclDst.left,
  515. (SHORT) rclDst.top,
  516. (SHORT) (rclDst.right - rclDst.left),
  517. (SHORT) (rclDst.bottom - rclDst.top),
  518. (SHORT) rclSrc.left,
  519. (SHORT) rclSrc.top,
  520. (SHORT) (rclSrc.right - rclSrc.left),
  521. (SHORT) (rclSrc.bottom - rclSrc.top),
  522. rop,
  523. lpBitmapInfo,
  524. cbBitmapInfo,
  525. lpBits,
  526. cbBits);
  527. }
  528. return(b);
  529. }
  530. BOOL APIENTRY DoRotatedStretchBlt
  531. (
  532. PLOCALDC pLocalDC,
  533. LONG xDst,
  534. LONG yDst,
  535. LONG cxDst,
  536. LONG cyDst,
  537. DWORD rop,
  538. LONG xSrc,
  539. LONG ySrc,
  540. LONG cxSrc,
  541. LONG cySrc,
  542. PXFORM pxformSrc,
  543. DWORD iUsageSrc,
  544. PBITMAPINFO lpBitmapInfo,
  545. DWORD cbBitmapInfo,
  546. LPBYTE lpBits
  547. )
  548. {
  549. BOOL b;
  550. POINTL aptlDst[4];
  551. RECTL rclBndDst;
  552. HDC hdcShadow, hdcSrc;
  553. HBITMAP hbmShadow, hbmShadowOld, hbmSrc, hbmSrcOld;
  554. PBITMAPINFO pbmiShadow;
  555. b = FALSE;
  556. if (pLocalDC->iXORPass != NOTXORPASS)
  557. {
  558. if (rop == SRCCOPY)
  559. {
  560. rop = SRCINVERT;
  561. }
  562. else if (rop == PATCOPY)
  563. {
  564. rop = PATINVERT;
  565. }
  566. else
  567. {
  568. pLocalDC->flags |= ERR_XORCLIPPATH;
  569. return FALSE;
  570. }
  571. }
  572. hdcShadow = hdcSrc = (HDC) 0;
  573. hbmShadow = hbmShadowOld = hbmSrc = hbmSrcOld = (HBITMAP) 0;
  574. pbmiShadow = (PBITMAPINFO) NULL;
  575. // First, compute the bounds of the destination rectangle.
  576. aptlDst[0].x = xDst;
  577. aptlDst[0].y = yDst;
  578. aptlDst[1].x = xDst + cxDst;
  579. aptlDst[1].y = yDst;
  580. aptlDst[2].x = xDst + cxDst;
  581. aptlDst[2].y = yDst + cyDst;
  582. aptlDst[3].x = xDst;
  583. aptlDst[3].y = yDst + cyDst;
  584. if (!bXformRWorldToPPage(pLocalDC, aptlDst, 4))
  585. goto drsb_exit;
  586. rclBndDst.left = min(aptlDst[0].x,min(aptlDst[1].x,min(aptlDst[2].x,aptlDst[3].x)));
  587. rclBndDst.top = min(aptlDst[0].y,min(aptlDst[1].y,min(aptlDst[2].y,aptlDst[3].y)));
  588. rclBndDst.right = max(aptlDst[0].x,max(aptlDst[1].x,max(aptlDst[2].x,aptlDst[3].x)));
  589. rclBndDst.bottom = max(aptlDst[0].y,max(aptlDst[1].y,max(aptlDst[2].y,aptlDst[3].y)));
  590. // Prepare the source if any.
  591. if (ISSOURCEINROP3(rop))
  592. {
  593. // Create a compatible shadow DC with the destination transform.
  594. if (!(hdcShadow = hdcMakeCompatibleDC(&pLocalDC->xformRWorldToPPage)))
  595. goto drsb_exit;
  596. // Create a shadow bitmap the size of the destination rectangle bounds.
  597. // Use the helper DC in CreateDIBitmap so that the colors get bind correctly.
  598. pbmiShadow = (PBITMAPINFO) LocalAlloc(LMEM_FIXED, cbBitmapInfo);
  599. if (pbmiShadow == (PBITMAPINFO) NULL)
  600. goto drsb_exit;
  601. RtlCopyMemory(pbmiShadow, lpBitmapInfo, cbBitmapInfo);
  602. pbmiShadow->bmiHeader.biWidth = rclBndDst.right - rclBndDst.left;
  603. pbmiShadow->bmiHeader.biHeight = rclBndDst.bottom - rclBndDst.top;
  604. pbmiShadow->bmiHeader.biSizeImage = 0;
  605. if (!(hbmShadow = CreateDIBitmap(pLocalDC->hdcHelper,
  606. (LPBITMAPINFOHEADER) pbmiShadow, CBM_CREATEDIB,
  607. (LPBYTE) NULL, pbmiShadow, iUsageSrc)))
  608. goto drsb_exit;
  609. // Select the bitmap.
  610. if (!(hbmShadowOld = (HBITMAP) SelectObject(hdcShadow, hbmShadow)))
  611. goto drsb_exit;
  612. // Create a compatible source DC with the given source transform.
  613. if (!(hdcSrc = hdcMakeCompatibleDC(pxformSrc)))
  614. goto drsb_exit;
  615. // Create the source bitmap.
  616. // Use the helper DC in CreateDIBitmap so that the colors get bind correctly.
  617. if (!(hbmSrc = CreateDIBitmap(pLocalDC->hdcHelper,
  618. (LPBITMAPINFOHEADER) lpBitmapInfo,
  619. CBM_INIT | CBM_CREATEDIB,
  620. lpBits,
  621. (LPBITMAPINFO) lpBitmapInfo,
  622. (UINT) iUsageSrc)))
  623. goto drsb_exit;
  624. // Select the bitmap.
  625. if (!(hbmSrcOld = (HBITMAP) SelectObject(hdcSrc, hbmSrc)))
  626. goto drsb_exit;
  627. // Set up the viewport origin of the shadow DC so that the destination
  628. // rectangle will map into coordinates within the shadow bitmap.
  629. OffsetViewportOrgEx(hdcShadow, (int) -rclBndDst.left,
  630. (int) -rclBndDst.top, (LPPOINT) NULL);
  631. // Stretch the source to the shadow.
  632. if (!StretchBlt
  633. (
  634. hdcShadow,
  635. (int) xDst,
  636. (int) yDst,
  637. (int) cxDst,
  638. (int) cyDst,
  639. hdcSrc,
  640. (int) xSrc,
  641. (int) ySrc,
  642. (int) cxSrc,
  643. (int) cySrc,
  644. SRCCOPY
  645. )
  646. )
  647. goto drsb_exit;
  648. // Deselect the shadow bitmap.
  649. if (!SelectObject(hdcShadow, hbmShadowOld))
  650. goto drsb_exit;
  651. }
  652. // Save the DC so that we can restore the clipping when we are done
  653. if (!DoSaveDC(pLocalDC))
  654. goto drsb_exit;
  655. // Set up the clipping rectangle on the destination.
  656. if (!DoClipRect(pLocalDC, xDst, yDst,
  657. xDst + cxDst, yDst + cyDst, EMR_INTERSECTCLIPRECT))
  658. {
  659. (void) DoRestoreDC(pLocalDC, -1);
  660. goto drsb_exit;
  661. }
  662. // Blt the shadow to the destination.
  663. // Emit a Win16 metafile record.
  664. if (ISSOURCEINROP3(rop))
  665. b = bEmitBitmap(pLocalDC,
  666. hbmShadow,
  667. rclBndDst.left,
  668. rclBndDst.top,
  669. rclBndDst.right - rclBndDst.left,
  670. rclBndDst.bottom - rclBndDst.top,
  671. 0,
  672. 0,
  673. rclBndDst.right - rclBndDst.left,
  674. rclBndDst.bottom - rclBndDst.top,
  675. rop);
  676. else
  677. b = bEmitWin16BitBltNoSrc(pLocalDC,
  678. (SHORT) rclBndDst.left,
  679. (SHORT) rclBndDst.top,
  680. (SHORT) (rclBndDst.right - rclBndDst.left),
  681. (SHORT) (rclBndDst.bottom - rclBndDst.top),
  682. rop);
  683. // Restore the clipping region.
  684. (void) DoRestoreDC(pLocalDC, -1);
  685. // Cleanup
  686. drsb_exit:
  687. if (hbmShadowOld)
  688. SelectObject(hdcShadow, hbmShadowOld);
  689. if (hbmShadow)
  690. DeleteObject(hbmShadow);
  691. if (hdcShadow)
  692. DeleteDC(hdcShadow);
  693. if (hbmSrcOld)
  694. SelectObject(hdcSrc, hbmSrcOld);
  695. if (hbmSrc)
  696. DeleteObject(hbmSrc);
  697. if (hdcSrc)
  698. DeleteDC(hdcSrc);
  699. if (pbmiShadow)
  700. LocalFree((HANDLE) pbmiShadow);
  701. return(b);
  702. }
  703. /*****************************************************************************
  704. * hdcMakeCompatibleDC
  705. * Create a compatible DC with the given transform.
  706. ****************************************************************************/
  707. HDC hdcMakeCompatibleDC(LPXFORM lpxform)
  708. {
  709. HDC hdc;
  710. hdc = CreateCompatibleDC((HDC) 0);
  711. if(hdc == 0)
  712. {
  713. RIPS("MF3216: hdcMakeCompatibleDC, CreateCompatibleDC failed\n");
  714. return (HDC)0;
  715. }
  716. // Must be in the advanced graphics mode to modify the world transform.
  717. SetGraphicsMode(hdc, GM_ADVANCED);
  718. // Set the transform.
  719. if (!SetWorldTransform(hdc, lpxform))
  720. {
  721. DeleteDC(hdc);
  722. RIPS("MF3216: hdcMakeCompatibleDC, SetWorldTransform failed\n");
  723. return((HDC) 0);
  724. }
  725. return(hdc);
  726. }
  727. /***************************************************************************
  728. * bEmitBitmap
  729. **************************************************************************/
  730. BOOL bEmitBitmap
  731. (
  732. PLOCALDC pLocalDC,
  733. HBITMAP hbm,
  734. LONG xDst,
  735. LONG yDst,
  736. LONG cxDst,
  737. LONG cyDst,
  738. LONG xSrc,
  739. LONG ySrc,
  740. LONG cxSrc,
  741. LONG cySrc,
  742. DWORD rop
  743. )
  744. {
  745. BITMAPINFOHEADER bmih;
  746. DWORD cbBitmapInfo;
  747. LPBITMAPINFO lpBitmapInfo;
  748. DWORD cbBits;
  749. LPBYTE lpBits;
  750. BOOL b;
  751. b = FALSE;
  752. lpBitmapInfo = (LPBITMAPINFO) NULL;
  753. lpBits = (LPBYTE) NULL;
  754. bmih.biSize = sizeof(BITMAPINFOHEADER);
  755. bmih.biBitCount = 0; // don't fill in color table
  756. bmih.biCompression = BI_RGB;
  757. if (!GetDIBits(pLocalDC->hdcHelper, hbm, 0, 0,
  758. (LPBYTE) NULL, (LPBITMAPINFO) &bmih, DIB_RGB_COLORS))
  759. goto eb_exit;
  760. // Compute size of the bitmap info with color table.
  761. cbBitmapInfo= sizeof(BITMAPINFOHEADER);
  762. if (bmih.biPlanes != 1 || bmih.biBitCount == 16 || bmih.biBitCount == 32)
  763. {
  764. bmih.biPlanes = 1;
  765. bmih.biBitCount = 24;
  766. bmih.biCompression = BI_RGB;
  767. bmih.biSizeImage = 0;
  768. bmih.biClrUsed = 0;
  769. bmih.biClrImportant = 0;
  770. }
  771. else if (bmih.biClrUsed)
  772. cbBitmapInfo += bmih.biClrUsed * sizeof(RGBQUAD);
  773. else if (bmih.biBitCount < 16)
  774. cbBitmapInfo += (1 << bmih.biBitCount) * sizeof(RGBQUAD);
  775. // Compute size of the buffer required for bitmap bits.
  776. if (bmih.biSizeImage)
  777. cbBits = bmih.biSizeImage;
  778. else
  779. cbBits = CJSCAN(bmih.biWidth,bmih.biPlanes, bmih.biBitCount) *
  780. ABS(bmih.biHeight);
  781. lpBitmapInfo = (LPBITMAPINFO) LocalAlloc(LMEM_FIXED, cbBitmapInfo);
  782. if (lpBitmapInfo == (LPBITMAPINFO) NULL)
  783. goto eb_exit;
  784. lpBits = (LPBYTE) LocalAlloc(LMEM_FIXED, cbBits);
  785. if (lpBits == (LPBYTE) NULL)
  786. goto eb_exit;
  787. // Get bitmap info and bits.
  788. *(PBITMAPINFOHEADER) lpBitmapInfo = bmih;
  789. if (!GetDIBits(pLocalDC->hdcHelper,
  790. hbm,
  791. 0,
  792. (UINT) ABS(bmih.biHeight),
  793. lpBits,
  794. lpBitmapInfo,
  795. DIB_RGB_COLORS))
  796. goto eb_exit;
  797. // Emit the metafile record.
  798. b = bEmitWin16StretchBlt(pLocalDC,
  799. (SHORT) xDst,
  800. (SHORT) yDst,
  801. (SHORT) cxDst,
  802. (SHORT) cyDst,
  803. (SHORT) xSrc,
  804. (SHORT) ySrc,
  805. (SHORT) cxSrc,
  806. (SHORT) cySrc,
  807. rop,
  808. lpBitmapInfo,
  809. cbBitmapInfo,
  810. lpBits,
  811. cbBits);
  812. eb_exit:
  813. if (lpBitmapInfo)
  814. LocalFree((HANDLE) lpBitmapInfo);
  815. if (lpBits)
  816. LocalFree((HANDLE) lpBits);
  817. return(b);
  818. }
  819. /***************************************************************************
  820. * MaskBlt - Win32 to Win16 Metafile Converter Entry Point
  821. **************************************************************************/
  822. BOOL APIENTRY DoMaskBlt
  823. (
  824. PLOCALDC pLocalDC,
  825. LONG xDst,
  826. LONG yDst,
  827. LONG cxDst,
  828. LONG cyDst,
  829. DWORD rop4,
  830. LONG xSrc,
  831. LONG ySrc,
  832. PXFORM pxformSrc,
  833. DWORD iUsageSrc,
  834. PBITMAPINFO lpBitmapInfoSrc,
  835. DWORD cbBitmapInfoSrc,
  836. LPBYTE lpBitsSrc,
  837. DWORD cbBitsSrc,
  838. LONG xMask,
  839. LONG yMask,
  840. DWORD iUsageMask,
  841. PBITMAPINFO lpBitmapInfoMask,
  842. DWORD cbBitmapInfoMask,
  843. LPBYTE lpBitsMask,
  844. DWORD cbBitsMask
  845. )
  846. {
  847. BOOL b;
  848. DWORD rop1;
  849. DWORD rop0;
  850. HDC hdcMask, hdcSrc;
  851. HBITMAP hbmMask, hbmMaskOld, hbmSrc, hbmSrcOld;
  852. RECTL rclMask;
  853. b = FALSE;
  854. hdcMask = hdcSrc = (HDC) 0;
  855. hbmMask = hbmMaskOld = hbmSrc = hbmSrcOld = (HBITMAP) 0;
  856. rop0 = rop4 >> 8; // rop for 0's
  857. rop1 = rop4 & 0xFF0000; // rop for 1's
  858. // If no mask is given, the mask is assumed to contain all 1's.
  859. // This is equivalent to a BitBlt using the low rop.
  860. if (!cbBitmapInfoMask)
  861. return
  862. (
  863. DoStretchBlt
  864. (
  865. pLocalDC,
  866. xDst,
  867. yDst,
  868. cxDst,
  869. cyDst,
  870. rop1,
  871. xSrc,
  872. ySrc,
  873. cxDst,
  874. cyDst,
  875. pxformSrc,
  876. iUsageSrc,
  877. lpBitmapInfoSrc,
  878. cbBitmapInfoSrc,
  879. lpBitsSrc,
  880. cbBitsSrc
  881. )
  882. );
  883. // Handle MaskBlt with no source bitmap.
  884. if (!ISSOURCEINROP3(rop4))
  885. return
  886. (
  887. DoMaskBltNoSrc
  888. (
  889. pLocalDC,
  890. xDst,
  891. yDst,
  892. cxDst,
  893. cyDst,
  894. rop4,
  895. pxformSrc,
  896. xMask,
  897. yMask,
  898. iUsageMask,
  899. lpBitmapInfoMask,
  900. cbBitmapInfoMask,
  901. lpBitsMask,
  902. cbBitsMask
  903. )
  904. );
  905. // Create a compatible mask DC.
  906. if (!(hdcMask = CreateCompatibleDC((HDC) 0)))
  907. goto dmb_exit;
  908. // Must be in the advanced graphics mode to modify the world transform.
  909. SetGraphicsMode(hdcMask, GM_ADVANCED);
  910. // Create the mask bitmap.
  911. // Make it as big as the source and initialize it.
  912. // Create the mask bitmap as big as the source bitmap.
  913. if (!(hbmMask = CreateBitmap((int) lpBitmapInfoSrc->bmiHeader.biWidth,
  914. (int) lpBitmapInfoSrc->bmiHeader.biHeight,
  915. 1, 1, (CONST VOID *) NULL)))
  916. goto dmb_exit;
  917. // Select the bitmap.
  918. if (!(hbmMaskOld = (HBITMAP) SelectObject(hdcMask, hbmMask)))
  919. goto dmb_exit;
  920. // Initialize the mask bitmap to 0's.
  921. if (!PatBlt(hdcMask,0,0,(int) lpBitmapInfoSrc->bmiHeader.biWidth,
  922. (int) lpBitmapInfoSrc->bmiHeader.biHeight,BLACKNESS))
  923. goto dmb_exit;
  924. // Compute the mask rectangle.
  925. // The mask bitmap is aligned against the source device rectangle.
  926. rclMask.left = xSrc;
  927. rclMask.top = ySrc;
  928. rclMask.right = xSrc + cxDst;
  929. rclMask.bottom = ySrc + cyDst;
  930. if (!bXformWorkhorse((PPOINTL) &rclMask, 2, pxformSrc))
  931. goto dmb_exit;
  932. if (rclMask.left > rclMask.right)
  933. rclMask.left = rclMask.right /* + 1 */;// align the mask against the left edge
  934. if (rclMask.top > rclMask.bottom)
  935. rclMask.top = rclMask.bottom /* + 1 */;// align the mask against the top edge
  936. // Set the mask bits.
  937. if (!StretchDIBits(hdcMask,
  938. (int) rclMask.left - xMask,
  939. (int) rclMask.top - yMask,
  940. (int) lpBitmapInfoMask->bmiHeader.biWidth,
  941. (int) lpBitmapInfoMask->bmiHeader.biHeight,
  942. (int) 0,
  943. (int) 0,
  944. (int) lpBitmapInfoMask->bmiHeader.biWidth,
  945. (int) lpBitmapInfoMask->bmiHeader.biHeight,
  946. (CONST VOID *) lpBitsMask,
  947. (LPBITMAPINFO) lpBitmapInfoMask,
  948. (UINT) iUsageMask,
  949. SRCCOPY))
  950. goto dmb_exit;
  951. // Set the source transform in the mask DC.
  952. if (!SetWorldTransform(hdcMask, pxformSrc))
  953. goto dmb_exit;
  954. // Create a compatible source DC with the given source transform.
  955. if (!(hdcSrc = hdcMakeCompatibleDC(pxformSrc)))
  956. goto dmb_exit;
  957. // Create the source bitmap.
  958. // We cannot use CBM_CREATEDIB option here because index 0 does not
  959. // neccesarily contain black and index 15 or 255 does not have to be white.
  960. // We need a compatible bitmap that contain the standard color table so
  961. // that we can perform the following rop operations to emulate the maskblt.
  962. // Gdi uses rgb colors to perform rop operations in dibs, not color indices!
  963. // The helper DC is needed to create the compatible format bitmap.
  964. if (!(hbmSrc = CreateDIBitmap(pLocalDC->hdcHelper,
  965. (LPBITMAPINFOHEADER) lpBitmapInfoSrc,
  966. CBM_INIT,
  967. lpBitsSrc,
  968. (LPBITMAPINFO) lpBitmapInfoSrc,
  969. (UINT) iUsageSrc)))
  970. goto dmb_exit;
  971. // Select the bitmap.
  972. if (!(hbmSrcOld = (HBITMAP) SelectObject(hdcSrc, hbmSrc)))
  973. goto dmb_exit;
  974. // We need to handle the low rop (mask bit 1) and high rop (mask bit 0)
  975. // separately. For each rop, we need to go through two passes.
  976. //
  977. // For the low rop (mask bit 1), we use the following rop table:
  978. //
  979. // P S D | R1 R2
  980. // ------+--------
  981. // 0 0 0 | 0 x
  982. // 0 0 1 | 1 x
  983. // 0 1 0 | x 0
  984. // 0 1 1 | x 1
  985. // 1 0 0 | 0 x
  986. // 1 0 1 | 1 x
  987. // 1 1 0 | x 0
  988. // 1 1 1 | x 1
  989. //
  990. // In the first pass, we AND the mask to the source bitmap to remove
  991. // the mask 0 bits. This is then used to get the result (R1) for the
  992. // bitblt involving source 1's.
  993. //
  994. // In the second pass, we OR the NOT of the mask to the source bitmap
  995. // to obtain the source 0 bits. This is then used to get the result (R2)
  996. // for the bitblt involving source 0's.
  997. // AND the mask to the source bitmap to remove the mask 0 bits.
  998. if (!BitBlt(hdcSrc,
  999. (int) xSrc, (int) ySrc,
  1000. (int) cxDst, (int) cyDst,
  1001. hdcMask,
  1002. (int) xSrc, (int) ySrc,
  1003. SRCAND))
  1004. goto dmb_exit;
  1005. // Get the result (R1) for the bits involving source 1's.
  1006. if (!DoStretchBltAlt
  1007. (
  1008. pLocalDC,
  1009. xDst,
  1010. yDst,
  1011. cxDst,
  1012. cyDst,
  1013. (rop1 & 0xCC0000) | 0x220000,
  1014. xSrc,
  1015. ySrc,
  1016. cxDst,
  1017. cyDst,
  1018. hdcSrc,
  1019. hbmSrc,
  1020. pxformSrc
  1021. )
  1022. )
  1023. goto dmb_exit;
  1024. // OR the NOT of the mask to the source bitmap to obtain the source 0 bits.
  1025. if (!BitBlt(hdcSrc,
  1026. (int) xSrc, (int) ySrc,
  1027. (int) cxDst, (int) cyDst,
  1028. hdcMask,
  1029. (int) xSrc, (int) ySrc,
  1030. MERGEPAINT))
  1031. goto dmb_exit;
  1032. // Get the result (R2) for the bitblt involving source 0's.
  1033. if (!DoStretchBltAlt
  1034. (
  1035. pLocalDC,
  1036. xDst,
  1037. yDst,
  1038. cxDst,
  1039. cyDst,
  1040. (rop1 & 0x330000) | 0x880000,
  1041. xSrc,
  1042. ySrc,
  1043. cxDst,
  1044. cyDst,
  1045. hdcSrc,
  1046. hbmSrc,
  1047. pxformSrc
  1048. )
  1049. )
  1050. goto dmb_exit;
  1051. // For the high rop (mask bit 0), we use the following rop table:
  1052. //
  1053. // P S D | R1 R2
  1054. // ------+--------
  1055. // 0 0 0 | 0 x
  1056. // 0 0 1 | 1 x
  1057. // 0 1 0 | x 0
  1058. // 0 1 1 | x 1
  1059. // 1 0 0 | 0 x
  1060. // 1 0 1 | 1 x
  1061. // 1 1 0 | x 0
  1062. // 1 1 1 | x 1
  1063. //
  1064. // In the first pass, we AND the NOT of the mask to the source bitmap to remove
  1065. // the mask 1 bits. This is then used to get the result (R1) for the
  1066. // bitblt involving source 1's.
  1067. //
  1068. // In the second pass, we OR the mask to the source bitmap
  1069. // to obtain the source 0 bits. This is then used to get the result (R2)
  1070. // for the bitblt involving source 0's.
  1071. // Restore the source bits.
  1072. if (!SelectObject(hdcSrc, hbmSrcOld))
  1073. goto dmb_exit;
  1074. if (!SetDIBits(pLocalDC->hdcHelper,
  1075. hbmSrc,
  1076. 0,
  1077. (UINT) lpBitmapInfoSrc->bmiHeader.biHeight,
  1078. (CONST VOID *) lpBitsSrc,
  1079. (LPBITMAPINFO) lpBitmapInfoSrc,
  1080. (UINT) iUsageSrc))
  1081. goto dmb_exit;
  1082. if (!SelectObject(hdcSrc, hbmSrc))
  1083. goto dmb_exit;
  1084. // AND the NOT of the mask to the source bitmap to remove the mask 1 bits.
  1085. if (!BitBlt(hdcSrc,
  1086. (int) xSrc, (int) ySrc,
  1087. (int) cxDst, (int) cyDst,
  1088. hdcMask,
  1089. (int) xSrc, (int) ySrc,
  1090. 0x220326)) // DSna
  1091. goto dmb_exit;
  1092. // Get the result (R1) for the bits involving source 1's.
  1093. if (!DoStretchBltAlt
  1094. (
  1095. pLocalDC,
  1096. xDst,
  1097. yDst,
  1098. cxDst,
  1099. cyDst,
  1100. (rop0 & 0xCC0000) | 0x220000,
  1101. xSrc,
  1102. ySrc,
  1103. cxDst,
  1104. cyDst,
  1105. hdcSrc,
  1106. hbmSrc,
  1107. pxformSrc
  1108. )
  1109. )
  1110. goto dmb_exit;
  1111. // OR the mask to the source bitmap to obtain the source 0 bits.
  1112. if (!BitBlt(hdcSrc,
  1113. (int) xSrc, (int) ySrc,
  1114. (int) cxDst, (int) cyDst,
  1115. hdcMask,
  1116. (int) xSrc, (int) ySrc,
  1117. SRCPAINT))
  1118. goto dmb_exit;
  1119. // Get the result (R2) for the bitblt involving source 0's.
  1120. if (!DoStretchBltAlt
  1121. (
  1122. pLocalDC,
  1123. xDst,
  1124. yDst,
  1125. cxDst,
  1126. cyDst,
  1127. (rop0 & 0x330000) | 0x880000,
  1128. xSrc,
  1129. ySrc,
  1130. cxDst,
  1131. cyDst,
  1132. hdcSrc,
  1133. hbmSrc,
  1134. pxformSrc
  1135. )
  1136. )
  1137. goto dmb_exit;
  1138. b = TRUE;
  1139. // Cleanup.
  1140. dmb_exit:
  1141. if (hbmMaskOld)
  1142. SelectObject(hdcMask, hbmMaskOld);
  1143. if (hbmMask)
  1144. DeleteObject(hbmMask);
  1145. if (hdcMask)
  1146. DeleteDC(hdcMask);
  1147. if (hbmSrcOld)
  1148. SelectObject(hdcSrc, hbmSrcOld);
  1149. if (hbmSrc)
  1150. DeleteObject(hbmSrc);
  1151. if (hdcSrc)
  1152. DeleteDC(hdcSrc);
  1153. return(b);
  1154. }
  1155. /***************************************************************************
  1156. * MaskBltNoSrc
  1157. **************************************************************************/
  1158. BOOL APIENTRY DoMaskBltNoSrc
  1159. (
  1160. PLOCALDC pLocalDC,
  1161. LONG xDst,
  1162. LONG yDst,
  1163. LONG cxDst,
  1164. LONG cyDst,
  1165. DWORD rop4,
  1166. PXFORM pxformSrc,
  1167. LONG xMask,
  1168. LONG yMask,
  1169. DWORD iUsageMask,
  1170. PBITMAPINFO lpBitmapInfoMask,
  1171. DWORD cbBitmapInfoMask,
  1172. LPBYTE lpBitsMask,
  1173. DWORD cbBitsMask
  1174. )
  1175. {
  1176. BOOL b;
  1177. DWORD rop1;
  1178. DWORD rop0;
  1179. HDC hdcMask;
  1180. HBITMAP hbmMask, hbmMaskOld;
  1181. RECTL rclMask;
  1182. LONG cxMask, cyMask;
  1183. b = FALSE;
  1184. hdcMask = (HDC) 0;
  1185. hbmMask = hbmMaskOld = (HBITMAP) 0;
  1186. rop0 = rop4 >> 8; // rop for 0's
  1187. rop1 = rop4 & 0xFF0000; // rop for 1's
  1188. // When no source bitmap is required in the rop4, the mask is used
  1189. // as the source in that the low rop is applied to the corresponding
  1190. // mask 1 bits and the high rop is applied to mask 0 bits. The source
  1191. // transform is used to determine the mask rectangle to be used.
  1192. // Create a compatible mask DC.
  1193. if (!(hdcMask = CreateCompatibleDC((HDC) 0)))
  1194. goto dmbns_exit;
  1195. // Create the mask bitmap.
  1196. if (!(hbmMask = CreateMonoDib(lpBitmapInfoMask, lpBitsMask, (UINT) iUsageMask)))
  1197. goto dmbns_exit;
  1198. // Select the bitmap.
  1199. if (!(hbmMaskOld = (HBITMAP) SelectObject(hdcMask, hbmMask)))
  1200. goto dmbns_exit;
  1201. // Compute the mask extents.
  1202. rclMask.left = 0;
  1203. rclMask.top = 0;
  1204. rclMask.right = cxDst;
  1205. rclMask.bottom = cyDst;
  1206. if (!bXformWorkhorse((PPOINTL) &rclMask, 2, pxformSrc))
  1207. goto dmbns_exit;
  1208. cxMask = rclMask.right - rclMask.left;
  1209. cyMask = rclMask.bottom - rclMask.top;
  1210. // Align the mask rectangle.
  1211. if (cxMask < 0)
  1212. xMask = xMask - cxMask + 1;
  1213. if (cyMask < 0)
  1214. yMask = yMask - cyMask + 1;
  1215. // We need to handle the low rop (mask bit 1) and high rop (mask bit 0)
  1216. // separately.
  1217. //
  1218. // For the low rop (mask bit 1), we use the following rop table:
  1219. //
  1220. // P M D | R
  1221. // ------+---
  1222. // 0 0 0 | 0
  1223. // 0 0 1 | 1
  1224. // 0 1 0 | x
  1225. // 0 1 1 | x
  1226. // 1 0 0 | 0
  1227. // 1 0 1 | 1
  1228. // 1 1 0 | x
  1229. // 1 1 1 | x
  1230. //
  1231. // The above rop will give us the result for bits that correspond to 1's
  1232. // in the mask bitmap. The destination bits that correspond to the 0 mask
  1233. // bits will not be changed. We effectively treat the mask as the source
  1234. // in the operation.
  1235. // Get the result (R) for the bits involving mask 1's.
  1236. if (!DoStretchBltAlt
  1237. (
  1238. pLocalDC,
  1239. xDst,
  1240. yDst,
  1241. cxDst,
  1242. cyDst,
  1243. (rop1 & 0xCC0000) | 0x220000,
  1244. xMask,
  1245. yMask,
  1246. cxMask,
  1247. cyMask,
  1248. hdcMask,
  1249. hbmMask,
  1250. &xformIdentity
  1251. )
  1252. )
  1253. goto dmbns_exit;
  1254. #if 0
  1255. DoStretchBlt
  1256. (
  1257. pLocalDC,
  1258. xDst,
  1259. yDst,
  1260. cxDst,
  1261. cyDst,
  1262. (rop1 & 0xCC0000) | 0x220000,
  1263. xMask,
  1264. yMask,
  1265. cxMask,
  1266. cyMask,
  1267. &xformIdentity,
  1268. iUsageMask,
  1269. lpBitmapInfoMask,
  1270. cbBitmapInfoMask,
  1271. lpBitsMask,
  1272. cbBitsMask
  1273. )
  1274. #endif // 0
  1275. // For the high rop (mask bit 0), we use the following rop table:
  1276. //
  1277. // P M D | R
  1278. // ------+---
  1279. // 0 0 0 | x
  1280. // 0 0 1 | x
  1281. // 0 1 0 | 0
  1282. // 0 1 1 | 1
  1283. // 1 0 0 | x
  1284. // 1 0 1 | x
  1285. // 1 1 0 | 0
  1286. // 1 1 1 | 1
  1287. //
  1288. // The above rop will give us the result for bits that correspond to 0's
  1289. // in the mask bitmap. The destination bits that correspond to the 1 mask
  1290. // bits will not be changed. We effectively treat the mask as the source
  1291. // in the operation.
  1292. // Get the result (R) for the bits involving mask 0's.
  1293. if (!DoStretchBltAlt
  1294. (
  1295. pLocalDC,
  1296. xDst,
  1297. yDst,
  1298. cxDst,
  1299. cyDst,
  1300. (rop0 & 0x330000) | 0x880000,
  1301. xMask,
  1302. yMask,
  1303. cxMask,
  1304. cyMask,
  1305. hdcMask,
  1306. hbmMask,
  1307. &xformIdentity
  1308. )
  1309. )
  1310. goto dmbns_exit;
  1311. #if 0
  1312. DoStretchBlt
  1313. (
  1314. pLocalDC,
  1315. xDst,
  1316. yDst,
  1317. cxDst,
  1318. cyDst,
  1319. (rop0 & 0x330000) | 0x880000,
  1320. xMask,
  1321. yMask,
  1322. cxMask,
  1323. cyMask,
  1324. &xformIdentity,
  1325. iUsageMask,
  1326. lpBitmapInfoMask,
  1327. cbBitmapInfoMask,
  1328. lpBitsMask,
  1329. cbBitsMask
  1330. )
  1331. #endif // 0
  1332. b = TRUE;
  1333. // Cleanup.
  1334. dmbns_exit:
  1335. if (hbmMaskOld)
  1336. SelectObject(hdcMask, hbmMaskOld);
  1337. if (hbmMask)
  1338. DeleteObject(hbmMask);
  1339. if (hdcMask)
  1340. DeleteDC(hdcMask);
  1341. return(b);
  1342. }
  1343. /***************************************************************************
  1344. * PlgBlt - Win32 to Win16 Metafile Converter Entry Point
  1345. **************************************************************************/
  1346. BOOL APIENTRY DoPlgBlt
  1347. (
  1348. PLOCALDC pLocalDC,
  1349. PPOINTL pptlDst,
  1350. LONG xSrc,
  1351. LONG ySrc,
  1352. LONG cxSrc,
  1353. LONG cySrc,
  1354. PXFORM pxformSrc,
  1355. DWORD iUsageSrc,
  1356. PBITMAPINFO lpBitmapInfoSrc,
  1357. DWORD cbBitmapInfoSrc,
  1358. LPBYTE lpBitsSrc,
  1359. DWORD cbBitsSrc,
  1360. LONG xMask,
  1361. LONG yMask,
  1362. DWORD iUsageMask,
  1363. PBITMAPINFO lpBitmapInfoMask,
  1364. DWORD cbBitmapInfoMask,
  1365. LPBYTE lpBitsMask,
  1366. DWORD cbBitsMask
  1367. )
  1368. {
  1369. BOOL b, bMask;
  1370. DWORD rop4;
  1371. HDC hdcSrc, hdcSrcRDev;
  1372. PBITMAPINFO pbmiSrcRDev, pbmiMaskRDev;
  1373. LPBYTE lpBitsSrcRDev, lpBitsMaskRDev;
  1374. DWORD cbBitsSrcRDev, cbBitsMaskRDev;
  1375. HBITMAP hbmMask, hbmMaskRDev, hbmSrc, hbmSrcRDev, hbmSrcOld, hbmSrcRDevOld;
  1376. RECTL rclBndRDev;
  1377. POINTL aptlDst[4];
  1378. POINT ptMask;
  1379. BITMAPINFOHEADER bmihMask;
  1380. // We are going to convert the PlgBlt into a MaskBlt. This can be done
  1381. // by converting the source and mask bitmaps to the device space of the
  1382. // recording device and then maskblt the result.
  1383. b = FALSE;
  1384. hdcSrc = hdcSrcRDev = (HDC) 0;
  1385. hbmMask = hbmMaskRDev = hbmSrc = hbmSrcRDev = hbmSrcOld = hbmSrcRDevOld = (HBITMAP) 0;
  1386. pbmiSrcRDev = pbmiMaskRDev = (PBITMAPINFO) NULL;
  1387. lpBitsSrcRDev = lpBitsMaskRDev = (LPBYTE) NULL;
  1388. bMask = (cbBitmapInfoMask != 0);
  1389. rop4 = 0xAACC0000; // rop for MaskBlt
  1390. // First, we transform the destination parallelogram to the device space
  1391. // of the recording device. This device parallelogram is then used in
  1392. // plgblt'ing the source and mask bitmaps to the device space of the
  1393. // recording device.
  1394. aptlDst[0] = pptlDst[0];
  1395. aptlDst[1] = pptlDst[1];
  1396. aptlDst[2] = pptlDst[2];
  1397. aptlDst[3].x = aptlDst[1].x + aptlDst[2].x - aptlDst[0].x;
  1398. aptlDst[3].y = aptlDst[1].y + aptlDst[2].y - aptlDst[0].y;
  1399. if (!bXformRWorldToRDev(pLocalDC, aptlDst, 4))
  1400. goto dpb_exit;
  1401. // Find the bounding rectangle of the parallelogram in the recording
  1402. // device space. This rectangle is used as the basis of the MaskBlt call.
  1403. rclBndRDev.left = min(aptlDst[0].x,min(aptlDst[1].x,min(aptlDst[2].x,aptlDst[3].x)));
  1404. rclBndRDev.top = min(aptlDst[0].y,min(aptlDst[1].y,min(aptlDst[2].y,aptlDst[3].y)));
  1405. rclBndRDev.right = max(aptlDst[0].x,max(aptlDst[1].x,max(aptlDst[2].x,aptlDst[3].x)));
  1406. rclBndRDev.bottom = max(aptlDst[0].y,max(aptlDst[1].y,max(aptlDst[2].y,aptlDst[3].y)));
  1407. // Offset the device parallelogram to the origin.
  1408. aptlDst[0].x -= rclBndRDev.left; aptlDst[0].y -= rclBndRDev.top;
  1409. aptlDst[1].x -= rclBndRDev.left; aptlDst[1].y -= rclBndRDev.top;
  1410. aptlDst[2].x -= rclBndRDev.left; aptlDst[2].y -= rclBndRDev.top;
  1411. aptlDst[3].x -= rclBndRDev.left; aptlDst[3].y -= rclBndRDev.top;
  1412. // Create the source bitmap in the recording device space for MaskBlt.
  1413. // The size of the source bitmap is that of rclBndRDev.
  1414. // The source image is then plgblt'd into the device parallelogram.
  1415. // PlgBlt always takes a source bitmap.
  1416. // Create the original source.
  1417. if (!(hdcSrc = hdcMakeCompatibleDC(pxformSrc)))
  1418. goto dpb_exit;
  1419. if (!(hbmSrc = CreateDIBitmap(hdcSrc,
  1420. (LPBITMAPINFOHEADER) lpBitmapInfoSrc,
  1421. CBM_INIT | CBM_CREATEDIB,
  1422. lpBitsSrc,
  1423. (LPBITMAPINFO) lpBitmapInfoSrc,
  1424. (UINT) iUsageSrc)))
  1425. goto dpb_exit;
  1426. if (!(hbmSrcOld = (HBITMAP) SelectObject(hdcSrc, hbmSrc)))
  1427. goto dpb_exit;
  1428. // Create the source for MaskBlt.
  1429. if (!(hdcSrcRDev = CreateCompatibleDC((HDC) 0)))
  1430. goto dpb_exit;
  1431. pbmiSrcRDev = (PBITMAPINFO) LocalAlloc(LMEM_FIXED, cbBitmapInfoSrc);
  1432. if (pbmiSrcRDev == (PBITMAPINFO) NULL)
  1433. goto dpb_exit;
  1434. RtlCopyMemory(pbmiSrcRDev, lpBitmapInfoSrc, cbBitmapInfoSrc);
  1435. pbmiSrcRDev->bmiHeader.biWidth = rclBndRDev.right - rclBndRDev.left + 1;
  1436. pbmiSrcRDev->bmiHeader.biHeight = rclBndRDev.bottom - rclBndRDev.top + 1;
  1437. pbmiSrcRDev->bmiHeader.biSizeImage = 0;
  1438. if (!(hbmSrcRDev = CreateDIBitmap(hdcSrcRDev, (LPBITMAPINFOHEADER) pbmiSrcRDev,
  1439. CBM_CREATEDIB, (LPBYTE) NULL, pbmiSrcRDev, iUsageSrc)))
  1440. goto dpb_exit;
  1441. if (!(hbmSrcRDevOld = (HBITMAP) SelectObject(hdcSrcRDev, hbmSrcRDev)))
  1442. goto dpb_exit;
  1443. // PlgBlt the original source bitmap into the source bitmap for MaskBlt.
  1444. if (!PlgBlt(hdcSrcRDev, (LPPOINT) aptlDst, hdcSrc, xSrc, ySrc, cxSrc, cySrc, (HBITMAP) NULL, 0, 0))
  1445. goto dpb_exit;
  1446. // Retrieve the source bits for MaskBlt.
  1447. // Get biSizeImage!
  1448. if (!GetDIBits(hdcSrcRDev, hbmSrcRDev, 0, 0, (LPBYTE) NULL, pbmiSrcRDev, iUsageSrc))
  1449. goto dpb_exit;
  1450. // Compute size of the buffer required for source bits.
  1451. if (pbmiSrcRDev->bmiHeader.biSizeImage)
  1452. cbBitsSrcRDev = pbmiSrcRDev->bmiHeader.biSizeImage;
  1453. else
  1454. cbBitsSrcRDev = CJSCAN(pbmiSrcRDev->bmiHeader.biWidth,
  1455. pbmiSrcRDev->bmiHeader.biPlanes,
  1456. pbmiSrcRDev->bmiHeader.biBitCount)
  1457. * ABS(pbmiSrcRDev->bmiHeader.biHeight);
  1458. lpBitsSrcRDev = (LPBYTE) LocalAlloc(LMEM_FIXED, cbBitsSrcRDev);
  1459. if (lpBitsSrcRDev == (LPBYTE) NULL)
  1460. goto dpb_exit;
  1461. // Get the source bits.
  1462. if (!GetDIBits(hdcSrcRDev, hbmSrcRDev, 0, (UINT) pbmiSrcRDev->bmiHeader.biHeight,
  1463. lpBitsSrcRDev, pbmiSrcRDev, iUsageSrc))
  1464. goto dpb_exit;
  1465. // Create the mask bitmap in the recording device space for MaskBlt.
  1466. // The size of the mask bitmap is that of rclBndRDev.
  1467. // The mask image is then plgblt'd into the device parallelogram.
  1468. // If a mask is not given, create one that describes the parallelogram
  1469. // for the source.
  1470. if (bMask)
  1471. {
  1472. // Create the original mask.
  1473. if (!(hbmMask = CreateMonoDib(lpBitmapInfoMask, lpBitsMask, (UINT) iUsageMask)))
  1474. goto dpb_exit;
  1475. if (!SelectObject(hdcSrc, hbmMask))
  1476. goto dpb_exit;
  1477. }
  1478. else
  1479. {
  1480. // Create a mask describing the original source bitmap.
  1481. ASSERTGDI(sizeof(BITMAPINFOHEADER) == 0x28,
  1482. "MF3216: DoPlgBlt, BITMAPINFOHEADER has changed!\n");
  1483. iUsageMask = DIB_PAL_INDICES;
  1484. cbBitmapInfoMask = 0x28;
  1485. lpBitmapInfoMask = (PBITMAPINFO) &bmihMask;
  1486. bmihMask.biSize = 0x28;
  1487. bmihMask.biWidth = lpBitmapInfoSrc->bmiHeader.biWidth;
  1488. bmihMask.biHeight = lpBitmapInfoSrc->bmiHeader.biHeight;
  1489. bmihMask.biPlanes = 1;
  1490. bmihMask.biBitCount = 1;
  1491. bmihMask.biCompression = BI_RGB;
  1492. bmihMask.biSizeImage = 0;
  1493. bmihMask.biXPelsPerMeter = 0;
  1494. bmihMask.biYPelsPerMeter = 0;
  1495. bmihMask.biClrUsed = 0;
  1496. bmihMask.biClrImportant = 0;
  1497. if (!(hbmMask = CreateBitmap((int) bmihMask.biWidth,
  1498. (int) bmihMask.biHeight, 1, 1, (CONST VOID *) NULL)))
  1499. goto dpb_exit;
  1500. if (!SelectObject(hdcSrc, hbmMask))
  1501. goto dpb_exit;
  1502. // Initialize the mask bitmap to 1's.
  1503. if (!PatBlt(hdcSrc,0,0,(int)bmihMask.biWidth,(int)bmihMask.biHeight,WHITENESS))
  1504. goto dpb_exit;
  1505. }
  1506. // Create the mask for MaskBlt.
  1507. pbmiMaskRDev = (PBITMAPINFO) LocalAlloc(LMEM_FIXED, cbBitmapInfoMask);
  1508. if (pbmiMaskRDev == (PBITMAPINFO) NULL)
  1509. goto dpb_exit;
  1510. RtlCopyMemory(pbmiMaskRDev, lpBitmapInfoMask, cbBitmapInfoMask);
  1511. pbmiMaskRDev->bmiHeader.biWidth = rclBndRDev.right - rclBndRDev.left + 1;
  1512. pbmiMaskRDev->bmiHeader.biHeight = rclBndRDev.bottom - rclBndRDev.top + 1;
  1513. pbmiMaskRDev->bmiHeader.biSizeImage = 0;
  1514. pbmiMaskRDev->bmiHeader.biCompression = BI_RGB;
  1515. if (!(hbmMaskRDev = CreateBitmap(pbmiMaskRDev->bmiHeader.biWidth,
  1516. pbmiMaskRDev->bmiHeader.biHeight, 1, 1, (CONST VOID *) NULL)))
  1517. goto dpb_exit;
  1518. if (!SelectObject(hdcSrcRDev, hbmMaskRDev))
  1519. goto dpb_exit;
  1520. // Initialize the mask bitmap to 0's.
  1521. if (!PatBlt(hdcSrcRDev,0,0,(int)pbmiMaskRDev->bmiHeader.biWidth,
  1522. (int)pbmiMaskRDev->bmiHeader.biHeight,BLACKNESS))
  1523. goto dpb_exit;
  1524. // PlgBlt the original mask bitmap into the mask bitmap for MaskBlt.
  1525. if (bMask)
  1526. {
  1527. ptMask.x = xMask;
  1528. ptMask.y = yMask;
  1529. if (!DPtoLP(hdcSrc, &ptMask, 1))
  1530. goto dpb_exit;
  1531. }
  1532. else
  1533. {
  1534. ptMask.x = xSrc;
  1535. ptMask.y = ySrc;
  1536. }
  1537. if (!PlgBlt(hdcSrcRDev, (LPPOINT) aptlDst, hdcSrc, ptMask.x, ptMask.y, cxSrc, cySrc, (HBITMAP) NULL, 0, 0))
  1538. goto dpb_exit;
  1539. // Retrieve the mask bits for MaskBlt.
  1540. // Compute size of the buffer required for mask bits.
  1541. cbBitsMaskRDev = CJSCAN(pbmiMaskRDev->bmiHeader.biWidth,
  1542. pbmiMaskRDev->bmiHeader.biPlanes,
  1543. pbmiMaskRDev->bmiHeader.biBitCount)
  1544. * ABS(pbmiMaskRDev->bmiHeader.biHeight);
  1545. lpBitsMaskRDev = (LPBYTE) LocalAlloc(LMEM_FIXED, cbBitsMaskRDev);
  1546. if (lpBitsMaskRDev == (LPBYTE) NULL)
  1547. goto dpb_exit;
  1548. // Get the mask bits.
  1549. if (!GetDIBits(hdcSrcRDev, hbmMaskRDev, 0, (UINT) pbmiMaskRDev->bmiHeader.biHeight,
  1550. lpBitsMaskRDev, pbmiMaskRDev, iUsageMask))
  1551. goto dpb_exit;
  1552. // Prepare for the MaskBlt.
  1553. // The destination for the MaskBlt is rclBndRDev. Since the extents for
  1554. // the destination and source share the same logical values in MaskBlt,
  1555. // we have to set the transform in the destination DC to identity.
  1556. // Save the DC so that we can restore the transform when we are done
  1557. if (!DoSaveDC(pLocalDC))
  1558. goto dpb_exit;
  1559. // Set the transforms to identity.
  1560. if (!DoSetMapMode(pLocalDC, MM_TEXT)
  1561. || !DoModifyWorldTransform(pLocalDC, (PXFORM) NULL, MWT_IDENTITY)
  1562. || !DoSetWindowOrg(pLocalDC, 0, 0)
  1563. || !DoSetViewportOrg(pLocalDC, 0, 0))
  1564. goto dpb_restore_exit;
  1565. // Now do the MaskBlt.
  1566. b = DoMaskBlt
  1567. (
  1568. pLocalDC,
  1569. rclBndRDev.left, // xDst
  1570. rclBndRDev.top, // yDst
  1571. rclBndRDev.right - rclBndRDev.left + 1,
  1572. rclBndRDev.bottom - rclBndRDev.top + 1,
  1573. rop4,
  1574. 0, // xSrc
  1575. 0, // ySrc
  1576. &xformIdentity,
  1577. iUsageSrc,
  1578. pbmiSrcRDev,
  1579. cbBitmapInfoSrc,
  1580. lpBitsSrcRDev,
  1581. cbBitsSrcRDev,
  1582. 0, // xMask
  1583. 0, // yMask
  1584. iUsageMask,
  1585. pbmiMaskRDev,
  1586. cbBitmapInfoMask,
  1587. lpBitsMaskRDev,
  1588. cbBitsMaskRDev
  1589. );
  1590. // Restore the transforms.
  1591. dpb_restore_exit:
  1592. (void) DoRestoreDC(pLocalDC, -1);
  1593. // Cleanup.
  1594. dpb_exit:
  1595. if (hbmSrcOld)
  1596. SelectObject(hdcSrc, hbmSrcOld);
  1597. if (hbmSrcRDevOld)
  1598. SelectObject(hdcSrcRDev, hbmSrcRDevOld);
  1599. if (hbmSrc)
  1600. DeleteObject(hbmSrc);
  1601. if (hbmSrcRDev)
  1602. DeleteObject(hbmSrcRDev);
  1603. if (hbmMask)
  1604. DeleteObject(hbmMask);
  1605. if (hbmMaskRDev)
  1606. DeleteObject(hbmMaskRDev);
  1607. if (hdcSrc)
  1608. DeleteDC(hdcSrc);
  1609. if (hdcSrcRDev)
  1610. DeleteDC(hdcSrcRDev);
  1611. if (pbmiSrcRDev)
  1612. LocalFree((HANDLE) pbmiSrcRDev);
  1613. if (pbmiMaskRDev)
  1614. LocalFree((HANDLE) pbmiMaskRDev);
  1615. if (lpBitsSrcRDev)
  1616. LocalFree((HANDLE) lpBitsSrcRDev);
  1617. if (lpBitsMaskRDev)
  1618. LocalFree((HANDLE) lpBitsMaskRDev);
  1619. return(b);
  1620. }
  1621. /***************************************************************************
  1622. * SetPixel - Win32 to Win16 Metafile Converter Entry Point
  1623. **************************************************************************/
  1624. BOOL WINAPI DoSetPixel
  1625. (
  1626. PLOCALDC pLocalDC,
  1627. int x,
  1628. int y,
  1629. COLORREF crColor
  1630. )
  1631. {
  1632. POINTL ptl ;
  1633. BOOL b ;
  1634. ptl.x = (LONG) x ;
  1635. ptl.y = (LONG) y ;
  1636. b = bXformRWorldToPPage(pLocalDC, &ptl, 1) ;
  1637. if (b == FALSE)
  1638. goto exit1 ;
  1639. b = bEmitWin16SetPixel(pLocalDC, LOWORD(ptl.x), LOWORD(ptl.y), crColor) ;
  1640. exit1:
  1641. return(b) ;
  1642. }
  1643. /***************************************************************************
  1644. * SetStretchBltMode - Win32 to Win16 Metafile Converter Entry Point
  1645. **************************************************************************/
  1646. BOOL WINAPI DoSetStretchBltMode
  1647. (
  1648. PLOCALDC pLocalDC,
  1649. DWORD iStretchMode
  1650. )
  1651. {
  1652. BOOL b ;
  1653. // Emit the Win16 metafile drawing order.
  1654. b = bEmitWin16SetStretchBltMode(pLocalDC, LOWORD(iStretchMode)) ;
  1655. return(b) ;
  1656. }
  1657. BOOL WINAPI DoMakeBitmapBottomUp
  1658. (
  1659. PBITMAPINFO lpBitmapInfo,
  1660. DWORD cbBitmapInfo,
  1661. LPBYTE lpBits,
  1662. DWORD cbBits
  1663. )
  1664. {
  1665. BYTE * lpNewBits;
  1666. DWORD destByteWidth;
  1667. BYTE * destRaster, * srcRaster;
  1668. INT i;
  1669. // If it's already Bottom-Up then nothing to do
  1670. if (lpBitmapInfo->bmiHeader.biHeight >= 0)
  1671. {
  1672. return TRUE;
  1673. }
  1674. if (lpBitmapInfo->bmiHeader.biPlanes != 1 ||
  1675. !(lpBitmapInfo->bmiHeader.biBitCount == 1 ||
  1676. lpBitmapInfo->bmiHeader.biBitCount == 4 ||
  1677. lpBitmapInfo->bmiHeader.biBitCount == 8 ||
  1678. lpBitmapInfo->bmiHeader.biBitCount == 16 ||
  1679. lpBitmapInfo->bmiHeader.biBitCount == 24 ||
  1680. lpBitmapInfo->bmiHeader.biBitCount == 32)
  1681. || lpBitmapInfo->bmiHeader.biCompression != BI_RGB )
  1682. {
  1683. return FALSE;
  1684. }
  1685. lpBitmapInfo->bmiHeader.biHeight = ABS(lpBitmapInfo->bmiHeader.biHeight);
  1686. lpNewBits = (BYTE*) LocalAlloc(LMEM_FIXED, cbBits);
  1687. if (lpNewBits == NULL)
  1688. {
  1689. return FALSE;
  1690. }
  1691. destByteWidth = ((lpBitmapInfo->bmiHeader.biWidth * lpBitmapInfo->bmiHeader.biBitCount + 31) & ~31) >> 3;
  1692. ASSERT(((cbBits/lpBitmapInfo->bmiHeader.biHeight)*lpBitmapInfo->bmiHeader.biHeight)==cbBits);
  1693. ASSERT(cbBits == destByteWidth * lpBitmapInfo->bmiHeader.biHeight);
  1694. // Start the destination at the end of the bitmap.
  1695. destRaster = lpNewBits + (destByteWidth * (lpBitmapInfo->bmiHeader.biHeight - 1));
  1696. srcRaster = lpBits;
  1697. for (i = 0; i < lpBitmapInfo->bmiHeader.biHeight ; i++)
  1698. {
  1699. memcpy(destRaster, srcRaster, destByteWidth);
  1700. destRaster -= destByteWidth;
  1701. srcRaster += destByteWidth;
  1702. }
  1703. // Recopy the reversed bitmap into the original buffer
  1704. memcpy(lpBits, lpNewBits, cbBits);
  1705. LocalFree( (HLOCAL) lpNewBits);
  1706. return TRUE;
  1707. }