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

663 lines
16 KiB

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include "lockbm.h"
  4. //////////////////////////////////////////////////////////////////////////////
  5. //////////////////////////////////////////////////////////////////////////////
  6. #ifndef BI_BITFIELDS
  7. #define BI_BITFIELDS 3
  8. #endif
  9. #ifndef BI_BITMAP
  10. #define BI_BITMAP 0x4D544942 // 'BITM'
  11. #endif
  12. //////////////////////////////////////////////////////////////////////////////
  13. //////////////////////////////////////////////////////////////////////////////
  14. //
  15. // GDI!GDIInit2() GDI.403
  16. //
  17. // this GDI function does the following:
  18. //
  19. // GetSetBitmapHandle(hbm, 0) - will return global handle of bitmap
  20. //
  21. // GetSetBitmapHandle(hbm, h) - will set global handle to <h>
  22. //
  23. // GetSetBitmapHandle(hbm, -1) - will set global handle to NULL
  24. //
  25. static HANDLE (FAR PASCAL *GetSetBitmapHandle)(HBITMAP hbm, HANDLE h);
  26. //////////////////////////////////////////////////////////////////////////////
  27. //////////////////////////////////////////////////////////////////////////////
  28. #define muldiv(a,b,c) (UINT)(((DWORD)(UINT)(a) * (DWORD)(UINT)(b)) / (UINT)(c))
  29. //////////////////////////////////////////////////////////////////////////////
  30. //
  31. // CanLockBitmaps()
  32. //
  33. // determime if we can lock bitmaps on the current display device
  34. //
  35. //////////////////////////////////////////////////////////////////////////////
  36. BOOL FAR CanLockBitmaps(void)
  37. {
  38. UINT w;
  39. UINT rc;
  40. HDC hdc;
  41. BOOL f;
  42. static BOOL fCanLockBitmaps = -1;
  43. if (fCanLockBitmaps == -1)
  44. {
  45. w = (UINT)GetVersion();
  46. w = ((UINT)LOBYTE(w) << 8) | HIBYTE(w);
  47. hdc = GetDC(NULL);
  48. rc = GetDeviceCaps(hdc, RASTERCAPS);
  49. ReleaseDC(NULL, hdc);
  50. (FARPROC)GetSetBitmapHandle =
  51. GetProcAddress(GetModuleHandle("GDI"),MAKEINTATOM(403));
  52. //
  53. // assume we dont need this on windows 4.0?
  54. //
  55. // what about the DIBENG? it does DEVBITS and in win 4.0?
  56. //
  57. // if the display handles device bitmaps, dont do this either
  58. //
  59. f = GetProfileInt("DrawDib", "Bitmaps", TRUE);
  60. #ifdef DEBUG
  61. fCanLockBitmaps = f && GetSetBitmapHandle != NULL;
  62. #else
  63. fCanLockBitmaps = f && /* (w < 0x0400) && */
  64. !(rc & RC_DEVBITS) &&
  65. GetSetBitmapHandle != NULL;
  66. #endif
  67. }
  68. return fCanLockBitmaps;
  69. }
  70. //////////////////////////////////////////////////////////////////////////////
  71. //
  72. // LockBitmap
  73. //
  74. // return a pointer to the bitmap bits
  75. //
  76. //////////////////////////////////////////////////////////////////////////////
  77. LPVOID FAR LockBitmap(HBITMAP hbm)
  78. {
  79. return GetBitmap(hbm, NULL, 0);
  80. }
  81. //////////////////////////////////////////////////////////////////////////////
  82. //
  83. // GetBitmapDIB
  84. //
  85. //////////////////////////////////////////////////////////////////////////////
  86. LPVOID FAR GetBitmapDIB(LPBITMAPINFOHEADER lpbi, LPVOID lpBits, LPVOID p, int cb)
  87. {
  88. IBITMAP FAR *pbm;
  89. if (lpBits == NULL)
  90. lpBits = (LPBYTE)lpbi + (int)lpbi->biSize + lpbi->biClrUsed * sizeof(RGBQUAD);
  91. if (p == NULL || cb < sizeof(BITMAP))
  92. return lpBits;
  93. pbm = p;
  94. if (lpbi->biCompression == 0)
  95. {
  96. switch ((int)lpbi->biBitCount + (int)lpbi->biPlanes*256)
  97. {
  98. case 0x0101: pbm->bmType = BM_1BIT; break;
  99. case 0x0104: pbm->bmType = BM_4BIT; break;
  100. case 0x0108: pbm->bmType = BM_8BIT; break;
  101. case 0x0110: pbm->bmType = BM_16555; break;
  102. case 0x0118: pbm->bmType = BM_24BGR; break;
  103. case 0x0120: pbm->bmType = BM_32BGR; break;
  104. case 0x0401: pbm->bmType = BM_VGA; break;
  105. default: return NULL;
  106. }
  107. }
  108. else if (lpbi->biCompression == BI_BITFIELDS)
  109. {
  110. switch ((int)lpbi->biBitCount + (int)lpbi->biPlanes*256)
  111. {
  112. //!!! hack: realy should check the bit fields!
  113. case 0x0110: pbm->bmType = BM_16565; break;
  114. case 0x0118: pbm->bmType = BM_24RGB; break;
  115. case 0x0120: pbm->bmType = BM_32RGB; break;
  116. default: return NULL;
  117. }
  118. }
  119. else
  120. return NULL;
  121. pbm->bmWidth = (int)lpbi->biWidth;
  122. pbm->bmHeight = ((int)lpbi->biHeight > 0) ? (int)lpbi->biHeight : -(int)lpbi->biHeight;
  123. pbm->bmWidthBytes = (((int)lpbi->biBitCount * (int)lpbi->biWidth + 31)&~31)/8;
  124. pbm->bmPlanes = (BYTE)lpbi->biPlanes;
  125. pbm->bmBitsPixel = (BYTE)lpbi->biBitCount;
  126. pbm->bmBits = lpBits;
  127. if (cb > sizeof(BITMAP))
  128. {
  129. pbm->bmSegmentIndex = 0;
  130. pbm->bmScanSegment = pbm->bmHeight;
  131. pbm->bmFillBytes = 0;
  132. pbm->bmBitmapInfo = (long)lpbi;
  133. if ((long)lpbi->biHeight < 0)
  134. {
  135. pbm->bmNextScan = -pbm->bmWidthBytes;
  136. pbm->bmOffset = (long)pbm->bmWidthBytes * (pbm->bmHeight-1);
  137. }
  138. else
  139. {
  140. pbm->bmNextScan = pbm->bmWidthBytes;
  141. pbm->bmOffset = 0;
  142. }
  143. }
  144. return lpBits;
  145. }
  146. #if 0
  147. //////////////////////////////////////////////////////////////////////////////
  148. //////////////////////////////////////////////////////////////////////////////
  149. void FAR BitmapXY(IBITMAP FAR *pbm, int x, int y)
  150. {
  151. UINT t;
  152. if (pbm->bmFillBytes)
  153. {
  154. while (y-- > 0)
  155. {
  156. t = (UINT)(pbm->bmOffset & 0xFFFF0000);
  157. pbm->bmOffset += pbm->bmNextScan;
  158. if ((UINT)(pbm->bmOffset & 0xFFFF0000) != t)
  159. pbm->bmOffset += pbm->bmFillBytes;
  160. }
  161. }
  162. else
  163. {
  164. pbm->bmOffset += y * (long)pbm->bmNextScan;
  165. }
  166. pbm->bmOffset += x * pbm->bmBitsPixel / 8;
  167. }
  168. #endif
  169. //////////////////////////////////////////////////////////////////////////////
  170. //
  171. // GetDIBBitmap
  172. //
  173. //////////////////////////////////////////////////////////////////////////////
  174. LPVOID FAR GetDIBBitmap(HBITMAP hbm, LPBITMAPINFOHEADER lpbi)
  175. {
  176. UINT wType;
  177. BITMAP bm;
  178. UINT ScansPerSeg;
  179. UINT FillBytes;
  180. if (hbm)
  181. GetObject(hbm, sizeof(bm), &bm);
  182. wType = GetBitmapType();
  183. if (wType == 0)
  184. return NULL;
  185. lpbi->biSize = sizeof(BITMAPINFOHEADER);
  186. lpbi->biWidth = bm.bmWidth;
  187. lpbi->biHeight = bm.bmHeight;
  188. lpbi->biPlanes = bm.bmPlanes;
  189. lpbi->biBitCount = bm.bmBitsPixel;
  190. lpbi->biCompression = 0;
  191. lpbi->biSizeImage = (DWORD)(bm.bmWidthBytes * bm.bmPlanes) * (DWORD)bm.bmHeight;
  192. lpbi->biXPelsPerMeter = 0;
  193. lpbi->biYPelsPerMeter = 0;
  194. lpbi->biClrUsed = 0;
  195. lpbi->biClrImportant = 0;
  196. switch(wType & BM_TYPE)
  197. {
  198. case BM_VGA:
  199. break;
  200. case BM_1BIT:
  201. case BM_4BIT:
  202. case BM_8BIT:
  203. break;
  204. case BM_16555:
  205. break;
  206. case BM_24BGR:
  207. case BM_32BGR:
  208. break;
  209. case BM_16565:
  210. lpbi->biCompression = BI_BITFIELDS;
  211. ((LPDWORD)(lpbi+1))[0] = 0x00F800;
  212. ((LPDWORD)(lpbi+1))[1] = 0x0007E0;
  213. ((LPDWORD)(lpbi+1))[2] = 0x00001F;
  214. break;
  215. case BM_24RGB:
  216. case BM_32RGB:
  217. lpbi->biCompression = BI_BITFIELDS;
  218. ((LPDWORD)(lpbi+1))[0] = 0x0000FF;
  219. ((LPDWORD)(lpbi+1))[1] = 0x00FF00;
  220. ((LPDWORD)(lpbi+1))[2] = 0xFF0000;
  221. break;
  222. default:
  223. return NULL;
  224. }
  225. //
  226. // make sure WidthBytes is right, dont forget bitmaps are WORD aligned
  227. // and DIBs are DWORD aligned.
  228. //
  229. if (bm.bmWidthBytes != ((bm.bmWidth * bm.bmBitsPixel + 31) & ~31)/8)
  230. {
  231. if (lpbi->biCompression != 0)
  232. return NULL;
  233. lpbi->biCompression = BI_BITMAP;
  234. lpbi->biXPelsPerMeter = bm.bmWidthBytes;
  235. }
  236. if ((wType & BM_HUGE) && (lpbi->biSizeImage > 64*1024l))
  237. {
  238. if (lpbi->biCompression == BI_BITFIELDS)
  239. return NULL;
  240. lpbi->biCompression = BI_BITMAP;
  241. ScansPerSeg = muldiv(64,1024,bm.bmWidthBytes * bm.bmPlanes);
  242. FillBytes = (UINT)(64ul*1024 - bm.bmWidthBytes * bm.bmPlanes * ScansPerSeg);
  243. lpbi->biSizeImage += FillBytes * (bm.bmHeight / ScansPerSeg);
  244. lpbi->biXPelsPerMeter = bm.bmWidthBytes;
  245. lpbi->biYPelsPerMeter = FillBytes;
  246. }
  247. if (!(wType & BM_BOTTOMTOTOP))
  248. lpbi->biHeight = -bm.bmHeight;
  249. return LockBitmap(hbm);
  250. }
  251. //////////////////////////////////////////////////////////////////////////////
  252. //
  253. // GetBitmap
  254. //
  255. //////////////////////////////////////////////////////////////////////////////
  256. LPVOID FAR GetBitmap(HBITMAP hbm, LPVOID p, int cb)
  257. {
  258. HANDLE h;
  259. DWORD dwSize;
  260. IBITMAP FAR *pbm;
  261. HDC hdc = NULL;
  262. HBITMAP hbmT;
  263. if (!CanLockBitmaps())
  264. return NULL;
  265. if (hbm == NULL)
  266. return NULL;
  267. h = GetSetBitmapHandle(hbm, 0);
  268. if (h == NULL)
  269. return NULL;
  270. pbm = (LPVOID)GlobalLock(h);
  271. if (IsBadReadPtr(pbm, sizeof(IBITMAP)))
  272. return NULL;
  273. //
  274. // see if it is realy a bitmap.
  275. //
  276. if (pbm->bmType != 0)
  277. return NULL;
  278. //
  279. // make sure the bmBits pointer is valid.
  280. //
  281. if (pbm->bmBits == NULL)
  282. {
  283. hdc = CreateCompatibleDC(NULL);
  284. hbmT = SelectObject(hdc, hbm);
  285. }
  286. dwSize = (DWORD)pbm->bmHeight * (DWORD)pbm->bmWidthBytes;
  287. if (IsBadHugeWritePtr((LPVOID)pbm->bmBits, dwSize))
  288. {
  289. if (hdc)
  290. {
  291. SelectObject(hdc, hbmT);
  292. DeleteDC(hdc);
  293. }
  294. return NULL;
  295. }
  296. if (p)
  297. {
  298. UINT u;
  299. hmemcpy(p, pbm, min(cb, sizeof(IBITMAP)));
  300. pbm = p;
  301. u = GetBitmapType();
  302. pbm->bmType = u & BM_TYPE;
  303. if (cb > sizeof(BITMAP))
  304. {
  305. pbm->bmBitmapInfo = NULL;
  306. pbm->bmNextScan = pbm->bmWidthBytes * pbm->bmPlanes;
  307. if (u & BM_BOTTOMTOTOP)
  308. {
  309. pbm->bmOffset = 0;
  310. }
  311. else
  312. {
  313. pbm->bmOffset = (long)pbm->bmNextScan * (pbm->bmHeight-1);
  314. pbm->bmNextScan = -pbm->bmNextScan;
  315. pbm->bmFillBytes = -pbm->bmFillBytes;
  316. }
  317. //
  318. // see if this particular bitmap is HUGE
  319. //
  320. if (!(u & BM_HUGE) || (DWORD)pbm->bmHeight * pbm->bmWidthBytes < 64l*1024)
  321. {
  322. pbm->bmFillBytes = 0;
  323. pbm->bmScanSegment = pbm->bmHeight;
  324. }
  325. else
  326. {
  327. if (pbm->bmOffset)
  328. pbm->bmOffset -= (long)((pbm->bmHeight-1) / pbm->bmScanSegment) * pbm->bmFillBytes;
  329. }
  330. }
  331. }
  332. if (hdc)
  333. {
  334. SelectObject(hdc, hbmT);
  335. DeleteDC(hdc);
  336. }
  337. return (LPVOID)pbm->bmBits;
  338. }
  339. /////////////////////////////////////////////////////////////////////////////
  340. //
  341. // SetPixel
  342. //
  343. // some cards cant't seam to do SetPixel right it is amazing they work at all
  344. //
  345. /////////////////////////////////////////////////////////////////////////////
  346. static void SetPixelX(HDC hdc, int x, int y, COLORREF rgb)
  347. {
  348. RECT rc;
  349. rc.left = x;
  350. rc.top = y;
  351. rc.right = x+1;
  352. rc.bottom = y+1;
  353. SetBkColor(hdc, rgb);
  354. ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
  355. }
  356. #define SetPixel SetPixelX
  357. ///////////////////////////////////////////////////////////////////////////////
  358. //
  359. // GetSurfaceType
  360. //
  361. ///////////////////////////////////////////////////////////////////////////////
  362. #define BCODE _based(_segname("_CODE"))
  363. static BYTE BCODE bits8[] = {0x00,0xF9,0xFA,0xFC,0xFF};
  364. static WORD BCODE bits555[] = {0x0000,0x7C00,0x03E0,0x001F,0x7FFF};
  365. static WORD BCODE bits5551[]= {0x8000,0xFC00,0x83E0,0x801F,0xFFFF};
  366. static WORD BCODE bits565[] = {0x0000,0xF800,0x07E0,0x001F,0xFFFF};
  367. static BYTE BCODE bitsBGR[] = {0x00,0x00,0x00, 0x00,0x00,0xFF, 0x00,0xFF,0x00, 0xFF,0x00,0x00, 0xFF,0xFF,0xFF};
  368. static BYTE BCODE bitsRGB[] = {0x00,0x00,0x00, 0xFF,0x00,0x00, 0x00,0xFF,0x00, 0x00,0x00,0xFF, 0xFF,0xFF,0xFF};
  369. static DWORD BCODE bitsRGBX[]= {0x000000, 0x0000FF, 0x00FF00, 0xFF0000, 0xFFFFFF};
  370. static DWORD BCODE bitsBGRX[]= {0x000000, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFFFF};
  371. void FAR TestSurfaceType(HDC hdc, int x, int y)
  372. {
  373. PatBlt(hdc, x, y, 5, 1, BLACKNESS);
  374. SetPixel(hdc, x+0, y, RGB(000,000,000));
  375. SetPixel(hdc, x+1, y, RGB(255,000,000));
  376. SetPixel(hdc, x+2, y, RGB(000,255,000));
  377. SetPixel(hdc, x+3, y, RGB(000,000,255));
  378. SetPixel(hdc, x+4, y, RGB(255,255,255));
  379. GetPixel(hdc, x, y);
  380. }
  381. UINT FAR GetSurfaceType(LPVOID lpBits)
  382. {
  383. #define TESTFMT(a,n) \
  384. if (_fmemcmp(lpBits, (LPVOID)a, sizeof(a)) == 0) return n;
  385. TESTFMT(bits8, BM_8BIT);
  386. TESTFMT(bits555, BM_16555);
  387. TESTFMT(bits5551, BM_16555);
  388. TESTFMT(bits565, BM_16565);
  389. TESTFMT(bitsRGB, BM_24RGB);
  390. TESTFMT(bitsBGR, BM_24BGR);
  391. TESTFMT(bitsRGBX, BM_32RGB);
  392. TESTFMT(bitsBGRX, BM_32BGR);
  393. return 0;
  394. }
  395. ///////////////////////////////////////////////////////////////////////////////
  396. //
  397. // GetBitmapType
  398. //
  399. // return the bitmap type that the display driver uses
  400. //
  401. ///////////////////////////////////////////////////////////////////////////////
  402. UINT FAR GetBitmapType()
  403. {
  404. BITMAP bm;
  405. HBITMAP hbm;
  406. HBITMAP hbmT;
  407. HDC hdc;
  408. UINT u;
  409. BYTE bits[20*4*2];
  410. static UINT wBitmapType = 0xFFFF;
  411. if (wBitmapType != 0xFFFF)
  412. return wBitmapType;
  413. //
  414. // create a test bitmap (<64k)
  415. //
  416. hdc = GetDC(NULL);
  417. hbm = CreateCompatibleBitmap(hdc,20,2);
  418. ReleaseDC(NULL, hdc);
  419. hdc = CreateCompatibleDC(NULL);
  420. hbmT = SelectObject(hdc, hbm);
  421. GetObject(hbm, sizeof(bm), &bm);
  422. PatBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, BLACKNESS);
  423. TestSurfaceType(hdc, 0, 0);
  424. GetBitmapBits(hbm, sizeof(bits), bits);
  425. u = GetSurfaceType(bits);
  426. if (u == 0) {
  427. u = GetSurfaceType(bits + bm.bmWidthBytes);
  428. if (u)
  429. u |= BM_BOTTOMTOTOP;
  430. }
  431. #ifndef WIN32
  432. if (u) {
  433. BYTE _huge *pb;
  434. UINT dy,w;
  435. //
  436. // see if bitmap(s) are huge format
  437. //
  438. dy = (UINT)(0x10000l/bm.bmWidthBytes) + 1;
  439. hbm = CreateCompatibleBitmap(hdc,bm.bmWidth,dy);
  440. DeleteObject(SelectObject(hdc, hbm));
  441. PatBlt(hdc, 0, 0, bm.bmWidth, dy, BLACKNESS);
  442. pb = (BYTE _huge *)LockBitmap(hbm);
  443. if (pb == NULL || OFFSETOF(pb) != 0)
  444. ; // cant lock bitmaps
  445. else {
  446. u |= BM_CANLOCK;
  447. w = (dy-1) * bm.bmWidthBytes;
  448. pb[64l*1024] = 0;
  449. pb[w] = 0;
  450. if (u & BM_BOTTOMTOTOP)
  451. SetPixel(hdc, 0, 0, RGB(255,255,255));
  452. else
  453. SetPixel(hdc, 0, dy-1, RGB(255,255,255));
  454. if (pb[64l*1024] != 0 && pb[w] == 0)
  455. u |= BM_HUGE;
  456. else if (pb[64l*1024] == 0 && pb[w] != 0)
  457. ;
  458. else
  459. u = 0;
  460. }
  461. }
  462. #endif
  463. SelectObject(hdc, hbmT);
  464. DeleteObject(hbm);
  465. DeleteDC(hdc);
  466. wBitmapType = u;
  467. return u;
  468. }
  469. //////////////////////////////////////////////////////////////////////////////
  470. //
  471. // returns the PDevice of the given physical or memory DC
  472. //
  473. // return the bitmap type that the display driver uses
  474. //
  475. ///////////////////////////////////////////////////////////////////////////////
  476. LPVOID FAR GetPDevice(HDC hdc)
  477. {
  478. HANDLE h;
  479. HBITMAP hbm;
  480. HBITMAP hbmT;
  481. HDC hdcT=NULL;
  482. IBITMAP FAR *pbm;
  483. LPVOID lpPDevice = NULL;
  484. // GDI.403
  485. static HANDLE (FAR PASCAL *GdiGetBitmapHandle)(HBITMAP hbm, HANDLE h);
  486. if (GdiGetBitmapHandle == NULL)
  487. (FARPROC)GdiGetBitmapHandle = GetProcAddress(GetModuleHandle("GDI"),MAKEINTATOM(403));
  488. if (GdiGetBitmapHandle == NULL)
  489. return NULL;
  490. hbm = CreateBitmap(1,1,1,1,NULL);
  491. //
  492. // first try the passed DC if it is a bitmap/DC
  493. //
  494. hbmT = SelectBitmap(hdc, hbm);
  495. if (hbmT != NULL)
  496. {
  497. //
  498. // it is a memory DC.
  499. //
  500. h = GdiGetBitmapHandle(hbmT, 0);
  501. }
  502. else
  503. {
  504. //
  505. // it is a physical DC.
  506. //
  507. hdcT = CreateCompatibleDC(hdc);
  508. hbmT = SelectBitmap(hdcT, hbm);
  509. h = GdiGetBitmapHandle(hbm, 0);
  510. }
  511. if (h == NULL)
  512. goto exit;
  513. pbm = (IBITMAP FAR *)GlobalLock(h);
  514. if (IsBadReadPtr(pbm, sizeof(IBITMAP)))
  515. goto exit;
  516. if (pbm)
  517. pbm = (IBITMAP FAR *)pbm->bmlpPDevice;
  518. else
  519. pbm = NULL;
  520. if (IsBadReadPtr(pbm, 2))
  521. goto exit;
  522. lpPDevice = (LPVOID)pbm;
  523. exit:
  524. if (hdcT)
  525. {
  526. SelectObject(hdcT, hbmT);
  527. DeleteObject(hdcT);
  528. }
  529. else
  530. {
  531. SelectObject(hdc, hbmT);
  532. }
  533. DeleteObject(hbm);
  534. return lpPDevice;
  535. }