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.

2103 lines
59 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name
  4. Abstract:
  5. Lingyun Wang
  6. Author:
  7. Enviornment:
  8. User Mode
  9. Revision History:
  10. --*/
  11. #include "precomp.hxx"
  12. #include <ddraw.h>
  13. #include <ddrawp.h>
  14. #include <ddrawi.h>
  15. /*extern HRESULT DD_Surface_GetSurfaceDesc(LPDIRECTDRAWSURFACE, LPDDSURFACEDESC);
  16. extern HRESULT GetSurfaceFromDC(
  17. HDC hdc,
  18. LPDIRECTDRAWSURFACE *ppdds,
  19. HDC *phdcDriver) ;
  20. */
  21. #pragma hdrstop
  22. extern PFNTRANSBLT gpfnTransparentImage;
  23. extern PFNTRANSDIB gpfnTransparentDIBImage;
  24. #if (_WIN32_WINNT == 0x400)
  25. PFN_GETSURFACEFROMDC pfnGetSurfaceFromDC = NULL;
  26. PFN_GETSURFACEFROMDC pfnGetSurfaceDesc;
  27. static PALETTEENTRY gapeVgaPalette[16] =
  28. {
  29. { 0, 0, 0, 0 },
  30. { 0x80,0, 0, 0 },
  31. { 0, 0x80,0, 0 },
  32. { 0x80,0x80,0, 0 },
  33. { 0, 0, 0x80, 0 },
  34. { 0x80,0, 0x80, 0 },
  35. { 0, 0x80,0x80, 0 },
  36. { 0x80,0x80,0x80, 0 },
  37. { 0xC0,0xC0,0xC0, 0 },
  38. { 0xFF,0, 0, 0 },
  39. { 0, 0xFF,0, 0 },
  40. { 0xFF,0xFF,0, 0 },
  41. { 0, 0, 0xFF, 0 },
  42. { 0xFF,0, 0xFF, 0 },
  43. { 0, 0xFF,0xFF, 0 },
  44. { 0xFF,0xFF,0xFF, 0 }
  45. };
  46. /**************************************************************************\
  47. * Dprintf
  48. *
  49. *
  50. * Arguments:
  51. *
  52. * szFmt - format string and argrs
  53. *
  54. * Return Value:
  55. *
  56. * none
  57. *
  58. * History:
  59. *
  60. *
  61. \**************************************************************************/
  62. VOID Dprintf( LPSTR szFmt, ... ) {
  63. TCHAR szMsg[80];
  64. DWORD cb;
  65. va_list marker;
  66. va_start( marker, szFmt );
  67. wvsprintf( szMsg, szFmt, marker );
  68. cb = lstrlen(szMsg);
  69. szMsg[cb++] = '\r';
  70. szMsg[cb++] = '\n';
  71. WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), szMsg, sizeof(TCHAR) * cb,
  72. &cb, NULL );
  73. va_end( marker );
  74. return;
  75. }
  76. /******************************Public*Routine******************************\
  77. * MyGetSystemPaletteEntries
  78. *
  79. * Internal version of GetSystemPaletteEntries.
  80. *
  81. * GetSystemPaletteEntries fails on some 4bpp devices. This version
  82. * will detect the 4bpp case and supply the hardcoded 16-color VGA palette.
  83. * Otherwise, it will pass the call on to GDI's GetSystemPaletteEntries.
  84. *
  85. * It is expected that this call will only be called in the 4bpp and 8bpp
  86. * cases as it is not necessary for OpenGL to query the system palette
  87. * for > 8bpp devices.
  88. *
  89. * History:
  90. * 17-Aug-1995 -by- Gilman Wong [gilmanw]
  91. * Wrote it.
  92. \**************************************************************************/
  93. static UINT
  94. MyGetSystemPaletteEntries(HDC hdc, UINT iStartIndex, UINT nEntries,
  95. LPPALETTEENTRY lppe)
  96. {
  97. int nDeviceBits;
  98. nDeviceBits = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  99. //
  100. // Some 4bpp displays will fail the GetSystemPaletteEntries call.
  101. // So if detected, return the hardcoded table.
  102. //
  103. if ( nDeviceBits == 4 )
  104. {
  105. if ( lppe )
  106. {
  107. nEntries = min(nEntries, (16 - iStartIndex));
  108. memcpy(lppe, &gapeVgaPalette[iStartIndex],
  109. nEntries * sizeof(PALETTEENTRY));
  110. }
  111. else
  112. nEntries = 16;
  113. return nEntries;
  114. }
  115. else
  116. {
  117. return GetSystemPaletteEntries(hdc, iStartIndex, nEntries, lppe);
  118. }
  119. }
  120. /******************************Public*Routine******************************\
  121. * bFillColorTable
  122. *
  123. * Initialize the color table of the BITMAPINFO pointed to by pbmi. Colors
  124. * are set to the current system palette.
  125. *
  126. * Note: call only valid for displays of 8bpp or less.
  127. *
  128. * Returns:
  129. * TRUE if successful, FALSE otherwise.
  130. *
  131. * History:
  132. * 23-Jan-1996 -by- Gilman Wong [gilmanw]
  133. * Wrote it.
  134. \**************************************************************************/
  135. static BOOL
  136. bFillColorTable(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi)
  137. {
  138. BOOL bRet = FALSE;
  139. BYTE aj[sizeof(PALETTEENTRY) * 256];
  140. LPPALETTEENTRY lppe = (LPPALETTEENTRY) aj;
  141. RGBQUAD *prgb = (RGBQUAD *) &pbmi->bmiColors[0];
  142. ULONG cColors;
  143. cColors = 1 << pbmi->bmiHeader.biBitCount;
  144. if ( cColors <= 256 )
  145. {
  146. if ( hpal ? GetPaletteEntries(hpal, 0, cColors, lppe)
  147. : MyGetSystemPaletteEntries(hdc, 0, cColors, lppe) )
  148. {
  149. UINT i;
  150. for (i = 0; i < cColors; i++)
  151. {
  152. prgb[i].rgbRed = lppe[i].peRed;
  153. prgb[i].rgbGreen = lppe[i].peGreen;
  154. prgb[i].rgbBlue = lppe[i].peBlue;
  155. prgb[i].rgbReserved = 0;
  156. }
  157. bRet = TRUE;
  158. }
  159. else
  160. {
  161. //WARNING ("bFillColorTable: MyGetSystemPaletteEntries failed\n");
  162. }
  163. }
  164. return bRet;
  165. }
  166. /******************************Public*Routine******************************\
  167. * bFillBitmapInfoDirect
  168. *
  169. * Fills in the fields of a BITMAPINFO so that we can create a bitmap
  170. * that matches the format of the display.
  171. *
  172. * This is done by creating a compatible bitmap and calling GetDIBits
  173. * to return the color masks. This is done with two calls. The first
  174. * call passes in biBitCount = 0 to GetDIBits which will fill in the
  175. * base BITMAPINFOHEADER data. The second call to GetDIBits (passing
  176. * in the BITMAPINFO filled in by the first call) will return the color
  177. * table or bitmasks, as appropriate.
  178. *
  179. * Returns:
  180. * TRUE if successful, FALSE otherwise.
  181. *
  182. * History:
  183. * 07-Jun-1995 -by- Gilman Wong [gilmanw]
  184. * Wrote it.
  185. \**************************************************************************/
  186. BOOL
  187. bFillBitmapInfoDirect(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi)
  188. {
  189. HBITMAP hbm;
  190. BOOL bRet = FALSE;
  191. //
  192. // Create a dummy bitmap from which we can query color format info
  193. // about the device surface.
  194. //
  195. if ((hbm = CreateCompatibleBitmap(hdc, 1, 1)) != NULL)
  196. {
  197. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  198. //
  199. // Call first time to fill in BITMAPINFO header.
  200. //
  201. GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
  202. if (( pbmi->bmiHeader.biBitCount <= 8 ) || ( pbmi->bmiHeader.biCompression == BI_BITFIELDS ))
  203. {
  204. //
  205. // Call a second time to get the color masks.
  206. // It's a GetDIBits Win32 "feature".
  207. //
  208. GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight, NULL, pbmi,
  209. DIB_RGB_COLORS);
  210. }
  211. bRet = TRUE;
  212. DeleteObject(hbm);
  213. }
  214. else
  215. {
  216. WARNING("bFillBitmapInfoDirect: CreateCompatibleBitmap failed\n");
  217. }
  218. return bRet;
  219. }
  220. /******************************Public*Routine******************************\
  221. * bFillBitmapInfoMemory
  222. *
  223. * Fills in the fields of a BITMAPINFO so that we can create a bitmap
  224. * that matches the format of a memory DC.
  225. *
  226. *
  227. * Returns:
  228. * TRUE if successful, FALSE otherwise.
  229. *
  230. * History:
  231. * 05-Dec-1996 -by- Lingyun Wang [lingyunw]
  232. * Wrote it.
  233. \**************************************************************************/
  234. BOOL
  235. bFillBitmapInfoMemory(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi)
  236. {
  237. HBITMAP hbm;
  238. BOOL bRet = FALSE;
  239. if ( (hbm = (HBITMAP)GetCurrentObject(hdc, OBJ_BITMAP)) != NULL )
  240. {
  241. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  242. //
  243. // Call first time to fill in BITMAPINFO header.
  244. //
  245. GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
  246. if (( pbmi->bmiHeader.biBitCount <= 8 )
  247. || ( pbmi->bmiHeader.biCompression == BI_BITFIELDS ))
  248. {
  249. //
  250. // Call a second time to get the color masks.
  251. // It's a GetDIBits Win32 "feature".
  252. //
  253. GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight, NULL, pbmi,
  254. DIB_RGB_COLORS);
  255. }
  256. bRet = TRUE;
  257. }
  258. else
  259. {
  260. WARNING("bFillBitmapInfoMemory: CreateCompatibleBitmap failed\n");
  261. }
  262. return bRet;
  263. }
  264. /******************************Public*Routine******************************\
  265. * bFillDIBSection
  266. *
  267. * Fill in the DIBSection structure for a memory dc
  268. * Fills in the fields of a BITMAPINFO so that we can create a bitmap
  269. * that matches the format of a memory DC.
  270. *
  271. *
  272. * Returns:
  273. * TRUE if successful, FALSE otherwise.
  274. *
  275. * History:
  276. * 05-Dec-1996 -by- Lingyun Wang [lingyunw]
  277. * Wrote it.
  278. \**************************************************************************/
  279. BOOL
  280. bFillDIBSection(
  281. PDIBINFO pDibInfo)
  282. {
  283. HBITMAP hbm;
  284. BOOL bRet = FALSE;
  285. BOOL bddraw = FALSE;
  286. DIBSECTION dib;
  287. if ( (hbm = (HBITMAP)GetCurrentObject(pDibInfo->hdc, OBJ_BITMAP)) != NULL )
  288. {
  289. GetObject (hbm, sizeof(DIBSECTION), &dib);
  290. //
  291. // it is a DIBSECTION
  292. //
  293. if ((pDibInfo->pvBits = dib.dsBm.bmBits) != NULL)
  294. {
  295. //
  296. // it is a DIBSection, now see if it might be a DD Surface (on WIn95)
  297. //
  298. if (dib.dsBm.bmWidthBytes < dib.dsBm.bmWidth * dib.dsBm.bmBitsPixel/8)
  299. {
  300. HMODULE hddrawlib = GetModuleHandleA("ddraw");
  301. if (hddrawlib)
  302. {
  303. Dprintf("GetModuleHandleA succeed\n");
  304. hddrawlib = LoadLibrary (TEXT("ddraw.dll"));
  305. Dprintf("LoadLibrary returns %x", hddrawlib);
  306. if (hddrawlib)
  307. pfnGetSurfaceFromDC = (PFN_GETSURFACEFROMDC)GetProcAddress(
  308. hddrawlib, "GetSurfaceFromDC");
  309. }
  310. //
  311. // check if it is DIRECTDRAW surface
  312. //
  313. HDC hdcDevice;
  314. if (pfnGetSurfaceFromDC && (pfnGetSurfaceFromDC(pDibInfo->hdc, &pDibInfo->pdds, &hdcDevice) == DD_OK))
  315. {
  316. bddraw = TRUE;
  317. Dprintf("pfnGetSurfaceFromDC succeed\n");
  318. //pdds->GetSurfaceDesc(&ddsd);
  319. //
  320. // we need to lock the surface here
  321. //
  322. if (pDibInfo->pdds->Lock((RECT *)&pDibInfo->rclBounds, &pDibInfo->ddsd, DDLOCK_SURFACEMEMORYPTR, NULL) == DD_OK)
  323. {
  324. pDibInfo->pvBits = pDibInfo->ddsd.lpSurface;
  325. pDibInfo->pvBase = pDibInfo->ddsd.lpSurface;
  326. pDibInfo->stride = pDibInfo->ddsd.lPitch;
  327. pDibInfo->pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  328. pDibInfo->pbmi->bmiHeader.biCompression = BI_RGB;
  329. pDibInfo->pbmi->bmiHeader.biPlanes = 1;
  330. pDibInfo->pbmi->bmiHeader.biWidth = pDibInfo->ddsd.dwWidth;
  331. pDibInfo->pbmi->bmiHeader.biHeight = pDibInfo->ddsd.dwHeight;
  332. switch (pDibInfo->ddsd.ddpfPixelFormat.dwRGBBitCount)
  333. {
  334. case DDBD_1:
  335. pDibInfo->pbmi->bmiHeader.biBitCount = 1;
  336. break;
  337. case DDBD_4:
  338. pDibInfo->pbmi->bmiHeader.biBitCount = 4;
  339. break;
  340. case DDBD_8:
  341. pDibInfo->pbmi->bmiHeader.biBitCount = 8;
  342. bFillColorTable (pDibInfo->hdc, 0, pDibInfo->pbmi);
  343. break;
  344. case DDBD_16:
  345. pDibInfo->pbmi->bmiHeader.biBitCount = 16;
  346. *(DWORD *)&pDibInfo->pbmi->bmiColors[0] = pDibInfo->ddsd.ddpfPixelFormat.dwRBitMask;
  347. *(DWORD *)&pDibInfo->pbmi->bmiColors[1] = pDibInfo->ddsd.ddpfPixelFormat.dwGBitMask;
  348. *(DWORD *)&pDibInfo->pbmi->bmiColors[2] = pDibInfo->ddsd.ddpfPixelFormat.dwBBitMask;
  349. break;
  350. case DDBD_24:
  351. pDibInfo->pbmi->bmiHeader.biBitCount = 24;
  352. break;
  353. case DDBD_32:
  354. pDibInfo->pbmi->bmiHeader.biBitCount = 32;
  355. break;
  356. default:
  357. WARNING("bad bitformat for ddraw surface\n");
  358. }
  359. pDibInfo->rclClipDC.left = 0;
  360. pDibInfo->rclClipDC.top =0;
  361. pDibInfo->rclClipDC.right = pDibInfo->ddsd.dwWidth;
  362. pDibInfo->rclClipDC.bottom = pDibInfo->ddsd.dwWidth;
  363. bRet = TRUE;
  364. }
  365. }
  366. if (hddrawlib)
  367. {
  368. FreeLibrary(hddrawlib);
  369. }
  370. }
  371. Dprintf ("bddraw = %x\n", bddraw);
  372. #if 0
  373. if (bddraw)
  374. {
  375. Dprintf("is a directdraw surf dsbm.bmbits = %x", pDibInfo->pvBits);
  376. Dprintf("bmType=%x, bmWidthBytes = %x", dib.dsBm.bmType, dib.dsBm.bmWidthBytes);
  377. Dprintf("bmWidth = %x, bmHeight = %x, bmPlanes = %x, bmBitsPixel = %x\n",
  378. dib.dsBm.bmWidth, dib.dsBm.bmHeight, dib.dsBm.bmPlanes, dib.dsBm.bmBitsPixel);
  379. Dprintf("dsBmh.biSize=%x, biWidth = %x, biHeight = %x\n",
  380. dib.dsBmih.biSize, dib.dsBmih.biWidth, dib.dsBmih.biHeight);
  381. Dprintf("dsBmh.biPlanes = %x, biBitCount = %x, biCompression = %x, biSizeImage = %x\n",
  382. dib.dsBmih.biPlanes, dib.dsBmih.biBitCount, dib.dsBmih.biSizeImage);
  383. }
  384. #endif
  385. if (!bddraw)
  386. {
  387. //
  388. // If biHeight is positive, then the bitmap is a bottom-up DIB.
  389. // If biHeight is negative, then the bitmap is a top-down DIB.
  390. //
  391. if ( dib.dsBmih.biHeight > 0 )
  392. {
  393. pDibInfo->pvBase = (PVOID) (((int) dib.dsBm.bmBits) + (dib.dsBm.bmWidthBytes *
  394. (dib.dsBm.bmHeight - 1)));
  395. pDibInfo->stride = (ULONG) (-dib.dsBm.bmWidthBytes);
  396. }
  397. else
  398. {
  399. pDibInfo->pvBase = dib.dsBm.bmBits;
  400. pDibInfo->stride = dib.dsBm.bmWidthBytes;
  401. }
  402. //
  403. // fill up the BITMAPINFOHEADER
  404. //
  405. pDibInfo->pbmi->bmiHeader = dib.dsBmih;
  406. //
  407. // fill up the color table
  408. //
  409. if ((pDibInfo->pbmi->bmiHeader.biBitCount <= 8) || ( pDibInfo->pbmi->bmiHeader.biCompression == BI_BITFIELDS ))
  410. {
  411. ULONG count = 1 << pDibInfo->pbmi->bmiHeader.biBitCount;
  412. GetDIBits(pDibInfo->hdc, hbm, 0, pDibInfo->pbmi->bmiHeader.biHeight, NULL, pDibInfo->pbmi,
  413. DIB_RGB_COLORS);
  414. }
  415. //
  416. // fill prcl
  417. //
  418. pDibInfo->rclClipDC.left = 0;
  419. pDibInfo->rclClipDC.top = 0;
  420. pDibInfo->rclClipDC.right = dib.dsBm.bmWidth;
  421. pDibInfo->rclClipDC.bottom = dib.dsBm.bmHeight;
  422. if (pDibInfo->rclClipDC.bottom < 0)
  423. {
  424. pDibInfo->rclClipDC.bottom = -pDibInfo->rclClipDC.bottom;
  425. }
  426. bRet = TRUE;
  427. }
  428. }
  429. else
  430. {
  431. Dprintf("not a dibseciton");
  432. }
  433. }
  434. return(bRet);
  435. }
  436. /******************************Public*Routine******************************\
  437. * bFillBimapInfo
  438. *
  439. * Fill up the BITMAPINFO structure based on the hdc passed in
  440. * and fill up the window(if direct dc) or surface (if memory dc)
  441. * rectangle.
  442. *
  443. * if it's a dibsection, convert DIBSECTION to BITMAPINFO
  444. *
  445. * Returns:
  446. * BOOLEAN
  447. *
  448. * History:
  449. * 09-Dec-1996 -by- Lingyun Wang [lingyunw]
  450. * Wrote it.
  451. \**************************************************************************/
  452. BOOL bFillBitmapInfo(
  453. PDIBINFO pDibInfo
  454. // HDC hdc,
  455. // RECTL *prcl,
  456. // PBITMAPINFO pbmi,
  457. // PVOID *ppvBits,
  458. // PVOID *ppvBase,
  459. // LONG *plStride
  460. )
  461. {
  462. BOOL bRet = FALSE;
  463. {
  464. //
  465. // fill up a BITMAPINFO structure compatible with the
  466. // Destination DC and reduce ulWidth and ulHeight if
  467. // possible
  468. //
  469. if (GetObjectType(pDibInfo->hdc) == OBJ_DC)
  470. {
  471. //
  472. // get the destination bitmapinfo struct
  473. //
  474. if (bRet = bFillBitmapInfoDirect(pDibInfo->hdc, 0, pDibInfo->pbmi))
  475. {
  476. HWND hwnd = WindowFromDC(pDibInfo->hdc);
  477. if (hwnd)
  478. {
  479. GetClientRect(hwnd,(RECT *)&pDibInfo->rclClipDC);
  480. }
  481. }
  482. }
  483. else if (GetObjectType(pDibInfo->hdc) == OBJ_MEMDC)
  484. {
  485. if (!(bRet = bFillDIBSection (pDibInfo)))
  486. {
  487. //
  488. // if the bitmap selected in the memory dc is NOT
  489. // a DIBSECTION, call bFillBitmapInfoMemory
  490. //
  491. if (bRet = bFillBitmapInfoMemory(pDibInfo->hdc, 0, pDibInfo->pbmi))
  492. {
  493. pDibInfo->rclClipDC.left = 0;
  494. pDibInfo->rclClipDC.top = 0;
  495. pDibInfo->rclClipDC.right = pDibInfo->pbmi->bmiHeader.biWidth;
  496. pDibInfo->rclClipDC.bottom = pDibInfo->pbmi->bmiHeader.biHeight;
  497. if (pDibInfo->rclClipDC.bottom < 0)
  498. {
  499. pDibInfo->rclClipDC.bottom = -pDibInfo->rclClipDC.bottom;
  500. }
  501. }
  502. }
  503. }
  504. }
  505. return(bRet);
  506. }
  507. /******************************Public*Routine******************************\
  508. * bSameDIBformat
  509. *
  510. * Given two BITMAPINFO structs and compare if they are the same
  511. *
  512. * Returns:
  513. * VOID
  514. *
  515. * History:
  516. * 09-Dec-1996 -by- Lingyun Wang [lingyunw]
  517. * Wrote it.
  518. \**************************************************************************/
  519. BOOL bSameDIBformat (
  520. PBITMAPINFO pbmiDst,
  521. PBITMAPINFO pbmiSrc)
  522. {
  523. BOOL bRet = FALSE;
  524. if ((pbmiDst->bmiHeader.biBitCount == pbmiSrc->bmiHeader.biBitCount) &&
  525. (pbmiDst->bmiHeader.biCompression == pbmiSrc->bmiHeader.biCompression))
  526. {
  527. bRet = TRUE;
  528. //
  529. // compare bit Bitfields masks
  530. //
  531. if (pbmiDst->bmiHeader.biCompression == BI_BITFIELDS)
  532. {
  533. if ((*(DWORD *)&pbmiDst->bmiColors[0] != *(DWORD *)&pbmiSrc->bmiColors[0]) ||
  534. (*(DWORD *)&pbmiDst->bmiColors[1] != *(DWORD *)&pbmiSrc->bmiColors[1]) ||
  535. (*(DWORD *)&pbmiDst->bmiColors[2] != *(DWORD *)&pbmiSrc->bmiColors[2]))
  536. {
  537. bRet = FALSE;
  538. }
  539. }
  540. //
  541. // compare color table
  542. //
  543. if (pbmiDst->bmiHeader.biBitCount <= 8)
  544. {
  545. ULONG cColors = 1 << pbmiDst->bmiHeader.biBitCount;
  546. ULONG i;
  547. for (i = 0; i < cColors; i++)
  548. {
  549. if ((pbmiDst->bmiColors[i].rgbBlue != pbmiSrc->bmiColors[i].rgbBlue) ||
  550. (pbmiDst->bmiColors[i].rgbGreen != pbmiSrc->bmiColors[i].rgbGreen) ||
  551. (pbmiDst->bmiColors[i].rgbRed != pbmiSrc->bmiColors[i].rgbRed))
  552. {
  553. return (FALSE);
  554. }
  555. }
  556. }
  557. }
  558. return (bRet);
  559. }
  560. /******************************Public*Routine******************************\
  561. * CreateCompatibleDIB
  562. *
  563. * Create a DIB_RGB_COLORS dib section based on the given width/height and pbmi
  564. *
  565. * Returns:
  566. * Bitmap handle
  567. *
  568. * History:
  569. * 09-Dec-1996 -by- Lingyun Wang [lingyunw]
  570. * Wrote it.
  571. \**************************************************************************/
  572. HBITMAP CreateCompatibleDIB (
  573. HDC hdc,
  574. ULONG ulWidth,
  575. ULONG ulHeight,
  576. PVOID *ppvBits,
  577. PBITMAPINFO pbmi)
  578. {
  579. HBITMAP hbm;
  580. //
  581. // Change bitmap size to match specified dimensions.
  582. //
  583. pbmi->bmiHeader.biWidth = ulWidth;
  584. pbmi->bmiHeader.biHeight = ulHeight;
  585. if (pbmi->bmiHeader.biCompression == BI_RGB)
  586. {
  587. pbmi->bmiHeader.biSizeImage = 0;
  588. }
  589. else
  590. {
  591. if ( pbmi->bmiHeader.biBitCount == 16 )
  592. pbmi->bmiHeader.biSizeImage = ulWidth * ulHeight * 2;
  593. else if ( pbmi->bmiHeader.biBitCount == 32 )
  594. pbmi->bmiHeader.biSizeImage = ulWidth * ulHeight * 4;
  595. else
  596. pbmi->bmiHeader.biSizeImage = 0;
  597. }
  598. pbmi->bmiHeader.biClrUsed = 0;
  599. pbmi->bmiHeader.biClrImportant = 0;
  600. hbm = CreateDIBSection(hdc, (PBITMAPINFO)pbmi, DIB_RGB_COLORS, ppvBits, NULL, 0);
  601. return (hbm);
  602. }
  603. /******************************Public*Routine******************************\
  604. * GetCompatibleDIBInfo
  605. *
  606. * Copies pointer to bitmap origin to ppvBase and bitmap stride to plStride.
  607. * Win32 DIBs can be created bottom-up (the default) with the origin at the
  608. * lower left corner or top-down with the origin at the upper left corner.
  609. * If the bitmap is top-down, *plStride is positive; if bottom-up, *plStride
  610. * us negative.
  611. *
  612. * Also, because of restrictions on the alignment of scan lines the width
  613. * the bitmap is often not the same as the stride (stride is the number of
  614. * bytes between vertically adjacent pixels).
  615. *
  616. * The ppvBase and plStride value returned will allow you to address any
  617. * given pixel (x, y) in the bitmap as follows:
  618. *
  619. * PIXEL *ppix;
  620. *
  621. * ppix = (PIXEL *) (((BYTE *)*ppvBase) + (y * *plStride) + (x * sizeof(PIXEL)));
  622. *
  623. * Returns:
  624. * TRUE if successful, FALSE otherwise.
  625. *
  626. * History:
  627. * 02-Feb-1996 -by- Gilman Wong [gilmanw]
  628. * Wrote it.
  629. \**************************************************************************/
  630. BOOL GetCompatibleDIBInfo(HBITMAP hbm, PVOID *ppvBase, LONG *plStride)
  631. {
  632. BOOL bRet = FALSE;
  633. DIBSECTION ds;
  634. //
  635. // Call GetObject to return a DIBSECTION. If successful, the
  636. // bitmap is a DIB section and we can retrieve the pointer to
  637. // the bitmap bits and other parameters.
  638. //
  639. if ( (GetObject(hbm, sizeof(ds), &ds) == sizeof(ds))
  640. && ds.dsBm.bmBits )
  641. {
  642. //!!!dbug -- GDI Bug 19374: bmWidthBytes returns pitch assuming
  643. //!!! that DIB scanlines are WORD aligned (as they
  644. //!!! are in Win95). But NT DIBs are DWORD aligned.
  645. //!!! When bug if corrected, we can remove this block of
  646. //!!! code.
  647. {
  648. OSVERSIONINFO osvi;
  649. osvi.dwOSVersionInfoSize = sizeof(osvi);
  650. if (GetVersionEx(&osvi))
  651. {
  652. if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
  653. {
  654. ds.dsBm.bmWidthBytes = (ds.dsBm.bmWidthBytes + 3) & ~3;
  655. }
  656. }
  657. else
  658. {
  659. return bRet;
  660. }
  661. }
  662. //
  663. // If biHeight is positive, then the bitmap is a bottom-up DIB.
  664. // If biHeight is negative, then the bitmap is a top-down DIB.
  665. //
  666. if ( ds.dsBmih.biHeight > 0 )
  667. {
  668. *ppvBase = (PVOID) (((int) ds.dsBm.bmBits) + (ds.dsBm.bmWidthBytes * (ds.dsBm.bmHeight - 1)));
  669. *plStride = (ULONG) (-ds.dsBm.bmWidthBytes);
  670. }
  671. else
  672. {
  673. *ppvBase = ds.dsBm.bmBits;
  674. *plStride = ds.dsBm.bmWidthBytes;
  675. }
  676. bRet = TRUE;
  677. }
  678. else
  679. {
  680. WARNING("GetCompatibleDIBInfo: cannot get pointer to DIBSECTION bmBits\n");
  681. }
  682. return bRet;
  683. }
  684. /******************************************************
  685. * bSetupBitmapInfos
  686. *
  687. * Calls bFillBitmapInfo to fill the Dst and Src DIBINFO
  688. *
  689. * 4/4/97 -- by Lingyun Wang [lingyunw]
  690. *******************************************************/
  691. BOOL bSetupBitmapInfos(
  692. PDIBINFO pDibInfoDst,
  693. PDIBINFO pDibInfoSrc
  694. )
  695. {
  696. BOOL bRet;
  697. bRet = bFillBitmapInfo (pDibInfoDst);
  698. //
  699. // fill up bitmapinfo if it is not coming from TransparentDIBits
  700. //
  701. if (bRet && (pDibInfoSrc != NULL))
  702. {
  703. if (pDibInfoSrc->hdc != NULL)
  704. {
  705. bRet = bFillBitmapInfo (pDibInfoSrc);
  706. }
  707. else
  708. {
  709. //
  710. // src is DIB
  711. //
  712. pDibInfoSrc->rclClipDC.left = 0;
  713. pDibInfoSrc->rclClipDC.right = pDibInfoSrc->pbmi->bmiHeader.biWidth;
  714. pDibInfoSrc->rclClipDC.top = 0;
  715. pDibInfoSrc->rclClipDC.bottom = pDibInfoSrc->pbmi->bmiHeader.biHeight;
  716. if (pDibInfoSrc->rclClipDC.bottom < 0)
  717. {
  718. pDibInfoSrc->rclClipDC.bottom = -pDibInfoSrc->rclClipDC.bottom;
  719. }
  720. }
  721. }
  722. return (bRet);
  723. }
  724. /******************************Public*Routine******************************\
  725. * vCopyBitmapInfo
  726. *
  727. * Copy a BITMAPINFO stucture along with its bit masks or colortable
  728. *
  729. * Returns:
  730. * VOID.
  731. *
  732. * History:
  733. * 16-Dec-1996 -by- Lingyun Wang [lingyunw]
  734. * Wrote it.
  735. \**************************************************************************/
  736. VOID vCopyBitmapInfo (
  737. PBITMAPINFO pbmiTo,
  738. PBITMAPINFO pbmiFrom
  739. )
  740. {
  741. *pbmiTo = *pbmiFrom;
  742. //
  743. // copy BitFields masks
  744. //
  745. if (pbmiFrom->bmiHeader.biCompression == BI_BITFIELDS)
  746. {
  747. pbmiTo->bmiColors[0] = pbmiFrom->bmiColors[0];
  748. pbmiTo->bmiColors[1] = pbmiFrom->bmiColors[1];
  749. pbmiTo->bmiColors[2] = pbmiFrom->bmiColors[2];
  750. }
  751. else
  752. {
  753. //
  754. // copy color table
  755. //
  756. ULONG cMaxColors = 1 << pbmiFrom->bmiHeader.biBitCount;
  757. ULONG cColors = pbmiFrom->bmiHeader.biClrUsed;
  758. //
  759. // validate number of colors
  760. //
  761. if ((cColors == 0) || (cColors > cMaxColors))
  762. {
  763. cColors = cMaxColors;
  764. }
  765. if (cColors <= 256)
  766. {
  767. UINT i;
  768. for (i = 0; i < cColors; i++)
  769. {
  770. pbmiTo->bmiColors[i] = pbmiFrom->bmiColors[i];
  771. }
  772. }
  773. }
  774. return;
  775. }
  776. /**************************************************************************\
  777. * vIndexToRGB
  778. *
  779. *
  780. * Arguments:
  781. *
  782. *
  783. *
  784. * Return Value:
  785. *
  786. *
  787. *
  788. * History:
  789. *
  790. * 4/16/1997 -by- Lingyun Wang [lingyunw]
  791. *
  792. \**************************************************************************/
  793. VOID vIndexToRGB (
  794. RGBQUAD *pIndex,
  795. RGBQUAD *pColors,
  796. ULONG count)
  797. {
  798. ULONG i;
  799. if (count > 256)
  800. {
  801. WARNING ("vIndexToRGB -- bad count\n");
  802. return;
  803. }
  804. for (i=0; i < count; i++)
  805. {
  806. pIndex[i] = pColors[((ULONG *)pIndex)[i]];
  807. }
  808. return;
  809. }
  810. #if 1
  811. /******************************Public*Routine******************************\
  812. * vMapPALtoRGB
  813. *
  814. * Given a DIB_PAL_COLORS iusage bmiColors table, convert the indices into RGB
  815. * colors, the bmiColors table will be a DIB_RGB_COLORS table after the convertion.
  816. *
  817. * Returns:
  818. * VOID.
  819. *
  820. * History:
  821. * 16-Dec-1996 -by- Lingyun Wang [lingyunw]
  822. * Wrote it.
  823. \**************************************************************************/
  824. VOID
  825. vMapPALtoRGB(
  826. PDIBINFO pDibInfoDst,
  827. PDIBINFO pDibInfoSrc,
  828. ULONG TransColor)
  829. {
  830. //
  831. // only called in DIB API case
  832. //
  833. if (pDibInfoSrc->hdc == NULL)
  834. {
  835. PBITMAPINFO pbmi = (PBITMAPINFO)LOCALALLOC(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255);
  836. if (pbmi)
  837. {
  838. ZeroMemory (pbmi,sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255);
  839. vCopyBitmapInfo(pbmi, pDibInfoSrc->pbmi);
  840. HPALETTE hpalDC = (HPALETTE)GetCurrentObject(pDibInfoDst->hdc,OBJ_PAL);
  841. if (hpalDC)
  842. {
  843. USHORT usNumPaletteEntries = 0;
  844. DWORD numColors;
  845. DWORD bmiClrUsed = pDibInfoSrc->pbmi->bmiHeader.biClrUsed;
  846. int iRet = GetObject(hpalDC,2,&usNumPaletteEntries);
  847. if ((iRet != 0) && (usNumPaletteEntries != 0))
  848. {
  849. switch (pDibInfoSrc->pbmi->bmiHeader.biBitCount)
  850. {
  851. case 1:
  852. numColors = 2;
  853. break;
  854. case 4:
  855. numColors = 16;
  856. if ((bmiClrUsed > 0) &&
  857. (bmiClrUsed < 16)
  858. )
  859. {
  860. numColors = bmiClrUsed;
  861. }
  862. break;
  863. case 8:
  864. numColors = 256;
  865. if ((bmiClrUsed > 0) &&
  866. (bmiClrUsed < 256)
  867. )
  868. {
  869. numColors = bmiClrUsed;
  870. }
  871. break;
  872. default:
  873. numColors = 0;
  874. }
  875. if (numColors != 0)
  876. {
  877. PALETTEENTRY *ppal = (PALETTEENTRY *)LOCALALLOC(sizeof(PALETTEENTRY) * usNumPaletteEntries);
  878. if (ppal)
  879. {
  880. iRet = GetPaletteEntries(hpalDC,0,usNumPaletteEntries,ppal);
  881. if (iRet == (int)usNumPaletteEntries)
  882. {
  883. ULONG Index;
  884. RGBQUAD *pRGB = (RGBQUAD *)&pbmi->bmiColors[0];
  885. PUSHORT pPalIndex = (PUSHORT)&pDibInfoSrc->pbmi->bmiColors[0];
  886. //
  887. // map PALETTEENTRY to RGBQUAD
  888. //
  889. for (Index=0;Index<numColors;Index++)
  890. {
  891. ULONG CurIndex = pPalIndex[Index];
  892. if (CurIndex > usNumPaletteEntries)
  893. {
  894. CurIndex = CurIndex % usNumPaletteEntries;
  895. }
  896. pRGB[Index].rgbRed = ppal[CurIndex].peRed;
  897. pRGB[Index].rgbGreen = ppal[CurIndex].peGreen;
  898. pRGB[Index].rgbBlue = ppal[CurIndex].peBlue;
  899. pRGB[Index].rgbReserved = ppal[CurIndex].peFlags;
  900. }
  901. //
  902. // swap pbmi in pDibInfoSrc
  903. //
  904. LOCALFREE(pDibInfoSrc->pbmi);
  905. pDibInfoSrc->pbmi = pbmi;
  906. }
  907. LOCALFREE(ppal);
  908. }
  909. }
  910. }
  911. }
  912. }
  913. }
  914. }
  915. #else
  916. /******************************Public*Routine******************************\
  917. * vMapPALtoRGB
  918. *
  919. * Given a DIB_PAL_COLORS iusage bmiColors table, convert the indices into RGB
  920. * colors, the bmiColors table will be a DIB_RGB_COLORS table after the convertion.
  921. *
  922. * Returns:
  923. * VOID.
  924. *
  925. * History:
  926. * 16-Dec-1996 -by- Lingyun Wang [lingyunw]
  927. * Wrote it.
  928. \**************************************************************************/
  929. VOID
  930. vMapPALtoRGB(
  931. PDIBINFO pDibInfoDst,
  932. PDIBINFO pDibInfoSrc,
  933. ULONG TransColor)
  934. {
  935. HDC hdc = pDibInfoDst->hdc;
  936. HDC hdcMem;
  937. ULONG cx = 1 << pDibInfoSrc->pbmi->bmiHeader.biBitCount;
  938. HBITMAP hbm;
  939. PULONG pBits;
  940. ULONG cBytes = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 2;
  941. PBITMAPINFO pbmi;
  942. ULONG i;
  943. BYTE pBytes[256];
  944. ULONG ulWidthDst, ulHeightDst, ulWidthSrc, ulHeightSrc;
  945. HPALETTE hpalDC;
  946. pbmi = (PBITMAPINFO)LOCALALLOC(cBytes);
  947. if (pbmi == NULL)
  948. {
  949. WARNING("MapCopy fail to alloc mem\n");
  950. return ;
  951. }
  952. hdcMem = CreateCompatibleDC (hdc);
  953. if (hdcMem != NULL)
  954. {
  955. HPALETTE hpalDC = (HPALETTE)GetCurrentObject(hdc,OBJ_PAL);
  956. SelectPalette(hdcMem,hpalDC,TRUE);
  957. RealizePalette(hdcMem);
  958. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  959. pbmi->bmiHeader.biWidth = 256;
  960. pbmi->bmiHeader.biHeight = 1;
  961. pbmi->bmiHeader.biPlanes = 1;
  962. pbmi->bmiHeader.biBitCount = 32;
  963. pbmi->bmiHeader.biCompression = BI_RGB;
  964. pbmi->bmiHeader.biSizeImage = 0;
  965. pbmi->bmiHeader.biXPelsPerMeter = 0;
  966. pbmi->bmiHeader.biYPelsPerMeter = 0;
  967. pbmi->bmiHeader.biClrUsed = 0;
  968. pbmi->bmiHeader.biClrImportant = 0;
  969. //
  970. // save the original width/height
  971. //
  972. ulWidthDst = pDibInfoDst->pbmi->bmiHeader.biWidth;
  973. ulHeightDst = pDibInfoDst->pbmi->bmiHeader.biHeight;
  974. pDibInfoDst->pbmi->bmiHeader.biWidth = 256;
  975. pDibInfoDst->pbmi->bmiHeader.biHeight = 1;
  976. //
  977. // create a dib using 32 format
  978. //
  979. hbm = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (PVOID *)&pBits, NULL, 0);
  980. if ((hbm != NULL) && (SelectObject(hdcMem,hbm) != NULL))
  981. {
  982. //
  983. // init pBytes to array of each pixel
  984. //
  985. switch (cx)
  986. {
  987. case 256:
  988. for (i=0; i < cx; i++)
  989. {
  990. pBytes[i] = (BYTE)i;
  991. }
  992. break;
  993. case 16:
  994. pBytes[0] = 0x01;
  995. pBytes[1] = 0x23;
  996. pBytes[2] = 0x45;
  997. pBytes[3] = 0x67;
  998. pBytes[4] = 0x89;
  999. pBytes[5] = 0xab;
  1000. pBytes[6] = 0xcd;
  1001. pBytes[7] = 0xef;
  1002. break;
  1003. case 2:
  1004. pBytes[0] = 0x40;
  1005. break;
  1006. }
  1007. ulWidthSrc = pDibInfoSrc->pbmi->bmiHeader.biWidth;
  1008. ulHeightSrc = pDibInfoSrc->pbmi->bmiHeader.biHeight;
  1009. pDibInfoSrc->pbmi->bmiHeader.biWidth = cx;
  1010. pDibInfoSrc->pbmi->bmiHeader.biHeight = 1;
  1011. if (!SetDIBitsToDevice (hdcMem, 0, 0, cx, 1, 0, 0, 0, 1, pBytes, pDibInfoSrc->pbmi, DIB_PAL_COLORS))
  1012. {
  1013. //Dprintf("fail to SetDIBitsTodevice HDC=%x\n",hdcMem);
  1014. }
  1015. for (i=0; i < cx; i++)
  1016. {
  1017. pDibInfoSrc->pbmi->bmiColors[i] = ((RGBQUAD *)pBits)[i];
  1018. //Dprintf("i=%x, pBits[i]=%x", i, pBits[i]);
  1019. }
  1020. pDibInfoSrc->pbmi->bmiHeader.biWidth = ulWidthSrc;
  1021. pDibInfoSrc->pbmi->bmiHeader.biHeight = ulHeightSrc;
  1022. pDibInfoDst->pbmi->bmiHeader.biWidth = ulWidthDst;
  1023. pDibInfoDst->pbmi->bmiHeader.biHeight = ulHeightDst;
  1024. pDibInfoSrc->iUsage = DIB_RGB_COLORS;
  1025. }
  1026. DeleteDC (hdcMem);
  1027. if (hbm != NULL)
  1028. {
  1029. DeleteObject(hbm);
  1030. }
  1031. }
  1032. }
  1033. #endif
  1034. /**************************************************************************\
  1035. * bGetSrcDIBits:
  1036. *
  1037. * Setup SRC DIB surface and retrieve the dibits.
  1038. * Ported from kernel mode
  1039. *
  1040. * Arguments:
  1041. *
  1042. * pDibInfoDst - information on dest surface
  1043. * pDibInfoSrc - information on src surfcace
  1044. * ulSourceType - type of src surface needed
  1045. * ulTranColor - transparent color for TransparentBlt
  1046. *
  1047. * Return Value:
  1048. *
  1049. * Status
  1050. *
  1051. * History:
  1052. *
  1053. * 4/16/1997 - by Lingyun Wang [lingyunw]
  1054. *
  1055. \**************************************************************************/
  1056. BOOL
  1057. bGetSrcDIBits(
  1058. PDIBINFO pDibInfoDst,
  1059. PDIBINFO pDibInfoSrc,
  1060. ULONG ulSourceType,
  1061. ULONG ulTranColor
  1062. )
  1063. {
  1064. BOOL bRet = TRUE;
  1065. LONG DstCx = pDibInfoDst->rclBounds.right - pDibInfoDst->rclBounds.left;
  1066. LONG DstCy = pDibInfoDst->rclBounds.bottom - pDibInfoDst->rclBounds.top;
  1067. LONG SrcCx = pDibInfoSrc->rclBounds.right - pDibInfoSrc->rclBounds.left;
  1068. LONG SrcCy = pDibInfoSrc->rclBounds.bottom - pDibInfoSrc->rclBounds.top;
  1069. PVOID pvBits = pDibInfoSrc->pvBits;
  1070. PBITMAPINFO pbmi = NULL;
  1071. HDC hdcTemp = NULL;
  1072. HBITMAP hbm;
  1073. LONG SrcTrimLeft;
  1074. LONG SrcTrimRight;
  1075. LONG SrcTrimTop;
  1076. LONG SrcTrimBottom;
  1077. BOOL bStretch = ((DstCx != SrcCx) || (DstCy != SrcCy));
  1078. SrcTrimLeft = 0;
  1079. SrcTrimRight = 0;
  1080. SrcTrimTop = 0;
  1081. SrcTrimBottom = 0;
  1082. //
  1083. // trim destination bounds rect to surface bounds. Src rect must also
  1084. // be trimmed by same amount (in src space)
  1085. //
  1086. if (pDibInfoDst->rclBoundsTrim.left < pDibInfoDst->rclClipDC.left)
  1087. {
  1088. SrcTrimLeft = pDibInfoDst->rclClipDC.left - pDibInfoDst->rclBoundsTrim.left;
  1089. pDibInfoDst->rclBoundsTrim.left = pDibInfoDst->rclClipDC.left;
  1090. }
  1091. if (pDibInfoDst->rclBoundsTrim.top < pDibInfoDst->rclClipDC.top)
  1092. {
  1093. SrcTrimTop = pDibInfoDst->rclClipDC.top - pDibInfoDst->rclBoundsTrim.top;
  1094. pDibInfoDst->rclBoundsTrim.top = pDibInfoDst->rclClipDC.top;
  1095. }
  1096. if (pDibInfoDst->rclBoundsTrim.right > pDibInfoDst->rclClipDC.right)
  1097. {
  1098. SrcTrimRight = pDibInfoDst->rclBoundsTrim.right - pDibInfoDst->rclClipDC.right;
  1099. pDibInfoDst->rclBoundsTrim.right = pDibInfoDst->rclClipDC.right;
  1100. }
  1101. if (pDibInfoDst->rclBoundsTrim.bottom > pDibInfoDst->rclClipDC.bottom)
  1102. {
  1103. SrcTrimBottom = pDibInfoDst->rclBoundsTrim.bottom - pDibInfoDst->rclClipDC.bottom;
  1104. pDibInfoDst->rclBoundsTrim.bottom = pDibInfoDst->rclClipDC.bottom;
  1105. }
  1106. //
  1107. // does src need to be reduced because of dst
  1108. //
  1109. if (bStretch)
  1110. {
  1111. //
  1112. // convert dst trim to src space and reduce src rect
  1113. //
  1114. // WARNING: ROUNDING
  1115. //
  1116. if ((SrcTrimLeft != 0) || (SrcTrimRight != 0))
  1117. {
  1118. double fDstToSrcX = (double)SrcCx / (double)DstCx;
  1119. //
  1120. // convert dst trim amound to src
  1121. //
  1122. SrcTrimLeft = (LONG)((double)SrcTrimLeft * fDstToSrcX);
  1123. SrcTrimRight = (LONG)((double)SrcTrimRight * fDstToSrcX);
  1124. pDibInfoSrc->rclBoundsTrim.left += SrcTrimLeft;
  1125. pDibInfoSrc->rclBoundsTrim.right -= SrcTrimRight;
  1126. }
  1127. if ((SrcTrimTop != 0) || (SrcTrimBottom != 0))
  1128. {
  1129. double fDstToSrcY = (double)SrcCy / (double)DstCy;
  1130. //
  1131. // convert dst trim amound to src
  1132. //
  1133. SrcTrimTop = (LONG)((double)SrcTrimTop * fDstToSrcY);
  1134. SrcTrimBottom = (LONG)((double)SrcTrimBottom * fDstToSrcY);
  1135. pDibInfoSrc->rclBoundsTrim.top += SrcTrimTop;
  1136. pDibInfoSrc->rclBoundsTrim.bottom -= SrcTrimBottom;
  1137. }
  1138. }
  1139. else
  1140. {
  1141. //
  1142. // reduce src rect
  1143. //
  1144. if (SrcTrimLeft != 0)
  1145. {
  1146. pDibInfoSrc->rclBoundsTrim.left += SrcTrimLeft;
  1147. }
  1148. if (SrcTrimRight != 0)
  1149. {
  1150. pDibInfoSrc->rclBoundsTrim.right -= SrcTrimRight;
  1151. }
  1152. if (SrcTrimTop != 0)
  1153. {
  1154. pDibInfoSrc->rclBoundsTrim.top += SrcTrimTop;
  1155. }
  1156. if (SrcTrimBottom != 0)
  1157. {
  1158. pDibInfoSrc->rclBoundsTrim.bottom -= SrcTrimBottom;
  1159. }
  1160. }
  1161. //
  1162. // Does src still exceed bounds
  1163. //
  1164. SrcTrimLeft = 0;
  1165. SrcTrimRight = 0;
  1166. SrcTrimTop = 0;
  1167. SrcTrimBottom = 0;
  1168. //
  1169. // trim destination bounds rect to surface bounds. Src rect must also
  1170. // be trimmed by same amount (in src space)
  1171. //
  1172. if (pDibInfoSrc->rclBoundsTrim.left < pDibInfoSrc->rclClipDC.left)
  1173. {
  1174. SrcTrimLeft = pDibInfoSrc->rclClipDC.left - pDibInfoSrc->rclBoundsTrim.left;
  1175. pDibInfoSrc->rclBoundsTrim.left = pDibInfoSrc->rclClipDC.left;
  1176. }
  1177. if (pDibInfoSrc->rclBoundsTrim.top < pDibInfoSrc->rclClipDC.top)
  1178. {
  1179. SrcTrimTop = pDibInfoSrc->rclClipDC.top - pDibInfoSrc->rclBoundsTrim.top;
  1180. pDibInfoSrc->rclBoundsTrim.top = pDibInfoSrc->rclClipDC.top;
  1181. }
  1182. if (pDibInfoSrc->rclBoundsTrim.right > pDibInfoSrc->rclClipDC.right)
  1183. {
  1184. SrcTrimRight = pDibInfoSrc->rclBoundsTrim.right - pDibInfoSrc->rclClipDC.right;
  1185. pDibInfoSrc->rclBoundsTrim.right = pDibInfoSrc->rclClipDC.right;
  1186. }
  1187. if (pDibInfoSrc->rclBoundsTrim.bottom > pDibInfoSrc->rclClipDC.bottom)
  1188. {
  1189. SrcTrimBottom = pDibInfoSrc->rclBoundsTrim.bottom - pDibInfoSrc->rclClipDC.bottom;
  1190. pDibInfoSrc->rclBoundsTrim.bottom = pDibInfoSrc->rclClipDC.bottom;
  1191. }
  1192. //
  1193. // does Dst need to be reduced because of Src
  1194. //
  1195. if (bStretch)
  1196. {
  1197. //
  1198. // WARNING: ROUNDING
  1199. //
  1200. if ((SrcTrimLeft != 0) || (SrcTrimRight != 0))
  1201. {
  1202. double fSrcToDstX = (double)DstCx / (double)SrcCx;
  1203. //
  1204. // convert dst trim amound to src
  1205. //
  1206. SrcTrimLeft = (LONG)((double)SrcTrimLeft * fSrcToDstX);
  1207. SrcTrimRight = (LONG)((double)SrcTrimRight * fSrcToDstX);
  1208. pDibInfoDst->rclBoundsTrim.left += SrcTrimLeft;
  1209. pDibInfoDst->rclBoundsTrim.right -= SrcTrimRight;
  1210. }
  1211. if ((SrcTrimTop != 0) || (SrcTrimBottom != 0))
  1212. {
  1213. double fSrcToDstY = (double)DstCy / (double)SrcCy;
  1214. //
  1215. // convert dst trim amound to src
  1216. //
  1217. SrcTrimTop = (LONG)((double)SrcTrimTop * fSrcToDstY);
  1218. SrcTrimBottom = (LONG)((double)SrcTrimBottom * fSrcToDstY);
  1219. pDibInfoDst->rclBoundsTrim.top += SrcTrimTop;
  1220. pDibInfoDst->rclBoundsTrim.bottom -= SrcTrimBottom;
  1221. }
  1222. }
  1223. else
  1224. {
  1225. //
  1226. // reduce dst rect
  1227. //
  1228. if (SrcTrimLeft != 0)
  1229. {
  1230. pDibInfoDst->rclBoundsTrim.left += SrcTrimLeft;
  1231. }
  1232. if (SrcTrimRight != 0)
  1233. {
  1234. pDibInfoDst->rclBoundsTrim.right -= SrcTrimRight;
  1235. }
  1236. if (SrcTrimTop != 0)
  1237. {
  1238. pDibInfoDst->rclBoundsTrim.top += SrcTrimTop;
  1239. }
  1240. if (SrcTrimBottom != 0)
  1241. {
  1242. pDibInfoDst->rclBoundsTrim.bottom -= SrcTrimBottom;
  1243. }
  1244. }
  1245. //
  1246. // check for clipped out Dst and Src
  1247. //
  1248. if (
  1249. (pDibInfoDst->rclBoundsTrim.left < pDibInfoDst->rclBoundsTrim.right) &&
  1250. (pDibInfoDst->rclBoundsTrim.top < pDibInfoDst->rclBoundsTrim.bottom) &&
  1251. (pDibInfoSrc->rclBoundsTrim.left < pDibInfoSrc->rclBoundsTrim.right) &&
  1252. (pDibInfoSrc->rclBoundsTrim.top < pDibInfoSrc->rclBoundsTrim.bottom)
  1253. )
  1254. {
  1255. //
  1256. // allocate compatible DC and surface
  1257. //
  1258. hdcTemp = CreateCompatibleDC(pDibInfoSrc->hdc);
  1259. if (hdcTemp)
  1260. {
  1261. //
  1262. // copy pDibInfoSrc->pbmi into pbmi
  1263. //
  1264. if (!pDibInfoSrc->hdc)
  1265. {
  1266. ULONG cBytes = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255;
  1267. pbmi = (PBITMAPINFO)LOCALALLOC(cBytes);
  1268. if (pbmi != NULL)
  1269. {
  1270. ZeroMemory (pbmi,cBytes);
  1271. vCopyBitmapInfo (pbmi, pDibInfoSrc->pbmi);
  1272. }
  1273. else
  1274. {
  1275. WARNING("bGetSrcDIBits fail to alloc mem\n");
  1276. bRet = FALSE;
  1277. }
  1278. }
  1279. if (bRet)
  1280. {
  1281. //
  1282. // create temp DIB size of dst rect
  1283. //
  1284. RECTL rclDstCopy = {
  1285. 0,
  1286. 0,
  1287. pDibInfoDst->rclBoundsTrim.right - pDibInfoDst->rclBoundsTrim.left,
  1288. pDibInfoDst->rclBoundsTrim.bottom - pDibInfoDst->rclBoundsTrim.top
  1289. };
  1290. hbm = CreateCompatibleDIB(hdcTemp,
  1291. rclDstCopy.right,
  1292. rclDstCopy.bottom,
  1293. &pDibInfoSrc->pvBits,
  1294. pDibInfoSrc->pbmi);
  1295. if (hbm)
  1296. {
  1297. pDibInfoSrc->hDIB = hbm;
  1298. GetCompatibleDIBInfo (hbm, &pDibInfoSrc->pvBase, &pDibInfoSrc->stride);
  1299. HBITMAP hbmDefault = (HBITMAP)SelectObject (hdcTemp, hbm);
  1300. ULONG OldMode = SetStretchBltMode(hdcTemp,COLORONCOLOR);
  1301. //
  1302. // Stretch data into source temp DIB
  1303. //
  1304. //
  1305. // Blt data into source temp DIB
  1306. //
  1307. if (pDibInfoSrc->hdc)
  1308. {
  1309. StretchBlt (hdcTemp,
  1310. 0,
  1311. 0,
  1312. rclDstCopy.right,
  1313. rclDstCopy.bottom,
  1314. pDibInfoSrc->hdc,
  1315. pDibInfoSrc->rclBoundsTrim.left,
  1316. pDibInfoSrc->rclBoundsTrim.top,
  1317. pDibInfoSrc->rclBoundsTrim.right - pDibInfoSrc->rclBoundsTrim.left,
  1318. pDibInfoSrc->rclBoundsTrim.bottom - pDibInfoSrc->rclBoundsTrim.top,
  1319. SRCCOPY);
  1320. }
  1321. else
  1322. {
  1323. //
  1324. // adjust ySrc to be compatible
  1325. //
  1326. LONG cySrc = pDibInfoSrc->rclBoundsTrim.bottom-pDibInfoSrc->rclBoundsTrim.top;
  1327. LONG ySrc = pDibInfoSrc->rclClipDC.bottom - pDibInfoSrc->rclBoundsTrim.top - cySrc;
  1328. StretchDIBits (hdcTemp,
  1329. 0,
  1330. 0,
  1331. rclDstCopy.right,
  1332. rclDstCopy.bottom,
  1333. pDibInfoSrc->rclBoundsTrim.left,
  1334. ySrc,
  1335. pDibInfoSrc->rclBoundsTrim.right-pDibInfoSrc->rclBoundsTrim.left,
  1336. cySrc,
  1337. pvBits,
  1338. pbmi,
  1339. DIB_RGB_COLORS,
  1340. SRCCOPY);
  1341. }
  1342. SetStretchBltMode(hdcTemp,OldMode);
  1343. SelectObject (hdcTemp, hbmDefault);
  1344. pDibInfoSrc->rclDIB = rclDstCopy;
  1345. }
  1346. else
  1347. {
  1348. WARNING ("bGetSrcDIBits -- fail to createcompatibleDIB\n");
  1349. bRet = FALSE;
  1350. }
  1351. }
  1352. }
  1353. else
  1354. {
  1355. WARNING ("bGetSrcDIBits -- fail to createcompatibledc\n");
  1356. bRet = FALSE;
  1357. }
  1358. }
  1359. else
  1360. {
  1361. //
  1362. // clipped out
  1363. //
  1364. pDibInfoDst->rclBoundsTrim.left = pDibInfoDst->rclBoundsTrim.right = 0;
  1365. pDibInfoDst->rclBoundsTrim.top = pDibInfoDst->rclBoundsTrim.bottom = 0;
  1366. pDibInfoSrc->rclBoundsTrim.left = pDibInfoSrc->rclBoundsTrim.right = 0;
  1367. pDibInfoSrc->rclBoundsTrim.top = pDibInfoSrc->rclBoundsTrim.bottom = 0;
  1368. }
  1369. if (pbmi)
  1370. {
  1371. LOCALFREE (pbmi);
  1372. }
  1373. if (hdcTemp)
  1374. {
  1375. DeleteDC(hdcTemp);
  1376. }
  1377. return(bRet);
  1378. }
  1379. /******************************Public*Routine******************************\
  1380. * bGetDstDIBits
  1381. *
  1382. * Setup the destination DIB surface and retrieve the bits
  1383. *
  1384. * Ported from psSetupDstSurface
  1385. *
  1386. *
  1387. *
  1388. * Return Value:
  1389. *
  1390. *
  1391. *
  1392. * History:
  1393. *
  1394. * 4-April-1997 -by- Lingyun Wang [lingyunw]
  1395. *
  1396. \**************************************************************************/
  1397. BOOL
  1398. bGetDstDIBits
  1399. (
  1400. PDIBINFO pDibInfoDst,
  1401. BOOL *pbReadable,
  1402. FLONG flCopyMode
  1403. )
  1404. {
  1405. HDC hdc = pDibInfoDst->hdc;
  1406. BOOL bRet = TRUE;
  1407. //
  1408. // try to clip to dst surface, dst should be clipped in all cases except
  1409. // gradient fill
  1410. //
  1411. if (flCopyMode & (SOURCE_GRADIENT_RECT | SOURCE_GRADIENT_TRI))
  1412. {
  1413. //
  1414. // trim destination bounds rect to surface bounds. Src rect must also
  1415. // be trimmed by same amount (in src space)
  1416. //
  1417. if (pDibInfoDst->rclBoundsTrim.left < pDibInfoDst->rclClipDC.left)
  1418. {
  1419. pDibInfoDst->rclBoundsTrim.left = pDibInfoDst->rclClipDC.left;
  1420. }
  1421. if (pDibInfoDst->rclBoundsTrim.top < pDibInfoDst->rclClipDC.top)
  1422. {
  1423. pDibInfoDst->rclBoundsTrim.top = pDibInfoDst->rclClipDC.top;
  1424. }
  1425. if (pDibInfoDst->rclBoundsTrim.right > pDibInfoDst->rclClipDC.right)
  1426. {
  1427. pDibInfoDst->rclBoundsTrim.right = pDibInfoDst->rclClipDC.right;
  1428. }
  1429. if (pDibInfoDst->rclBoundsTrim.bottom > pDibInfoDst->rclClipDC.bottom)
  1430. {
  1431. pDibInfoDst->rclBoundsTrim.bottom = pDibInfoDst->rclClipDC.bottom;
  1432. }
  1433. //
  1434. // set offset for gradient fill
  1435. //
  1436. pDibInfoDst->ptlGradOffset.x = 0;
  1437. pDibInfoDst->ptlGradOffset.y = 0;
  1438. }
  1439. LONG DstCx = pDibInfoDst->rclBoundsTrim.right - pDibInfoDst->rclBoundsTrim.left;
  1440. LONG DstCy = pDibInfoDst->rclBoundsTrim.bottom - pDibInfoDst->rclBoundsTrim.top;
  1441. *pbReadable = TRUE;
  1442. if (!pDibInfoDst->pvBits)
  1443. {
  1444. if (pDibInfoDst->rclBounds.left > 0)
  1445. {
  1446. pDibInfoDst->ptlGradOffset.x = pDibInfoDst->rclBounds.left;
  1447. }
  1448. if (pDibInfoDst->rclBounds.top > 0)
  1449. {
  1450. pDibInfoDst->ptlGradOffset.y = pDibInfoDst->rclBounds.top;
  1451. }
  1452. //
  1453. // allocate surface
  1454. //
  1455. HDC hdcTemp = CreateCompatibleDC (hdc);
  1456. if (hdcTemp)
  1457. {
  1458. HBITMAP hbm = CreateCompatibleDIB (hdcTemp,
  1459. DstCx,
  1460. DstCy,
  1461. &pDibInfoDst->pvBits,
  1462. pDibInfoDst->pbmi);
  1463. if (hbm != NULL)
  1464. {
  1465. pDibInfoDst->hDIB = hbm;
  1466. GetCompatibleDIBInfo (hbm, &pDibInfoDst->pvBase, &pDibInfoDst->stride);
  1467. HGDIOBJ hret = SelectObject(hdcTemp, hbm);
  1468. if (hret != NULL)
  1469. {
  1470. RECTL rclCopy;
  1471. rclCopy.left = 0;
  1472. rclCopy.right = DstCx;
  1473. rclCopy.top = 0;
  1474. rclCopy.bottom = DstCy;
  1475. //
  1476. // gradient rect does not need source bitmap data
  1477. //
  1478. if (flCopyMode != SOURCE_GRADIENT_RECT)
  1479. {
  1480. bRet = BitBlt(hdcTemp,
  1481. 0,
  1482. 0,
  1483. DstCx,
  1484. DstCy,
  1485. pDibInfoDst->hdc,
  1486. pDibInfoDst->rclBoundsTrim.left,
  1487. pDibInfoDst->rclBoundsTrim.top,
  1488. SRCCOPY);
  1489. }
  1490. //
  1491. // adjust dst rect
  1492. //
  1493. if (bRet)
  1494. {
  1495. pDibInfoDst->rclDIB = rclCopy;
  1496. }
  1497. }
  1498. else
  1499. {
  1500. bRet = NULL;
  1501. WARNING ("bGetDstDIBits -- fail to select compatible DIB\n");
  1502. }
  1503. *pbReadable = bRet;
  1504. }
  1505. else
  1506. {
  1507. bRet = FALSE;
  1508. }
  1509. DeleteDC (hdcTemp);
  1510. }
  1511. else
  1512. {
  1513. WARNING ("bGetDstDIBits -- fail to createcompatibledc\n");
  1514. bRet = FALSE;
  1515. }
  1516. }
  1517. else
  1518. {
  1519. pDibInfoDst->rclDIB = pDibInfoDst->rclClipDC;
  1520. }
  1521. return(bRet);
  1522. }
  1523. /******************************Public*Routine******************************\
  1524. * bDIBGetSrcDIBits
  1525. *
  1526. * Create or get the source dib bits
  1527. *
  1528. * Returns:
  1529. * VOID.
  1530. *
  1531. * History:
  1532. * 09-Dec-1996 -by- Lingyun Wang [lingyunw]
  1533. * Wrote it.
  1534. \**************************************************************************/
  1535. BOOL bDIBGetSrcDIBits (
  1536. PDIBINFO pDibInfoDst,
  1537. PDIBINFO pDibInfoSrc,
  1538. FLONG flSourceMode,
  1539. ULONG TransColor
  1540. )
  1541. {
  1542. if (pDibInfoSrc->iUsage == DIB_PAL_COLORS)
  1543. {
  1544. vMapPALtoRGB (pDibInfoDst, pDibInfoSrc, 0);
  1545. }
  1546. //pDibInfoSrc->rclDIB = pDibInfoSrc->rclClipDC;
  1547. return (bGetSrcDIBits(pDibInfoDst,pDibInfoSrc,flSourceMode, TransColor));
  1548. }
  1549. /******************************Public*Routine******************************\
  1550. * bDIBInitDIBINFO
  1551. *
  1552. * Returns:
  1553. * BOOLEAN.
  1554. *
  1555. * History:
  1556. * 09-Dec-1996 -by- Lingyun Wang [lingyunw]
  1557. * Wrote it.
  1558. \**************************************************************************/
  1559. BOOL
  1560. bDIBInitDIBINFO(
  1561. PBITMAPINFO pbmi,
  1562. CONST VOID * pvBits,
  1563. int x,
  1564. int y,
  1565. int cx,
  1566. int cy,
  1567. PDIBINFO pDibInfo)
  1568. {
  1569. PVOID p;
  1570. ULONG cBytes = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255;
  1571. int bmWidthBytes;
  1572. POINT lpPoints[2];
  1573. p = LOCALALLOC(cBytes);
  1574. if (!p)
  1575. {
  1576. WARNING("fail to alloc mem\n");
  1577. return (FALSE);
  1578. }
  1579. ZeroMemory (p,cBytes);
  1580. //
  1581. // copy the input pbmi
  1582. //
  1583. vCopyBitmapInfo ((PBITMAPINFO)p, pbmi);
  1584. pDibInfo->pbmi = (PBITMAPINFO)p;
  1585. pDibInfo->hdc = NULL;
  1586. pDibInfo->rclBounds.left = x;
  1587. pDibInfo->rclBounds.top = y;
  1588. pDibInfo->rclBounds.right = x+cx;
  1589. pDibInfo->rclBounds.bottom = y+cy;
  1590. pDibInfo->rclBoundsTrim = pDibInfo->rclBounds;
  1591. pDibInfo->pvBits = (PVOID)pvBits;
  1592. pDibInfo->iUsage = DIB_RGB_COLORS;
  1593. pDibInfo->pxlate332 = NULL;
  1594. //
  1595. // align width to WORD boundary
  1596. //
  1597. bmWidthBytes = ((pbmi->bmiHeader.biWidth*pbmi->bmiHeader.biBitCount + 15)>>4)<<1;
  1598. if (pbmi->bmiHeader.biHeight > 0)
  1599. {
  1600. pDibInfo->pvBase = (PBYTE)pDibInfo->pvBits + bmWidthBytes * (pbmi->bmiHeader.biHeight - 1);
  1601. pDibInfo->stride = (ULONG) (-bmWidthBytes);
  1602. }
  1603. else
  1604. {
  1605. pDibInfo->pvBase = pDibInfo->pvBits;
  1606. pDibInfo->stride = bmWidthBytes;
  1607. }
  1608. pDibInfo->hDIB = NULL;
  1609. pDibInfo->pdds = NULL;
  1610. pDibInfo->ddsd.dwSize = sizeof(DDSURFACEDESC);
  1611. return(TRUE);
  1612. }
  1613. /******************************Public*Routine******************************\
  1614. * bInitDIBINFO
  1615. *
  1616. * Returns:
  1617. * BOOLEAN.
  1618. *
  1619. * History:
  1620. * 09-Dec-1996 -by- Lingyun Wang [lingyunw]
  1621. * Wrote it.
  1622. \**************************************************************************/
  1623. BOOL
  1624. bInitDIBINFO(
  1625. HDC hdc,
  1626. int x,
  1627. int y,
  1628. int cx,
  1629. int cy,
  1630. PDIBINFO pDibInfo)
  1631. {
  1632. ULONG cBytes;
  1633. PVOID p;
  1634. POINT lpPoints[2];
  1635. pDibInfo->hdc = hdc;
  1636. pDibInfo->rclBounds.left = x;
  1637. pDibInfo->rclBounds.top = y;
  1638. pDibInfo->rclBounds.right = x+cx;
  1639. pDibInfo->rclBounds.bottom = y+cy;
  1640. //
  1641. // setup rclBounds in device space
  1642. //
  1643. LPtoDP (hdc, (POINT *)&pDibInfo->rclBounds, 2);
  1644. pDibInfo->rclBoundsTrim = pDibInfo->rclBounds;
  1645. //
  1646. // Now operate in MM_TEXT mode
  1647. //
  1648. pDibInfo->Mapmode = SetMapMode(hdc,MM_TEXT);
  1649. SetViewportOrgEx (hdc, 0, 0, &pDibInfo->ViewportOrg);
  1650. SetWindowOrgEx (hdc, 0, 0, &pDibInfo->WindowOrg);
  1651. pDibInfo->pvBits = NULL;
  1652. pDibInfo->pvBase = NULL;
  1653. pDibInfo->hDIB = NULL;
  1654. pDibInfo->iUsage = DIB_RGB_COLORS;
  1655. pDibInfo->pxlate332 = NULL;
  1656. cBytes = sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255;
  1657. p = LOCALALLOC(cBytes);
  1658. if (!p)
  1659. {
  1660. WARNING("fail to alloc mem\n");
  1661. return (FALSE);
  1662. }
  1663. ZeroMemory (p,cBytes);
  1664. pDibInfo->pbmi = (PBITMAPINFO)p;
  1665. pDibInfo->pdds = NULL;
  1666. pDibInfo->ddsd.dwSize = sizeof(DDSURFACEDESC);
  1667. return(TRUE);
  1668. }
  1669. /******************************Public*Routine******************************\
  1670. * bSendDIBInfo
  1671. *
  1672. * Returns:
  1673. * BOOLEAN.
  1674. *
  1675. * History:
  1676. * 09-Dec-1996 -by- Lingyun Wang [lingyunw]
  1677. * Wrote it.
  1678. \**************************************************************************/
  1679. BOOL
  1680. bSendDIBINFO(
  1681. HDC hdcDst,
  1682. PDIBINFO pDibInfo
  1683. )
  1684. {
  1685. BOOL bRet = TRUE;
  1686. if (pDibInfo->hDIB)
  1687. {
  1688. ULONG OldMode = SetStretchBltMode(hdcDst,COLORONCOLOR);
  1689. bRet = SetDIBitsToDevice(hdcDst,
  1690. pDibInfo->rclBoundsTrim.left,
  1691. pDibInfo->rclBoundsTrim.top,
  1692. pDibInfo->rclBoundsTrim.right - pDibInfo->rclBoundsTrim.left,
  1693. pDibInfo->rclBoundsTrim.bottom - pDibInfo->rclBoundsTrim.top,
  1694. 0,
  1695. 0,
  1696. 0,
  1697. pDibInfo->rclDIB.bottom - pDibInfo->rclDIB.top,
  1698. pDibInfo->pvBits,
  1699. pDibInfo->pbmi,
  1700. DIB_RGB_COLORS);
  1701. SetStretchBltMode(hdcDst,OldMode);
  1702. }
  1703. return (bRet);
  1704. }
  1705. /******************************Public*Routine******************************\
  1706. * vCleanupDIBInfo
  1707. *
  1708. * Returns:
  1709. * VOID.
  1710. *
  1711. * History:
  1712. * 09-Dec-1996 -by- Lingyun Wang [lingyunw]
  1713. * Wrote it.
  1714. \**************************************************************************/
  1715. VOID vCleanupDIBINFO (
  1716. PDIBINFO pDibInfo)
  1717. {
  1718. //
  1719. // restore DC map modes
  1720. //
  1721. SetMapMode(pDibInfo->hdc,pDibInfo->Mapmode);
  1722. SetViewportOrgEx (pDibInfo->hdc, pDibInfo->ViewportOrg.x, pDibInfo->ViewportOrg.y, NULL);
  1723. SetWindowOrgEx (pDibInfo->hdc, pDibInfo->WindowOrg.x, pDibInfo->WindowOrg.y, NULL);
  1724. if (pDibInfo->hDIB)
  1725. {
  1726. DeleteObject (pDibInfo->hDIB);
  1727. }
  1728. if (pDibInfo->pbmi)
  1729. {
  1730. LOCALFREE ((PVOID)pDibInfo->pbmi);
  1731. }
  1732. if ((pDibInfo->pxlate332) && (pDibInfo->pxlate332 != gHalftoneColorXlate332))
  1733. {
  1734. LOCALFREE(pDibInfo->pxlate332);
  1735. }
  1736. if (pDibInfo->pdds)
  1737. pDibInfo->pdds->Unlock(pDibInfo->ddsd.lpSurface);
  1738. }
  1739. #endif