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.

4023 lines
125 KiB

  1. /**************************************************************************
  2. DRAWDIB.C - routines for drawing DIBs to the screen.
  3. this code handles stretching and dithering with custom code, none
  4. of this slow GDI code.
  5. the following DIB formats are supported:
  6. 4bpp (will just draw it with GDI...)
  7. 8bpp
  8. 16bpp
  9. 24bpp
  10. compressed DIBs
  11. drawing to:
  12. 16 color DC (will dither 8bpp down)
  13. 256 (paletized) DC (will dither 16 and 24bpp down)
  14. Full-color DC (will just draw it!)
  15. **************************************************************************/
  16. #include <windows.h>
  17. #include <windowsx.h>
  18. #include "drawdibi.h"
  19. #ifndef ICMODE_FASTDECOMPRESS
  20. #define ICMODE_FASTDECOMPRESS 3
  21. #endif
  22. #define USE_SETDI 1
  23. #ifndef BI_BITMAP
  24. #define BI_BITMAP 0x4D544942 // 'BITM'
  25. #endif
  26. #ifdef WIN32
  27. #define FlatToHuge(a, b, c)
  28. #define HugeToFlat(a, b, c)
  29. #else
  30. extern FAR PASCAL FlatToHuge(LPVOID,DWORD,DWORD);
  31. extern FAR PASCAL HugeToFlat(LPVOID,DWORD,DWORD);
  32. #endif
  33. //!!! not quite right.
  34. #ifndef WIN32
  35. #define IsScreenDC(hdc) (GetDCOrg(hdc) != 0L)
  36. #else
  37. #define IsScreenDC(hdc) (WindowFromDC(hdc) != NULL)
  38. #endif
  39. #define DCAlignment 3
  40. __inline int DCNotAligned(HDC hdc, int xDst) {
  41. POINT pt;
  42. pt.x = xDst; pt.y = 0;
  43. LPtoDP(hdc, &pt, 1);
  44. xDst = pt.x;
  45. #ifdef _WIN32
  46. GetDCOrgEx(hdc, &pt);
  47. #else
  48. pt.x = LOWORD(GetDCOrg(hdc));
  49. #endif
  50. return (pt.x + xDst) & DCAlignment;
  51. }
  52. /**************************************************************************
  53. **************************************************************************/
  54. UINT gwScreenBitDepth = (UINT)-1;
  55. UINT gwRasterCaps = 0;
  56. BOOL gf286= FALSE;
  57. static UINT gUsage = 0;
  58. static BOOL gfInit = FALSE;
  59. static BOOL gfHalftone = FALSE;
  60. static BOOL gfBitmap = FALSE;
  61. static BOOL gfBitmapX = FALSE;
  62. static BOOL gfScreenX = FALSE;
  63. static BOOL gfDrawX = FALSE;
  64. static HBITMAP hbmStockMono; // the stock mono bitmap.
  65. #ifndef WIN32
  66. static BOOL gfDisplayHasBrokenRasters;
  67. static HDC hdcDCI;
  68. static DCISURFACEINFO FAR *pdci;
  69. static struct {
  70. BITMAPINFOHEADER bi;
  71. DWORD dwMask[3];
  72. } biScreen;
  73. static LPVOID lpScreen;
  74. SZCODE szDVA[] = TEXT("dva");
  75. #endif
  76. /**************************************************************************
  77. **************************************************************************/
  78. SZCODE szDrawDib[] = TEXT("DrawDib");
  79. SZCODE szHalftone[] = TEXT("Halftone");
  80. SZCODE szDrawToBitmap[] = TEXT("DrawToBitmap");
  81. SZCODE szDecompressToBitmap[] = TEXT("DecompressToBitmap");
  82. SZCODE szDecompressToScreen[] = TEXT("DecompressToScreen");
  83. SZCODE szDrawToScreen[] = TEXT("DrawToScreen");
  84. /**************************************************************************
  85. **************************************************************************/
  86. static BOOL NEAR PASCAL DrawDibFree(PDD pdd, BOOL fSameDib, BOOL fSameSize);
  87. static HPALETTE CreateBIPalette(HPALETTE hpal, LPBITMAPINFOHEADER lpbi);
  88. static BOOL NEAR IsIdentityPalette(HPALETTE hpal);
  89. static BOOL NEAR AreColorsAllGDIColors(LPBITMAPINFOHEADER lpbi);
  90. static BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, UINT wFlags);
  91. static HPALETTE CreateExplicitPalette(void);
  92. void DrawDibPalChange(PDD pdd, HDC hdc, HPALETTE hpal);
  93. void DrawDibClipChange(PDD pdd, UINT wFlags);
  94. static BOOL FixUpCodecPalette(HIC hic, LPBITMAPINFOHEADER lpbi);
  95. static BOOL NEAR SendSetPalette(PDD pdd);
  96. #ifndef WIN32
  97. extern BOOL gf286;
  98. /**************************************************************************
  99. **************************************************************************/
  100. static void InitDCI()
  101. {
  102. UINT WidthBytes;
  103. //
  104. // initialize DCI and open a surface handle to it.
  105. //
  106. // if DVA = 0 in WIN.INI, don't use DCI or DVA.
  107. // PSS tells people to use this if they have video problems,
  108. // so we shouldn't change the string.
  109. if (gf286 || !GetProfileInt(szDrawDib, szDVA, TRUE))
  110. return;
  111. hdcDCI = DCIOpenProvider();
  112. if (hdcDCI == NULL)
  113. return;
  114. DCICreatePrimary(hdcDCI, &pdci);
  115. if (pdci == NULL)
  116. return;
  117. WidthBytes = abs((UINT)pdci->lStride);
  118. //
  119. // convert DCISURFACEINFO into a BITMAPINFOHEADER...
  120. //
  121. biScreen.bi.biSize = sizeof(BITMAPINFOHEADER);
  122. biScreen.bi.biWidth = WidthBytes*8/(UINT)pdci->dwBitCount;
  123. biScreen.bi.biHeight = pdci->dwHeight;
  124. biScreen.bi.biPlanes = 1;
  125. biScreen.bi.biBitCount = (UINT)pdci->dwBitCount;
  126. biScreen.bi.biCompression = BI_1632; //!!!???
  127. biScreen.bi.biSizeImage = pdci->dwHeight * WidthBytes;
  128. biScreen.bi.biXPelsPerMeter = WidthBytes;
  129. biScreen.bi.biYPelsPerMeter = 0;
  130. biScreen.bi.biClrUsed = 0;
  131. biScreen.bi.biClrImportant = 0;
  132. biScreen.dwMask[0] = pdci->dwMask[0];
  133. biScreen.dwMask[1] = pdci->dwMask[1];
  134. biScreen.dwMask[2] = pdci->dwMask[2];
  135. if (pdci->dwCompression == 0 && (UINT)pdci->dwBitCount == 16)
  136. {
  137. biScreen.dwMask[0] = 0x007C00;
  138. biScreen.dwMask[1] = 0x0003E0;
  139. biScreen.dwMask[2] = 0x00001F;
  140. }
  141. if (pdci->dwCompression == 0 && (UINT)pdci->dwBitCount >= 24)
  142. {
  143. biScreen.dwMask[0] = 0xFF0000;
  144. biScreen.dwMask[1] = 0x00FF00;
  145. biScreen.dwMask[2] = 0x0000FF;
  146. }
  147. DPF(("DCI Surface: %dx%dx%d", (int)pdci->dwWidth, (int)pdci->dwHeight, (int)LOWORD(pdci->dwBitCount)));
  148. DPF(("DCI Surface: biCompression=%ld Masks: %04lX %04lX %04lX",biScreen.bi.biCompression,biScreen.dwMask[0],biScreen.dwMask[1],biScreen.dwMask[2]));
  149. if (pdci->lStride > 0)
  150. biScreen.bi.biHeight = -(int)pdci->dwHeight;
  151. else
  152. pdci->dwOffSurface -= biScreen.bi.biSizeImage;
  153. //
  154. // make sure the pointer is valid.
  155. //
  156. if (pdci->dwOffSurface >= 0x10000)
  157. {
  158. DPF(("DCI Surface cant be supported"));
  159. lpScreen = NULL;
  160. biScreen.bi.biSize = 0;
  161. }
  162. else
  163. {
  164. lpScreen = (LPVOID)MAKELP(pdci->wSelSurface,pdci->dwOffSurface);
  165. }
  166. //
  167. // check if the display has broken rasters.
  168. //
  169. if (pdci->dwDCICaps & DCI_1632_ACCESS)
  170. gfDisplayHasBrokenRasters = (0x10000l % WidthBytes) != 0;
  171. if (gfDisplayHasBrokenRasters)
  172. {
  173. DPF(("*** Display has broken rasters"));
  174. }
  175. }
  176. void TermDCI()
  177. {
  178. if (pdci)
  179. {
  180. DCIDestroy(pdci);
  181. pdci = NULL;
  182. }
  183. if (hdcDCI)
  184. {
  185. DeleteDC(hdcDCI);
  186. hdcDCI = NULL;
  187. }
  188. }
  189. #else
  190. #define InitDCI()
  191. #define TermDCI()
  192. #endif
  193. /**************************************************************************
  194. * @doc INTERNAL DrawDib
  195. *
  196. * @api BOOL | DrawDibInit | This function initalizes the DrawDib library.
  197. *
  198. * @rdesc Returns TRUE if the library is initialized properly, otherwise
  199. * it returns FALSE.
  200. *
  201. * @comm Users don't need to call this, because <f DrawDibOpen> does it for them.
  202. *
  203. * @xref DrawDibTerm
  204. *
  205. **************************************************************************/
  206. BOOL VFWAPI DrawDibInit()
  207. {
  208. HDC hdc;
  209. if (gfInit)
  210. return TRUE;
  211. gf286 = (BOOL)(GetWinFlags() & WF_CPU286);
  212. hdc = GetDC(NULL);
  213. gwScreenBitDepth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  214. gwRasterCaps = GetDeviceCaps(hdc, RASTERCAPS);
  215. InitDCI();
  216. ReleaseDC(NULL, hdc);
  217. gfHalftone = GetProfileInt(szDrawDib, szHalftone, FALSE);
  218. gfBitmap = GetProfileInt(szDrawDib, szDrawToBitmap, -1);
  219. gfBitmapX = GetProfileInt(szDrawDib, szDecompressToBitmap, TRUE);
  220. gfScreenX = GetProfileInt(szDrawDib, szDecompressToScreen, TRUE);
  221. gfDrawX = GetProfileInt(szDrawDib, szDrawToScreen, TRUE);
  222. #ifdef DEBUG
  223. gwRasterCaps = GetProfileIntA("drawdib", "RasterCaps", gwRasterCaps);
  224. gwScreenBitDepth = GetProfileIntA("drawdib", "ScreenBitDepth", gwScreenBitDepth);
  225. gf286 = GetProfileIntA("drawdib", "cpu", gf286 ? 286 : 386) == 286;
  226. #endif
  227. //
  228. // fix up the bit-depth of the display.
  229. //
  230. if (gwScreenBitDepth > 32)
  231. gwScreenBitDepth = 32;
  232. if (gwScreenBitDepth == 16 || gwScreenBitDepth == 32)
  233. {
  234. BITMAPINFOHEADER bi;
  235. UINT u;
  236. bi.biSize = sizeof(bi);
  237. bi.biWidth = 1;
  238. bi.biHeight = 1;
  239. bi.biPlanes = 1;
  240. bi.biBitCount = gwScreenBitDepth;
  241. bi.biCompression = 0;
  242. bi.biSizeImage = 0;
  243. bi.biXPelsPerMeter = 0;
  244. bi.biYPelsPerMeter = 0;
  245. bi.biClrUsed = 0;
  246. bi.biClrImportant = 0;
  247. u = (UINT)DrawDibProfileDisplay(&bi);
  248. if (u == 0)
  249. {
  250. DPF(("Pretending display is 24 bit (not %d)", gwScreenBitDepth));
  251. gwScreenBitDepth = 24;
  252. }
  253. }
  254. gfInit = TRUE;
  255. return TRUE;
  256. }
  257. /**************************************************************************
  258. * @doc INTERNAL DrawTerm
  259. *
  260. * @api BOOL | DrawDibTerm | This function teminates the DrawDib library.
  261. *
  262. * @rdesc Returns TRUE.
  263. *
  264. * @comm Users don't need to call this, because <f DrawDibClose> does it for them.
  265. *
  266. * @xref DrawDibInit
  267. *
  268. **************************************************************************/
  269. BOOL VFWAPI DrawDibTerm()
  270. {
  271. //
  272. // free global stuff.
  273. //
  274. TermDCI();
  275. gfInit = FALSE;
  276. return TRUE;
  277. }
  278. /**************************************************************************
  279. * @doc INTERNAL DrawDib
  280. *
  281. * @api void | DrawDibCleanup | clean up drawdib stuff
  282. * called in MSVIDEOs WEP()
  283. *
  284. **************************************************************************/
  285. void FAR PASCAL DrawDibCleanup(HTASK hTask)
  286. {
  287. if (gUsage > 0)
  288. RPF(("%d DrawDib handles left open", gUsage));
  289. DrawDibTerm();
  290. }
  291. /**************************************************************************
  292. * @doc INTERNAL
  293. *
  294. * @api BOOL | DibEq | This function compares two dibs.
  295. *
  296. * @parm LPBITMAPINFOHEADER | lpbi1 | Pointer to one bitmap.
  297. * this DIB is assumed to have the colors after biSize bytes.
  298. *
  299. * @parm LPBITMAPINFOHEADER | lpbi2 | Pointer to second bitmap.
  300. * this DIB is assumed to have the colors after biSize bytes.
  301. *
  302. * @rdesc Returns TRUE if bitmaps are identical, FALSE otherwise.
  303. *
  304. **************************************************************************/
  305. INLINE BOOL NEAR PASCAL DibEq(LPBITMAPINFOHEADER lpbi1, LPBITMAPINFOHEADER lpbi2)
  306. {
  307. if (lpbi1 == NULL || lpbi2 == NULL)
  308. return FALSE;
  309. return
  310. lpbi1->biCompression == lpbi2->biCompression &&
  311. (int)lpbi1->biSize == (int)lpbi2->biSize &&
  312. (int)lpbi1->biWidth == (int)lpbi2->biWidth &&
  313. (int)lpbi1->biHeight == (int)lpbi2->biHeight &&
  314. (int)lpbi1->biBitCount == (int)lpbi2->biBitCount &&
  315. ((int)lpbi1->biBitCount > 8 ||
  316. (int)lpbi1->biClrUsed == (int)lpbi2->biClrUsed &&
  317. _fmemcmp((LPBYTE)lpbi1 + lpbi1->biSize,
  318. (LPBYTE)lpbi2 + lpbi2->biSize,
  319. (int)lpbi1->biClrUsed*sizeof(RGBQUAD)) == 0);
  320. }
  321. /**************************************************************************
  322. * @doc INTERNAL
  323. *
  324. * @api PDD NEAR | DrawDibLock | Lock the DrawDib handle.
  325. *
  326. * @parm HDRAWDIB | hdd | DrawDib handle.
  327. *
  328. * @rdesc Returns a pointer to a <t DRAWDIB_STRUCT> if successful, NULL otherwise.
  329. *
  330. **************************************************************************/
  331. #define DrawDibLock(hdd) (\
  332. hdd == NULL || ((PDD)hdd)->wSize != sizeof(DRAWDIB_STRUCT) ? NULL : \
  333. (PDD)hdd)
  334. /**************************************************************************
  335. * @doc EXTERNAL DrawDib
  336. *
  337. * @api HDRAWDIB | DrawDibOpen | This function opens a DrawDib context for drawing.
  338. *
  339. * @rdesc Returns a handle to a DrawDib context if successful,
  340. * otherwise it returns NULL.
  341. *
  342. * @comm Use this function to obtain a handle to a DrawDib context
  343. * before drawing device independent bitmaps.
  344. *
  345. * If drawing multiple device independent bitmaps simultaneously,
  346. * obtain a handle to a DrawDib context for each bitmap.
  347. *
  348. * @xref <f DrawDibClose>
  349. *
  350. **************************************************************************/
  351. HDRAWDIB VFWAPI DrawDibOpen(void)
  352. {
  353. HDRAWDIB hdd;
  354. PDD pdd;
  355. hdd = LocalAlloc(LPTR, sizeof(DRAWDIB_STRUCT)); /* zero init */
  356. if (hdd == NULL)
  357. return NULL;
  358. pdd = (PDD)hdd;
  359. pdd->wSize = sizeof(DRAWDIB_STRUCT);
  360. if (gUsage++ == 0)
  361. DrawDibInit();
  362. return hdd;
  363. }
  364. /**************************************************************************
  365. * @doc EXTERNAL DrawDib
  366. *
  367. * @api BOOL | DrawDibClose | This function closes a DrawDib context
  368. * and frees the resources DrawDib allocated for it.
  369. *
  370. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  371. *
  372. * @rdesc Returns TRUE if the context closed successfully.
  373. *
  374. * @comm Use this function to free the <p hdd> handle
  375. * after the application has finished drawing.
  376. *
  377. * @xref <f DrawDibOpen>
  378. **************************************************************************/
  379. BOOL VFWAPI DrawDibClose(HDRAWDIB hdd)
  380. {
  381. PDD pdd;
  382. if ((pdd = DrawDibLock(hdd)) == NULL)
  383. return FALSE;
  384. DrawDibFree(pdd, FALSE, FALSE);
  385. pdd->wSize = 0;
  386. LocalFree(hdd);
  387. if (--gUsage == 0)
  388. DrawDibTerm();
  389. return TRUE;
  390. }
  391. /**************************************************************************
  392. * @doc INTERNAL
  393. *
  394. * @api BOOL | DrawDibFree | Free up everything in a <t DRAWDIB_STRUCT>.
  395. *
  396. * @parm PDD | pdd | Pointer to a <t DRAWDIB_STRUCT>.
  397. *
  398. * @rdesc Returns TRUE if successful, FALSE otherwise.
  399. *
  400. **************************************************************************/
  401. static BOOL NEAR PASCAL DrawDibFree(PDD pdd, BOOL fSameDib, BOOL fSameSize)
  402. {
  403. if (pdd == NULL)
  404. return FALSE;
  405. //
  406. // If the draw palette has changed, the compressor may now be giving us DIBs
  407. // mapped to a different palette, so we need to clean up so we'll produce
  408. // a new mapping table so we'll actually draw with the new palette.
  409. // (see SendSetPalette)
  410. //
  411. if (!fSameDib)
  412. {
  413. //
  414. // if this palette is selected as the foreground palette
  415. // and we delete it we are going to hose GDI!
  416. //
  417. if (pdd->hpal)
  418. DeleteObject(pdd->hpal);
  419. if (pdd->hpalCopy)
  420. DeleteObject(pdd->hpalCopy);
  421. pdd->hpal = NULL;
  422. pdd->hpalCopy = NULL;
  423. }
  424. if (!fSameDib)
  425. {
  426. if (pdd->lpbi) {
  427. GlobalFreePtr(pdd->lpbi);
  428. pdd->lpbi = NULL;
  429. pdd->lpargbqIn = NULL;
  430. }
  431. if (pdd->lpDitherTable)
  432. {
  433. DitherTerm(pdd->lpDitherTable);
  434. pdd->lpDitherTable = NULL;
  435. }
  436. if (pdd->hic && pdd->hic != (HIC)-1)
  437. {
  438. ICDecompressEnd(pdd->hic);
  439. ICDecompressExEnd(pdd->hic);
  440. ICClose(pdd->hic);
  441. }
  442. pdd->ulFlags &= ~(DDF_IDENTITYPAL);
  443. pdd->hic = NULL;
  444. pdd->iAnimateStart = 0;
  445. pdd->iAnimateLen = 0;
  446. pdd->iAnimateEnd = 0;
  447. }
  448. if (!fSameSize || !fSameDib)
  449. {
  450. if (pdd->hdcDraw && hbmStockMono)
  451. SelectObject(pdd->hdcDraw, hbmStockMono);
  452. if (pdd->hdcDraw)
  453. DeleteDC(pdd->hdcDraw);
  454. if (pdd->hbmDraw) {
  455. DeleteObject(pdd->hbmDraw);
  456. //
  457. // if we have a bitmap pointer lose it
  458. //
  459. if (pdd->ulFlags & (DDF_CANBITMAPX))
  460. pdd->pbBitmap = NULL;
  461. }
  462. if ((pdd->pbStretch) && (pdd->pbStretch != pdd->lpDIBSection))
  463. GlobalFreePtr(pdd->pbStretch);
  464. if ((pdd->pbDither) && (pdd->pbDither != pdd->lpDIBSection))
  465. GlobalFreePtr(pdd->pbDither);
  466. if ((pdd->pbBuffer) && (pdd->pbBuffer != pdd->lpDIBSection))
  467. GlobalFreePtr(pdd->pbBuffer);
  468. #if USE_SETDI
  469. if (pdd->hbmDraw)
  470. SetBitmapEnd(&pdd->sd);
  471. #endif
  472. pdd->hdcDraw = NULL;
  473. pdd->hbmDraw = NULL;
  474. pdd->lpDIBSection = NULL;
  475. pdd->pbStretch = NULL;
  476. pdd->pbDither = NULL;
  477. pdd->pbBuffer = NULL;
  478. pdd->biDraw.biBitCount = 0;
  479. pdd->biDraw.biWidth = 0;
  480. pdd->biDraw.biHeight = 0;
  481. pdd->biBuffer.biBitCount = 0;
  482. pdd->biBuffer.biWidth = 0;
  483. pdd->biBuffer.biHeight = 0;
  484. // clear all the internal flags (except palette stuff)
  485. pdd->ulFlags &= ~(DDF_OURFLAGS ^ DDF_IDENTITYPAL);
  486. pdd->ulFlags |= DDF_DIRTY;
  487. pdd->iDecompress = 0;
  488. }
  489. return TRUE;
  490. }
  491. /**************************************************************************
  492. * @doc INTERNAL
  493. *
  494. * @api UINT | QueryDraw | see if the current display device
  495. * (DISPDIB or GDI) can draw the given dib
  496. *
  497. * @parm PDD | pdd | pointer to a <t DRAWDIB_STRUCT>.
  498. *
  499. * @parm LPBITMAPINFOHEADER | lpbi | pointer to a bitmap.
  500. *
  501. * @rdesc Returns display flags, see profdisp.h
  502. *
  503. **************************************************************************/
  504. static UINT NEAR QueryDraw(PDD pdd, LPBITMAPINFOHEADER lpbi)
  505. {
  506. return (UINT)DrawDibProfileDisplay(lpbi);
  507. }
  508. /**************************************************************************
  509. * @doc INTERNAL DrawDib
  510. *
  511. * @comm Called from DrawDibBegin to try decompression to a bitmap.
  512. *
  513. **************************************************************************/
  514. BOOL DrawDibQueryBitmapX(
  515. PDD pdd
  516. )
  517. {
  518. BITMAPINFOHEADER *pbi;
  519. #ifndef _WIN32
  520. if (!CanLockBitmaps()) {
  521. return FALSE;
  522. }
  523. #endif
  524. if (gwScreenBitDepth == 8 && !(gwRasterCaps & RC_PALETTE))
  525. return FALSE;
  526. if ((gwRasterCaps & RC_PALETTE) && !(pdd->ulFlags & DDF_IDENTITYPAL))
  527. return FALSE;
  528. pbi = &pdd->biStretch;
  529. if (!GetDIBBitmap(pdd->hbmDraw, pbi))
  530. return FALSE;
  531. #ifdef XDEBUG
  532. if (ICDecompressQuery(pdd->hic, pdd->lpbi, pbi) != ICERR_OK)
  533. {
  534. if (mmGetProfileIntA(szDrawDib, "ForceDecompressToBitmap", FALSE))
  535. {
  536. pbi->biHeight = -pbi->biHeight;
  537. pbi->biCompression = 0;
  538. }
  539. }
  540. #endif
  541. if (ICDecompressQuery(pdd->hic, pdd->lpbi, pbi) != ICERR_OK)
  542. {
  543. if (pbi->biCompression == BI_BITMAP &&
  544. pbi->biSizeImage <= 128*1024l &&
  545. (pbi->biXPelsPerMeter & 0x03) == 0 &&
  546. pbi->biSizeImage > 64*1024l)
  547. {
  548. pdd->ulFlags |= DDF_HUGEBITMAP;
  549. pbi->biCompression = 0;
  550. pbi->biSizeImage -= pbi->biYPelsPerMeter; //FillBytes
  551. if (ICDecompressQuery(pdd->hic, pdd->lpbi, pbi) != ICERR_OK)
  552. return FALSE;
  553. }
  554. else
  555. return FALSE;
  556. }
  557. pdd->ulFlags |= DDF_NEWPALETTE; // force check in DrawDibRealize
  558. pdd->ulFlags |= DDF_CANBITMAPX; // can decompress to bitmaps
  559. if (pdd->ulFlags & DDF_HUGEBITMAP)
  560. RPF((" Can decompress '%4.4hs' to a HUGE BITMAP (%dx%dx%d)",(LPSTR)&pdd->lpbi->biCompression, PUSHBI(*pbi)));
  561. else
  562. RPF((" Can decompress '%4.4hs' to a BITMAP (%dx%dx%d)",(LPSTR)&pdd->lpbi->biCompression, PUSHBI(*pbi)));
  563. //
  564. // reuse the stretch buffer for the bitmap.
  565. //
  566. pdd->biStretch = *pbi;
  567. #ifndef _WIN32
  568. pdd->pbStretch = LockBitmap(pdd->hbmDraw);
  569. if (pdd->pbStretch == NULL)
  570. {
  571. DPF((" Unable to lock bitmap!"));
  572. pdd->ulFlags &= ~DDF_CANBITMAPX; // can't decompress to bitmaps
  573. return FALSE;
  574. }
  575. #endif
  576. return TRUE;
  577. }
  578. #define Is565(bi) (((bi)->biCompression == BI_BITFIELDS) && \
  579. ((bi)->biBitCount == 16) && \
  580. (((LPDWORD)((bi)+1))[0] == 0x00F800) && \
  581. (((LPDWORD)((bi)+1))[1] == 0x0007E0) && \
  582. (((LPDWORD)((bi)+1))[2] == 0x00001F) )
  583. /**************************************************************************
  584. * @doc EXTERNAL DrawDib
  585. *
  586. * @api BOOL | DrawDibBegin | This function changes parameters
  587. * of a DrawDib context or it initializes a new DrawDib context.
  588. *
  589. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  590. *
  591. * @parm HDC | hdc | Specifies a handle to a display context for drawing (optional).
  592. *
  593. * @parm int | dxDest | Specifies the width of the destination rectangle.
  594. * Width is specified in MM_TEXT client units.
  595. *
  596. * @parm int | dyDest | Specifies the height of the destination rectangle.
  597. * Height is specified in MM_TEXT client units.
  598. *
  599. * @parm LPBITMAPINFOHEADER | lpbi | Specifies a pointer to a
  600. * <t BITMAPINFOHEADER> structure containing the
  601. * image format. The color table for the DIB follows the
  602. * image format.
  603. *
  604. * @parm int | dxSrc | Specifies the width of the source rectangle.
  605. * Width is specified in pixels.
  606. *
  607. * @parm int | dySrc | Specifies the height of the source rectangle.
  608. * Height is specified in pixels.
  609. *
  610. * @parm UNIT | wFlags | Specifies the applicable flags for
  611. * the function. The following flags are defined:
  612. *
  613. * @flag DDF_SAME_HDC | Assumes the handle to the display context
  614. * is already specified. When this flag is used,
  615. * DrawDib also assumes the correct palette has already been
  616. * realized into the device context (possibly by
  617. * <f DrawDibRealize>).
  618. *
  619. * @flag DDF_SAME_DRAW | Uses the drawing parameters previously
  620. * specified for this function. Use this flag only
  621. * if <p lpbi>, <p dxDst>, <p dyDst>, <p dxSrc>, and <p dySrc>
  622. * have not changed since using <f DrawDibDraw> or <f DrawDibBegin>.
  623. *
  624. * @flag DDF_DONTDRAW | Indicates the frame is to be decompressed
  625. * and not drawn. The DDF_UPDATE flag can be used later
  626. * to actually draw the image.
  627. *
  628. * @flag DDF_ANIMATE | Allows palette animation. If this flag is present,
  629. * the palette <f DrawDib> creates will have the PC_RESERVED flag set for
  630. * as many entries as possible, and the palette can be animated by
  631. * <f DrawDibChangePalette>. If using <f DrawDibBegin> with
  632. * <f DrawDibDraw>, set this flag with <f DrawDibBegin>
  633. * rather than <f DrawDibDraw>.
  634. *
  635. * @flag DDF_JUSTDRAWIT | Uses GDI to draw the image. This prevents
  636. * the DrawDib functions from calling ICM to decompress
  637. * the image or prevents them from
  638. * using their own routines to stretch or dither the image.
  639. * This essentially reduces <f DrawDibDraw> to <f StretchDIBits>.
  640. *
  641. * @flag DDF_BACKGROUNDPAL | Realizes the palette used for drawing
  642. * in the background leaving the actual palette used for display
  643. * unchanged. (This flag is valid only if DDF_SAME_HDC is not set.)
  644. *
  645. * @flag DDF_HALFTONE | Always dithers the DIB to a standard palette
  646. * regardless of the palette of the DIB. If using <f DrawDibBegin> with
  647. * <f DrawDibDraw>, set this flag with <f DrawDibBegin>
  648. * rather than <f DrawDibDraw>.
  649. *
  650. * @flag DDF_BUFFER | Indicates DrawDib should try to use a
  651. * offscreen buffer so DDF_UPDATE can be used. This
  652. * disables decompression and drawing directly to the screen.
  653. * If DrawDib is unable to create an offscreen buffer,
  654. * it will decompress or draw directly to the screen.
  655. *
  656. * For more information, see the DDF_UPDATE and DDF_DONTDRAW
  657. * flags described for <f DrawDibDraw>.
  658. *
  659. *
  660. * @rdesc Returns TRUE if successful.
  661. *
  662. * @comm This function prepares to draw a bitmap specified by <p lpbi>
  663. * to the display context <p hdc>. The image is stretched to
  664. * the size specified by <p dxDest> and <p dyDest>. If <p dxDest> and
  665. * <p dyDest> are (-1, -1), the bitmap is drawn to a
  666. * 1:1 scale without stretching.
  667. *
  668. * Use this function only if you want to prepare DrawDib
  669. * before using <f DrawDibDraw> to draw the image.
  670. * If you do not use this function, <f DrawDibDraw> implicitly
  671. * uses it when it draws the image.
  672. *
  673. * To update the flags set with <f DrawDibBegin>, call <f DrawDibBegin>
  674. * with new parameters.
  675. *
  676. * When <f DrawDibBegin> is used, the <f DDF_SAME_DRAW>
  677. * flag is normally set for <f DrawDibDraw>.
  678. *
  679. * If the parameters of <f DrawDibBegin> have not changed, subsequent
  680. * uses of it have not effect.
  681. *
  682. * Use <f DrawDibEnd> to free memory used by the DrawDib context.
  683. *
  684. * @xref <f DrawDibEnd> <f DrawDibDraw>
  685. **************************************************************************/
  686. //#ifndef WIN32
  687. //#pragma message("Make DrawDibBegin faster for changing the size only!")
  688. //#endif
  689. BOOL VFWAPI DrawDibBegin(HDRAWDIB hdd,
  690. HDC hdc,
  691. int dxDst,
  692. int dyDst,
  693. LPBITMAPINFOHEADER lpbi,
  694. int dxSrc,
  695. int dySrc,
  696. UINT wFlags)
  697. {
  698. PDD pdd;
  699. int ScreenBitDepth;
  700. int dxSave,dySave;
  701. BOOL fNewPal;
  702. BOOL fSameDib;
  703. BOOL fSameSize;
  704. BOOL fSameFlags;
  705. BOOL fSameHdc;
  706. UINT wFlagsChanged;
  707. DWORD ulFlagsSave;
  708. DWORD dw;
  709. UINT w;
  710. HPALETTE hPal;
  711. LONG lSize;
  712. //
  713. // Quick sanity checks....
  714. //
  715. if (lpbi == NULL)
  716. return FALSE;
  717. if ((pdd = DrawDibLock(hdd)) == NULL)
  718. return FALSE;
  719. if (!gfInit)
  720. DrawDibInit();
  721. //
  722. // fill in defaults.
  723. //
  724. if (dxSrc < 0)
  725. dxSrc = (int)lpbi->biWidth;
  726. if (dySrc < 0)
  727. dySrc = (int)lpbi->biHeight;
  728. if (dxDst < 0)
  729. dxDst = dxSrc;
  730. if (dyDst < 0)
  731. dyDst = dySrc;
  732. if (dxSrc == 0 || dySrc == 0) // !!! || dxDst == 0 || dyDst == 0)
  733. return FALSE;
  734. ulFlagsSave = pdd->ulFlags;
  735. wFlagsChanged = ((UINT)pdd->ulFlags ^ wFlags);
  736. fSameHdc = hdc == pdd->hdcLast;
  737. fSameDib = DibEq(pdd->lpbi, lpbi) &&
  738. !(wFlagsChanged & DDF_HALFTONE) &&
  739. (pdd->hpalDraw == pdd->hpalDrawLast);
  740. fSameFlags = (pdd->ulFlags & DDF_BEGINFLAGS) == (wFlags & DDF_BEGINFLAGS);
  741. fSameSize = pdd->dxDst == dxDst && pdd->dyDst == dyDst &&
  742. pdd->dxSrc == dxSrc && pdd->dySrc == dySrc;
  743. pdd->hdcLast = hdc;
  744. //
  745. // do a quick check to see if the params have changed.
  746. // If the DIB, and size of the DIB, and flags used are the same as the last
  747. // time we called DrawDibBegin, then there's nothing to do and we'll only
  748. // waste time plodding through this code.
  749. // There is one case when all these could be the same, but the situation
  750. // has still changed enough so that we need to recompute things... if the
  751. // hdc is different than last time, and we're dealing with RLE. You see,
  752. // we make some decisions about RLE (like we can go direct to a screen DC
  753. // but not a memory DC) that are affected by what hdc we're using. So
  754. // we will not bail out early if we are using RLE and the hdc's are
  755. // different.
  756. //
  757. if (fSameDib && fSameSize && fSameFlags)
  758. {
  759. if ((lpbi->biCompression != BI_RLE8 && lpbi->biCompression != BI_RLE4)
  760. || fSameHdc)
  761. return TRUE;
  762. }
  763. pdd->hpalDrawLast = pdd->hpalDraw;
  764. RPF(("DrawDibBegin %dx%dx%d '%4.4hs' [%d %d] [%d %d]",
  765. (int)lpbi->biWidth,
  766. (int)lpbi->biHeight,
  767. (int)lpbi->biBitCount,
  768. (lpbi->biCompression == BI_RGB ? (LPSTR)"None" :
  769. lpbi->biCompression == BI_RLE8 ? (LPSTR)"Rle8" :
  770. lpbi->biCompression == BI_RLE4 ? (LPSTR)"Rle4" :
  771. (LPSTR)&lpbi->biCompression),
  772. dxSrc, dySrc, dxDst, dyDst));
  773. fNewPal = pdd->hpal == NULL || !fSameDib;
  774. //
  775. // make sure this palette is not the in the DC, because we
  776. // are going to delete it, and GDI get real upset if we do this.
  777. //
  778. if (fNewPal && pdd->hpal && hdc)
  779. {
  780. hPal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE);
  781. if (hPal == pdd->hpal)
  782. RPF((" Warning unselecting palette..."));
  783. }
  784. DrawDibFree(pdd, fSameDib, fSameSize);
  785. pdd->dxSrc = dxSrc;
  786. pdd->dySrc = dySrc;
  787. pdd->dxDst = dxDst;
  788. pdd->dyDst = dyDst;
  789. //
  790. // copy the source DIB header and the colors.
  791. //
  792. if (lpbi->biClrUsed == 0 && lpbi->biBitCount <= 8)
  793. lpbi->biClrUsed = (1 << (int)lpbi->biBitCount);
  794. ////if (lpbi->biClrUsed != 0 && lpbi->biBitCount > 8)
  795. //// lpbi->biClrUsed = 0;
  796. // Make a copy of the source format. Remember, some codec could have
  797. // defined a custom format larger than a BITMAPINFOHEADER so make a copy
  798. // of EVERYTHING.
  799. if (!fSameDib) {
  800. lSize = lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
  801. pdd->lpbi = (LPBITMAPINFOHEADER)GlobalAllocPtr(GPTR, lSize);
  802. if (pdd->lpbi == NULL)
  803. return FALSE;
  804. _fmemcpy(pdd->lpbi, lpbi, (int)lSize);
  805. // This is where the colour info is
  806. pdd->lpargbqIn = (LPVOID)((LPBYTE)lpbi + lpbi->biSize);
  807. }
  808. pdd->biBuffer = *lpbi;
  809. pdd->lpbi->biSizeImage = 0;
  810. pdd->biBuffer.biSizeImage = 0;
  811. //
  812. // init all other color tables to be the initial colors
  813. //
  814. if (lpbi->biBitCount <= 8)
  815. {
  816. _fmemcpy(pdd->argbq, (LPBYTE)lpbi+(int)lpbi->biSize,
  817. (int)lpbi->biClrUsed * sizeof(RGBQUAD));
  818. _fmemcpy(pdd->aw, (LPBYTE)lpbi+(int)lpbi->biSize,
  819. (int)lpbi->biClrUsed * sizeof(RGBQUAD));
  820. }
  821. // set PalUse to default: DIB_PAL_COLORS. This will be set
  822. // to DIB_PAL_INDICES if DrawdibCheckPalette is called and detects
  823. // that it is safe to use indices. DIB_PAL_COLORS is a safe
  824. // default.
  825. pdd->uiPalUse = DIB_RGB_COLORS; // assume RGB colors for now.
  826. //
  827. // make sure the device is a palette device before dinking with
  828. // palette animation.
  829. //
  830. if (wFlags & DDF_ANIMATE)
  831. {
  832. if (!(gwRasterCaps & RC_PALETTE) ||
  833. (int)lpbi->biBitCount > 8 || pdd->hpalDraw)
  834. wFlags &= ~DDF_ANIMATE;
  835. }
  836. //
  837. // copy the flags
  838. //
  839. try_again:
  840. pdd->ulFlags &= ~DDF_USERFLAGS;
  841. pdd->ulFlags |= (wFlags & DDF_USERFLAGS);
  842. pdd->ulFlags &= ~DDF_UPDATE;
  843. //
  844. // deal with a decompressor if needed.
  845. //
  846. switch (lpbi->biCompression)
  847. {
  848. case BI_RGB:
  849. break;
  850. default:
  851. //
  852. // see if the DISPLAY/DISPDIB can draw the format directly!
  853. //
  854. // if the buffer flag is set we MUST use a decompress buffer.
  855. // regardless of what the display can do
  856. //
  857. if (wFlags & DDF_BUFFER)
  858. w = 0;
  859. else
  860. w = QueryDraw(pdd, lpbi);
  861. if (w & PD_CAN_DRAW_DIB)
  862. {
  863. if (((dxSrc == dxDst && dySrc == dyDst) && (w & PD_STRETCHDIB_1_1_OK)) ||
  864. ((dxSrc != dxDst || dySrc != dyDst) && (w & PD_STRETCHDIB_1_N_OK)) ||
  865. ((dxDst % dxSrc) == 0 && (dyDst % dySrc) == 0 && (w & PD_STRETCHDIB_1_2_OK)))
  866. {
  867. // GDI can't handle drawing RLEs to a memory DC so we will
  868. // have to pretend that RLE can't be drawn to the screen
  869. // and decompress it first.
  870. // We also can't DITHER RLE, so if we're running on a
  871. // 16 colour display, make sure we're using a decompressor.
  872. if (((lpbi->biCompression != BI_RLE8) &&
  873. (lpbi->biCompression != BI_RLE4)) ||
  874. (hdc && IsScreenDC(hdc) && gwScreenBitDepth >=8))
  875. {
  876. wFlags |= DDF_JUSTDRAWIT;
  877. if (pdd->hic)
  878. ICClose(pdd->hic);
  879. pdd->hic = NULL;
  880. goto no_decomp;
  881. }
  882. }
  883. }
  884. if (pdd->hic == NULL)
  885. {
  886. DWORD fccHandler;
  887. fccHandler = 0;
  888. if (lpbi->biCompression == BI_RLE8)
  889. fccHandler = mmioFOURCC('R','L','E',' ');
  890. pdd->hic = ICLocate(ICTYPE_VIDEO,
  891. fccHandler,
  892. lpbi, NULL,
  893. ICMODE_FASTDECOMPRESS);
  894. if (pdd->hic == NULL)
  895. pdd->hic = ICDecompressOpen(ICTYPE_VIDEO,
  896. fccHandler,lpbi,NULL);
  897. if (pdd->hic)
  898. {
  899. //
  900. // make sure the codec uses its default palette out of the gate
  901. //
  902. if (ICDecompressSetPalette(pdd->hic, NULL) == ICERR_OK)
  903. {
  904. pdd->ulFlags |= DDF_CANSETPAL;
  905. RPF((" codec supports ICM_SET_PALETTE"));
  906. }
  907. else
  908. {
  909. pdd->ulFlags &= ~DDF_CANSETPAL;
  910. }
  911. }
  912. }
  913. if (pdd->hic == NULL || pdd->hic == (HIC)-1)
  914. {
  915. RPF((" Unable to open compressor '%4.4ls'",(LPSTR)&lpbi->biCompression));
  916. pdd->hic = (HIC)-1;
  917. if (wFlags & DDF_BUFFER)
  918. {
  919. RPF((" Turning DDF_BUFFER off"));
  920. wFlags &= ~DDF_BUFFER;
  921. goto try_again;
  922. }
  923. return FALSE;
  924. }
  925. //
  926. // now find the best DIB format to decompress to.
  927. //
  928. if (!ICGetDisplayFormat(pdd->hic, lpbi, &pdd->biBuffer,
  929. (gfHalftone || (wFlags & DDF_HALFTONE)) ? 16 : 0,
  930. MulDiv(dxDst,abs((int)lpbi->biWidth),dxSrc),
  931. MulDiv(dyDst,abs((int)lpbi->biHeight),dySrc)))
  932. {
  933. RPF((" Compressor error!"));
  934. codec_error:
  935. //ICClose(pdd->hic);
  936. //pdd->hic = (HIC)-1;
  937. return FALSE;
  938. }
  939. //
  940. // we have new source params
  941. //
  942. dxSrc = MulDiv(dxSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  943. dySrc = MulDiv(dySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  944. // xSrc = MulDiv(xSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  945. // ySrc = MulDiv(ySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  946. //
  947. // now allocate the decompress buffer!
  948. //
  949. pdd->biBuffer.biSizeImage = DIBSIZEIMAGE(pdd->biBuffer);
  950. pdd->pbBuffer = GlobalAllocPtr(GHND,pdd->biBuffer.biSizeImage);
  951. if (pdd->pbBuffer == NULL)
  952. {
  953. RPF((" No Memory for decompress buffer"));
  954. ICClose(pdd->hic);
  955. pdd->hic = (HIC)-1;
  956. return FALSE;
  957. }
  958. pdd->ulFlags |= DDF_DIRTY;
  959. dw = ICDecompressBegin(pdd->hic, lpbi, &pdd->biBuffer);
  960. if (dw != ICERR_OK)
  961. {
  962. RPF((" Compressor failed ICM_DECOMPRESS_BEGIN"));
  963. goto codec_error;
  964. return FALSE;
  965. }
  966. RPF((" Decompressing '%4.4hs' to %dx%dx%d%s",(LPSTR)&lpbi->biCompression, PUSHBI(pdd->biBuffer),
  967. Is565(&pdd->biBuffer) ? (LPSTR) "(565)" : (LPSTR) ""
  968. ));
  969. pdd->iDecompress = DECOMPRESS_BUFFER;
  970. _fmemcpy(pdd->aw,pdd->argbq, 256*sizeof(RGBQUAD));
  971. lpbi = &pdd->biBuffer;
  972. break;
  973. }
  974. no_decomp:
  975. pdd->biDraw = pdd->biBuffer;
  976. pdd->biDraw.biSizeImage = 0;
  977. pdd->biDraw.biHeight = abs((int)pdd->biDraw.biHeight);
  978. if ((!(wFlags & DDF_JUSTDRAWIT)) && (lpbi->biCompression == BI_RGB))
  979. {
  980. //
  981. // test the display device for this DIB format
  982. //
  983. w = QueryDraw(pdd, lpbi);
  984. //
  985. // get the bit depth of the screen device.
  986. //
  987. ScreenBitDepth = gwScreenBitDepth;
  988. if (ScreenBitDepth > 24)
  989. ScreenBitDepth = 32; //???!!!
  990. // does the display support drawing 16bpp DIBs?
  991. // if it does not, treat it like a 24bpp device.
  992. if (ScreenBitDepth >= 24 && lpbi->biBitCount == 32 && !(w & PD_CAN_DRAW_DIB))
  993. ScreenBitDepth = 24;
  994. if (ScreenBitDepth >= 16 && lpbi->biBitCount == 16 && !(w & PD_CAN_DRAW_DIB))
  995. ScreenBitDepth = 24;
  996. //
  997. // check if the display driver isn't very good, for this format
  998. //
  999. if (!(w & PD_STRETCHDIB_1_1_OK))
  1000. {
  1001. pdd->ulFlags |= DDF_BITMAP;
  1002. }
  1003. //
  1004. // if the display driver isn't very good make a bitmap to copy into
  1005. // to draw.
  1006. //
  1007. switch (gfBitmap)
  1008. {
  1009. case 0:
  1010. pdd->ulFlags &= ~DDF_BITMAP;
  1011. break;
  1012. case 1:
  1013. pdd->ulFlags |= DDF_BITMAP;
  1014. break;
  1015. }
  1016. #ifndef WIN32
  1017. //
  1018. // for 16/32 bit DIBs, the display may not support DIBS at all and
  1019. // we should use bitmaps anyway just in case, even if the user
  1020. // tried to override
  1021. //
  1022. if ((pdd->biDraw.biBitCount == 16 || pdd->biDraw.biBitCount == 32) &&
  1023. w == PD_CAN_DRAW_DIB)
  1024. {
  1025. pdd->ulFlags |= DDF_BITMAP;
  1026. }
  1027. #endif
  1028. if ((dxSrc != dxDst || dySrc != dyDst) && !(w & PD_STRETCHDIB_1_N_OK))
  1029. pdd->ulFlags |= DDF_STRETCH;
  1030. if (dxSrc*2 == dxDst && dySrc*2 == dyDst && (w & PD_STRETCHDIB_1_2_OK))
  1031. pdd->ulFlags &= ~DDF_STRETCH;
  1032. if ((dxDst % dxSrc) == 0 && (dyDst % dySrc) == 0 && (w & PD_STRETCHDIB_1_2_OK))
  1033. pdd->ulFlags &= ~DDF_STRETCH;
  1034. if ((int)lpbi->biBitCount > ScreenBitDepth)
  1035. pdd->ulFlags |= DDF_DITHER;
  1036. //
  1037. // force halftone palette
  1038. //
  1039. if ((gfHalftone || (wFlags & DDF_HALFTONE)) && ScreenBitDepth <= 8)
  1040. pdd->ulFlags |= DDF_DITHER;
  1041. // NOTE we treat a convert up (ie 16->24) as a dither too.
  1042. if ((int)lpbi->biBitCount > 8 && (int)lpbi->biBitCount < ScreenBitDepth)
  1043. pdd->ulFlags |= DDF_DITHER;
  1044. if (pdd->ulFlags & DDF_DITHER) {
  1045. if (lpbi->biBitCount == 16 && (w & PD_CAN_DRAW_DIB)) {
  1046. pdd->ulFlags &= ~DDF_DITHER;
  1047. DPF(("Turning off DITHER for 16-bit DIBs, since we can draw them"));
  1048. }
  1049. if (lpbi->biBitCount == 32 && (w & PD_CAN_DRAW_DIB)) {
  1050. pdd->ulFlags &= ~DDF_DITHER;
  1051. DPF(("Turning off DITHER for 32-bit DIBs, since we can draw them"));
  1052. }
  1053. if (lpbi->biBitCount == 8 &&
  1054. lpbi->biClrUsed <= 16 &&
  1055. AreColorsAllGDIColors(lpbi)) {
  1056. pdd->ulFlags &= ~DDF_DITHER;
  1057. DPF(("Turning off DITHER for 8-bit DIBs already using the VGA colors"));
  1058. }
  1059. }
  1060. // force stretching in drawdib if we are dithering
  1061. if ((pdd->ulFlags & DDF_DITHER) &&
  1062. ((dxSrc != dxDst) || (dySrc != dyDst))) {
  1063. pdd->ulFlags |= DDF_STRETCH;
  1064. }
  1065. //
  1066. // force a buffer if we dont have one.
  1067. //
  1068. if ((pdd->ulFlags & DDF_BUFFER) &&
  1069. pdd->hic == NULL &&
  1070. !(pdd->ulFlags & DDF_DITHER) &&
  1071. !(pdd->ulFlags & DDF_STRETCH) &&
  1072. !(pdd->ulFlags & DDF_BITMAP))
  1073. {
  1074. RPF((" Using a buffer because DDF_BUFFER is set."));
  1075. pdd->ulFlags |= DDF_STRETCH; // force a 1:1 stretch
  1076. }
  1077. if (lpbi->biBitCount != 8
  1078. && lpbi->biBitCount != 16
  1079. && lpbi->biBitCount != 24
  1080. #ifndef _WIN32
  1081. && lpbi->biBitCount != 32
  1082. #endif
  1083. ) {
  1084. DPF(("Turning off stretch for an unsupported format...."));
  1085. pdd->ulFlags &= ~(DDF_STRETCH);
  1086. }
  1087. }
  1088. //
  1089. // delete the palette if we are changing who dithers.
  1090. //
  1091. if (pdd->hpal &&
  1092. pdd->lpbi->biBitCount > 8 &&
  1093. ((pdd->ulFlags ^ ulFlagsSave) & (DDF_DITHER)))
  1094. {
  1095. DPF((" Dither person has changed..."));
  1096. if (pdd->lpDitherTable)
  1097. {
  1098. DitherTerm(pdd->lpDitherTable);
  1099. pdd->lpDitherTable = NULL;
  1100. }
  1101. if (hdc) {
  1102. hPal = SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE);
  1103. if (hPal == pdd->hpal)
  1104. RPF((" Warning unselecting palette..."));
  1105. }
  1106. DeleteObject(pdd->hpal);
  1107. if (pdd->hpalCopy)
  1108. DeleteObject(pdd->hpalCopy);
  1109. pdd->hpal = NULL;
  1110. pdd->hpalCopy = NULL;
  1111. }
  1112. if (pdd->ulFlags & DDF_STRETCH)
  1113. {
  1114. /* the code for stretching *only* works on a 386+ */
  1115. if (gf286 || pdd->biBuffer.biBitCount < 8)
  1116. {
  1117. RPF((" Using GDI to stretch"));
  1118. pdd->ulFlags &= ~DDF_STRETCH;
  1119. }
  1120. else
  1121. {
  1122. //
  1123. // we have stretching to do, this requires extra
  1124. // headers and buffers.
  1125. //
  1126. pdd->biStretch = pdd->biBuffer;
  1127. pdd->biStretch.biWidth = dxDst;
  1128. pdd->biStretch.biHeight = dyDst;
  1129. pdd->biStretch.biSizeImage = DIBSIZEIMAGE(pdd->biStretch);
  1130. pdd->pbStretch = GlobalAllocPtr(GHND,pdd->biStretch.biSizeImage);
  1131. if (pdd->pbStretch == NULL)
  1132. {
  1133. RPF((" No memory for stretch buffer, using GDI"));
  1134. pdd->ulFlags &= ~DDF_STRETCH;
  1135. }
  1136. else
  1137. {
  1138. RPF((" Stretching %dx%dx%d%s --> %dx%dx%d",
  1139. dxSrc, dySrc, (int)lpbi->biBitCount,
  1140. (LPSTR) (Is565(lpbi) ? "(565)":""),
  1141. dxDst, dyDst, (int)pdd->biStretch.biBitCount,
  1142. (LPSTR) (Is565(&pdd->biStretch) ? "(565)":"")
  1143. ));
  1144. pdd->biDraw.biWidth = dxDst;
  1145. pdd->biDraw.biHeight = dyDst;
  1146. dxSrc = dxDst;
  1147. dySrc = dyDst;
  1148. lpbi = &pdd->biStretch;
  1149. }
  1150. }
  1151. }
  1152. if (pdd->ulFlags & DDF_DITHER)
  1153. {
  1154. pdd->ulFlags &= ~DDF_ANIMATE; // cant animate and dither!
  1155. if (ScreenBitDepth <= 8)
  1156. pdd->biDraw.biBitCount = 8;
  1157. else if (lpbi->biBitCount <= 8)
  1158. pdd->biDraw.biBitCount = lpbi->biBitCount;
  1159. else
  1160. ////////////pdd->biDraw.biBitCount = 24; //!!! what about 16bit DIB support
  1161. pdd->biDraw.biBitCount = ScreenBitDepth;
  1162. w = QueryDraw(pdd, &pdd->biDraw);
  1163. if (w & PD_STRETCHDIB_1_1_OK)
  1164. pdd->ulFlags &= ~DDF_BITMAP;
  1165. else
  1166. pdd->ulFlags |= DDF_BITMAP;
  1167. // this is wrong isn't it ? biDraw will be set to
  1168. // dxDst if we are stretching, or dxSrc if not. If we are asked to
  1169. // dither and stretch together, and we choose to leave the stretching
  1170. // to GDI, we will here set biDraw so that we ask the dither code
  1171. // to dither from dx/dySrc to dx/dyDst - ie stretch and dither in
  1172. // one go. Our current dither code will crash if you ask it to do this.
  1173. dxSave = (int)pdd->biDraw.biWidth;
  1174. dySave = (int)pdd->biDraw.biHeight;
  1175. #if 0
  1176. pdd->biDraw.biWidth = dxDst; // lpbi->biWidth;
  1177. pdd->biDraw.biHeight = dyDst; // lpbi->biHeight;
  1178. #endif
  1179. // !!! So DrawDibDraw will not DebugBreak
  1180. pdd->biDraw.biWidth = dxSrc;
  1181. pdd->biDraw.biHeight = dySrc;
  1182. pdd->biDraw.biSizeImage = DIBSIZEIMAGE(pdd->biDraw);
  1183. RPF((" Dithering %dx%dx%d --> %dx%dx%d", PUSHBI(*lpbi), PUSHBI(pdd->biDraw)));
  1184. //
  1185. // NOTE we need to use &pdd->biBuffer *not* lpbi because in the
  1186. // stretched case lpbi will point to pdd->biStretch and biStretch
  1187. // has NO COLOR TABLE
  1188. //
  1189. pdd->lpDitherTable = DitherInit(&pdd->biBuffer, &pdd->biDraw,
  1190. &pdd->DitherProc, pdd->lpDitherTable);
  1191. if (pdd->lpDitherTable == (LPVOID)-1 ||
  1192. pdd->DitherProc == NULL ||
  1193. !(pdd->pbDither = GlobalAllocPtr(GHND,pdd->biDraw.biSizeImage)))
  1194. {
  1195. if (pdd->lpDitherTable == (LPVOID)-1)
  1196. pdd->lpDitherTable = NULL;
  1197. if (pdd->lpDitherTable)
  1198. DitherTerm(pdd->lpDitherTable);
  1199. if (pdd->pbDither)
  1200. GlobalFreePtr(pdd->pbDither);
  1201. pdd->lpDitherTable = NULL;
  1202. pdd->pbDither = NULL;
  1203. pdd->biDraw.biBitCount = pdd->biBuffer.biBitCount;
  1204. pdd->biDraw.biWidth = dxSave;
  1205. pdd->biDraw.biHeight = dySave;
  1206. pdd->biDraw.biSizeImage = 0;
  1207. pdd->ulFlags &= ~DDF_DITHER;
  1208. #ifdef DEBUG_RETAIL
  1209. if (pdd->DitherProc)
  1210. RPF((" No Memory for dither tables!"));
  1211. else
  1212. RPF((" No DitherProc!"));
  1213. #endif
  1214. }
  1215. }
  1216. //
  1217. // create a palette (if needed)
  1218. //
  1219. if ((gwRasterCaps & RC_PALETTE) &&
  1220. pdd->biDraw.biBitCount <= 8 &&
  1221. pdd->hpal == NULL)
  1222. {
  1223. pdd->hpal = CreateBIPalette(pdd->hpal, &pdd->biDraw);
  1224. pdd->ulFlags |= DDF_NEWPALETTE;
  1225. }
  1226. //
  1227. // make sure we treat the palette as new when starting/stopping animate
  1228. //
  1229. if (wFlagsChanged & DDF_ANIMATE)
  1230. {
  1231. pdd->ulFlags |= DDF_NEWPALETTE;
  1232. }
  1233. //
  1234. // check for a identity palette
  1235. //
  1236. if (pdd->hpal == NULL)
  1237. {
  1238. pdd->ClrUsed = 0;
  1239. }
  1240. else if (pdd->ulFlags & DDF_NEWPALETTE)
  1241. {
  1242. GetObject(pdd->hpal,sizeof(int),(LPVOID)&pdd->ClrUsed);
  1243. if (wFlagsChanged & DDF_ANIMATE)
  1244. SetPalFlags(pdd->hpal,0,pdd->ClrUsed,0);
  1245. if (IsIdentityPalette(pdd->hpal))
  1246. {
  1247. pdd->ulFlags |= DDF_IDENTITYPAL;
  1248. pdd->iAnimateStart = 10;
  1249. }
  1250. else
  1251. {
  1252. pdd->ulFlags &= ~DDF_IDENTITYPAL;
  1253. pdd->iAnimateStart = 0;
  1254. }
  1255. pdd->iAnimateLen = min(236,pdd->ClrUsed);
  1256. pdd->iAnimateEnd = pdd->iAnimateStart + pdd->iAnimateLen;
  1257. if (pdd->ulFlags & DDF_ANIMATE)
  1258. {
  1259. RPF((" Palette animation"));
  1260. SetPalFlags(pdd->hpal,pdd->iAnimateStart,pdd->iAnimateLen,PC_RESERVED);
  1261. }
  1262. }
  1263. //
  1264. // because of bugs in GDIs StretchDIBits (doing a stretch) we
  1265. // always set the number of colors to be the maximum.
  1266. //
  1267. // this is not a big deal because we are mostly drawing full-color-table
  1268. // DIBs any way.
  1269. //
  1270. if (pdd->biDraw.biBitCount <= 8)
  1271. pdd->biDraw.biClrUsed = (1 << (int)pdd->biDraw.biBitCount);
  1272. else
  1273. pdd->biDraw.biClrUsed = 0;
  1274. DrawDibSetPalette(hdd, pdd->hpalDraw);
  1275. if (pdd->hpal)
  1276. {
  1277. if (pdd->ulFlags & DDF_IDENTITYPAL)
  1278. RPF((" Drawing with an identity palette"));
  1279. else
  1280. RPF((" Drawing with a non-identity palette"));
  1281. }
  1282. if (pdd->uiPalUse == DIB_RGB_COLORS)
  1283. RPF((" Using DIB_RGB_COLORS"));
  1284. else
  1285. RPF((" Using DIB_PAL_COLORS"));
  1286. if (pdd->hpalDraw)
  1287. RPF((" Mapping to another palette"));
  1288. if (pdd->ulFlags & DDF_BITMAP)
  1289. {
  1290. BOOL fGetDC;
  1291. BOOL f;
  1292. HWND hwndActive;
  1293. RPF((" Display driver slow for DIBs, using bitmaps"));
  1294. if (fGetDC = (hdc == NULL))
  1295. {
  1296. hwndActive = GetActiveWindow();
  1297. hdc = GetDC(hwndActive);
  1298. }
  1299. if (pdd->hdcDraw) {
  1300. if (hbmStockMono) {
  1301. SelectObject(pdd->hdcDraw, hbmStockMono);
  1302. }
  1303. } else /* if (!pdd->hdcDraw) */ {
  1304. pdd->hdcDraw = CreateCompatibleDC(hdc);
  1305. }
  1306. if (pdd->hbmDraw) {
  1307. // This fixes a memory leak. Perhaps we can just use the old one?
  1308. DPF(("Freeing hbmDraw!\n"));
  1309. DeleteObject(pdd->hbmDraw);
  1310. }
  1311. //
  1312. // NOTE the bitmap must be as wide as the source DIB when we are
  1313. // using SetDIBits() because SetDIBits() only takes a start scan not a (x,y)
  1314. //
  1315. // pdd->hbmDraw = CreateCompatibleBitmap(hdc, (int)pdd->biDraw.biWidth, (int)pdd->biDraw.biHeight);
  1316. pdd->hbmDraw = CreateCompatibleBitmap(hdc, (int)pdd->biDraw.biWidth, dySrc);
  1317. if (pdd->hbmDraw == NULL || pdd->hdcDraw == NULL)
  1318. goto bitmap_fail;
  1319. hbmStockMono = SelectObject(pdd->hdcDraw,pdd->hbmDraw);
  1320. pdd->ulFlags |= DDF_NEWPALETTE;
  1321. #if USE_SETDI
  1322. f = SetBitmapBegin(
  1323. &pdd->sd, // structure
  1324. hdc, // device
  1325. pdd->hbmDraw, // bitmap to set into
  1326. &pdd->biDraw, // --> BITMAPINFO of source
  1327. pdd->uiPalUse);
  1328. #else
  1329. f = TRUE;
  1330. #endif
  1331. if (!f)
  1332. {
  1333. bitmap_fail:
  1334. if (pdd->hdcDraw)
  1335. DeleteDC(pdd->hdcDraw);
  1336. if (pdd->hbmDraw)
  1337. DeleteObject(pdd->hbmDraw);
  1338. pdd->hdcDraw = NULL;
  1339. pdd->hbmDraw = NULL;
  1340. pdd->ulFlags &= ~DDF_BITMAP;
  1341. }
  1342. if (fGetDC)
  1343. {
  1344. ReleaseDC(hwndActive, hdc);
  1345. hdc = NULL;
  1346. }
  1347. }
  1348. //
  1349. // now try to decompress to a bitmap, we only decompress to
  1350. // bitmaps if the following is true.
  1351. //
  1352. // the decompressor must decompress direct, we will not
  1353. // stretch/dither afterward
  1354. //
  1355. // if on a palette device, the color table must be 1:1
  1356. //
  1357. // we should check a decompressor flag
  1358. //
  1359. if (pdd->hic &&
  1360. !(pdd->ulFlags & (DDF_STRETCH|DDF_DITHER)) &&
  1361. gfBitmapX &&
  1362. (pdd->lpDIBSection == NULL) &&
  1363. (dxDst == pdd->lpbi->biWidth) &&
  1364. (dyDst == pdd->lpbi->biHeight)
  1365. )
  1366. {
  1367. if (pdd->ulFlags & DDF_BITMAP) {
  1368. if (pdd->hbmDraw) {
  1369. DrawDibQueryBitmapX(pdd);
  1370. }
  1371. } else {
  1372. //even though we decided not to use bitmaps, it might still
  1373. //be worth trying decompression to bitmaps. the DDF_BITMAP
  1374. //flag is based on a comparison of StretchDIBits vs
  1375. //SetDIBits+BitBlt. Decompressing to a bitmap could be
  1376. //faster even when SetDIBits+Bitblt is slower
  1377. // but in this case, if we fail, we have to make sure we don't
  1378. // end up doing DDF_BITMAP as we know that's slower.
  1379. #if 0
  1380. if (QueryDraw(pdd, &pdd->biBuffer) & PD_BITBLT_FAST) {
  1381. BOOL fGetDC;
  1382. HWND hwndActive;
  1383. RPF((" Not using BITMAPS, but trying Decomp to Bitmap"));
  1384. if (fGetDC = (hdc == NULL))
  1385. {
  1386. hwndActive = GetActiveWindow();
  1387. hdc = GetDC(hwndActive);
  1388. }
  1389. pdd->hdcDraw = CreateCompatibleDC(hdc);
  1390. pdd->hbmDraw = CreateCompatibleBitmap(hdc, (int)pdd->biDraw.biWidth, (int)pdd->biDraw.biHeight);
  1391. if ((pdd->hbmDraw != NULL) && (pdd->hdcDraw != NULL)) {
  1392. hbmStockMono = SelectObject(pdd->hdcDraw,pdd->hbmDraw);
  1393. if (fGetDC)
  1394. {
  1395. ReleaseDC(hwndActive, hdc);
  1396. hdc = NULL;
  1397. }
  1398. DrawDibQueryBitmapX(pdd);
  1399. }
  1400. if (!(pdd->ulFlags & DDF_CANBITMAPX)) {
  1401. if (pdd->hdcDraw) {
  1402. DeleteDC(pdd->hdcDraw);
  1403. pdd->hdcDraw = NULL;
  1404. }
  1405. if (pdd->hbmDraw) {
  1406. DeleteObject(pdd->hbmDraw);
  1407. pdd->hbmDraw = NULL;
  1408. }
  1409. }
  1410. }
  1411. #endif
  1412. }
  1413. }
  1414. #ifndef WIN32 // Note: pdci will be 0 for Win32
  1415. //
  1416. // see if the decompressor can decompress directly to the screen
  1417. // doing everything, stretching and all.
  1418. //
  1419. if (pdd->hic && pdci && gfScreenX)
  1420. {
  1421. if (wFlags & DDF_BUFFER)
  1422. {
  1423. DPF((" DDF_BUFFER specified, unable to decompress to screen"));
  1424. goto cant_do_screen;
  1425. }
  1426. //
  1427. // try to decompress to screen.
  1428. //
  1429. if (((gwRasterCaps & RC_PALETTE) && !(pdd->ulFlags & DDF_IDENTITYPAL)) ||
  1430. (gwScreenBitDepth == 8 && !(gwRasterCaps & RC_PALETTE)) ||
  1431. (pdd->ulFlags & (DDF_STRETCH|DDF_DITHER)) ||
  1432. (ICDecompressExQuery(pdd->hic, 0,
  1433. pdd->lpbi, NULL, 0, 0, pdd->dxSrc, pdd->dySrc,
  1434. (LPBITMAPINFOHEADER) &biScreen, lpScreen,
  1435. 0, 0, pdd->dxDst, pdd->dyDst) != ICERR_OK))
  1436. {
  1437. cant_do_screen:
  1438. ; // we can't decompress to the screen
  1439. }
  1440. else
  1441. { // we can decompress to the screen
  1442. pdd->ulFlags |= DDF_CLIPCHECK; // we need clipping checking
  1443. pdd->ulFlags |= DDF_NEWPALETTE; // force check in DrawDibRealize
  1444. pdd->ulFlags |= DDF_CANSCREENX; // we can decompress to screen
  1445. pdd->ulFlags |= DDF_CLIPPED; // we are initialized for clipped now
  1446. RPF((" Can decompress '%4.4hs' to the SCREEN",(LPSTR)&pdd->lpbi->biCompression));
  1447. }
  1448. }
  1449. #if 0
  1450. //
  1451. // see if we can draw direct to the screen
  1452. //
  1453. if (pdd->hic && pdci && gfDrawX)
  1454. {
  1455. if (TRUE)
  1456. goto cant_draw_screen;
  1457. pdd->ulFlags |= DDF_CLIPCHECK; // we need clipping checking
  1458. pdd->ulFlags |= DDF_NEWPALETTE; // force check in DrawDibRealize
  1459. pdd->ulFlags |= DDF_CANDRAWX; // we can decompress to screen
  1460. pdd->ulFlags |= DDF_CLIPPED; // we are initialized for clipped now
  1461. RPF((" Can draw to the SCREEN"));
  1462. cant_draw_screen:
  1463. ;
  1464. }
  1465. #endif
  1466. #endif
  1467. //
  1468. // see if the source cordinates need translated
  1469. //
  1470. if (abs((int)pdd->biBuffer.biWidth) != (int)pdd->lpbi->biWidth ||
  1471. abs((int)pdd->biBuffer.biHeight) != (int)pdd->lpbi->biHeight)
  1472. {
  1473. pdd->ulFlags |= DDF_XLATSOURCE;
  1474. }
  1475. return TRUE;
  1476. }
  1477. /**************************************************************************
  1478. * @doc EXTERNAL DrawDib
  1479. *
  1480. * @api BOOL | DrawDibEnd | This function frees a DrawDib context.
  1481. *
  1482. * @parm HDRAWDIB | hdd | Specifies the handle to the DrawDib context to free.
  1483. *
  1484. * @rdesc Returns TRUE if successful.
  1485. *
  1486. * @comm Any flags set or palette changes made by <f DrawDibBegin> or
  1487. * <f DrawDibDraw> is discarded by <f DrawDibEnd>.
  1488. *
  1489. **************************************************************************/
  1490. BOOL VFWAPI DrawDibEnd(HDRAWDIB hdd)
  1491. {
  1492. PDD pdd;
  1493. if ((pdd = DrawDibLock(hdd)) == NULL)
  1494. return FALSE;
  1495. DrawDibFree(pdd, FALSE, FALSE);
  1496. return TRUE;
  1497. }
  1498. /**************************************************************************
  1499. * @doc EXTERNAL DrawDib
  1500. *
  1501. * @api BOOL | DrawDibTime | Returns timing information about
  1502. * the drawing during debug operation.
  1503. *
  1504. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  1505. *
  1506. * @parm LPDRAWDIBTIME | lpddtime | Specifies a pointer to
  1507. * a <t DRAWDIBTIME> structure.
  1508. *
  1509. * @rdesc Returns TRUE if successful.
  1510. *
  1511. **************************************************************************/
  1512. BOOL VFWAPI DrawDibTime(HDRAWDIB hdd, LPDRAWDIBTIME lpddtime)
  1513. {
  1514. #ifdef DEBUG_RETAIL
  1515. PDD pdd;
  1516. if ((pdd = DrawDibLock(hdd)) == NULL)
  1517. return FALSE;
  1518. if (lpddtime)
  1519. *lpddtime = pdd->ddtime;
  1520. if (pdd->ddtime.timeCount > 0)
  1521. {
  1522. RPF(("timeCount: %u", (UINT)pdd->ddtime.timeCount));
  1523. RPF(("timeDraw: %ums (%u)", (UINT)pdd->ddtime.timeDraw, (UINT)pdd->ddtime.timeDraw/(UINT)pdd->ddtime.timeCount));
  1524. RPF(("timeDecompress: %ums (%u)", (UINT)pdd->ddtime.timeDecompress, (UINT)pdd->ddtime.timeDecompress/(UINT)pdd->ddtime.timeCount));
  1525. RPF(("timeDither: %ums (%u)", (UINT)pdd->ddtime.timeDither, (UINT)pdd->ddtime.timeDither/(UINT)pdd->ddtime.timeCount));
  1526. RPF(("timeStretch: %ums (%u)", (UINT)pdd->ddtime.timeStretch, (UINT)pdd->ddtime.timeStretch/(UINT)pdd->ddtime.timeCount));
  1527. RPF(("timeSetDIBits: %ums (%u)", (UINT)pdd->ddtime.timeSetDIBits, (UINT)pdd->ddtime.timeSetDIBits/(UINT)pdd->ddtime.timeCount));
  1528. RPF(("timeBlt: %ums (%u)", (UINT)pdd->ddtime.timeBlt, (UINT)pdd->ddtime.timeBlt/(UINT)pdd->ddtime.timeCount));
  1529. }
  1530. pdd->ddtime.timeCount = 0;
  1531. pdd->ddtime.timeDraw = 0;
  1532. pdd->ddtime.timeDecompress = 0;
  1533. pdd->ddtime.timeDither = 0;
  1534. pdd->ddtime.timeStretch = 0;
  1535. pdd->ddtime.timeSetDIBits = 0;
  1536. pdd->ddtime.timeBlt = 0;
  1537. return TRUE;
  1538. #else
  1539. return FALSE;
  1540. #endif
  1541. }
  1542. /*
  1543. * CopyPal -- copy a palette
  1544. */
  1545. HPALETTE CopyPal(HPALETTE hpal)
  1546. {
  1547. NPLOGPALETTE pLogPal = NULL;
  1548. HPALETTE hpalNew = NULL;
  1549. int iSizePalette = 0; // size of entire palette
  1550. if (hpal == NULL)
  1551. return NULL;
  1552. GetObject(hpal,sizeof(iSizePalette),(LPSTR)&iSizePalette);
  1553. pLogPal = (NPLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE)
  1554. + iSizePalette * sizeof(PALETTEENTRY));
  1555. if (!pLogPal)
  1556. return NULL;
  1557. pLogPal->palVersion = 0x300;
  1558. pLogPal->palNumEntries = iSizePalette;
  1559. GetPaletteEntries(hpal, 0, iSizePalette, pLogPal->palPalEntry);
  1560. hpal = CreatePalette(pLogPal);
  1561. LocalFree((HLOCAL) pLogPal);
  1562. return hpal;
  1563. }
  1564. /**************************************************************************
  1565. * @doc EXTERNAL DrawDib
  1566. *
  1567. * @api HPALETTE | DrawDibGetPalette | This function obtains the palette
  1568. * used by a DrawDib context.
  1569. *
  1570. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  1571. *
  1572. * @rdesc Returns a handle for the palette if successful, otherwise
  1573. * it returns NULL.
  1574. *
  1575. * @comm Use <f DrawDibRealize> instead of this function
  1576. * to realize the correct palette in response to a window
  1577. * message. You should rarely need to call this function.
  1578. *
  1579. * Applications do not have exclusive use of the palette
  1580. * obtained with this function. Applications should not
  1581. * free the palette or assign it to a display context
  1582. * with functions such as <f SelectPalette>. Applications
  1583. * should also anticipate that some other
  1584. * application can invalidate the handle. The palette
  1585. * handle might also become invalid after the next use of a DrawDib function.
  1586. *
  1587. * This function returns a valid handle only after
  1588. * <f DrawDibBegin> has been used without pairing it with
  1589. * <f DrawDibEnd>, or if <f DrawDibDraw> has been used.
  1590. *
  1591. * @xref <f DrawDibSetPalette> <f DrawDibRealize>
  1592. *
  1593. **************************************************************************/
  1594. HPALETTE VFWAPI DrawDibGetPalette(HDRAWDIB hdd)
  1595. {
  1596. PDD pdd;
  1597. if ((pdd = DrawDibLock(hdd)) == NULL)
  1598. return NULL;
  1599. if (pdd->hpalDraw)
  1600. return pdd->hpalDraw;
  1601. else {
  1602. // For palette animation we can't return a different palette than the
  1603. // real palette, so return hpal, not hpalCopy.
  1604. // Just trust me. - Toddla
  1605. if (pdd->ulFlags & DDF_ANIMATE)
  1606. return pdd->hpal;
  1607. // In order for us to play direct to screen, etc, all palette
  1608. // realization has to come through DrawDibRealize. But that won't
  1609. // always happen. Some apps will always ask us for our palette and
  1610. // realize it themselves. So if we give them a copy of our palette,
  1611. // and never our true palette, when our play code realizes the true
  1612. // palette it's guarenteed to cause an actual palette change and we'll
  1613. // correctly detect playing to screen. (BUG 1761)
  1614. if (pdd->hpalCopy == NULL)
  1615. pdd->hpalCopy = CopyPal(pdd->hpal);
  1616. return pdd->hpalCopy;
  1617. }
  1618. }
  1619. /**************************************************************************
  1620. * @doc EXTERNAL DrawDib
  1621. *
  1622. * @api BOOL | DrawDibSetPalette | This function sets the palette
  1623. * used for drawing device independent bitmaps.
  1624. *
  1625. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  1626. *
  1627. * @parm HPALETTE | hpal | Specifies a handle to the palette.
  1628. * Specify NULL to use the default palette.
  1629. *
  1630. * @rdesc Returns TRUE if successful.
  1631. *
  1632. * @comm Use this function when the application needs to realize an
  1633. * alternate palette. The function forces the DrawDib context to use the
  1634. * specified palette, possibly at the expense of image quality.
  1635. *
  1636. * Do not free a palette assigned to a DrawDib context until
  1637. * either a new palette replaces it (for example, if hpal1 is the
  1638. * current palette, replacing it with DrawDibSetPalette(hdd, hpal2)),
  1639. * or until the palette handle for the DrawDib context is set to
  1640. * to the default palette (for example, DrawDibSetPalette(hdd, NULL)).
  1641. *
  1642. * @xref <f DrawDibGetPalette>
  1643. *
  1644. **************************************************************************/
  1645. BOOL VFWAPI DrawDibSetPalette(HDRAWDIB hdd, HPALETTE hpal)
  1646. {
  1647. PDD pdd;
  1648. int i;
  1649. if ((pdd = DrawDibLock(hdd)) == NULL)
  1650. return FALSE;
  1651. if (hpal == pdd->hpalCopy)
  1652. hpal = NULL;
  1653. if (pdd->hpalDraw != hpal)
  1654. pdd->ulFlags |= DDF_NEWPALETTE;
  1655. pdd->hpalDraw = hpal; // always set this variable
  1656. if (pdd->hpal == NULL) // no palette to dink with
  1657. return TRUE;
  1658. if (pdd->biDraw.biBitCount > 8) // make sure we are drawing palettized
  1659. return TRUE;
  1660. if (pdd->ulFlags & DDF_ANIMATE)
  1661. {
  1662. DPF(("DrawDibSetPalette called while in DDF_ANIMATE mode!"));
  1663. }
  1664. //
  1665. // we are now using PAL colors...
  1666. //
  1667. pdd->uiPalUse = DIB_PAL_COLORS;
  1668. if (pdd->hpalDraw != NULL)
  1669. {
  1670. /* Set up table for BI_PAL_COLORS non 1:1 drawing */
  1671. //
  1672. // map all of our colors onto the given palette
  1673. // NOTE we can't use the select background trick
  1674. // because the given palette <hpalDraw> may have
  1675. // PC_RESERVED entries in it.
  1676. //
  1677. // SendSetPalette(pdd);
  1678. for (i=0; i < 256; i++)
  1679. {
  1680. if (pdd->biBuffer.biBitCount == 8)
  1681. {
  1682. pdd->aw[i] = GetNearestPaletteIndex(pdd->hpalDraw,
  1683. RGB(pdd->argbq[i].rgbRed,
  1684. pdd->argbq[i].rgbGreen,
  1685. pdd->argbq[i].rgbBlue));
  1686. }
  1687. else
  1688. {
  1689. PALETTEENTRY pe;
  1690. GetPaletteEntries(pdd->hpal, i, 1, &pe);
  1691. pdd->aw[i] = GetNearestPaletteIndex(pdd->hpalDraw,
  1692. RGB(pe.peRed,
  1693. pe.peGreen,
  1694. pe.peBlue));
  1695. }
  1696. }
  1697. for (; i<256; i++)
  1698. pdd->aw[i] = 0;
  1699. }
  1700. else
  1701. {
  1702. /* Set up table for BI_PAL_COLORS 1:1 drawing */
  1703. // SendSetPalette(pdd);
  1704. for (i=0; i<(int)pdd->ClrUsed; i++)
  1705. pdd->aw[i] = i;
  1706. for (; i<256; i++)
  1707. pdd->aw[i] = 0;
  1708. }
  1709. return TRUE;
  1710. }
  1711. /**************************************************************************
  1712. * @doc EXTERNAL DrawDib
  1713. *
  1714. * @api BOOL | DrawDibChangePalette | This function sets the palette entries
  1715. * used for drawing device independent bitmaps.
  1716. *
  1717. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  1718. *
  1719. * @parm int | iStart | Specifies the starting palette entry number.
  1720. *
  1721. * @parm int | iLen | Specifies the number of palette entries.
  1722. *
  1723. * @parm LPPALETTEENTRY | lppe | Specifies a pointer to an
  1724. * array of palette entries.
  1725. *
  1726. * @rdesc Returns TRUE if successful.
  1727. *
  1728. * @comm
  1729. * Use this function when the DIB color table changes and
  1730. * other parameters stay constant. This function changes
  1731. * the physical palette only if the current
  1732. * DrawDib palette is curently realized by calling <f DrawDibRealize>.
  1733. *
  1734. * The DIB color table must be changed by the user or
  1735. * the next use of <f DrawDibDraw> without the DDF_SAME_DRAW flag
  1736. * implicity calls <f DrawDibBegin>.
  1737. *
  1738. * If the DDF_ANIMATE flag is not set in the previous call to
  1739. * <f DrawDibBegin> or <f DrawDibDraw>, this function will
  1740. * animate the palette. In this case, update the DIB color
  1741. * table from the palette specified by <p lppe> and use
  1742. * <f DrawDibRealize> to realize the updated palette. Redraw
  1743. * the image to see the updated colors.
  1744. *
  1745. * @xref <f DrawDibSetPalette> <f DrawDibRealize>
  1746. *
  1747. **************************************************************************/
  1748. BOOL VFWAPI DrawDibChangePalette(HDRAWDIB hdd, int iStart, int iLen, LPPALETTEENTRY lppe)
  1749. {
  1750. PDD pdd;
  1751. int i;
  1752. int iStartSave;
  1753. int iLenSave;
  1754. LPPALETTEENTRY lppeSave;
  1755. if ((pdd = DrawDibLock(hdd)) == NULL)
  1756. return FALSE;
  1757. if (pdd->biBuffer.biBitCount != 8)
  1758. return FALSE;
  1759. if (lppe == NULL || iStart < 0 || iLen + iStart > 256)
  1760. return FALSE;
  1761. for (i=0; i<iLen; i++)
  1762. {
  1763. (*(pdd->lpargbqIn))[iStart+i].rgbRed = lppe[i].peRed;
  1764. (*(pdd->lpargbqIn))[iStart+i].rgbGreen = lppe[i].peGreen;
  1765. (*(pdd->lpargbqIn))[iStart+i].rgbBlue = lppe[i].peBlue;
  1766. }
  1767. //
  1768. // handle a palette change for 8bit dither
  1769. //
  1770. if (pdd->lpDitherTable)
  1771. {
  1772. for (i=0; i<iLen; i++)
  1773. {
  1774. pdd->argbq[iStart+i].rgbRed = lppe[i].peRed;
  1775. pdd->argbq[iStart+i].rgbGreen = lppe[i].peGreen;
  1776. pdd->argbq[iStart+i].rgbBlue = lppe[i].peBlue;
  1777. }
  1778. pdd->lpDitherTable = DitherInit(pdd->lpbi, &pdd->biDraw, &pdd->DitherProc, pdd->lpDitherTable);
  1779. }
  1780. else if (pdd->hpalDraw)
  1781. {
  1782. SetPaletteEntries(pdd->hpal, iStart, iLen, lppe);
  1783. pdd->ulFlags |= DDF_NEWPALETTE;
  1784. for (i=iStart; i<iLen; i++)
  1785. {
  1786. pdd->aw[i] = GetNearestPaletteIndex(pdd->hpalDraw,
  1787. RGB(lppe[i].peRed,lppe[i].peGreen,lppe[i].peBlue));
  1788. }
  1789. }
  1790. else if (pdd->ulFlags & DDF_ANIMATE)
  1791. {
  1792. for (i=iStart; i<iStart+iLen; i++)
  1793. {
  1794. if (i >= pdd->iAnimateStart && i < pdd->iAnimateEnd)
  1795. lppe[i-iStart].peFlags = PC_RESERVED;
  1796. else
  1797. lppe[i-iStart].peFlags = 0;
  1798. }
  1799. /* Change iLen, iStart so that they only include the colors
  1800. ** we can actually animate. If we don't do this, the
  1801. ** AnimatePalette() call just returns without doing anything.
  1802. */
  1803. iStartSave = iStart;
  1804. iLenSave = iLen;
  1805. lppeSave = lppe;
  1806. if (iStart < pdd->iAnimateStart)
  1807. {
  1808. iLen -= (pdd->iAnimateStart - iStart);
  1809. lppe += (pdd->iAnimateStart - iStart);
  1810. iStart = pdd->iAnimateStart;
  1811. }
  1812. if (iStart + iLen > pdd->iAnimateEnd)
  1813. iLen = pdd->iAnimateEnd - iStart;
  1814. AnimatePalette(pdd->hpal, iStart, iLen, lppe);
  1815. //
  1816. // any colors we could not animate, map to nearest
  1817. //
  1818. for (i=iStartSave; i<iStartSave+iLenSave; i++)
  1819. {
  1820. if (i >= pdd->iAnimateStart && i < pdd->iAnimateEnd)
  1821. pdd->aw[i] = i;
  1822. else
  1823. pdd->aw[i] = GetNearestPaletteIndex(pdd->hpal,
  1824. RGB(lppeSave[i-iStartSave].peRed,
  1825. lppeSave[i-iStartSave].peGreen,
  1826. lppeSave[i-iStartSave].peBlue));
  1827. }
  1828. }
  1829. else if (pdd->hpal)
  1830. {
  1831. SetPaletteEntries(pdd->hpal, iStart, iLen, lppe);
  1832. pdd->ulFlags |= DDF_NEWPALETTE;
  1833. }
  1834. else
  1835. {
  1836. for (i=0; i<iLen; i++)
  1837. {
  1838. ((RGBQUAD *)pdd->aw)[iStart+i].rgbRed = lppe[i].peRed;
  1839. ((RGBQUAD *)pdd->aw)[iStart+i].rgbGreen = lppe[i].peGreen;
  1840. ((RGBQUAD *)pdd->aw)[iStart+i].rgbBlue = lppe[i].peBlue;
  1841. }
  1842. if (pdd->hbmDraw)
  1843. pdd->ulFlags |= DDF_NEWPALETTE;
  1844. }
  1845. #ifdef DIBSECTION
  1846. if (pdd->lpDIBSection) {
  1847. // the colour table of a DIB Section is not changed when the palette
  1848. // used to create it changes. We need to explicitly change it.
  1849. SetDIBColorTable(pdd->hdcDraw, iStart, iLen,
  1850. &(*(pdd->lpargbqIn))[iStart]);
  1851. }
  1852. #endif
  1853. // We'll break buggy apps if we delete a palette we've given them
  1854. // even though we told them not to use it.
  1855. //
  1856. // if (pdd->hpalCopy)
  1857. // DeleteObject(pdd->hpalCopy);
  1858. // pdd->hpalCopy = NULL;
  1859. return TRUE;
  1860. }
  1861. /**************************************************************************
  1862. *
  1863. * @doc EXTERNAL DrawDib
  1864. *
  1865. * @api UINT | DrawDibRealize | This function realizes palette
  1866. * of the display context specified into the DrawDib context.
  1867. *
  1868. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  1869. *
  1870. * @parm HDC | hdc | Specifies a handle to the display context containing
  1871. * the palette.
  1872. *
  1873. * @parm BOOL | fBackground | If set to a nonzero value,
  1874. * the selected palette is selected as a background palette.
  1875. * If this is set to zero and the device context is attached
  1876. * to a window, the logical palette is a foreground palette when
  1877. * the window has the input focus. (The device context is attached
  1878. * to a window if it was obtained by using the <f GetDC> function
  1879. * or if the window-class style is CS_OWNDC.)
  1880. *
  1881. * @rdesc Returns number of entries in the logical palette
  1882. * mapped to different values in the system palette. If
  1883. * an error occurs or no colors were updated, it returns zero.
  1884. *
  1885. * @comm This function should only be used to
  1886. * handle a <m WM_PALETTECHANGE> or <m WM_QUERYNEWPALETTE>
  1887. * message, or used in conjunction with the DDF_SAME_HDC flag
  1888. * to prepare a display context prior to calling <f DrawDibDraw>
  1889. * multiple times.
  1890. *
  1891. * @ex The following example shows how the function is used to
  1892. * handle a <m WM_PALETTECHANGE> or <m WM_QUERYNEWPALETTE>
  1893. * message: |
  1894. *
  1895. * case WM_PALETTECHANGE:
  1896. * if ((HWND)wParam == hwnd)
  1897. * break;
  1898. *
  1899. * case WM_QUERYNEWPALETTE:
  1900. * hdc = GetDC(hwnd);
  1901. *
  1902. * f = DrawDibRealize(hdd, hdc, FALSE) > 0;
  1903. *
  1904. * ReleaseDC(hwnd, hdc);
  1905. *
  1906. * if (f)
  1907. * InvalidateRect(hwnd, NULL, TRUE);
  1908. * break;
  1909. *
  1910. * @ex The following example shows using <f DrawDibRealize> prior to
  1911. * calling <f DrawDibDraw> multiple times: |
  1912. *
  1913. * hdc = GetDC(hwnd);
  1914. * DrawDibRealize(hdd, hdc, fBackground);
  1915. * DrawDibDraw(hdd, hdc, ..........., DDF_SAME_DRAW|DDF_SAME_HDC);
  1916. * DrawDibDraw(hdd, hdc, ..........., DDF_SAME_DRAW|DDF_SAME_HDC);
  1917. * DrawDibDraw(hdd, hdc, ..........., DDF_SAME_DRAW|DDF_SAME_HDC);
  1918. * ReleaseDC(hwnd, hdc);
  1919. *
  1920. * @ex The following example shows using <f DrawDibRealize> with <f DDF_ANIMATE>
  1921. * and (f DrawDibChangePalette> to do palette animation |
  1922. *
  1923. * hdc = GetDC(hwnd);
  1924. * DrawDibBegin(hdd, ....., DDF_ANIMATE);
  1925. * DrawDibRealize(hdd, hdc, fBackground);
  1926. * DrawDibDraw(hdd, hdc, ...., DDF_SAME_DRAW|DDF_SAME_HDC);
  1927. * DrawDibChangePalette(hdd, ....);
  1928. * ReleaseDC(hwnd, hdc);
  1929. *
  1930. * @comm To draw an image mapped to another palette use <f DrawDibSetPalette>.
  1931. *
  1932. * To make <f DrawDibDraw> select its palette as a background palette
  1933. * use the DDF_BACKGROUNDPAL flag and not this function.
  1934. *
  1935. * While the DrawDib palette is selected into the display context,
  1936. * do not call <f DrawDibEnd>, <f DrawDibClose>, <f DrawDibBegin>, or
  1937. * <f DrawDibDraw> (with a different draw/format) on the same DrawDib
  1938. * context <p hdd>. These can free the selected palette
  1939. * while it is being used by your display context and cause
  1940. * a GDI error.
  1941. *
  1942. * <f DrawDibRealize> will return 0 if called before a
  1943. * <f DrawDibBegin> or <f DrawDibDraw>
  1944. *
  1945. * @xref <f SelectPalette>
  1946. *
  1947. **************************************************************************/
  1948. UINT VFWAPI DrawDibRealize(HDRAWDIB hdd, HDC hdc, BOOL fBackground)
  1949. {
  1950. PDD pdd;
  1951. HPALETTE hpal;
  1952. UINT u;
  1953. if (hdc == NULL)
  1954. return 0;
  1955. if ((pdd = DrawDibLock(hdd)) == NULL)
  1956. return 0;
  1957. if (IsScreenDC(hdc))
  1958. pdd->ulFlags &= ~DDF_MEMORYDC;
  1959. else
  1960. pdd->ulFlags |= DDF_MEMORYDC;
  1961. if (pdd->ulFlags & DDF_MEMORYDC)
  1962. DPF(("Drawing to a memory DC"));
  1963. SetStretchBltMode(hdc, COLORONCOLOR);
  1964. //
  1965. // what palette should we realize
  1966. //
  1967. hpal = pdd->hpalDraw ? pdd->hpalDraw : pdd->hpal;
  1968. //
  1969. // if we dont have a palette, we have nothing to realize
  1970. // still call DrawDibPalChange though
  1971. //
  1972. if (hpal == NULL)
  1973. {
  1974. if (pdd->ulFlags & DDF_NEWPALETTE)
  1975. {
  1976. DrawDibPalChange(pdd, hdc, hpal);
  1977. pdd->ulFlags &= ~DDF_NEWPALETTE;
  1978. }
  1979. return 0;
  1980. }
  1981. // !!! There is a bug in GDI that will not map an identity palette 1-1 into
  1982. // !!! the system palette every time, which hoses us and makes it look like
  1983. // !!! dog spew. This ICKITY-ACKITY-OOP code will flush the palette and
  1984. // !!! prevent the bug... BUT it introduces another bug where if we are a
  1985. // !!! background app, we hose everybody else's palette but ours. So let's
  1986. // !!! live with the GDI bug. One other thing... attempting this fix will
  1987. // !!! cause the bug to repro more often than it would have if you had left
  1988. // !!! it alone, unless you do the fix JUST RIGHT! I don't trust myself
  1989. // !!! that much.
  1990. #if 0
  1991. if ((pdd->ulFlags & DDF_NEWPALETTE) && (pdd->ulFlags & DDF_IDENTITYPAL) &&
  1992. !fBackground)
  1993. {
  1994. //
  1995. // this will flush the palette clean to avoid a GDI BUG!!!
  1996. //
  1997. SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
  1998. SetSystemPaletteUse(hdc, SYSPAL_STATIC);
  1999. }
  2000. #endif
  2001. //
  2002. // select and realize it
  2003. //
  2004. SelectPalette(hdc, hpal, fBackground);
  2005. u = RealizePalette(hdc);
  2006. // !!! If two DrawDib instances share the same palette handle, the second
  2007. // one will not change any colours and u will be 0, and it will not stop
  2008. // decompressing to screen or recompute stuff for bitmaps when it goes
  2009. // into the background and it will get a messed up palette.
  2010. // !!! This is a known bug we don't care about
  2011. //
  2012. // this should be fixed by the hpalCopy stuff.
  2013. if (u > 0 || (pdd->ulFlags & DDF_NEWPALETTE))
  2014. {
  2015. pdd->ulFlags |= DDF_NEWPALETTE;
  2016. DrawDibPalChange(pdd, hdc, hpal);
  2017. pdd->ulFlags &= ~DDF_NEWPALETTE;
  2018. }
  2019. return u;
  2020. }
  2021. /**************************************************************************
  2022. * @doc EXTERNAL DrawDib VFW11
  2023. *
  2024. * @api LPVOID | DrawDibGetBuffer | This function returns the pointer
  2025. * to the DrawDib decompress buffer.
  2026. *
  2027. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2028. *
  2029. * @parm LPBITMAPINFOHEADER | lpbi | Specifies a pointer to a
  2030. * <t BITMAPINFOHEADER> structure.
  2031. *
  2032. * @parm DWORD | dwSize | Specifies the size of the buffer pointed to by <p lpbi>
  2033. *
  2034. * @parm DWORD | dwFlags | Set to zero.
  2035. *
  2036. * @rdesc Returns a pointer to the buffer used by DrawDib for decompression,
  2037. * or NULL if no buffer is used. If <p lpbi> is not NULL,
  2038. * it is filled in with a copy of the <t BITMAPINFOHEADER>
  2039. * describing the buffer.
  2040. *
  2041. * The structure for <p lpbi> must have room for a
  2042. * <t BITMAPINFOHEADER> and 256 colors.
  2043. *
  2044. **************************************************************************/
  2045. LPVOID VFWAPI DrawDibGetBuffer(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi, DWORD dwSize, DWORD dwFlags)
  2046. {
  2047. PDD pdd;
  2048. if ((pdd = DrawDibLock(hdd)) == NULL)
  2049. return NULL;
  2050. if (lpbi)
  2051. {
  2052. hmemcpy(lpbi, &pdd->biBuffer,
  2053. min(dwSize, pdd->biBuffer.biSize + 256*sizeof(RGBQUAD)));
  2054. }
  2055. return pdd->pbBuffer;
  2056. }
  2057. LPVOID VFWAPI DrawDibGetBufferOld(HDRAWDIB hdd, LPBITMAPINFOHEADER lpbi)
  2058. {
  2059. return DrawDibGetBuffer(hdd, lpbi, sizeof(BITMAPINFOHEADER), 0);
  2060. }
  2061. /**************************************************************************
  2062. * @doc EXTERNAL DrawDibStart
  2063. *
  2064. * @api BOOL | DrawDibStart | This function prepares a DrawDib
  2065. * context for streaming playback.
  2066. *
  2067. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2068. *
  2069. * @parm LONG | rate | Specifies the playback rate (in microseconds per frame).
  2070. *
  2071. * @rdesc Returns TRUE if successful.
  2072. *
  2073. * @xref <f DrawDibStop>
  2074. *
  2075. **************************************************************************/
  2076. BOOL VFWAPI DrawDibStart(HDRAWDIB hdd, DWORD rate)
  2077. {
  2078. PDD pdd;
  2079. if ((pdd = DrawDibLock(hdd)) == NULL)
  2080. return FALSE;
  2081. if (pdd->hic == (HIC)-1)
  2082. return FALSE;
  2083. // if the codec does not care about this message dont fail.
  2084. if (pdd->hic != NULL)
  2085. ICSendMessage(pdd->hic, ICM_DRAW_START, rate, 0);
  2086. return TRUE;
  2087. }
  2088. /**************************************************************************
  2089. * @doc EXTERNAL DrawDibStop
  2090. *
  2091. * @api BOOL | DrawDibStop | This function frees the resources
  2092. * used by a DrawDib context for streaming playback.
  2093. *
  2094. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2095. *
  2096. * @rdesc Returns TRUE if successful.
  2097. *
  2098. * @xref <f DrawDibStart>
  2099. *
  2100. **************************************************************************/
  2101. BOOL VFWAPI DrawDibStop(HDRAWDIB hdd)
  2102. {
  2103. PDD pdd;
  2104. if ((pdd = DrawDibLock(hdd)) == NULL)
  2105. return FALSE;
  2106. if (pdd->hic == (HIC)-1)
  2107. return FALSE;
  2108. if (pdd->hic != NULL)
  2109. ICSendMessage(pdd->hic, ICM_DRAW_STOP, 0, 0);
  2110. return TRUE;
  2111. }
  2112. /**************************************************************************
  2113. * @doc EXTERNAL DrawDib
  2114. *
  2115. * @api BOOL | DrawDibUpdate | This macro updates the last
  2116. * buffered frame drawn.
  2117. *
  2118. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2119. *
  2120. * @parm HDC | hdc | Specifies a handle to the display context.
  2121. *
  2122. * @parm int | xDst | Specifies the x-coordinate of the upper left-corner
  2123. * of the destination rectangle. Coordinates are specified
  2124. * in MM_TEXT client coordinates.
  2125. *
  2126. * @parm int | yDst | Specifies the y-coordinate of the upper-left corner
  2127. * of the destination rectangle. Coordinates are specified
  2128. * in MM_TEXT client coordinates.
  2129. *
  2130. * @rdesc Returns TRUE if successful.
  2131. *
  2132. * @comm This macro uses <f DrawDibDraw> to send the DDF_UPDATE flag
  2133. * to the DrawDib context.
  2134. *
  2135. **************************************************************************/
  2136. /**************************************************************************
  2137. * @doc EXTERNAL DrawDib
  2138. *
  2139. * @api BOOL | DrawDibDraw | This function draws a device independent
  2140. * bitmap to the screen.
  2141. *
  2142. * @parm HDRAWDIB | hdd | Specifies a handle to a DrawDib context.
  2143. *
  2144. * @parm HDC | hdc | Specifies a handle to the display context.
  2145. *
  2146. * @parm int | xDst | Specifies the x-coordinate of the upper left-corner
  2147. * of the destination rectangle. Coordinates are specified
  2148. * in MM_TEXT client coordinates.
  2149. *
  2150. * @parm int | yDst | Specifies the y-coordinate of the upper-left corner
  2151. * of the destination rectangle. Coordinates are specified
  2152. * in MM_TEXT client coordinates.
  2153. *
  2154. * @parm int | dxDst | Specifies the width of the destination rectangle.
  2155. * The width is specified in MM_TEXT client coordinates. If
  2156. * <p dxDst> is -1, the width of the bitmap is used.
  2157. *
  2158. * @parm int | dyDst | Specifies the height of the destination rectangle.
  2159. * The height is specified in MM_TEXT client coordinates. If
  2160. * <p dyDst> is -1, the height of the bitmap is used.
  2161. *
  2162. * @parm LPBITMAPINFOHEADER | lpbi | Specifies a pointer to the
  2163. * <t BITMAPINFOHEADER> structure for the bitmap. The color
  2164. * table for the DIB follows the format information. The
  2165. * height specified for the DIB in the structure must be
  2166. * positive (that is, this function will not draw inverted DIBs).
  2167. *
  2168. * @parm LPVOID | lpBits | Specifies a pointer to the buffer
  2169. * containing the bitmap bits.
  2170. *
  2171. * @parm int | xSrc | Specifies the x-coordinate of the upper-left corner
  2172. * source rectangle. Coordinates are specified in pixels.
  2173. * The coordinates (0,0) represent the upper left corner
  2174. * of the bitmap.
  2175. *
  2176. * @parm int | ySrc | Specifies the y-coordinate of the upper left corner
  2177. * source rectangle. Coordinates are specified in pixels.
  2178. * The coordinates (0,0) represent the upper left corner
  2179. * of the bitmap.
  2180. *
  2181. * @parm int | dxSrc | Specifies the width of the source rectangle.
  2182. * The width is specified in pixels.
  2183. *
  2184. * @parm int | dySrc | Specifies the height of the source rectangle.
  2185. * The height is specified in pixels.
  2186. *
  2187. * @parm UINT | wFlags | Specifies any applicable flags for drawing.
  2188. * The following flags are defined:
  2189. *
  2190. * @flag DDF_UPDATE | Indicates the last buffered bitmap is to be redrawn.
  2191. * If drawing fails with this flag, a buffered image is not available
  2192. * and a new image needs to be specified before the display is updated.
  2193. *
  2194. * @flag DDF_SAME_HDC | Assumes the display context has been prepared with
  2195. * <f DrawDibRealize> prior to this call and <f DrawDibDraw> should not
  2196. * initialize it.
  2197. *
  2198. * @flag DDF_SAME_DRAW | Uses the drawing parameters previously
  2199. * specified for this function. Use this flag only
  2200. * if <p lpbi>, <p dxDst>, <p dyDst>, <p dxSrc>, and <p dySrc>
  2201. * have not changed since using <f DrawDibDraw> or <f DrawDibBegin>.
  2202. * Normally <f DrawDibDraw> checks the parameters, and if they
  2203. * have changed, <f DrawDibBegin> prepares the DrawDib context
  2204. * for drawing.
  2205. *
  2206. * @flag DDF_DONTDRAW | Indicates the frame is not to be drawn and will
  2207. * later be recalled with the <f DDF_UPDATE> flag. DrawDib does
  2208. * not buffer an image if an offscreen buffer does not exist.
  2209. * In this case, DDF_DONTDRAW draws the frame to the screen and
  2210. * the subsequent use of DDF_UPDATE fails. DrawDib does
  2211. * guarantee that the following will
  2212. * always draw "image" B to the screen.
  2213. *
  2214. * DrawDibDraw(hdd, ..., lpbiA, ..., DDF_DONTDRAW);
  2215. *
  2216. * DrawDibDraw(hdd, ..., lpbiB, ..., DDF_DONTDRAW);
  2217. *
  2218. * DrawDibDraw(hdd, ..., NULL, ..., DDF_UPDATE);
  2219. *
  2220. * The DDF_UPDATE and DDF_DONTDRAW flags are used
  2221. * together to create composite images
  2222. * offscreen, and then do a final update when finished.
  2223. *
  2224. * @flag DDF_HURRYUP | Indicates the data does not have to
  2225. * drawn (that is, it can be dropped) and the DDF_UPDATE flags will
  2226. * not be used to recall this information. DrawDib looks at
  2227. * this data only if it is required to build the next frame, otherwise
  2228. * the data is ignored.
  2229. *
  2230. * This flag is usually used to resynchronize video and audio. When
  2231. * resynchronizing data, applications should send the image
  2232. * with this flag in case the driver needs to
  2233. * to buffer the frame to decompress subsequent frames.
  2234. *
  2235. * @flag DDF_UPDATE | Indicates the last buffered bitmap is to be redrawn.
  2236. * If drawing fails with this flag, a buffered image is not available
  2237. * and a new image needs to be specified before the display is updated.
  2238. * For more information, see the <f DDF_DONTDRAW> flag.
  2239. *
  2240. * @flag DDF_BACKGROUNDPAL | Realizes the palette used for drawing
  2241. * in the background leaving the actual palette used for display
  2242. * unchanged. (This flag is valid only if DDF_SAME_HDC is not set.)
  2243. *
  2244. * @flag DDF_HALFTONE | Always dithers the DIB to a standard palette
  2245. * regardless of the palette of the DIB. If using <f DrawDibBegin>,
  2246. * set this flag for it rather than <f DrawDibDraw>.
  2247. *
  2248. * @flag DDF_NOTKEYFRAME | Indicates the DIB data is not a key frame.
  2249. *
  2250. * @flag DDF_HURRYUP | Indicates the DIB data does not have to
  2251. * drawn (that is, it can be dropped). This flag is usually
  2252. * used to resynchronize the video to the audio. When
  2253. * resynchronizing data, applications should send the image
  2254. * with this flag in case the driver needs to
  2255. * to buffer the frame to decompress subsequent frames.
  2256. *
  2257. * @rdesc Returns TRUE if successful.
  2258. *
  2259. * @comm This function replaces <f StretchDIBits> and supports
  2260. * decompression of bitmaps by installable compressors.
  2261. * This function dithers true color bitmaps properly on
  2262. * 8-bit display devices.
  2263. *
  2264. **************************************************************************/
  2265. BOOL VFWAPI DrawDibDraw(HDRAWDIB hdd,
  2266. HDC hdc,
  2267. int xDst,
  2268. int yDst,
  2269. int dxDst,
  2270. int dyDst,
  2271. LPBITMAPINFOHEADER lpbi,
  2272. LPVOID lpBits,
  2273. int xSrc,
  2274. int ySrc,
  2275. int dxSrc,
  2276. int dySrc,
  2277. UINT wFlags)
  2278. {
  2279. PDD pdd;
  2280. BOOL f;
  2281. RECT rc;
  2282. DWORD icFlags;
  2283. DWORD dw;
  2284. if ((pdd = DrawDibLock(hdd)) == NULL)
  2285. return FALSE;
  2286. if (hdc == NULL)
  2287. return FALSE;
  2288. if (wFlags & DDF_UPDATE)
  2289. {
  2290. lpbi = pdd->lpbi;
  2291. dxDst = pdd->dxDst;
  2292. dyDst = pdd->dyDst;
  2293. dxSrc = pdd->dxSrc;
  2294. dySrc = pdd->dySrc;
  2295. }
  2296. else
  2297. {
  2298. if (lpbi == NULL)
  2299. return FALSE;
  2300. //
  2301. // fill in defaults.
  2302. //
  2303. if (dxSrc < 0)
  2304. dxSrc = (int)lpbi->biWidth - xSrc;
  2305. if (dySrc < 0)
  2306. dySrc = (int)lpbi->biHeight - ySrc;
  2307. if (dxDst < 0)
  2308. dxDst = dxSrc;
  2309. if (dyDst < 0)
  2310. dyDst = dySrc;
  2311. }
  2312. #ifdef DEBUG_RETAIL
  2313. if (xSrc < 0 ||
  2314. ySrc < 0 ||
  2315. dxSrc <= 0 ||
  2316. dySrc <= 0 ||
  2317. xSrc + dxSrc > (int)lpbi->biWidth ||
  2318. ySrc + dySrc > (int)lpbi->biHeight)
  2319. {
  2320. RPF(("DrawDibBegin(): bad source parameters [%d %d %d %d]", xSrc, ySrc, dxSrc, dySrc));
  2321. // return 0; // see what happens.
  2322. }
  2323. #endif
  2324. if (dxSrc == 0 || dySrc == 0) // !!! || dxDst == 0 || dyDst == 0)
  2325. return FALSE;
  2326. //
  2327. // check and make sure the params of the draw has not changed
  2328. //
  2329. if (!(wFlags & (DDF_SAME_DRAW|DDF_UPDATE)) &&
  2330. !(DibEq(pdd->lpbi, lpbi) &&
  2331. !(((UINT)pdd->ulFlags ^ wFlags) & DDF_HALFTONE) &&
  2332. pdd->dxDst == dxDst &&
  2333. pdd->dyDst == dyDst &&
  2334. pdd->dxSrc == dxSrc &&
  2335. pdd->dySrc == dySrc))
  2336. {
  2337. wFlags &= ~(DDF_UPDATE | DDF_FULLSCREEN);
  2338. if (!DrawDibBegin(hdd, hdc, dxDst, dyDst, lpbi, dxSrc, dySrc, wFlags))
  2339. return FALSE;
  2340. }
  2341. TIMEINC(); // should we include DibEq?
  2342. TIMESTART(timeDraw);
  2343. // convert to DIB cordinates
  2344. ySrc = (int)pdd->lpbi->biHeight - (ySrc + dySrc);
  2345. //
  2346. // Initialize the DC: We need to realize the palette if we are not
  2347. // guarenteed to be using the same DC as before, if we've been told we
  2348. // have a new palette, or if we are mapping to somebody else's palette.
  2349. // The owner of the palette could be changing it on us all the time or
  2350. // doing who knows what, so to be safe we will realize it every frame.
  2351. // If nothing's changed, this should be a really cheap operation, and
  2352. // it doesn't appear to be causing any palette fights that end in somebody
  2353. // getting hurt. This is required for Magic School Bus, and PageMaster,
  2354. // at the very least. (WIN95B 12204 and 9637)
  2355. //
  2356. if (!(wFlags & DDF_SAME_HDC) || (pdd->ulFlags & DDF_NEWPALETTE) ||
  2357. pdd->hpalDraw)
  2358. {
  2359. //
  2360. // image will be totally clipped anyway
  2361. //
  2362. if (GetClipBox(hdc, &rc) == NULLREGION)
  2363. {
  2364. wFlags |= DDF_DONTDRAW;
  2365. }
  2366. //
  2367. // select and realize the palette.
  2368. //
  2369. // NOTE you must unselect this thing, dont return early
  2370. //
  2371. DrawDibRealize(hdd, hdc, (wFlags & DDF_BACKGROUNDPAL) != 0);
  2372. }
  2373. #ifndef WIN32
  2374. //
  2375. // do a clipping check
  2376. //
  2377. if (pdd->ulFlags & DDF_CLIPCHECK)
  2378. {
  2379. RECT rc;
  2380. if (!(pdd->ulFlags & DDF_CLIPPED) &&
  2381. (pdd->iDecompress == DECOMPRESS_SCREEN) && // (pdd->ulFlags & DDF_SCREENX) &&
  2382. (wFlags & (DDF_PREROLL|DDF_DONTDRAW)))
  2383. {
  2384. DPF(("DDF_DONTDRAW while decompressing to screen, staying clipped"));
  2385. }
  2386. if ((pdd->ulFlags & DDF_MEMORYDC) ||
  2387. GetClipBox(hdc, &rc) != SIMPLEREGION ||
  2388. xDst < rc.left ||
  2389. yDst < rc.top ||
  2390. xDst + dxDst > rc.right ||
  2391. yDst + dyDst > rc.bottom ||
  2392. (wFlags & (DDF_PREROLL|DDF_DONTDRAW)) ||
  2393. (gfDisplayHasBrokenRasters &&
  2394. (DCNotAligned(hdc, xDst) || gwScreenBitDepth == 24)))
  2395. // Note: if we're on a 24-bit display with broken rasters, we don't
  2396. // decompress to the screen even if the rectangle is aligned,
  2397. // because it's just too easy for somebody to try to write out
  2398. // a whole pixel in one gulp and hit the 64K boundary.
  2399. {
  2400. //
  2401. // we are clipped, check for a change.
  2402. //
  2403. if (!(pdd->ulFlags & DDF_CLIPPED))
  2404. {
  2405. pdd->ulFlags |= DDF_CLIPPED;
  2406. DrawDibClipChange(pdd, wFlags);
  2407. }
  2408. }
  2409. else
  2410. {
  2411. //
  2412. // we are now unclipped, check for a change
  2413. //
  2414. if (pdd->ulFlags & DDF_CLIPPED)
  2415. {
  2416. #ifdef DEBUG
  2417. if (DCNotAligned(hdc, xDst))
  2418. DPF(("Warning draw is not aligned on 4 pixel boundry"));
  2419. #endif
  2420. pdd->ulFlags &= ~DDF_CLIPPED;
  2421. DrawDibClipChange(pdd, wFlags);
  2422. }
  2423. }
  2424. }
  2425. #endif //WIN32
  2426. if (pdd->ulFlags & DDF_WANTKEY)
  2427. {
  2428. //
  2429. // Adobe hack: If the DDF_UPDATE flag is on in our internal
  2430. // flags, that means we've just been getting a bunch of frames
  2431. // with the DONTDRAW flag set. In that case, if this frame
  2432. // immediately after those frames is marked as a key frame
  2433. // we assume that it might not be a key frame and refrain from
  2434. // switching immediately to decompressing to screen.
  2435. //
  2436. if (!(wFlags & DDF_NOTKEYFRAME) && !(pdd->ulFlags & DDF_UPDATE))
  2437. {
  2438. pdd->ulFlags &= ~DDF_WANTKEY;
  2439. DrawDibClipChange(pdd, wFlags);
  2440. }
  2441. }
  2442. //
  2443. // if update is set re-draw what ever we drew last time
  2444. //
  2445. if (wFlags & DDF_UPDATE)
  2446. {
  2447. if (pdd->hic == (HIC)-1 || (pdd->ulFlags & DDF_DIRTY))
  2448. {
  2449. f = FALSE;
  2450. goto exit;
  2451. }
  2452. if (pdd->hic)
  2453. {
  2454. if (pdd->ulFlags & DDF_UPDATE)
  2455. {
  2456. goto redraw;
  2457. }
  2458. lpbi = &pdd->biBuffer;
  2459. lpBits = pdd->pbBuffer;
  2460. //!!! set the source right.
  2461. if ((pdd->ulFlags & DDF_XLATSOURCE))
  2462. {
  2463. dxSrc = MulDiv(dxSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  2464. dySrc = MulDiv(dySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  2465. xSrc = MulDiv(xSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  2466. ySrc = MulDiv(ySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  2467. }
  2468. }
  2469. if (pdd->ulFlags & DDF_STRETCH)
  2470. {
  2471. lpbi = &pdd->biStretch;
  2472. lpBits = pdd->pbStretch;
  2473. dxSrc = dxDst;
  2474. dySrc = dyDst;
  2475. xSrc = 0;
  2476. ySrc = 0;
  2477. }
  2478. if (pdd->ulFlags & DDF_DITHER)
  2479. {
  2480. lpBits = pdd->pbDither;
  2481. xSrc = 0;
  2482. ySrc = 0;
  2483. }
  2484. if (pdd->lpDIBSection != NULL)
  2485. goto bltDIB;
  2486. if (pdd->hbmDraw && (pdd->ulFlags & DDF_BITMAP))
  2487. goto bltit;
  2488. if (lpBits == NULL)
  2489. {
  2490. f = FALSE; // no buffer, can't update....
  2491. goto exit;
  2492. }
  2493. goto drawit;
  2494. }
  2495. //
  2496. // default for bits pointerdefault
  2497. //
  2498. if (lpBits == NULL)
  2499. lpBits = (LPBYTE)lpbi+(int)lpbi->biSize + (int)lpbi->biClrUsed * sizeof(RGBQUAD);
  2500. //
  2501. // call any decompressor if needed
  2502. //
  2503. if (pdd->hic)
  2504. {
  2505. if (pdd->hic == (HIC)-1)
  2506. {
  2507. f = FALSE;
  2508. goto exit;
  2509. }
  2510. #ifndef WIN32 // exclude all code that references biscreen
  2511. if (pdd->iDecompress == DECOMPRESS_SCREEN) // ulFlags & DDF_SCREENX
  2512. {
  2513. //
  2514. // we are decompressing to the screen not the buffer, so
  2515. // the buffer is dirty now
  2516. //
  2517. pdd->ulFlags |= DDF_DIRTY;
  2518. dw = GetDCOrg(hdc);
  2519. xDst += LOWORD(dw);
  2520. yDst += HIWORD(dw);
  2521. //
  2522. // if DCIBeginAccess fails we are in the background, and should
  2523. // not draw.
  2524. //
  2525. if (DCIBeginAccess(pdci, xDst, yDst, dxDst, dyDst) != 0)
  2526. {
  2527. DPF(("DCIBeginAccess failed!!!"));
  2528. f = TRUE; //!!! is this right?
  2529. goto exit;
  2530. }
  2531. //convert to DIB corrds.
  2532. yDst = (int)pdci->dwHeight - (yDst + dyDst);
  2533. TIMESTART(timeDecompress);
  2534. icFlags = 0;
  2535. if (wFlags & DDF_HURRYUP)
  2536. icFlags |= ICDECOMPRESS_HURRYUP;
  2537. if (wFlags & DDF_NOTKEYFRAME)
  2538. icFlags |= ICDECOMPRESS_NOTKEYFRAME;
  2539. dw = ICDecompressEx(pdd->hic, icFlags,
  2540. lpbi, lpBits, xSrc, ySrc, dxSrc, dySrc,
  2541. &biScreen, lpScreen,
  2542. xDst, yDst, dxDst, dyDst);
  2543. if (dw == ICERR_DONTDRAW)
  2544. dw = ICERR_OK;
  2545. f = (dw == ICERR_OK);
  2546. TIMEEND(timeDecompress);
  2547. DCIEndAccess(pdci);
  2548. goto exit;
  2549. }
  2550. else
  2551. #endif // biscreen references
  2552. {
  2553. //
  2554. // if the offscreen buffer is dirty, only a key frame will
  2555. // clean our soul.
  2556. //
  2557. if (pdd->ulFlags & DDF_DIRTY)
  2558. {
  2559. if (wFlags & DDF_NOTKEYFRAME)
  2560. {
  2561. //!!! playing files with no key frames we will get into
  2562. //a state where we will never draw a frame ever again.
  2563. //we need a punt count?
  2564. DPF(("punt frame"));
  2565. f = TRUE;
  2566. goto exit;
  2567. }
  2568. else // if (!(wFlags & DDF_HURRYUP))
  2569. {
  2570. pdd->ulFlags &= ~DDF_DIRTY;
  2571. }
  2572. }
  2573. TIMESTART(timeDecompress);
  2574. icFlags = 0;
  2575. if (wFlags & DDF_HURRYUP)
  2576. icFlags |= ICDECOMPRESS_HURRYUP;
  2577. if (wFlags & DDF_NOTKEYFRAME)
  2578. icFlags |= ICDECOMPRESS_NOTKEYFRAME;
  2579. if (pdd->iDecompress == DECOMPRESS_BITMAP) // ulFlags & DDF_BITMAPX
  2580. {
  2581. //!!! should we check FASTTEMPORALD?
  2582. if (pdd->ulFlags & DDF_HUGEBITMAP) {
  2583. HugeToFlat(pdd->pbBitmap,pdd->biBitmap.biSizeImage,pdd->biBitmap.biYPelsPerMeter);
  2584. }
  2585. dw = ICDecompress(pdd->hic, icFlags, lpbi, lpBits, &pdd->biBitmap, pdd->pbBitmap);
  2586. if (pdd->ulFlags & DDF_HUGEBITMAP) {
  2587. FlatToHuge(pdd->pbBitmap,pdd->biBitmap.biSizeImage,pdd->biBitmap.biYPelsPerMeter);
  2588. }
  2589. }
  2590. else
  2591. {
  2592. dw = ICDecompress(pdd->hic, icFlags, lpbi, lpBits, &pdd->biBuffer, pdd->pbBuffer);
  2593. }
  2594. TIMEEND(timeDecompress);
  2595. if (dw == ICERR_DONTDRAW) {
  2596. // Decompressor doesn't want us to draw, for some reason....
  2597. wFlags |= DDF_DONTDRAW;
  2598. } else if (dw != 0) {
  2599. f = FALSE;
  2600. DPF(("Error %ld from decompressor!\n", dw));
  2601. goto exit;
  2602. }
  2603. }
  2604. //
  2605. // if don't draw is set we just need to decompress
  2606. //
  2607. if (wFlags & (DDF_DONTDRAW|DDF_HURRYUP))
  2608. {
  2609. f = TRUE;
  2610. pdd->ulFlags |= DDF_UPDATE|DDF_DONTDRAW; // make sure update knows what to do
  2611. goto exit;
  2612. }
  2613. //
  2614. // draw RLE delta's to the screen even when we are buffering.
  2615. //
  2616. if (!(pdd->ulFlags & (DDF_DONTDRAW|DDF_STRETCH|DDF_DITHER|DDF_NAKED)) &&
  2617. lpbi->biCompression == BI_RLE8 &&
  2618. lpbi->biSizeImage != pdd->biBuffer.biSizeImage)
  2619. {
  2620. pdd->ulFlags |= DDF_UPDATE; // make sure update knows what to do
  2621. pdd->biDraw.biCompression = BI_RLE8;
  2622. goto drawit;
  2623. }
  2624. redraw:
  2625. pdd->ulFlags &= ~(DDF_UPDATE|DDF_DONTDRAW);
  2626. if ((pdd->ulFlags & DDF_XLATSOURCE))
  2627. {
  2628. dxSrc = MulDiv(dxSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  2629. dySrc = MulDiv(dySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  2630. xSrc = MulDiv(xSrc, abs((int)pdd->biBuffer.biWidth), (int)pdd->lpbi->biWidth);
  2631. ySrc = MulDiv(ySrc, abs((int)pdd->biBuffer.biHeight), (int)pdd->lpbi->biHeight);
  2632. }
  2633. lpbi = &pdd->biBuffer;
  2634. lpBits = pdd->pbBuffer;
  2635. pdd->biDraw.biCompression = pdd->biBuffer.biCompression;
  2636. }
  2637. else
  2638. {
  2639. if (pdd->lpDIBSection && ((pdd->ulFlags & (DDF_STRETCH|DDF_DITHER)) == 0)) {
  2640. // Include time taken here as 'stretching'.
  2641. // Really, though, we shouldn't be using DIB Sections in this case.
  2642. TIMESTART(timeStretch);
  2643. if (lpbi->biCompression == BI_RGB) {
  2644. lpbi->biSizeImage = DIBSIZEIMAGE(*lpbi);
  2645. }
  2646. hmemcpy(pdd->lpDIBSection, lpBits, lpbi->biSizeImage);
  2647. TIMEEND(timeStretch);
  2648. }
  2649. //
  2650. // when directly drawing RLE data we cant hurry
  2651. //
  2652. if (pdd->lpbi->biCompression == BI_RLE8)
  2653. wFlags &= ~DDF_HURRYUP;
  2654. //
  2655. // if don't draw is set we just need to stretch/dither
  2656. //
  2657. if (wFlags & DDF_HURRYUP)
  2658. {
  2659. f = TRUE;
  2660. pdd->ulFlags |= DDF_DIRTY;
  2661. goto exit;
  2662. }
  2663. pdd->ulFlags &= ~DDF_DIRTY;
  2664. pdd->biDraw.biCompression = lpbi->biCompression;
  2665. }
  2666. if (pdd->biDraw.biCompression == BI_RGB &&
  2667. (pdd->ulFlags & (DDF_DITHER|DDF_STRETCH)))
  2668. {
  2669. if (pdd->ulFlags & DDF_STRETCH)
  2670. {
  2671. TIMESTART(timeStretch);
  2672. StretchDIB(&pdd->biStretch, pdd->pbStretch,
  2673. 0, 0, dxDst, dyDst,
  2674. lpbi,lpBits,
  2675. xSrc,ySrc,dxSrc,dySrc);
  2676. TIMEEND(timeStretch);
  2677. lpbi = &pdd->biStretch;
  2678. lpBits = pdd->pbStretch;
  2679. dxSrc = dxDst;
  2680. dySrc = dyDst;
  2681. xSrc = 0;
  2682. ySrc = 0;
  2683. }
  2684. if (pdd->ulFlags & DDF_DITHER)
  2685. {
  2686. TIMESTART(timeDither);
  2687. pdd->DitherProc(&pdd->biDraw, pdd->pbDither,0,0,dxSrc,dySrc,
  2688. lpbi,lpBits,xSrc, ySrc, pdd->lpDitherTable);
  2689. TIMEEND(timeDither);
  2690. lpBits = pdd->pbDither;
  2691. xSrc = 0;
  2692. ySrc = 0;
  2693. }
  2694. if ((wFlags & DDF_DONTDRAW) && !pdd->hbmDraw)
  2695. {
  2696. f = TRUE;
  2697. goto exit;
  2698. }
  2699. }
  2700. else if (pdd->biDraw.biCompression == BI_RLE8)
  2701. {
  2702. /*
  2703. * if drawing RLE deltas on NT, the biSizeImage field needs to
  2704. * accurately reflect the amount of RLE data present in lpBits.
  2705. */
  2706. pdd->biDraw.biSizeImage = lpbi->biSizeImage;
  2707. }
  2708. if (pdd->lpDIBSection != NULL) {
  2709. //ASSERT(pdd->hbmDraw != NULL);
  2710. if (wFlags & DDF_DONTDRAW)
  2711. {
  2712. f = TRUE;
  2713. goto exit;
  2714. }
  2715. bltDIB:
  2716. TIMESTART(timeBlt);
  2717. // Put things back in right-side-up coordinates
  2718. ySrc = (int)pdd->biDraw.biHeight - (ySrc + dySrc);
  2719. // ySrc = 0; // Was like this for Chicago M6!
  2720. f = StretchBlt(hdc,xDst,yDst,dxDst,dyDst,pdd->hdcDraw,
  2721. xSrc,ySrc,dxSrc,dySrc,SRCCOPY) != 0;
  2722. TIMEEND(timeBlt);
  2723. } else if (pdd->hbmDraw)
  2724. {
  2725. //
  2726. // when MCIAVI is playing we need realize our palette for each
  2727. // draw operation because another app may have drawn a translated
  2728. // bitmap thus screwing up the GDI *global* device translate table.
  2729. // RonG I hate you some times
  2730. //
  2731. if (pdd->hpal && (wFlags & DDF_SAME_HDC)) {
  2732. if (GetProfileInt(szDrawDib, "switchpalette", TRUE))
  2733. RealizePalette(hdc);
  2734. }
  2735. if (pdd->iDecompress != DECOMPRESS_BITMAP) // !(pdd->ulFlags & DDF_BITMAPX)
  2736. {
  2737. TIMESTART(timeSetDIBits);
  2738. #if USE_SETDI
  2739. pdd->sd.hdc = hdc; //!!!ack!
  2740. SetBitmap(&pdd->sd,xSrc,0,dxSrc,dySrc,lpBits,xSrc,ySrc,dxSrc,dySrc);
  2741. pdd->sd.hdc = NULL; //!!!ack!
  2742. ySrc = 0;
  2743. #else
  2744. SetDIBits(hdc, pdd->hbmDraw, 0, dySrc,
  2745. lpBits, (LPBITMAPINFO)&pdd->biDraw, pdd->uiPalUse);
  2746. #endif
  2747. TIMEEND(timeSetDIBits);
  2748. }
  2749. if (wFlags & DDF_DONTDRAW)
  2750. {
  2751. f = TRUE;
  2752. goto exit;
  2753. }
  2754. bltit:
  2755. TIMESTART(timeBlt);
  2756. // Put things back in right-side-up coordinates
  2757. ySrc = (int)pdd->biDraw.biHeight - (ySrc + dySrc);
  2758. // ySrc = 0;
  2759. f = StretchBlt(hdc,xDst,yDst,dxDst,dyDst,pdd->hdcDraw,
  2760. xSrc,ySrc,dxSrc,dySrc,SRCCOPY) != 0;
  2761. TIMEEND(timeBlt);
  2762. }
  2763. else
  2764. drawit:
  2765. {
  2766. // Sometimes when you read an RLE file, you get RGB data back (ie. the
  2767. // first frame). Passing RGB data to a display driver who thinks it
  2768. // is getting RLE data will blow it up. If the RLE data is the exact
  2769. // size of RGB data, we decide that's just too much of a coincidence.
  2770. BOOL fNotReallyRLE = (pdd->biDraw.biCompression == BI_RLE8 &&
  2771. lpbi->biSizeImage == DIBWIDTHBYTES(*lpbi) * (DWORD)lpbi->biHeight);
  2772. // !!! We've been told not to draw, but I'm going to draw anyway, to fix bug
  2773. // WIN95C 14453. MCIAVI draws from a keyframe forward, saying DONTDRAW on
  2774. // every frame but the last. Works fine in theory, but in theory, communism
  2775. // works! Because of other bugs declared WONTFIX, Drawdib doesn't buffer the
  2776. // images as it goes along, so when it comes time to draw the result at the
  2777. // end, it goes "ACK! I have no idea what I was told to draw!". So the only
  2778. // safe way to fix it is to draw even though we were told not to. I feel safe
  2779. // doing this because this is the way VFW1.1 worked, and nobody has complained
  2780. // in over a year.
  2781. #if 0
  2782. if (wFlags & DDF_DONTDRAW)
  2783. {
  2784. f = TRUE;
  2785. goto exit;
  2786. }
  2787. #endif
  2788. if (fNotReallyRLE)
  2789. pdd->biDraw.biCompression = BI_RGB;
  2790. if (pdd->biDraw.biCompression == BI_RLE8)
  2791. {
  2792. /*
  2793. * if drawing RLE deltas on NT, the biSizeImage field needs to
  2794. * accurately reflect the amount of RLE data present in lpBits.
  2795. */
  2796. pdd->biDraw.biSizeImage = lpbi->biSizeImage;
  2797. }
  2798. TIMESTART(timeBlt);
  2799. /*
  2800. * NT stretchdibits does not work with RLE deltas, even 1:1
  2801. *
  2802. * also note use of pdd->uiPalUse: this is DIB_PAL_COLORS by
  2803. * default, but may be set to DIB_PAL_INDICES if we detect that
  2804. * the system palette is identical to ours, and thus
  2805. * we can safely take this huge performance benefit (on NT,
  2806. * DIB_PAL_INDICES nearly halves the cost of this call)
  2807. */
  2808. if ((dxDst == dxSrc) && (dyDst == dySrc))
  2809. {
  2810. f = SetDIBitsToDevice(hdc, xDst, yDst, dxDst, dyDst,
  2811. xSrc, ySrc, 0, (UINT)pdd->biDraw.biHeight, lpBits,
  2812. (LPBITMAPINFO)&pdd->biDraw, pdd->uiPalUse) != 0;
  2813. }
  2814. else
  2815. {
  2816. f = StretchDIBits(hdc,xDst,yDst,dxDst,dyDst,
  2817. xSrc,ySrc,dxSrc,dySrc,
  2818. lpBits, (LPBITMAPINFO)&pdd->biDraw,
  2819. pdd->uiPalUse, SRCCOPY) != 0;
  2820. }
  2821. TIMEEND(timeBlt);
  2822. if (fNotReallyRLE)
  2823. pdd->biDraw.biCompression = BI_RLE8;
  2824. }
  2825. exit:
  2826. if (!(wFlags & DDF_SAME_HDC) && pdd->hpal)
  2827. SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), TRUE);
  2828. TIMEEND(timeDraw);
  2829. return f;
  2830. }
  2831. #if 0
  2832. /**************************************************************************
  2833. * @doc INTERNAL
  2834. *
  2835. * @api BOOL| InitDrawToScreen | init drawing to the screen via DCI
  2836. *
  2837. **************************************************************************/
  2838. static BOOL InitDrawToScreen(PDD pdd)
  2839. {
  2840. BOOL f;
  2841. if (!(pdd->ulFlags & DDF_CANDRAWX))
  2842. return FALSE;
  2843. f = !(pdd->ulFlags & DDF_CLIPPED);
  2844. if (f && !(pdd->ulFlags & DDF_DRAWX))
  2845. {
  2846. DPF(("drawing to SCREEN now"));
  2847. pdd->ulFlags |= DDF_DRAWX;
  2848. }
  2849. else if (!f && (pdd->ulFlags & DDF_DRAWX))
  2850. {
  2851. DPF(("not drawing to SCREEN anymore"));
  2852. pdd->ulFlags &= ~DDF_DRAWX;
  2853. }
  2854. }
  2855. #endif
  2856. /**************************************************************************
  2857. * @doc INTERNAL
  2858. *
  2859. * @api BOOL| InitDecompress | init every thing for decompressing
  2860. * to the screen or a bitmap or a memory buffer.
  2861. *
  2862. * we can decompress to the screen if the following is true:
  2863. *
  2864. * palette must be 1:1
  2865. * must be unclipped
  2866. *
  2867. **************************************************************************/
  2868. static BOOL InitDecompress(PDD pdd)
  2869. {
  2870. BOOL f;
  2871. BOOL fBitmap;
  2872. BOOL fScreen;
  2873. //
  2874. // nothing to init
  2875. //
  2876. if (!(pdd->ulFlags & (DDF_CANSCREENX|DDF_CANBITMAPX)))
  2877. return TRUE;
  2878. //
  2879. // make sure we rebegin when the palette changes
  2880. //
  2881. if (pdd->ulFlags & (DDF_NEWPALETTE|DDF_WANTKEY))
  2882. pdd->iDecompress = 0;
  2883. //
  2884. // we need to decompress to either a memory bitmap or buffer.
  2885. //
  2886. fBitmap = (pdd->ulFlags & DDF_CANBITMAPX) &&
  2887. (pdd->ulFlags & (DDF_IDENTITYPAL|DDF_CANSETPAL));
  2888. fScreen = (pdd->ulFlags & DDF_CANSCREENX) &&
  2889. !(pdd->ulFlags & DDF_CLIPPED) &&
  2890. !(pdd->ulFlags & DDF_MEMORYDC) &&
  2891. (pdd->ulFlags & (DDF_IDENTITYPAL|DDF_CANSETPAL));
  2892. //
  2893. // should we be decompressing to the screen?
  2894. //
  2895. if (fScreen && pdd->iDecompress != DECOMPRESS_SCREEN)
  2896. {
  2897. if (pdd->ulFlags & DDF_IDENTITYPAL)
  2898. {
  2899. if (pdd->hpalDraw)
  2900. ICDecompressSetPalette(pdd->hic, &pdd->biBuffer);
  2901. else
  2902. ICDecompressSetPalette(pdd->hic, NULL);
  2903. }
  2904. else
  2905. {
  2906. if (FixUpCodecPalette(pdd->hic, pdd->lpbi))
  2907. {
  2908. DPF(("Codec notified of palette change...."));
  2909. }
  2910. else
  2911. {
  2912. DPF(("Codec failed palette change...."));
  2913. pdd->iDecompress = 0;
  2914. goto ack;
  2915. }
  2916. }
  2917. //
  2918. // now init the compressor for screen decompress.
  2919. //
  2920. f = ICDecompressExBegin(pdd->hic, 0,
  2921. pdd->lpbi, NULL, 0, 0, pdd->dxSrc, pdd->dySrc,
  2922. &biScreen, lpScreen, 0, 0, pdd->dxDst, pdd->dyDst) == ICERR_OK;
  2923. if (f)
  2924. {
  2925. pdd->ulFlags |= DDF_DIRTY; // buffer is dirty now?
  2926. RPF(("Decompressing to screen now"));
  2927. pdd->iDecompress = DECOMPRESS_SCREEN;
  2928. return TRUE;
  2929. }
  2930. else
  2931. {
  2932. ack: DPF(("Compressor failed decompress to SCREEN, so not decompressing to screen!!!!"));
  2933. pdd->iDecompress = 0;
  2934. pdd->ulFlags &= ~DDF_CANSCREENX;
  2935. }
  2936. }
  2937. else if (fScreen)
  2938. {
  2939. //
  2940. // already decompressing to screen.
  2941. //
  2942. return TRUE;
  2943. }
  2944. //
  2945. // should we decompress to a bitmap?
  2946. //
  2947. if (fBitmap && pdd->iDecompress != DECOMPRESS_BITMAP)
  2948. {
  2949. if (pdd->ulFlags & DDF_IDENTITYPAL)
  2950. {
  2951. if (pdd->hpalDraw)
  2952. ICDecompressSetPalette(pdd->hic, &pdd->biBuffer);
  2953. else
  2954. ICDecompressSetPalette(pdd->hic, NULL);
  2955. }
  2956. else
  2957. {
  2958. if (FixUpCodecPalette(pdd->hic, pdd->lpbi))
  2959. {
  2960. DPF(("Codec notified of palette change...."));
  2961. }
  2962. else
  2963. {
  2964. DPF(("Codec failed palette change...."));
  2965. pdd->iDecompress = 0;
  2966. goto ackack;
  2967. }
  2968. }
  2969. f = ICDecompressBegin(pdd->hic, pdd->lpbi, &pdd->biBitmap) == ICERR_OK;
  2970. if (f)
  2971. {
  2972. pdd->ulFlags |= DDF_DIRTY; // buffer is dirty now?
  2973. DPF(("decompressing to BITMAP now"));
  2974. pdd->iDecompress = DECOMPRESS_BITMAP;
  2975. return TRUE;
  2976. }
  2977. else
  2978. {
  2979. ackack: DPF(("Unable to init decompress to bitmap"));
  2980. pdd->iDecompress = 0;
  2981. }
  2982. }
  2983. else if (fBitmap)
  2984. {
  2985. //
  2986. // already decompressing to bitmap
  2987. //
  2988. return TRUE;
  2989. }
  2990. //
  2991. // should we decompress to a buffer?
  2992. //
  2993. if (pdd->iDecompress != DECOMPRESS_BUFFER)
  2994. {
  2995. DPF(("decompressing to DIB now"));
  2996. pdd->ulFlags |= DDF_DIRTY; // buffer is dirty now?
  2997. pdd->iDecompress = DECOMPRESS_BUFFER;
  2998. if (pdd->hpalDraw)
  2999. ICDecompressSetPalette(pdd->hic, &pdd->biBuffer);
  3000. else
  3001. ICDecompressSetPalette(pdd->hic, NULL);
  3002. f = ICDecompressBegin(pdd->hic, pdd->lpbi, &pdd->biBuffer) == ICERR_OK;
  3003. if (!f)
  3004. {
  3005. DPF(("Unable to re-begin compressor"));
  3006. }
  3007. }
  3008. return TRUE; // nothing to change
  3009. }
  3010. /**************************************************************************
  3011. * @doc INTERNAL
  3012. *
  3013. * @api void | DrawDibClipChange | called when the clipping has changed
  3014. * from clipped to totaly un-clipped or whatever.
  3015. *
  3016. **************************************************************************/
  3017. void DrawDibClipChange(PDD pdd, UINT wFlags)
  3018. {
  3019. if (!(pdd->ulFlags & DDF_NEWPALETTE))
  3020. {
  3021. if (pdd->ulFlags & DDF_CLIPPED)
  3022. DPF(("now clipped"));
  3023. else
  3024. DPF(("now un-clipped"));
  3025. }
  3026. ////InitDrawToScreen(pdd);
  3027. //
  3028. // dont change Decompressors on a non key frame, unless we have
  3029. // to (ie going clipped and decompressing to screen)
  3030. //
  3031. if (pdd->ulFlags & DDF_NEWPALETTE)
  3032. {
  3033. if (wFlags & DDF_NOTKEYFRAME)
  3034. {
  3035. if (pdd->iDecompress == DECOMPRESS_BUFFER) // !(pdd->ulFlags & DDF_SCREENX))
  3036. {
  3037. DPF(("waiting for a key frame to change (palette) decompressor"));
  3038. pdd->ulFlags |= DDF_WANTKEY;
  3039. return;
  3040. }
  3041. }
  3042. }
  3043. else
  3044. {
  3045. if (wFlags & DDF_NOTKEYFRAME)
  3046. {
  3047. if (pdd->iDecompress != DECOMPRESS_SCREEN) // !(pdd->ulFlags & DDF_SCREENX))
  3048. {
  3049. DPF(("waiting for a key frame to change (clipped) decompressor"));
  3050. pdd->ulFlags |= DDF_WANTKEY;
  3051. return;
  3052. }
  3053. }
  3054. }
  3055. InitDecompress(pdd);
  3056. pdd->ulFlags &= ~DDF_WANTKEY;
  3057. }
  3058. /**************************************************************************
  3059. * @doc INTERNAL
  3060. *
  3061. * @api void | DrawDibPalChange | called when the physical palette mapping
  3062. * has changed.
  3063. *
  3064. **************************************************************************/
  3065. void DrawDibPalChange(PDD pdd, HDC hdc, HPALETTE hpal)
  3066. {
  3067. #ifndef WIN32
  3068. #ifdef DEBUG
  3069. // extern BOOL FAR PASCAL IsDCCurrentPalette(HDC hdc);
  3070. // BOOL fForeground = IsDCCurrentPalette(hdc);
  3071. // if (fForeground)
  3072. // DPF(("Palette mapping has changed (foreground)..."));
  3073. // else
  3074. // DPF(("Palette mapping has changed (background)..."));
  3075. #endif
  3076. #endif
  3077. //
  3078. // if we are on a palette device we need to do some special stuff.
  3079. //
  3080. if (gwScreenBitDepth == 8 && (gwRasterCaps & RC_PALETTE))
  3081. {
  3082. //
  3083. // get the logical->physical mapping
  3084. //
  3085. if (GetPhysDibPaletteMap(hdc, &pdd->biDraw, pdd->uiPalUse, pdd->ab))
  3086. pdd->ulFlags |= DDF_IDENTITYPAL;
  3087. else
  3088. pdd->ulFlags &= ~DDF_IDENTITYPAL;
  3089. if (pdd->ulFlags & DDF_IDENTITYPAL)
  3090. DPF(("Palette mapping is 1:1"));
  3091. else
  3092. DPF(("Palette mapping is not 1:1"));
  3093. #ifdef WIN32 //!!!NT Only
  3094. if (pdd->ulFlags & DDF_IDENTITYPAL)
  3095. pdd->uiPalUse = DIB_PAL_INDICES;
  3096. else
  3097. pdd->uiPalUse = DIB_PAL_COLORS;
  3098. #endif
  3099. }
  3100. else
  3101. {
  3102. //
  3103. // we are not on a palette device, some code checks DDF_IDENTITYPAL
  3104. // anyway so set it.
  3105. //
  3106. pdd->ulFlags |= DDF_IDENTITYPAL;
  3107. }
  3108. if (pdd->hbmDraw && (pdd->ulFlags & DDF_BITMAP))
  3109. {
  3110. //!!! we should pass pdd->ab to this function!
  3111. //!!! and use a naked translate.
  3112. SetBitmapColorChange(&pdd->sd, hdc, hpal);
  3113. }
  3114. DrawDibClipChange(pdd, DDF_NOTKEYFRAME);
  3115. }
  3116. /**************************************************************************
  3117. * @doc INTERNAL
  3118. *
  3119. * @api HPALETTE | CreateBIPalette | Create palette from bitmap.
  3120. *
  3121. * @parm LPBITMAPINFOHEADER | lpbi | Pointer to bitmap.
  3122. *
  3123. * @rdesc Returns handle to the palette, NULL if error.
  3124. *
  3125. **************************************************************************/
  3126. static HPALETTE CreateBIPalette(HPALETTE hpal, LPBITMAPINFOHEADER lpbi)
  3127. {
  3128. LPRGBQUAD prgb;
  3129. int i;
  3130. // This structure is the same as LOGPALETTE EXCEPT for the array of
  3131. // palette entries which here is 256 long. The "template" in the
  3132. // SDK header files only has an array of size one, hence the "duplication".
  3133. struct {
  3134. WORD palVersion; /* tomor - don't mess with word */
  3135. WORD palNumEntries;
  3136. PALETTEENTRY palPalEntry[256];
  3137. } pal;
  3138. pal.palVersion = 0x300;
  3139. pal.palNumEntries = (int)lpbi->biClrUsed;
  3140. if (pal.palNumEntries == 0 && lpbi->biBitCount <= 8)
  3141. pal.palNumEntries = (1 << (int)lpbi->biBitCount);
  3142. if (pal.palNumEntries == 0)
  3143. return NULL;
  3144. prgb = (LPRGBQUAD)(lpbi+1);
  3145. for (i=0; i<(int)pal.palNumEntries; i++)
  3146. {
  3147. pal.palPalEntry[i].peRed = prgb[i].rgbRed;
  3148. pal.palPalEntry[i].peGreen = prgb[i].rgbGreen;
  3149. pal.palPalEntry[i].peBlue = prgb[i].rgbBlue;
  3150. pal.palPalEntry[i].peFlags = 0;
  3151. }
  3152. if (hpal)
  3153. {
  3154. ResizePalette(hpal, pal.palNumEntries);
  3155. SetPaletteEntries(hpal, 0, pal.palNumEntries, pal.palPalEntry);
  3156. }
  3157. else
  3158. {
  3159. hpal = CreatePalette((LPLOGPALETTE)&pal);
  3160. }
  3161. return hpal;
  3162. }
  3163. /**************************************************************************
  3164. * @doc INTERNAL
  3165. *
  3166. * @api BOOL | SetPalFlags | Modifies the palette flags.
  3167. *
  3168. * @parm HPALETTE | hpal | Handle to the palette.
  3169. *
  3170. * @parm int | iIndex | Starting palette index.
  3171. *
  3172. * @parm int | cntEntries | Number of entries to set flags on.
  3173. *
  3174. * @parm UINT | wFlags | Palette flags.
  3175. *
  3176. * @rdesc Returns TRUE if successful, FALSE otherwise.
  3177. *
  3178. **************************************************************************/
  3179. static BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, UINT wFlags)
  3180. {
  3181. int i;
  3182. PALETTEENTRY ape[256];
  3183. if (hpal == NULL)
  3184. return FALSE;
  3185. if (cntEntries < 0)
  3186. GetObject(hpal,sizeof(int),(LPSTR)&cntEntries);
  3187. GetPaletteEntries(hpal, iIndex, cntEntries, ape);
  3188. for (i=0; i<cntEntries; i++)
  3189. ape[i].peFlags = (BYTE)wFlags;
  3190. return SetPaletteEntries(hpal, iIndex, cntEntries, ape);
  3191. }
  3192. /**************************************************************************
  3193. * @doc INTERNAL
  3194. *
  3195. * @api BOOL | IsIdentityPalette | Check if palette is an identity palette.
  3196. *
  3197. * @parm HPALETTE | hpal | Handle to the palette.
  3198. *
  3199. * @rdesc Returns TRUE if the palette is an identity palette, FALSE otherwise.
  3200. *
  3201. **************************************************************************/
  3202. #define CODE _based(_segname("_CODE"))
  3203. //
  3204. // These are the standard VGA colors, we will be stuck with until the
  3205. // end of time!
  3206. //
  3207. static PALETTEENTRY CODE apeCosmic[16] = {
  3208. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3209. 0x80, 0x00, 0x00, 0x00, // 0001 dark red
  3210. 0x00, 0x80, 0x00, 0x00, // 0010 dark green
  3211. 0x80, 0x80, 0x00, 0x00, // 0011 mustard
  3212. 0x00, 0x00, 0x80, 0x00, // 0100 dark blue
  3213. 0x80, 0x00, 0x80, 0x00, // 0101 purple
  3214. 0x00, 0x80, 0x80, 0x00, // 0110 dark turquoise
  3215. 0xC0, 0xC0, 0xC0, 0x00, // 1000 gray
  3216. 0x80, 0x80, 0x80, 0x00, // 0111 dark gray
  3217. 0xFF, 0x00, 0x00, 0x00, // 1001 red
  3218. 0x00, 0xFF, 0x00, 0x00, // 1010 green
  3219. 0xFF, 0xFF, 0x00, 0x00, // 1011 yellow
  3220. 0x00, 0x00, 0xFF, 0x00, // 1100 blue
  3221. 0xFF, 0x00, 0xFF, 0x00, // 1101 pink (magenta)
  3222. 0x00, 0xFF, 0xFF, 0x00, // 1110 cyan
  3223. 0xFF, 0xFF, 0xFF, 0x00 // 1111 white
  3224. };
  3225. static PALETTEENTRY CODE apeFake[16] = {
  3226. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3227. 0xBF, 0x00, 0x00, 0x00, // 0001 dark red
  3228. 0x00, 0xBF, 0x00, 0x00, // 0010 dark green
  3229. 0xBF, 0xBF, 0x00, 0x00, // 0011 mustard
  3230. 0x00, 0x00, 0xBF, 0x00, // 0100 dark blue
  3231. 0xBF, 0x00, 0xBF, 0x00, // 0101 purple
  3232. 0x00, 0xBF, 0xBF, 0x00, // 0110 dark turquoise
  3233. 0xC0, 0xC0, 0xC0, 0x00, // 1000 gray
  3234. 0x80, 0x80, 0x80, 0x00, // 0111 dark gray
  3235. 0xFF, 0x00, 0x00, 0x00, // 1001 red
  3236. 0x00, 0xFF, 0x00, 0x00, // 1010 green
  3237. 0xFF, 0xFF, 0x00, 0x00, // 1011 yellow
  3238. 0x00, 0x00, 0xFF, 0x00, // 1100 blue
  3239. 0xFF, 0x00, 0xFF, 0x00, // 1101 pink (magenta)
  3240. 0x00, 0xFF, 0xFF, 0x00, // 1110 cyan
  3241. 0xFF, 0xFF, 0xFF, 0x00, // 1111 white
  3242. };
  3243. static PALETTEENTRY CODE apeBlackWhite[16] = {
  3244. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3245. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3246. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3247. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3248. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3249. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3250. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3251. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3252. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3253. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3254. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3255. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3256. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3257. 0x00, 0x00, 0x00, 0x00, // 0000 black
  3258. 0xFF, 0xFF, 0xFF, 0x00 // 1111 white
  3259. };
  3260. static BOOL NEAR IsIdentityPalette(HPALETTE hpal)
  3261. {
  3262. int i,n=0; // n is initialised as GetObject returns a 2 byte value
  3263. HDC hdc;
  3264. PALETTEENTRY ape[256];
  3265. PALETTEENTRY apeSystem[16];
  3266. if (hpal == NULL || !(gwRasterCaps & RC_PALETTE) || gwScreenBitDepth != 8)
  3267. return FALSE;
  3268. // Some wierd display cards actually have different numbers of system
  3269. // colours! We definitely don't want to think we can do identity palettes.
  3270. hdc = GetDC(NULL);
  3271. n = GetDeviceCaps(hdc, NUMRESERVED);
  3272. ReleaseDC(NULL, hdc);
  3273. if (n != 20)
  3274. return FALSE;
  3275. GetObject(hpal, sizeof(n), (LPVOID)&n);
  3276. if (n != 256)
  3277. return FALSE;
  3278. GetPaletteEntries(hpal, 0, 8, &ape[0]);
  3279. GetPaletteEntries(hpal, 248, 8, &ape[8]);
  3280. for (i=0; i<16; i++)
  3281. ape[i].peFlags = 0;
  3282. if (!_fmemcmp(ape, apeCosmic, sizeof(apeCosmic)))
  3283. goto DoneChecking;
  3284. if (!_fmemcmp(ape, apeFake, sizeof(apeFake)))
  3285. goto DoneChecking;
  3286. if (!_fmemcmp(ape, apeBlackWhite, sizeof(apeBlackWhite)))
  3287. goto DoneChecking;
  3288. hdc = GetDC(NULL);
  3289. GetSystemPaletteEntries(hdc, 0, 8, &apeSystem[0]);
  3290. GetSystemPaletteEntries(hdc, 248, 8, &apeSystem[8]);
  3291. ReleaseDC(NULL, hdc);
  3292. for (i=0; i<16; i++)
  3293. apeSystem[i].peFlags = 0;
  3294. if (!_fmemcmp(ape, apeSystem, sizeof(apeSystem)))
  3295. goto DoneChecking;
  3296. return FALSE;
  3297. DoneChecking:
  3298. //
  3299. // if we have an identity palette then, patch the colors to match
  3300. // the driver ones exactly.
  3301. //
  3302. GetPaletteEntries(hpal, 0, 256, ape);
  3303. hdc = GetDC(NULL);
  3304. GetSystemPaletteEntries(hdc, 0, 10, &ape[0]);
  3305. GetSystemPaletteEntries(hdc, 246, 10, &ape[246]);
  3306. ReleaseDC(NULL, hdc);
  3307. for (i=0; i<10; i++)
  3308. ape[i].peFlags = 0;
  3309. for (i=10; i<246; i++)
  3310. ape[i].peFlags = PC_NOCOLLAPSE;
  3311. for (i=246; i<256; i++)
  3312. ape[i].peFlags = 0;
  3313. SetPaletteEntries(hpal, 0, 256, ape);
  3314. UnrealizeObject(hpal); //??? needed
  3315. return TRUE;
  3316. }
  3317. #define COLORMASK 0xF8
  3318. STATICFN BOOL NEAR AreColorsAllGDIColors(LPBITMAPINFOHEADER lpbi)
  3319. {
  3320. int cColors;
  3321. LPRGBQUAD lprgb = (LPRGBQUAD) ((LPBYTE) lpbi + lpbi->biSize);
  3322. int i;
  3323. for (cColors = (int) lpbi->biClrUsed; cColors > 0; cColors--, lprgb++) {
  3324. for (i = 0; i < 16; i++) {
  3325. if (((lprgb->rgbRed & COLORMASK) == (apeCosmic[i].peRed & COLORMASK)) &&
  3326. ((lprgb->rgbGreen & COLORMASK) == (apeCosmic[i].peGreen & COLORMASK)) &&
  3327. ((lprgb->rgbBlue & COLORMASK) == (apeCosmic[i].peBlue & COLORMASK)))
  3328. goto Onward;
  3329. if (((lprgb->rgbRed & COLORMASK) == (apeFake[i].peRed & COLORMASK)) &&
  3330. ((lprgb->rgbGreen & COLORMASK) == (apeFake[i].peGreen & COLORMASK)) &&
  3331. ((lprgb->rgbBlue & COLORMASK) == (apeFake[i].peBlue & COLORMASK)))
  3332. goto Onward;
  3333. }
  3334. return FALSE;
  3335. Onward:
  3336. ; // There's got to be a nicer way to arrange this code!
  3337. }
  3338. return TRUE; // !!!!!
  3339. }
  3340. /**************************************************************************
  3341. let codec adapt to the system palette.
  3342. **************************************************************************/
  3343. static BOOL FixUpCodecPalette(HIC hic, LPBITMAPINFOHEADER lpbi)
  3344. {
  3345. struct {
  3346. BITMAPINFOHEADER bi;
  3347. RGBQUAD argbq[256];
  3348. } s;
  3349. int i;
  3350. HDC hdc;
  3351. s.bi.biSize = sizeof(s.bi);
  3352. s.bi.biWidth = lpbi->biWidth;
  3353. s.bi.biHeight = lpbi->biHeight;
  3354. s.bi.biPlanes = 1;
  3355. s.bi.biBitCount = 8;
  3356. s.bi.biCompression = 0;
  3357. s.bi.biSizeImage = 0;
  3358. s.bi.biXPelsPerMeter = 0;
  3359. s.bi.biYPelsPerMeter = 0;
  3360. s.bi.biClrUsed = 256;
  3361. s.bi.biClrImportant = 0;
  3362. hdc = GetDC(NULL);
  3363. GetSystemPaletteEntries(hdc, 0, 256, (LPPALETTEENTRY) &s.argbq);
  3364. ReleaseDC(NULL, hdc);
  3365. for (i = 0; i < 256; i++)
  3366. ((DWORD FAR*)s.argbq)[i] = i < 8 || i >= 248 ? 0 :
  3367. RGB(s.argbq[i].rgbRed,s.argbq[i].rgbGreen,s.argbq[i].rgbBlue);
  3368. return ICDecompressSetPalette(hic, &s.bi) == ICERR_OK;
  3369. }
  3370. /**************************************************************************
  3371. let codec adapt to a palette passed by the app.
  3372. **************************************************************************/
  3373. static BOOL NEAR SendSetPalette(PDD pdd)
  3374. {
  3375. int i;
  3376. int iPalColors = 0;
  3377. BOOL f;
  3378. if (pdd->hic == NULL) // nobody to send too
  3379. return FALSE;
  3380. if (pdd->biBuffer.biBitCount != 8) // not decompressing to 8bit
  3381. return FALSE;
  3382. if (!(gwRasterCaps & RC_PALETTE)) // not a palette device who cares.
  3383. return FALSE;
  3384. if (pdd->hpalDraw)
  3385. {
  3386. GetObject(pdd->hpalDraw, sizeof(iPalColors), (void FAR *)&iPalColors);
  3387. if (iPalColors == 0)
  3388. return FALSE;
  3389. if (iPalColors > 256)
  3390. iPalColors = 256;
  3391. pdd->biBuffer.biClrUsed = iPalColors;
  3392. GetPaletteEntries(pdd->hpalDraw, 0, iPalColors, (PALETTEENTRY FAR *)pdd->argbq);
  3393. for (i = 0; i < iPalColors; i++)
  3394. ((DWORD*)pdd->argbq)[i] = RGB(pdd->argbq[i].rgbRed,pdd->argbq[i].rgbGreen,pdd->argbq[i].rgbBlue);
  3395. f = ICDecompressSetPalette(pdd->hic, &pdd->biBuffer) == ICERR_OK;
  3396. ICDecompressGetPalette(pdd->hic, pdd->lpbi, &pdd->biBuffer);
  3397. }
  3398. else
  3399. {
  3400. pdd->biBuffer.biClrUsed = pdd->ClrUsed;
  3401. f = ICDecompressSetPalette(pdd->hic, NULL) == ICERR_OK;
  3402. ICDecompressGetPalette(pdd->hic, pdd->lpbi, &pdd->biBuffer);
  3403. }
  3404. return f;
  3405. }
  3406. #ifdef DEBUG_RETAIL
  3407. #define _WINDLL
  3408. #include <stdarg.h>
  3409. #include <stdio.h>
  3410. void FAR CDECL ddprintf(LPSTR szFormat, ...)
  3411. {
  3412. char ach[128];
  3413. va_list va;
  3414. UINT n;
  3415. static int fDebug = -1;
  3416. if (fDebug == -1)
  3417. fDebug = GetProfileIntA("Debug", MODNAME, FALSE);
  3418. if (!fDebug)
  3419. return;
  3420. va_start(va, szFormat);
  3421. #ifdef WIN32
  3422. n = sprintf(ach, MODNAME ": (tid %x) ", GetCurrentThreadId());
  3423. n += vsprintf(ach+n, szFormat, va);
  3424. #else
  3425. lstrcpy(ach, MODNAME ": ");
  3426. n = lstrlen(ach);
  3427. n += wvsprintf(ach+n, szFormat, va);
  3428. #endif
  3429. va_end(va);
  3430. ach[n++] = '\r';
  3431. ach[n++] = '\n';
  3432. ach[n] = 0;
  3433. OutputDebugStringA(ach);
  3434. }
  3435. #endif
  3436.