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.

2871 lines
86 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: bitmap.c *
  3. * *
  4. * Client side stubs that move bitmaps over the C/S interface. *
  5. * *
  6. * Created: 14-May-1991 11:04:49 *
  7. * Author: Eric Kutter [erick] *
  8. * *
  9. * Copyright (c) 1991-1999 Microsoft Corporation *
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #define EXTRAPIXEL 4
  14. //
  15. //The default band size is set to 4Mb
  16. //
  17. #define BAND_SIZE (4194304)
  18. /******************************Public*Routine******************************\
  19. * cjBitmapBitsSize - calculate the size of the bitmap bits for the
  20. * given BITMAPINFO
  21. *
  22. * Arguments:
  23. *
  24. * pbmi - pointer to BITMAPINFO
  25. *
  26. * Return Value:
  27. *
  28. * size of bitmap bits in butes
  29. *
  30. * History:
  31. *
  32. * 11-Jul-1996 -by- Mark Enstrom [marke]
  33. *
  34. \**************************************************************************/
  35. ULONG cjBitmapBitsSize(CONST BITMAPINFO *pbmi)
  36. {
  37. //
  38. // Check for PM-style DIB
  39. //
  40. if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  41. {
  42. LPBITMAPCOREINFO pbmci;
  43. pbmci = (LPBITMAPCOREINFO)pbmi;
  44. return(CJSCAN(pbmci->bmciHeader.bcWidth,pbmci->bmciHeader.bcPlanes,
  45. pbmci->bmciHeader.bcBitCount) *
  46. pbmci->bmciHeader.bcHeight);
  47. }
  48. //
  49. // not a core header
  50. //
  51. if ((pbmi->bmiHeader.biCompression == BI_RGB) ||
  52. (pbmi->bmiHeader.biCompression == BI_BITFIELDS) ||
  53. (pbmi->bmiHeader.biCompression == BI_CMYK))
  54. {
  55. return(CJSCAN(pbmi->bmiHeader.biWidth,pbmi->bmiHeader.biPlanes,
  56. pbmi->bmiHeader.biBitCount) *
  57. ABS(pbmi->bmiHeader.biHeight));
  58. }
  59. else
  60. {
  61. return(pbmi->bmiHeader.biSizeImage);
  62. }
  63. }
  64. //
  65. // IS_BMI_RLE
  66. //
  67. // Checks if the header pointed to by pv is a BITMAPINFO for a RLE4 or RLE8.
  68. // Evaluates to TRUE if RLE, FALSE otherwise.
  69. //
  70. #define IS_BMI_RLE(pv) \
  71. ((pv) && \
  72. (((BITMAPINFO *)(pv))->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && \
  73. ((((BITMAPINFO *)(pv))->bmiHeader.biCompression == BI_RLE4) || \
  74. (((BITMAPINFO *)(pv))->bmiHeader.biCompression == BI_RLE8) ))
  75. //
  76. // IS_BMI_JPEG
  77. //
  78. // Checks if the header pointed to by pv is a BITMAPINFO for a JPEG.
  79. // Evaluates to TRUE if JPEG, FALSE otherwise.
  80. //
  81. #define IS_BMI_JPEG(pv) \
  82. ((pv) && \
  83. (((BITMAPINFO *)(pv))->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && \
  84. (((BITMAPINFO *)(pv))->bmiHeader.biCompression == BI_JPEG))
  85. //
  86. // IS_BMI_PNG
  87. //
  88. // Checks if the header pointed to by pv is a BITMAPINFO for a PNG.
  89. // Evaluates to TRUE if PNG, FALSE otherwise.
  90. //
  91. #define IS_BMI_PNG(pv) \
  92. ((pv) && \
  93. (((BITMAPINFO *)(pv))->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && \
  94. (((BITMAPINFO *)(pv))->bmiHeader.biCompression == BI_PNG))
  95. //
  96. // IS_PASSTHROUGH_IMAGE
  97. //
  98. // Checks if the biCompression value is one of the passthrough formats that
  99. // can be passed to devices (BI_JPEG or BI_PNG).
  100. //
  101. #define IS_PASSTHROUGH_IMAGE(biCompression) \
  102. (((biCompression) == BI_JPEG) || ((biCompression) == BI_PNG))
  103. //
  104. // IS_BMI_PASSTHROUGH_IMAGE
  105. //
  106. // Checks if the header pointed to by pv is a BITMAPINFO for a JPEG or PNG.
  107. // Evaluates to TRUE if JPEG or PNG, FALSE otherwise.
  108. //
  109. #define IS_BMI_PASSTHROUGH_IMAGE(pv) \
  110. ((pv) && \
  111. (((BITMAPINFO *)(pv))->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && \
  112. IS_PASSTHROUGH_IMAGE(((BITMAPINFO *)(pv))->bmiHeader.biCompression))
  113. /******************************Public*Routine******************************\
  114. * cCalculateColorTableSize(
  115. *
  116. * Arguments:
  117. *
  118. *
  119. *
  120. * Return Value:
  121. *
  122. *
  123. *
  124. * History:
  125. *
  126. * 11-Jul-1996 -by- Mark Enstrom [marke]
  127. *
  128. \**************************************************************************/
  129. BOOL
  130. cCalculateColorTableSize(
  131. UINT uiBitCount,
  132. UINT uiPalUsed,
  133. UINT uiCompression,
  134. UINT biSize,
  135. ULONG *piUsage,
  136. ULONG *pColors
  137. )
  138. {
  139. BOOL bStatus = FALSE;
  140. ULONG cColorsMax = 0;
  141. if (uiCompression == BI_BITFIELDS)
  142. {
  143. //
  144. // Handle 16 and 32 bit per pel bitmaps.
  145. //
  146. if (*piUsage == DIB_PAL_COLORS)
  147. {
  148. *piUsage = DIB_RGB_COLORS;
  149. }
  150. switch (uiBitCount)
  151. {
  152. case 16:
  153. case 32:
  154. break;
  155. default:
  156. WARNING("ConvertInfo failed for BI_BITFIELDS\n");
  157. return(FALSE);
  158. }
  159. if (biSize <= sizeof(BITMAPINFOHEADER))
  160. {
  161. uiPalUsed = cColorsMax = 3;
  162. }
  163. else
  164. {
  165. //
  166. // masks are part of BITMAPV4 and greater
  167. //
  168. uiPalUsed = cColorsMax = 0;
  169. }
  170. }
  171. else if (uiCompression == BI_RGB)
  172. {
  173. switch (uiBitCount)
  174. {
  175. case 1:
  176. cColorsMax = 2;
  177. break;
  178. case 4:
  179. cColorsMax = 16;
  180. break;
  181. case 8:
  182. cColorsMax = 256;
  183. break;
  184. default:
  185. if (*piUsage == DIB_PAL_COLORS)
  186. {
  187. *piUsage = DIB_RGB_COLORS;
  188. }
  189. cColorsMax = 0;
  190. switch (uiBitCount)
  191. {
  192. case 16:
  193. case 24:
  194. case 32:
  195. break;
  196. default:
  197. WARNING("convertinfo failed invalid bitcount in bmi BI_RGB\n");
  198. return(FALSE);
  199. }
  200. }
  201. }
  202. else if (uiCompression == BI_CMYK)
  203. {
  204. if (*piUsage == DIB_PAL_COLORS)
  205. {
  206. *piUsage = DIB_RGB_COLORS;
  207. }
  208. switch (uiBitCount)
  209. {
  210. case 1:
  211. cColorsMax = 2;
  212. break;
  213. case 4:
  214. cColorsMax = 16;
  215. break;
  216. case 8:
  217. cColorsMax = 256;
  218. break;
  219. case 32:
  220. cColorsMax = 0;
  221. break;
  222. default:
  223. WARNING("convertinfo failed invalid bitcount in bmi BI_CMYK\n");
  224. return(FALSE);
  225. }
  226. }
  227. else if ((uiCompression == BI_RLE4) || (uiCompression == BI_CMYKRLE4))
  228. {
  229. if (uiBitCount != 4)
  230. {
  231. // WARNING("cCalculateColroTableSize invalid bitcount BI_RLE4\n");
  232. return(FALSE);
  233. }
  234. cColorsMax = 16;
  235. }
  236. else if ((uiCompression == BI_RLE8) || (uiCompression == BI_CMYKRLE8))
  237. {
  238. if (uiBitCount != 8)
  239. {
  240. // WARNING("cjBitmapSize invalid bitcount BI_RLE8\n");
  241. return(FALSE);
  242. }
  243. cColorsMax = 256;
  244. }
  245. else if ((uiCompression == BI_JPEG) || (uiCompression == BI_PNG))
  246. {
  247. cColorsMax = 0;
  248. }
  249. else
  250. {
  251. WARNING("convertinfo failed invalid Compression in header\n");
  252. return(FALSE);
  253. }
  254. if (uiPalUsed != 0)
  255. {
  256. if (uiPalUsed <= cColorsMax)
  257. {
  258. cColorsMax = uiPalUsed;
  259. }
  260. }
  261. *pColors = cColorsMax;
  262. return(TRUE);
  263. }
  264. /**********************************************************************\
  265. * pbmiConvertInfo
  266. *
  267. * Does two things:
  268. *
  269. * 1. takes BITMAPINFO, Converts BITMAPCOREHEADER
  270. * into BITMAPINFOHEADER and copies the the color table
  271. *
  272. * 2. also return the size of the size of INFO struct if bPackedDIB is
  273. * FALSE otherwise pass back the size of INFO plus cjBits
  274. *
  275. * Arguments:
  276. *
  277. * pbmi - original bitmapinfo
  278. * iUsage - iUsage from API
  279. * *count - return size
  280. * bCopyInfoHeader - force copy if input is BITMAPINFOHEADER
  281. * and bPackedDIB is NOT set
  282. * bPackedDIB - BITMAPINFO has bitmap data that must be
  283. * copied also
  284. *
  285. * Return Value:
  286. *
  287. * Converted PBITMAPINFO if successful, otherwise NULL
  288. *
  289. * 10-1-95 -by- Lingyun Wang [lingyunw]
  290. \**********************************************************************/
  291. LPBITMAPINFO
  292. pbmiConvertInfo(
  293. CONST BITMAPINFO *pbmi,
  294. ULONG iUsage,
  295. ULONG *count,
  296. BOOL bPackedDIB
  297. )
  298. {
  299. LPBITMAPINFO pbmiNew;
  300. ULONG cjRGB;
  301. ULONG cColors;
  302. UINT uiBitCount;
  303. UINT uiPalUsed;
  304. UINT uiCompression;
  305. BOOL bCoreHeader = FALSE;
  306. ULONG ulSize;
  307. ULONG cjBits = 0;
  308. PVOID pjBits, pjBitsNew;
  309. BOOL bStatus;
  310. if (pbmi == (LPBITMAPINFO) NULL)
  311. {
  312. return(0);
  313. }
  314. //
  315. // Checking for different bitmap headers
  316. //
  317. ulSize = pbmi->bmiHeader.biSize;
  318. if (ulSize == sizeof(BITMAPCOREHEADER))
  319. {
  320. cjRGB = sizeof(RGBQUAD);
  321. uiBitCount = ((LPBITMAPCOREINFO)pbmi)->bmciHeader.bcBitCount;
  322. uiPalUsed = 0;
  323. uiCompression = (UINT) BI_RGB;
  324. bCoreHeader = TRUE;
  325. }
  326. else if ((ulSize >= sizeof(BITMAPINFOHEADER)) &&
  327. (ulSize <= ( 2 * sizeof(BITMAPV5HEADER))))
  328. {
  329. cjRGB = sizeof(RGBQUAD);
  330. uiBitCount = pbmi->bmiHeader.biBitCount;
  331. uiPalUsed = pbmi->bmiHeader.biClrUsed;
  332. uiCompression = (UINT) pbmi->bmiHeader.biCompression;
  333. }
  334. else
  335. {
  336. WARNING("ConvertInfo failed - invalid header size\n");
  337. return(0);
  338. }
  339. //
  340. // figure out the size of the color table
  341. //
  342. bStatus = cCalculateColorTableSize(
  343. uiBitCount,
  344. uiPalUsed,
  345. uiCompression,
  346. ulSize,
  347. &iUsage,
  348. &cColors
  349. );
  350. if (!bStatus)
  351. {
  352. return(NULL);
  353. }
  354. if (iUsage == DIB_PAL_COLORS)
  355. {
  356. cjRGB = sizeof(USHORT);
  357. }
  358. else if (iUsage == DIB_PAL_INDICES)
  359. {
  360. cjRGB = 0;
  361. }
  362. if (bPackedDIB)
  363. {
  364. cjBits = cjBitmapBitsSize(pbmi);
  365. }
  366. //
  367. // if passed COREHEADER then convert to BITMAPINFOHEADER
  368. //
  369. if (bCoreHeader)
  370. {
  371. RGBTRIPLE *pTri;
  372. RGBQUAD *pQuad;
  373. //
  374. // allocate new header to hold the info
  375. //
  376. ulSize = sizeof(BITMAPINFOHEADER);
  377. pbmiNew = (PBITMAPINFO)LOCALALLOC(ulSize +
  378. cjRGB * cColors+cjBits);
  379. if (pbmiNew == NULL)
  380. return (0);
  381. //
  382. // copy COREHEADER info over
  383. //
  384. CopyCoreToInfoHeader(&pbmiNew->bmiHeader, (BITMAPCOREHEADER *)pbmi);
  385. //
  386. // copy the color table
  387. //
  388. pTri = (RGBTRIPLE *)((LPBYTE)pbmi + sizeof(BITMAPCOREHEADER));
  389. pQuad = (RGBQUAD *)((LPBYTE)pbmiNew + sizeof(BITMAPINFOHEADER));
  390. //
  391. // copy RGBTRIPLE to RGBQUAD
  392. //
  393. if (iUsage != DIB_PAL_COLORS)
  394. {
  395. INT cj = cColors;
  396. while (cj--)
  397. {
  398. pQuad->rgbRed = pTri->rgbtRed;
  399. pQuad->rgbGreen = pTri->rgbtGreen;
  400. pQuad->rgbBlue = pTri->rgbtBlue;
  401. pQuad->rgbReserved = 0;
  402. pQuad++;
  403. pTri++;
  404. }
  405. if (bPackedDIB)
  406. pjBits = (LPBYTE)pbmi + sizeof(BITMAPCOREHEADER) + cColors*sizeof(RGBTRIPLE);
  407. }
  408. else
  409. {
  410. //
  411. // DIB_PAL_COLORS
  412. //
  413. RtlCopyMemory((LPBYTE)pQuad,(LPBYTE)pTri,cColors * cjRGB);
  414. if (bPackedDIB)
  415. pjBits = (LPBYTE)pbmi + sizeof(BITMAPCOREHEADER) + cColors * cjRGB;
  416. }
  417. //
  418. // copy the packed bits
  419. //
  420. if (bPackedDIB)
  421. {
  422. pjBitsNew = (LPBYTE)pbmiNew + ulSize + cColors*cjRGB;
  423. RtlCopyMemory((LPBYTE)pjBitsNew,
  424. (LPBYTE)pjBits,
  425. cjBits);
  426. }
  427. }
  428. else
  429. {
  430. pbmiNew = (LPBITMAPINFO)pbmi;
  431. }
  432. *count = ((ulSize + (cjRGB * cColors) + cjBits) + 3) & ~3;
  433. return((LPBITMAPINFO) pbmiNew);
  434. }
  435. /******************************Public*Routine******************************\
  436. * cjBitmapScanSize
  437. *
  438. * Arguments:
  439. *
  440. * pbmi
  441. * nScans
  442. *
  443. * Return Value:
  444. *
  445. * Image size based on number of scans
  446. *
  447. * History:
  448. *
  449. * 11-Jul-1996 -by- Mark Enstrom [marke]
  450. *
  451. \**************************************************************************/
  452. ULONG cjBitmapScanSize(
  453. CONST BITMAPINFO *pbmi,
  454. int nScans
  455. )
  456. {
  457. // Check for PM-style DIB
  458. if (pbmi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
  459. {
  460. LPBITMAPCOREINFO pbmci;
  461. pbmci = (LPBITMAPCOREINFO)pbmi;
  462. return(CJSCAN(pbmci->bmciHeader.bcWidth,pbmci->bmciHeader.bcPlanes,
  463. pbmci->bmciHeader.bcBitCount) * nScans);
  464. }
  465. // not a core header
  466. if ((pbmi->bmiHeader.biCompression == BI_RGB) ||
  467. (pbmi->bmiHeader.biCompression == BI_BITFIELDS) ||
  468. (pbmi->bmiHeader.biCompression == BI_CMYK))
  469. {
  470. return(CJSCAN(pbmi->bmiHeader.biWidth,pbmi->bmiHeader.biPlanes,
  471. pbmi->bmiHeader.biBitCount) * nScans);
  472. }
  473. else
  474. {
  475. return(pbmi->bmiHeader.biSizeImage);
  476. }
  477. }
  478. /******************************Public*Routine******************************\
  479. * CopyCoreToInfoHeader
  480. *
  481. \**************************************************************************/
  482. VOID CopyCoreToInfoHeader(LPBITMAPINFOHEADER pbmih, LPBITMAPCOREHEADER pbmch)
  483. {
  484. pbmih->biSize = sizeof(BITMAPINFOHEADER);
  485. pbmih->biWidth = pbmch->bcWidth;
  486. pbmih->biHeight = pbmch->bcHeight;
  487. pbmih->biPlanes = pbmch->bcPlanes;
  488. pbmih->biBitCount = pbmch->bcBitCount;
  489. pbmih->biCompression = BI_RGB;
  490. pbmih->biSizeImage = 0;
  491. pbmih->biXPelsPerMeter = 0;
  492. pbmih->biYPelsPerMeter = 0;
  493. pbmih->biClrUsed = 0;
  494. pbmih->biClrImportant = 0;
  495. }
  496. /******************************Public*Routine******************************\
  497. * DWORD SetDIBitsToDevice *
  498. * *
  499. * Can reduce it to 1 scan at a time. If compressed mode, this could *
  500. * gete very difficult. There must be enough space for the header and *
  501. * color table. This will be needed for every batch. *
  502. * *
  503. * BITMAPINFO *
  504. * BITMAPINFOHEADER *
  505. * RGBQUAD[cEntries] | RGBTRIPLE[cEntries] *
  506. * *
  507. * *
  508. * 1. compute header size (including color table) *
  509. * 2. compute size of required bits *
  510. * 3. compute total size (header + bits + args) *
  511. * 4. if (memory window is large enough for header + at least 1 scan *
  512. * *
  513. * History: *
  514. * Tue 29-Oct-1991 -by- Patrick Haluptzok [patrickh] *
  515. * Add shared memory action for large RLE's. *
  516. * *
  517. * Tue 19-Oct-1991 -by- Patrick Haluptzok [patrickh] *
  518. * Add support for RLE's *
  519. * *
  520. * Thu 20-Jun-1991 01:41:45 -by- Charles Whitmer [chuckwh] *
  521. * Added handle translation and metafiling. *
  522. * *
  523. * 14-May-1991 -by- Eric Kutter [erick] *
  524. * Wrote it. *
  525. \**************************************************************************/
  526. int SetDIBitsToDevice(
  527. HDC hdc,
  528. int xDest,
  529. int yDest,
  530. DWORD nWidth,
  531. DWORD nHeight,
  532. int xSrc,
  533. int ySrc,
  534. UINT nStartScan,
  535. UINT nNumScans,
  536. CONST VOID * pBits,
  537. CONST BITMAPINFO *pbmi,
  538. UINT iUsage) // DIB_PAL_COLORS || DIB_RGB_COLORS
  539. {
  540. LONG cScansCopied = 0; // total # of scans copied
  541. LONG ySrcMax; // maximum ySrc possible
  542. // hold info about the header
  543. UINT uiWidth;
  544. UINT uiHeight;
  545. PULONG pulBits = NULL;
  546. INT cjHeader = 0;
  547. LPBITMAPINFO pbmiNew = NULL;
  548. ULONG cjBits;
  549. // ICM related variables
  550. PCACHED_COLORSPACE pBitmapColorSpace = NULL;
  551. PCACHED_COLORTRANSFORM pCXform = NULL;
  552. HANDLE hcmTempXform = NULL;
  553. FIXUP_HANDLE(hdc);
  554. // Let's validate the parameters so we don't gp-fault ourselves and
  555. // to save checks later on.
  556. if ((nNumScans == 0) ||
  557. (pbmi == (LPBITMAPINFO) NULL) ||
  558. (pBits == (LPVOID) NULL) ||
  559. ((iUsage != DIB_RGB_COLORS) &&
  560. (iUsage != DIB_PAL_COLORS) &&
  561. (iUsage != DIB_PAL_INDICES)))
  562. {
  563. WARNING("You failed a param validation in SetDIBitsToDevice\n");
  564. return(0);
  565. }
  566. pbmiNew = pbmiConvertInfo(pbmi,iUsage,&cjHeader,FALSE);
  567. if (pbmiNew == NULL)
  568. return (0);
  569. uiWidth = (UINT) pbmiNew->bmiHeader.biWidth;
  570. uiHeight = (UINT) pbmiNew->bmiHeader.biHeight;
  571. // Compute the minimum nNumScans to send across csr interface.
  572. // It will also prevent faults as a result of overreading the source.
  573. ySrcMax = max(ySrc, ySrc + (int) nHeight);
  574. if (ySrcMax <= 0)
  575. return(0);
  576. ySrcMax = min(ySrcMax, (int) uiHeight);
  577. nNumScans = min(nNumScans, (UINT) ySrcMax - nStartScan);
  578. // NEWFRAME support for backward compatibility.
  579. // Ship the transform to the server side if needed.
  580. if (IS_ALTDC_TYPE(hdc))
  581. {
  582. PLDC pldc;
  583. if (IS_METADC16_TYPE(hdc))
  584. {
  585. cScansCopied = MF_AnyDIBits(
  586. hdc,
  587. xDest,yDest,0,0,
  588. xSrc,ySrc,(int) nWidth,(int) nHeight,
  589. nStartScan,nNumScans,
  590. pBits,pbmi,
  591. iUsage,
  592. SRCCOPY,
  593. META_SETDIBTODEV
  594. );
  595. goto Exit;
  596. }
  597. DC_PLDC(hdc,pldc,0);
  598. if (pldc->iType == LO_METADC)
  599. {
  600. if (!MF_AnyDIBits(
  601. hdc,
  602. xDest,yDest,0,0,
  603. xSrc,ySrc,(int) nWidth,(int) nHeight,
  604. nStartScan,nNumScans,
  605. pBits,pbmi,
  606. iUsage,
  607. SRCCOPY,
  608. EMR_SETDIBITSTODEVICE
  609. ))
  610. {
  611. cScansCopied = 0;
  612. goto Exit;
  613. }
  614. }
  615. if (pldc->fl & LDC_CALL_STARTPAGE)
  616. StartPage(hdc);
  617. if (pldc->fl & LDC_SAP_CALLBACK)
  618. vSAPCallback(pldc);
  619. if (pldc->fl & LDC_DOC_CANCELLED)
  620. {
  621. cScansCopied = 0;
  622. goto Exit;
  623. }
  624. }
  625. // reset user's poll count so it counts this as output
  626. // put it right next to BEGINMSG so that NtCurrentTeb() is optimized
  627. RESETUSERPOLLCOUNT();
  628. //
  629. // Calculate bitmap bits size based on BITMAPINFO and nNumScans
  630. //
  631. cjBits = cjBitmapScanSize(pbmi,nNumScans);
  632. //
  633. // If the pBits are not dword aligned we need to allocate a buffer and
  634. // copy them (that's because we always guarantee display and printer
  635. // drivers that bitmaps are dword aligned):
  636. //
  637. cScansCopied = 1;
  638. if ((ULONG_PTR)pBits & (sizeof(DWORD) - 1))
  639. {
  640. pulBits = LOCALALLOC(cjBits);
  641. if (pulBits)
  642. {
  643. //
  644. // We used to simply access violate here if we had been given
  645. // a corrupt DIB bitmap. This was bad because WinLogon is
  646. // responsible for showing the original background bitmap, and
  647. // if that bitmap is corrupt, and we access violate, we'll
  648. // cause the system to blue-screen:
  649. //
  650. try
  651. {
  652. RtlCopyMemory(pulBits,pBits,cjBits);
  653. pBits = pulBits;
  654. }
  655. except(EXCEPTION_EXECUTE_HANDLER)
  656. {
  657. WARNING("SetDIBitsToDevice: Corrupt bitmap\n");
  658. cScansCopied = 0;
  659. }
  660. }
  661. }
  662. if (cScansCopied)
  663. {
  664. PDC_ATTR pdcattr;
  665. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  666. if (pdcattr)
  667. {
  668. //
  669. // ICM translation of BITMAP bits or color table
  670. //
  671. // At this moment, ensured that pBits and pbmiNew is not NULL.
  672. // (see above parameter validate check and NULL check !)
  673. //
  674. if (
  675. IS_ICM_INSIDEDC(pdcattr->lIcmMode) &&
  676. (iUsage != DIB_PAL_COLORS) &&
  677. !IS_BMI_PASSTHROUGH_IMAGE(pbmiNew))
  678. {
  679. LPBITMAPINFO pbmiIcm = NULL;
  680. PVOID pvBitsIcm = NULL;
  681. ULONG cjHeaderNew = 0;
  682. BOOL bIcmStatus;
  683. VOID *pBitsBand = (VOID *)pBits;
  684. ULONG CurrentBandSize;
  685. ULONG SizeOfOneScanline;
  686. ULONG nBands;
  687. ULONG nScansInBand;
  688. ULONG nScansInCurrentBand;
  689. ULONG nScansInRemainderBand;
  690. ULONG CumulativeScans=0;
  691. ULONG i;
  692. LONG PositiveBandDelta=0;
  693. LONG NegativeBandDelta=0;
  694. LONG TotalBandDelta=0;
  695. LONG IcmSizeOfOneScanline;
  696. INT iRet;
  697. LONG HeaderHeightHack;
  698. SizeOfOneScanline = cjBitmapScanSize(pbmi, 1);
  699. //
  700. //pbmiNew must be initialized before getting to this point.
  701. //
  702. ASSERTGDI(pbmiNew!=NULL, "SetDIBitsToDevice cannot proceed with pbmiNew==NULL\n");
  703. nScansInBand = BAND_SIZE/SizeOfOneScanline;
  704. //
  705. // Set the number of bands provided there are enough scanlines
  706. // and the hdc is a printer dc.
  707. //
  708. // Else set the nubmer of bands to 1 and the scanlines in the
  709. // remainder band to all of them, so the entire bitmap is printed
  710. // in one band (All the code below reduces to doing a single piece)
  711. //
  712. // If the bitmap is RLE compressed, we set it up to do one band
  713. // only. When this is the case, Start and NegativeBandDelta will be
  714. // computed as 0 and the SizeOfOneScanline parameter will be
  715. // multiplied away to zero.
  716. //
  717. if ((nScansInBand>0)&&
  718. (GetDeviceCaps(hdc, TECHNOLOGY)==DT_RASPRINTER)&&
  719. (!IS_BMI_RLE(pbmiNew)))
  720. {
  721. //
  722. // Compressed images cannot be converted in this way.
  723. // This should never be hit and is included as a guard against
  724. // someone inventing a new compression mode and not updating
  725. // this conditional.
  726. //
  727. ASSERTGDI(SizeOfOneScanline*nNumScans==cjBits, "SetDIBitsToDevice, cannot band compressed image");
  728. nBands = (nNumScans)/nScansInBand;
  729. nScansInRemainderBand = nNumScans % nScansInBand;
  730. }
  731. else
  732. {
  733. nBands = 0;
  734. nScansInRemainderBand = (nNumScans);
  735. }
  736. if (nScansInRemainderBand>0)
  737. {
  738. nBands++;
  739. nScansInCurrentBand = nScansInRemainderBand;
  740. }
  741. else
  742. {
  743. nScansInCurrentBand = nScansInBand;
  744. }
  745. cScansCopied = 0;
  746. HeaderHeightHack = pbmiNew->bmiHeader.biHeight;
  747. for (i=0; i<nBands; i++)
  748. {
  749. CurrentBandSize = nScansInCurrentBand*SizeOfOneScanline;
  750. IcmSizeOfOneScanline = SizeOfOneScanline;
  751. //
  752. // The Delta refers to the number of extra scanlines to pass
  753. // to the internal blting routines in order to avoid halftone
  754. // seams.
  755. //
  756. // PositiveBandDelta is the number of scanlines to
  757. // add on to the end of the band. (relative to the start in
  758. // memory)
  759. //
  760. // NegativeBandDelta is the number of scanlines to
  761. // subtract from the begining of the band (ie move the start
  762. // pointer back this many scanlines).
  763. //
  764. // Total BandDelta is simply the total number of extra scans
  765. // added for this band (both at the start and end).
  766. //
  767. PositiveBandDelta = MIN(EXTRAPIXEL, CumulativeScans);
  768. NegativeBandDelta = MIN(EXTRAPIXEL, nNumScans-(CumulativeScans+nScansInCurrentBand));
  769. TotalBandDelta = NegativeBandDelta+PositiveBandDelta;
  770. if (nBands!=1)
  771. {
  772. SaveDC(hdc);
  773. //
  774. // Intersect the clip rectangles.
  775. // This clip rectangle is designed to restrict the output to
  776. // just the displayed portion of the band.
  777. // We may pass more scanlines on the top and bottom of the band
  778. // to get halftoning to merge seamlessly.
  779. //
  780. iRet = IntersectClipRect(
  781. hdc,
  782. xDest,
  783. nNumScans - (nStartScan+CumulativeScans+nScansInCurrentBand),
  784. xDest+nWidth,
  785. nNumScans - (nStartScan+CumulativeScans));
  786. if (iRet==ERROR)
  787. {
  788. WARNING("SetDIBitsToDevice: error intersecting clip rect\n");
  789. RestoreDC(hdc, -1);
  790. goto Exit;
  791. }
  792. //
  793. // Empty clip rectangle
  794. // If the clip regions don't intersect, we can quit without
  795. // doing anything.
  796. //
  797. if (iRet==NULLREGION)
  798. {
  799. RestoreDC(hdc, -1);
  800. //
  801. // Nothing to do - fall through and do
  802. // initialization for next iteration.
  803. //
  804. goto Continue_With_Init;
  805. }
  806. }
  807. if (HeaderHeightHack >= 0)
  808. {
  809. //
  810. //Bottom Up
  811. //
  812. pBitsBand = (char *)pBits + (CumulativeScans-PositiveBandDelta)*SizeOfOneScanline;
  813. }
  814. else
  815. {
  816. //
  817. //TopDown
  818. //
  819. pBitsBand = (char *)pBits + (nNumScans-nScansInCurrentBand-CumulativeScans-NegativeBandDelta)*SizeOfOneScanline;
  820. }
  821. cjHeaderNew=0;
  822. pbmiIcm=NULL;
  823. pvBitsIcm = NULL;
  824. //
  825. // Call ICM with an oversized band for later halftoning by
  826. // NtGdiSetDIBitsInternal
  827. //
  828. bIcmStatus = IcmTranslateDIB(
  829. hdc,
  830. pdcattr,
  831. CurrentBandSize+TotalBandDelta*SizeOfOneScanline,
  832. (PVOID)pBitsBand,
  833. &pvBitsIcm,
  834. pbmiNew,
  835. &pbmiIcm,
  836. &cjHeaderNew,
  837. nScansInCurrentBand+TotalBandDelta,
  838. iUsage,
  839. ICM_FORWARD,
  840. &pBitmapColorSpace,
  841. &pCXform);
  842. if (bIcmStatus)
  843. {
  844. if (pvBitsIcm == NULL)
  845. {
  846. pvBitsIcm = pBitsBand;
  847. }
  848. if (pbmiIcm == NULL)
  849. {
  850. pbmiIcm = pbmiNew;
  851. cjHeaderNew = cjHeader;
  852. }
  853. else
  854. {
  855. CurrentBandSize = cjBitmapScanSize(pbmiIcm, nScansInCurrentBand);
  856. IcmSizeOfOneScanline = cjBitmapScanSize(pbmiIcm, 1);
  857. if (!cjHeaderNew)
  858. {
  859. cjHeaderNew = cjHeader;
  860. }
  861. }
  862. if (pCXform)
  863. {
  864. hcmTempXform = pCXform->ColorTransform;
  865. }
  866. }
  867. else
  868. {
  869. pvBitsIcm = pBitsBand;
  870. pbmiIcm = pbmiNew;
  871. cjHeaderNew = cjHeader;
  872. }
  873. cScansCopied += NtGdiSetDIBitsToDeviceInternal(
  874. hdc,
  875. xDest,
  876. yDest,
  877. nWidth,
  878. nHeight,
  879. xSrc,
  880. ySrc,
  881. nStartScan+CumulativeScans-PositiveBandDelta,
  882. nScansInCurrentBand+TotalBandDelta,
  883. (LPBYTE)pvBitsIcm,
  884. pbmiIcm,
  885. iUsage,
  886. (UINT)CurrentBandSize+TotalBandDelta*IcmSizeOfOneScanline,
  887. (UINT)cjHeaderNew,
  888. TRUE,
  889. hcmTempXform);
  890. cScansCopied -= TotalBandDelta;
  891. if (pBitmapColorSpace)
  892. {
  893. if (pCXform)
  894. {
  895. IcmDeleteColorTransform(pCXform,FALSE);
  896. }
  897. IcmReleaseColorSpace(NULL,pBitmapColorSpace,FALSE);
  898. }
  899. if ((pvBitsIcm!=NULL)&&(pvBitsIcm!=pBitsBand))
  900. {
  901. LOCALFREE(pvBitsIcm);
  902. pvBitsIcm = NULL;
  903. }
  904. if ((pbmiIcm!=NULL)&&(pbmiIcm!=pbmiNew))
  905. {
  906. LOCALFREE(pbmiIcm);
  907. pbmiIcm = NULL;
  908. }
  909. hcmTempXform = NULL;
  910. Continue_With_Init:
  911. CumulativeScans += nScansInCurrentBand;
  912. nScansInCurrentBand = nScansInBand;
  913. if (nBands != 1)
  914. {
  915. RestoreDC(hdc, -1);
  916. }
  917. }
  918. //
  919. // We do our own NtGdiSetDIBitsToDeviceInternal
  920. // So we need to fall through to cleanup at this point.
  921. //
  922. goto Exit;
  923. }
  924. }
  925. //
  926. // Do the non-ICM version of the SetDIB
  927. //
  928. cScansCopied = NtGdiSetDIBitsToDeviceInternal(
  929. hdc,
  930. xDest,
  931. yDest,
  932. nWidth,
  933. nHeight,
  934. xSrc,
  935. ySrc,
  936. nStartScan,
  937. nNumScans,
  938. (LPBYTE)pBits,
  939. pbmiNew,
  940. iUsage,
  941. (UINT)cjBits,
  942. (UINT)cjHeader,
  943. TRUE,
  944. hcmTempXform);
  945. }
  946. Exit:
  947. if (pulBits)
  948. {
  949. //
  950. // Free temporary buffer, this would be the buffer which allocated
  951. // to align, Or to do ICM.
  952. //
  953. LOCALFREE (pulBits);
  954. }
  955. if (pbmiNew && (pbmiNew != pbmi))
  956. {
  957. LOCALFREE (pbmiNew);
  958. }
  959. return (cScansCopied);
  960. }
  961. /******************************Public*Routine******************************\
  962. * DWORD GetDIBits
  963. *
  964. * Can reduce it to 1 scan at a time. There must be enough space
  965. * for the header and color table. This will be needed for every chunk
  966. *
  967. * History:
  968. * Wed 04-Dec-1991 -by- Patrick Haluptzok [patrickh]
  969. * bug fix, only check for valid DC if DIB_PAL_COLORS.
  970. *
  971. * Fri 22-Nov-1991 -by- Patrick Haluptzok [patrickh]
  972. * bug fix, copy the header into memory window for NULL bits.
  973. *
  974. * Tue 20-Aug-1991 -by- Patrick Haluptzok [patrickh]
  975. * bug fix, make iStart and cNum be in valid range.
  976. *
  977. * Thu 20-Jun-1991 01:44:41 -by- Charles Whitmer [chuckwh]
  978. * Added handle translation.
  979. *
  980. * 14-May-1991 -by- Eric Kutter [erick]
  981. * Wrote it.
  982. \**************************************************************************/
  983. int GetDIBits(
  984. HDC hdc,
  985. HBITMAP hbm,
  986. UINT nStartScan,
  987. UINT nNumScans,
  988. LPVOID pBits,
  989. LPBITMAPINFO pbmi,
  990. UINT iUsage) // DIB_PAL_COLORS || DIB_RGB_COLORS
  991. {
  992. PULONG pulBits = pBits;
  993. ULONG cjBits;
  994. int iRet = 0;
  995. PDC_ATTR pdcattr;
  996. FIXUP_HANDLE(hdc);
  997. FIXUP_HANDLE(hbm);
  998. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  999. if (pdcattr)
  1000. {
  1001. BOOL bNeedICM = TRUE;
  1002. cjBits = cjBitmapScanSize(pbmi,nNumScans);
  1003. //
  1004. // If pbmi is a input buffer specifying image format
  1005. // (i.e., pBits != NULL), then fail for passthrough
  1006. // images (BI_JPEG and BI_PNG)
  1007. //
  1008. if (pBits && IS_BMI_PASSTHROUGH_IMAGE(pbmi))
  1009. {
  1010. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1011. return 0;
  1012. }
  1013. if (pbmi->bmiHeader.biBitCount == 0)
  1014. {
  1015. //
  1016. // no color table required.
  1017. //
  1018. bNeedICM = FALSE;
  1019. }
  1020. //
  1021. // if the pBits are not dword aligned, we need to allocate
  1022. // a buffer and copy them
  1023. //
  1024. if ((ULONG_PTR)pBits & (sizeof(DWORD) - 1))
  1025. {
  1026. pulBits = LOCALALLOC(cjBits);
  1027. if (pulBits == NULL)
  1028. return(0);
  1029. }
  1030. iRet = NtGdiGetDIBitsInternal(
  1031. hdc,
  1032. hbm,
  1033. nStartScan,
  1034. nNumScans,
  1035. (LPVOID)pulBits,
  1036. pbmi,
  1037. iUsage,
  1038. cjBits,
  1039. 0);
  1040. //
  1041. // translate DIB if needed
  1042. //
  1043. if (bNeedICM &&
  1044. (IS_ICM_HOST(pdcattr->lIcmMode)) && (iUsage != DIB_PAL_COLORS))
  1045. {
  1046. //
  1047. // UNDER_CONSTRUCTION: Failed on GetDIBits() from CMYK surface.
  1048. //
  1049. if (IS_CMYK_COLOR(pdcattr->lIcmMode))
  1050. {
  1051. WARNING("GetDIBits(): was called on CMYK bitmap\n");
  1052. iRet = 0;
  1053. }
  1054. else
  1055. {
  1056. //
  1057. // Do backward transform.
  1058. //
  1059. if (!IcmTranslateDIB(hdc,
  1060. pdcattr,
  1061. cjBits,
  1062. pulBits,
  1063. NULL, // Indicates overwrite original...
  1064. pbmi,
  1065. NULL, // Indicates overwrite original...
  1066. NULL,
  1067. nNumScans,
  1068. iUsage,
  1069. ICM_BACKWARD,
  1070. NULL,NULL))
  1071. {
  1072. //
  1073. // ICM translation failed.
  1074. //
  1075. iRet = 0;
  1076. }
  1077. }
  1078. }
  1079. if (pulBits != pBits)
  1080. {
  1081. if (iRet)
  1082. {
  1083. RtlCopyMemory(pBits,pulBits,cjBits);
  1084. }
  1085. LOCALFREE(pulBits);
  1086. }
  1087. }
  1088. else
  1089. {
  1090. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1091. }
  1092. return(iRet);
  1093. }
  1094. /******************************Public*Routine******************************\
  1095. * CreateDIBitmap
  1096. *
  1097. * History:
  1098. * Mon 25-Jan-1993 -by- Patrick Haluptzok [patrickh]
  1099. * Add CBM_CREATEDIB support.
  1100. *
  1101. * Thu 20-Jun-1991 02:14:59 -by- Charles Whitmer [chuckwh]
  1102. * Added local handle support.
  1103. *
  1104. * 23-May-1991 -by- Eric Kutter [erick]
  1105. * Wrote it.
  1106. \**************************************************************************/
  1107. HBITMAP
  1108. CreateDIBitmap(
  1109. HDC hdc,
  1110. CONST BITMAPINFOHEADER *pbmih,
  1111. DWORD flInit,
  1112. CONST VOID *pjBits,
  1113. CONST BITMAPINFO *pbmi,
  1114. UINT iUsage)
  1115. {
  1116. LONG cjBMI = 0;
  1117. LONG cjBits = 0;
  1118. INT cx = 0;
  1119. INT cy = 0;
  1120. PULONG pulBits = NULL;
  1121. HBITMAP hRet = (HBITMAP)-1;
  1122. LPBITMAPINFO pbmiNew = NULL;
  1123. PDC_ATTR pdcattr;
  1124. // ICM related variables.
  1125. PCACHED_COLORSPACE pBitmapColorSpace = NULL;
  1126. PCACHED_COLORTRANSFORM pCXform = NULL;
  1127. HANDLE hcmTempXform = NULL;
  1128. FIXUP_HANDLEZ(hdc);
  1129. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  1130. pbmiNew = pbmiConvertInfo(pbmi,iUsage,&cjBMI,FALSE);
  1131. if (flInit & CBM_CREATEDIB)
  1132. {
  1133. // With CBM_CREATEDIB we ignore pbmih
  1134. pbmih = (LPBITMAPINFOHEADER) pbmi;
  1135. if (cjBMI == 0)
  1136. {
  1137. hRet = 0;
  1138. }
  1139. else if (flInit & CBM_INIT)
  1140. {
  1141. if (pjBits == NULL)
  1142. {
  1143. // doesn't make sence if they asked to initialize it but
  1144. // didn't pass the bits.
  1145. hRet = 0;
  1146. }
  1147. else
  1148. {
  1149. cjBits = cjBitmapBitsSize(pbmiNew);
  1150. }
  1151. }
  1152. else
  1153. {
  1154. pjBits = NULL;
  1155. }
  1156. }
  1157. else
  1158. {
  1159. // compute the size of the optional init bits and BITMAPINFO
  1160. if (flInit & CBM_INIT)
  1161. {
  1162. if (pjBits == NULL)
  1163. {
  1164. // doesn't make sence if they asked to initialize it but
  1165. // didn't pass the bits.
  1166. flInit &= ~CBM_INIT;
  1167. }
  1168. else
  1169. {
  1170. if (cjBMI == 0)
  1171. {
  1172. hRet = 0;
  1173. }
  1174. else
  1175. {
  1176. // compute the size of the bits
  1177. cjBits = cjBitmapBitsSize(pbmiNew);
  1178. }
  1179. }
  1180. }
  1181. else
  1182. {
  1183. pjBits = NULL;
  1184. }
  1185. }
  1186. // CreateDIBitmap cannot handle passthrough image (BI_JPEG or BI_PNG)
  1187. // init data
  1188. if (IS_BMI_PASSTHROUGH_IMAGE(pbmiNew))
  1189. {
  1190. hRet = 0;
  1191. }
  1192. // if they passed us a zero height or zero width
  1193. // bitmap then return a pointer to the stock bitmap
  1194. if (pbmih)
  1195. {
  1196. if (pbmih->biSize >= sizeof(BITMAPINFOHEADER))
  1197. {
  1198. cx = pbmih->biWidth;
  1199. cy = pbmih->biHeight;
  1200. }
  1201. else
  1202. {
  1203. cx = ((LPBITMAPCOREHEADER) pbmih)->bcWidth;
  1204. cy = ((LPBITMAPCOREHEADER) pbmih)->bcHeight;
  1205. }
  1206. if ((cx == 0) || (cy == 0))
  1207. {
  1208. hRet = GetStockObject(PRIV_STOCK_BITMAP);
  1209. }
  1210. }
  1211. // if hRet is still -1, then all is OK and we need to try to the bitmap
  1212. if (hRet == (HBITMAP)-1)
  1213. {
  1214. BOOL bStatus = TRUE;
  1215. // if the pJBits are not dword aligned we need to allocate a buffer and copy them
  1216. if ((ULONG_PTR)pjBits & (sizeof(DWORD) - 1))
  1217. {
  1218. pulBits = LOCALALLOC(cjBits);
  1219. if (pulBits)
  1220. {
  1221. RtlCopyMemory(pulBits,pjBits,cjBits);
  1222. pjBits = pulBits;
  1223. }
  1224. }
  1225. // ICM conversion
  1226. //
  1227. // Convert bitmap data only when ...
  1228. //
  1229. // - HDC is not NULL.
  1230. // - ICM is enanled.
  1231. // - ICM is not lazy mode.
  1232. // - Initialize data is not Palette Index.
  1233. // - Initialize data is provided.
  1234. if (pdcattr &&
  1235. IS_ICM_INSIDEDC(pdcattr->lIcmMode) &&
  1236. (IS_ICM_LAZY_CORRECTION(pdcattr->lIcmMode) == FALSE) &&
  1237. (iUsage != DIB_PAL_COLORS) &&
  1238. pjBits && pbmiNew)
  1239. {
  1240. PVOID pvBitsIcm = NULL;
  1241. PBITMAPINFO pbmiIcm = NULL;
  1242. ULONG cjBMINew = 0;
  1243. BOOL bIcmStatus;
  1244. bIcmStatus = IcmTranslateDIB(hdc,
  1245. pdcattr,
  1246. cjBits,
  1247. (PVOID)pjBits,
  1248. &pvBitsIcm,
  1249. pbmiNew,
  1250. &pbmiIcm,
  1251. &cjBMINew,
  1252. (DWORD)-1,
  1253. iUsage,
  1254. ICM_FORWARD,
  1255. &pBitmapColorSpace,
  1256. &pCXform);
  1257. //
  1258. // IcmTranslateDIB will create a duplicate dib
  1259. // pointed to by pulBits if needed.
  1260. //
  1261. if (bIcmStatus)
  1262. {
  1263. if (pvBitsIcm != NULL)
  1264. {
  1265. ICMMSG(("CreateDIBitmap(): Temp bits are allocated\n"));
  1266. if (pulBits)
  1267. {
  1268. LOCALFREE(pulBits);
  1269. }
  1270. pjBits = (PVOID)pulBits = pvBitsIcm;
  1271. }
  1272. if (pbmiIcm != NULL)
  1273. {
  1274. ICMMSG(("CreateDIBitmap(): Temp bmi are allocated\n"));
  1275. if (pbmiNew && (pbmiNew != pbmi))
  1276. {
  1277. LOCALFREE(pbmiNew);
  1278. }
  1279. pbmiNew = pbmiIcm;
  1280. //
  1281. // Calculate bitmap bits size based on BITMAPINFO and nNumScans
  1282. //
  1283. cjBits = cjBitmapBitsSize(pbmiNew);
  1284. //
  1285. // Update sizeof bitmap info (including color table)
  1286. //
  1287. if (cjBMINew)
  1288. {
  1289. cjBMI = cjBMINew;
  1290. }
  1291. }
  1292. //
  1293. // Get color transform handle need to pass kernel
  1294. //
  1295. if (pCXform)
  1296. {
  1297. hcmTempXform = pCXform->ColorTransform;
  1298. }
  1299. }
  1300. }
  1301. if (bStatus)
  1302. {
  1303. hRet = NtGdiCreateDIBitmapInternal(hdc,
  1304. cx,
  1305. cy,
  1306. flInit,
  1307. (LPBYTE) pjBits,
  1308. (LPBITMAPINFO) pbmiNew,
  1309. iUsage,
  1310. cjBMI,
  1311. cjBits,
  1312. 0,
  1313. hcmTempXform);
  1314. #if TRACE_SURFACE_ALLOCS
  1315. {
  1316. PULONGLONG pUserAlloc;
  1317. PSHARED_GET_VALIDATE(pUserAlloc, hRet, SURF_TYPE);
  1318. if (pUserAlloc != NULL)
  1319. {
  1320. RtlWalkFrameChain((PVOID *)&pUserAlloc[1], (ULONG)*pUserAlloc, 0);
  1321. }
  1322. }
  1323. #endif
  1324. }
  1325. if (pBitmapColorSpace)
  1326. {
  1327. if (pCXform)
  1328. {
  1329. IcmDeleteColorTransform(pCXform,FALSE);
  1330. }
  1331. IcmReleaseColorSpace(NULL,pBitmapColorSpace,FALSE);
  1332. }
  1333. if (pulBits)
  1334. {
  1335. LOCALFREE(pulBits);
  1336. }
  1337. }
  1338. if (pbmiNew && (pbmiNew != pbmi))
  1339. {
  1340. LOCALFREE(pbmiNew);
  1341. }
  1342. return(hRet);
  1343. }
  1344. /******************************Public*Routine******************************\
  1345. * Set/GetBitmapBits *
  1346. * *
  1347. * History: *
  1348. * 05-Jun-1991 -by- Eric Kutter [erick] *
  1349. * Wrote it. *
  1350. \**************************************************************************/
  1351. LONG WINAPI SetBitmapBits(
  1352. HBITMAP hbm,
  1353. DWORD c,
  1354. CONST VOID *pv)
  1355. {
  1356. LONG lRet;
  1357. FIXUP_HANDLE(hbm);
  1358. lRet = (LONG)NtGdiSetBitmapBits(hbm,c,(PBYTE)pv);
  1359. return(lRet);
  1360. }
  1361. LONG WINAPI GetBitmapBits(
  1362. HBITMAP hbm,
  1363. LONG c,
  1364. LPVOID pv)
  1365. {
  1366. LONG lRet;
  1367. FIXUP_HANDLE(hbm);
  1368. lRet = (LONG)NtGdiGetBitmapBits(hbm,c,(PBYTE)pv);
  1369. return(lRet);
  1370. }
  1371. /******************************Public*Routine******************************\
  1372. * GdiGetPaletteFromDC
  1373. *
  1374. * Returns the palette for the DC, 0 for error.
  1375. *
  1376. * History:
  1377. * 04-Oct-1991 -by- Patrick Haluptzok patrickh
  1378. * Wrote it.
  1379. \**************************************************************************/
  1380. HANDLE GdiGetPaletteFromDC(HDC h)
  1381. {
  1382. return((HANDLE)GetDCObject(h,LO_PALETTE_TYPE));
  1383. }
  1384. /******************************Public*Routine******************************\
  1385. * GdiGetDCforBitmap
  1386. *
  1387. * Returns the DC a bitmap is selected into, 0 if none or if error occurs.
  1388. *
  1389. * History:
  1390. * 22-Sep-1991 -by- Patrick Haluptzok patrickh
  1391. * Wrote it.
  1392. \**************************************************************************/
  1393. HDC GdiGetDCforBitmap(HBITMAP hbm)
  1394. {
  1395. FIXUP_HANDLE(hbm);
  1396. return (NtGdiGetDCforBitmap(hbm));
  1397. }
  1398. /******************************Public*Routine******************************\
  1399. * SetDIBits
  1400. *
  1401. * API to initialize bitmap with DIB
  1402. *
  1403. * History:
  1404. * Sun 22-Sep-1991 -by- Patrick Haluptzok [patrickh]
  1405. * Make it work even if it is selected into a DC, Win3.0 compatibility.
  1406. *
  1407. * 06-Jun-1991 -by- Patrick Haluptzok patrickh
  1408. * Wrote it.
  1409. \**************************************************************************/
  1410. int WINAPI SetDIBits(
  1411. HDC hdc,
  1412. HBITMAP hbm,
  1413. UINT iStartScans,
  1414. UINT cNumScans,
  1415. CONST VOID *pInitBits,
  1416. CONST BITMAPINFO *pInitInfo,
  1417. UINT iUsage)
  1418. {
  1419. HDC hdcTemp;
  1420. HBITMAP hbmTemp;
  1421. int iReturn = 0;
  1422. BOOL bMakeDC = FALSE;
  1423. HPALETTE hpalTemp;
  1424. DWORD cWidth;
  1425. DWORD cHeight;
  1426. FIXUP_HANDLE(hdc);
  1427. FIXUP_HANDLE(hbm);
  1428. // if no bits or hbm is not a bitmap, fail
  1429. if ((pInitBits == (PVOID) NULL) ||
  1430. (GRE_TYPE(hbm) != SURF_TYPE))
  1431. {
  1432. return(0);
  1433. }
  1434. // if passthrough image (BI_JPEG or BI_JPEG), fail
  1435. if (IS_BMI_PASSTHROUGH_IMAGE(pInitInfo))
  1436. {
  1437. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1438. return(0);
  1439. }
  1440. // First we need a DC to select this bitmap into. If he is already in a
  1441. // DC we just use that DC temporarily to blt to (we still have to select
  1442. // it in and out because someone might do a SaveDC and select another
  1443. // bitmap in). If he hasn't been stuck in a DC anywhere we just create
  1444. // one temporarily.
  1445. hdcTemp = GdiGetDCforBitmap(hbm);
  1446. if (hdcTemp == (HDC) 0)
  1447. {
  1448. hdcTemp = CreateCompatibleDC(hdc);
  1449. bMakeDC = TRUE;
  1450. if (hdcTemp == (HDC) NULL)
  1451. {
  1452. WARNING("SetDIBits failed CreateCompatibleDC, is hdc valid?\n");
  1453. return(0);
  1454. }
  1455. }
  1456. else
  1457. {
  1458. if (SaveDC(hdcTemp) == 0)
  1459. return(0);
  1460. }
  1461. hbmTemp = SelectObject(hdcTemp, hbm);
  1462. if (hbmTemp == (HBITMAP) 0)
  1463. {
  1464. //WARNING("ERROR SetDIBits failed to Select, is bitmap valid?\n");
  1465. goto Error_SetDIBits;
  1466. }
  1467. if (hdc != (HDC) 0)
  1468. {
  1469. hpalTemp = SelectPalette(hdcTemp, GdiGetPaletteFromDC(hdc), 0);
  1470. }
  1471. if (pInitInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
  1472. {
  1473. cWidth = ((LPBITMAPCOREHEADER)pInitInfo)->bcWidth;
  1474. cHeight = ((LPBITMAPCOREHEADER)pInitInfo)->bcHeight;
  1475. }
  1476. else
  1477. {
  1478. cWidth = pInitInfo->bmiHeader.biWidth;
  1479. cHeight = ABS(pInitInfo->bmiHeader.biHeight);
  1480. }
  1481. iReturn = SetDIBitsToDevice(hdcTemp,
  1482. 0,
  1483. 0,
  1484. cWidth,
  1485. cHeight,
  1486. 0, 0,
  1487. iStartScans,
  1488. cNumScans,
  1489. (VOID *) pInitBits,
  1490. pInitInfo,
  1491. iUsage);
  1492. if (hdc != (HDC) 0)
  1493. {
  1494. SelectPalette(hdcTemp, hpalTemp, 0);
  1495. }
  1496. SelectObject(hdcTemp, hbmTemp);
  1497. Error_SetDIBits:
  1498. if (bMakeDC)
  1499. {
  1500. DeleteDC(hdcTemp);
  1501. }
  1502. else
  1503. {
  1504. RestoreDC(hdcTemp, -1);
  1505. }
  1506. return(iReturn);
  1507. }
  1508. /******************************Public*Routine******************************\
  1509. * StretchDIBits()
  1510. *
  1511. *
  1512. * Effects:
  1513. *
  1514. * Warnings:
  1515. *
  1516. * History:
  1517. * 22-Jul-1991 -by- Eric Kutter [erick]
  1518. * Wrote it.
  1519. \**************************************************************************/
  1520. int WINAPI StretchDIBits(
  1521. HDC hdc,
  1522. int xDest,
  1523. int yDest,
  1524. int nDestWidth,
  1525. int nDestHeight,
  1526. int xSrc,
  1527. int ySrc,
  1528. int nSrcWidth,
  1529. int nSrcHeight,
  1530. CONST VOID *pj,
  1531. CONST BITMAPINFO *pbmi,
  1532. UINT iUsage,
  1533. DWORD lRop)
  1534. {
  1535. LONG cPoints = 0;
  1536. LONG cjHeader;
  1537. LONG cjBits;
  1538. ULONG ulResult = 0;
  1539. PULONG pulBits = NULL;
  1540. int iRet = 0;
  1541. BITMAPINFO * pbmiNew = NULL;
  1542. PDC_ATTR pdcattr;
  1543. BOOL bStatus = TRUE;
  1544. // ICM related variables.
  1545. PCACHED_COLORSPACE pBitmapColorSpace = NULL;
  1546. PCACHED_COLORTRANSFORM pCXform = NULL;
  1547. HANDLE hcmTempXform = NULL;
  1548. FIXUP_HANDLE(hdc);
  1549. // NEWFRAME support for backward compatibility.
  1550. // Ship the transform to the server side if needed.
  1551. if (IS_ALTDC_TYPE(hdc))
  1552. {
  1553. PLDC pldc;
  1554. if (IS_METADC16_TYPE(hdc))
  1555. {
  1556. return (MF_AnyDIBits(
  1557. hdc,
  1558. xDest,
  1559. yDest,
  1560. nDestWidth,
  1561. nDestHeight,
  1562. xSrc,
  1563. ySrc,
  1564. nSrcWidth,
  1565. nSrcHeight,
  1566. 0,
  1567. 0,
  1568. (BYTE *) pj,
  1569. pbmi,
  1570. iUsage,
  1571. lRop,
  1572. META_STRETCHDIB
  1573. ));
  1574. }
  1575. DC_PLDC(hdc,pldc,ulResult);
  1576. if (pldc->iType == LO_METADC)
  1577. {
  1578. //
  1579. // speeds up cases when partial sources bits are sent
  1580. //
  1581. int iStart = 0;
  1582. int iEnd = 0;
  1583. int cScans = 0;
  1584. if (pbmi && (pbmi->bmiHeader.biWidth == nSrcWidth) && (pbmi->bmiHeader.biHeight > nSrcHeight) &&
  1585. (pbmi->bmiHeader.biHeight > 0) &&
  1586. !(IS_BMI_RLE(pbmi) || IS_BMI_PASSTHROUGH_IMAGE(pbmi)))
  1587. {
  1588. iStart = ((ySrc - EXTRAPIXEL) > 0) ? (ySrc - EXTRAPIXEL) : 0;
  1589. iEnd = ((ySrc+nSrcHeight + EXTRAPIXEL) > pbmi->bmiHeader.biHeight)?
  1590. pbmi->bmiHeader.biHeight : (ySrc+nSrcHeight + EXTRAPIXEL);
  1591. cScans = iEnd - iStart;
  1592. }
  1593. if (!MF_AnyDIBits(hdc,
  1594. xDest,
  1595. yDest,
  1596. nDestWidth,
  1597. nDestHeight,
  1598. xSrc,
  1599. ySrc,
  1600. nSrcWidth,
  1601. nSrcHeight,
  1602. iStart,
  1603. cScans,
  1604. (BYTE *) pj,
  1605. pbmi,
  1606. iUsage,
  1607. lRop,
  1608. EMR_STRETCHDIBITS
  1609. ))
  1610. {
  1611. return (0);
  1612. }
  1613. }
  1614. if (pldc->fl & LDC_SAP_CALLBACK)
  1615. vSAPCallback(pldc);
  1616. if (pldc->fl & LDC_DOC_CANCELLED)
  1617. return (0);
  1618. if (pldc->fl & LDC_CALL_STARTPAGE)
  1619. StartPage(hdc);
  1620. }
  1621. if (pbmi != NULL)
  1622. {
  1623. pbmiNew = pbmiConvertInfo (pbmi, iUsage, &cjHeader,FALSE);
  1624. if (pbmiNew == NULL)
  1625. return (0);
  1626. cjBits = cjBitmapBitsSize(pbmiNew);
  1627. }
  1628. else
  1629. {
  1630. cjHeader = 0;
  1631. cjBits = 0;
  1632. }
  1633. // reset user's poll count so it counts this as output
  1634. // put it right next to BEGINMSG so that NtCurrentTeb() is optimized
  1635. RESETUSERPOLLCOUNT();
  1636. // if the pj are not dword aligned we need to allocate
  1637. // a buffer and copy them
  1638. if ((ULONG_PTR)pj & (sizeof(DWORD) - 1))
  1639. {
  1640. pulBits = LOCALALLOC(cjBits);
  1641. if (pulBits)
  1642. {
  1643. RtlCopyMemory(pulBits,pj,cjBits);
  1644. pj = pulBits;
  1645. }
  1646. }
  1647. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  1648. if (pdcattr)
  1649. {
  1650. // icm tranlation
  1651. //
  1652. // Convert bitmap data only when ...
  1653. //
  1654. // - ICM is enabled.
  1655. // - Bitmap is not Palette Index.
  1656. // - Bitmap header & data is provided.
  1657. // - Bitmap is not passthrough image (BI_JPEG or BI_PNG).
  1658. if (IS_ICM_INSIDEDC(pdcattr->lIcmMode) &&
  1659. (iUsage != DIB_PAL_COLORS) &&
  1660. pbmiNew && pj &&
  1661. !IS_BMI_PASSTHROUGH_IMAGE(pbmiNew))
  1662. {
  1663. LPBITMAPINFO pbmiIcm = NULL;
  1664. LPBITMAPINFO pbmiSave = NULL;
  1665. PVOID pvBitsIcm = NULL;
  1666. ULONG cjHeaderNew = 0;
  1667. ULONG cjBitsIcm;
  1668. BOOL bIcmStatus;
  1669. VOID *pBitsBand = (VOID *)pj;
  1670. LONG CurrentBandSize;
  1671. LONG SizeOfOneScanline;
  1672. LONG IcmSizeOfOneScanline;
  1673. LONG nBands;
  1674. LONG nScansInBand;
  1675. LONG nScansInCurrentBand;
  1676. LONG nScansInRemainderBand;
  1677. LONG CumulativeScans=0;
  1678. LONG i;
  1679. LONG PositiveBandDelta=0;
  1680. LONG NegativeBandDelta=0;
  1681. LONG TotalBandDelta=0;
  1682. HRGN hrgnBandClip = NULL;
  1683. RECT rectCurrentClip;
  1684. LONG HeaderHeightHack;
  1685. INT cScanCount=0;
  1686. float lMulDivStoreY1;
  1687. float lMulDivStoreY2;
  1688. SizeOfOneScanline = cjBitmapScanSize(pbmiNew, 1);
  1689. //
  1690. //pbmiNew must be initialized before getting to this point.
  1691. //
  1692. ASSERTGDI(pbmiNew!=NULL, "StretchDIBits cannot proceed with pbmiNew==NULL\n");
  1693. nScansInBand = BAND_SIZE/SizeOfOneScanline;
  1694. //
  1695. // Set the number of bands provided there are enough scanlines
  1696. // and the hdc is a printer dc.
  1697. //
  1698. // Else set the nubmer of bands to 1 and the scanlines in the
  1699. // remainder band to all of them, so the entire bitmap is printed
  1700. // in one band (All the code below reduces to doing a single piece)
  1701. //
  1702. // If the bitmap is RLE compressed, we set it up to do one band
  1703. // only. When this is the case, Start and NegativeBandDelta will be
  1704. // computed as 0 and the SizeOfOneScanline parameter will be
  1705. // multiplied away to zero.
  1706. //
  1707. if ((nScansInBand>0)&&
  1708. (GetDeviceCaps(hdc, TECHNOLOGY)==DT_RASPRINTER)&&
  1709. (!IS_BMI_RLE(pbmiNew)))
  1710. {
  1711. //
  1712. // Compressed images cannot be converted in this way.
  1713. // This should never be hit and is included as a guard against
  1714. // someone inventing a new compression mode and not updating
  1715. // this conditional.
  1716. //
  1717. //This assert needs a rethink - cjBits refers to the whole image
  1718. //which could be larger than the nSrcHeight portion.
  1719. //ASSERTGDI(SizeOfOneScanline*nSrcHeight==cjBits, "StretchDIBits, cannot band compressed image");
  1720. nBands = (nSrcHeight)/nScansInBand;
  1721. nScansInRemainderBand = nSrcHeight % nScansInBand;
  1722. }
  1723. else
  1724. {
  1725. nBands = 0;
  1726. nScansInRemainderBand = (nSrcHeight);
  1727. }
  1728. if (nScansInRemainderBand>0)
  1729. {
  1730. nBands++;
  1731. nScansInCurrentBand = nScansInRemainderBand;
  1732. }
  1733. else
  1734. {
  1735. nScansInCurrentBand = nScansInBand;
  1736. }
  1737. if (nBands != 1)
  1738. {
  1739. //
  1740. // We're going to have to modify the bmi for this image to
  1741. // coerce NtGdiStretchDIBitsInternal to do the banding.
  1742. // There is a codepath that gets to this point with pbmiNew
  1743. // set to pbmi (pointer copy) rather than local allocated space.
  1744. // if the memory passed in the pointer to pbmi is read only,
  1745. // we won't be able to hack the header, so we make a local copy
  1746. // for banding.
  1747. //
  1748. pbmiSave = pbmiNew; //store the old value
  1749. pbmiNew = (LPBITMAPINFO)LOCALALLOC(cjHeader);
  1750. if (pbmiNew)
  1751. {
  1752. RtlCopyMemory((LPBYTE)pbmiNew,
  1753. (LPBYTE)pbmiSave,
  1754. cjHeader);
  1755. HeaderHeightHack = pbmiNew->bmiHeader.biHeight;
  1756. }
  1757. else
  1758. {
  1759. //
  1760. // we need to bail out here. Goto the cleanup code.
  1761. //
  1762. WARNING("StretchDIBits: couldn't allocate memory for temporary BITMAPINFO\n");
  1763. pbmiNew = pbmiSave;
  1764. iRet = 0;
  1765. goto Exit;
  1766. }
  1767. }
  1768. for (i=0; i<nBands; i++)
  1769. {
  1770. //
  1771. // Initialize band specific size counters.
  1772. //
  1773. CurrentBandSize = nScansInCurrentBand*SizeOfOneScanline;
  1774. IcmSizeOfOneScanline = SizeOfOneScanline;
  1775. cjBitsIcm = cjBits;
  1776. //
  1777. // The Delta refers to the number of extra scanlines to pass
  1778. // to the internal blting routines in order to avoid halftone
  1779. // seams.
  1780. //
  1781. // PositiveBandDelta is usually the number of scanlines to
  1782. // add on to the end of the band. (relative to the start in
  1783. // memory)
  1784. //
  1785. // NegativeBandDelta is usually the number of scanlines to
  1786. // subtract from the begining of the band (ie move the start
  1787. // pointer back this many scanlines).
  1788. //
  1789. // Total BandDelta is simply the total number of extra scans
  1790. // added for this band (both at the start and end).
  1791. //
  1792. // We reverse the sense of positive and negative when rendering
  1793. // bottom up DIBs
  1794. //
  1795. NegativeBandDelta = MIN(EXTRAPIXEL, CumulativeScans);
  1796. PositiveBandDelta = MIN(EXTRAPIXEL, MAX(0, nSrcHeight-(CumulativeScans+nScansInCurrentBand)));
  1797. TotalBandDelta = NegativeBandDelta+PositiveBandDelta;
  1798. if (nBands != 1)
  1799. {
  1800. //
  1801. // We're going to be doing fancy banding stuff with the clip
  1802. // region so we'll want to restore it after the band is done.
  1803. //
  1804. SaveDC(hdc);
  1805. //
  1806. // Intersect the clip rectangles.
  1807. // This clip rectangle is designed to restrict the output to
  1808. // just the displayed portion of the band.
  1809. // We may pass more scanlines on the top and bottom of the band
  1810. // to get halftoning to merge seamlessly.
  1811. //
  1812. lMulDivStoreY1 = (float)nDestHeight*CumulativeScans;
  1813. lMulDivStoreY2 = (float)nDestHeight*(CumulativeScans+nScansInCurrentBand);
  1814. iRet = IntersectClipRect(
  1815. hdc,
  1816. xDest,
  1817. yDest+(LONG)(lMulDivStoreY1/nSrcHeight+0.5),
  1818. xDest+nDestWidth,
  1819. yDest+(LONG)(lMulDivStoreY2/nSrcHeight+0.5));
  1820. if (iRet==ERROR)
  1821. {
  1822. WARNING("StretchDIBits: error intersecting clip rect\n");
  1823. RestoreDC(hdc, -1);
  1824. goto Exit;
  1825. }
  1826. //
  1827. // Empty clip rectangle
  1828. // If the clip regions don't intersect, we can quit without
  1829. // doing anything.
  1830. //
  1831. if (iRet==NULLREGION)
  1832. {
  1833. RestoreDC(hdc, -1);
  1834. //
  1835. // Nothing to do - fall through and do
  1836. // initialization for next iteration.
  1837. //
  1838. goto Continue_With_Init;
  1839. }
  1840. //
  1841. // Hack the BITMAPINFO header so that NtGdiStretchDIBitsInternal
  1842. // works correctly. Note that hacking it before the ICM call will
  1843. // carry through to the NtGdiStretchDIBitsInteral call.
  1844. //
  1845. // This code also updates the pointer to the bits, in a manner
  1846. // appropriate to the topdown/bottomup nature of the DIB.
  1847. //
  1848. if (HeaderHeightHack >= 0)
  1849. {
  1850. //
  1851. //Bottom Up
  1852. //
  1853. pBitsBand = (char *)pj + (ySrc+nSrcHeight-nScansInCurrentBand-CumulativeScans-PositiveBandDelta)*SizeOfOneScanline;
  1854. pbmiNew->bmiHeader.biHeight = nScansInCurrentBand+TotalBandDelta;
  1855. }
  1856. else
  1857. {
  1858. //
  1859. //Top Down
  1860. //
  1861. pBitsBand = (char *)pj + (ySrc+CumulativeScans-NegativeBandDelta)*SizeOfOneScanline;
  1862. pbmiNew->bmiHeader.biHeight = -(nScansInCurrentBand+TotalBandDelta);
  1863. }
  1864. }
  1865. else
  1866. {
  1867. pBitsBand = (char *)pj;
  1868. }
  1869. //
  1870. // Initialize per band ICM variables
  1871. //
  1872. cjHeaderNew=0;
  1873. pbmiIcm = NULL;
  1874. pvBitsIcm = NULL;
  1875. //
  1876. // Call ICM with an oversized band for later halftoning by
  1877. // NtGdiStretchDIBitsInternal
  1878. //
  1879. bIcmStatus = IcmTranslateDIB(
  1880. hdc,
  1881. pdcattr,
  1882. (nBands==1)?cjBits:(CurrentBandSize+TotalBandDelta*SizeOfOneScanline),
  1883. (PVOID)pBitsBand,
  1884. &pvBitsIcm,
  1885. pbmiNew,
  1886. &pbmiIcm,
  1887. &cjHeaderNew,
  1888. (nBands==1)?((DWORD)-1):(nScansInCurrentBand+TotalBandDelta),
  1889. iUsage,
  1890. ICM_FORWARD,
  1891. &pBitmapColorSpace,
  1892. &pCXform);
  1893. if (bIcmStatus)
  1894. {
  1895. if (pvBitsIcm == NULL)
  1896. {
  1897. pvBitsIcm = pBitsBand;
  1898. }
  1899. if (pbmiIcm == NULL)
  1900. {
  1901. pbmiIcm = pbmiNew;
  1902. cjHeaderNew = cjHeader;
  1903. }
  1904. else
  1905. {
  1906. //
  1907. // new bits and header means a possibly different size bitmap
  1908. // and different size scanline.
  1909. //
  1910. // if nBands==1 then nScansInCurrentBand==nNumScans and
  1911. // TotalBandDelta==0
  1912. //
  1913. // Also note that nNumScans is the number of scans rendered,
  1914. // not the number of scans in the bitmap or converted in
  1915. // IcmTranslateDIB for nBands==1 case
  1916. //
  1917. if(nBands == 1) {
  1918. cjBitsIcm = cjBitmapBitsSize(pbmiIcm);
  1919. }
  1920. CurrentBandSize = cjBitmapScanSize(pbmiIcm, nScansInCurrentBand);
  1921. IcmSizeOfOneScanline = cjBitmapScanSize(pbmiIcm, 1);
  1922. if (!cjHeaderNew)
  1923. {
  1924. cjHeaderNew = cjHeader;
  1925. }
  1926. }
  1927. if (pCXform)
  1928. {
  1929. hcmTempXform = pCXform->ColorTransform;
  1930. }
  1931. }
  1932. else
  1933. {
  1934. pvBitsIcm = pBitsBand;
  1935. pbmiIcm = pbmiNew;
  1936. cjHeaderNew = cjHeader;
  1937. }
  1938. lMulDivStoreY1 = (float)nDestHeight*(CumulativeScans-NegativeBandDelta);
  1939. lMulDivStoreY2 = (float)nDestHeight*(nScansInCurrentBand+TotalBandDelta);
  1940. iRet = NtGdiStretchDIBitsInternal(
  1941. hdc,
  1942. xDest,
  1943. yDest+(LONG)(lMulDivStoreY1/nSrcHeight+0.5),
  1944. nDestWidth,
  1945. (LONG)(lMulDivStoreY2/nSrcHeight+0.5),
  1946. xSrc,
  1947. (nBands==1)?ySrc:0,
  1948. nSrcWidth,
  1949. nScansInCurrentBand+TotalBandDelta,
  1950. (LPBYTE) pvBitsIcm,
  1951. (LPBITMAPINFO) pbmiIcm,
  1952. iUsage,
  1953. lRop,
  1954. (UINT)cjHeaderNew,
  1955. (nBands==1)?cjBitsIcm:(UINT)CurrentBandSize+TotalBandDelta*IcmSizeOfOneScanline,
  1956. hcmTempXform);
  1957. if (nBands != 1)
  1958. {
  1959. //
  1960. // Unhack the header
  1961. //
  1962. pbmiNew->bmiHeader.biHeight = HeaderHeightHack;
  1963. }
  1964. if (iRet==GDI_ERROR)
  1965. {
  1966. WARNING("StretchDIBits: NtGdiStretchDIBitsInternal returned GDI_ERROR\n");
  1967. if (nBands!=1)
  1968. {
  1969. RestoreDC(hdc, -1);
  1970. }
  1971. goto Exit; //Some GDI error and we need to quit.
  1972. }
  1973. cScanCount+=iRet-TotalBandDelta;
  1974. //
  1975. //Throw away temp storage
  1976. //
  1977. if (pBitmapColorSpace)
  1978. {
  1979. if (pCXform)
  1980. {
  1981. IcmDeleteColorTransform(pCXform,FALSE);
  1982. pCXform = NULL;
  1983. }
  1984. IcmReleaseColorSpace(NULL,pBitmapColorSpace,FALSE);
  1985. pBitmapColorSpace = NULL;
  1986. }
  1987. if ((pvBitsIcm!=NULL)&&(pvBitsIcm!=pBitsBand))
  1988. {
  1989. LOCALFREE(pvBitsIcm);
  1990. pvBitsIcm = NULL;
  1991. }
  1992. if ((pbmiIcm!=NULL)&&(pbmiIcm!=pbmiNew))
  1993. {
  1994. LOCALFREE(pbmiIcm);
  1995. pbmiIcm = NULL;
  1996. }
  1997. hcmTempXform = NULL;
  1998. Continue_With_Init:
  1999. //
  2000. //Initialize variables for next loop.
  2001. //
  2002. CumulativeScans += nScansInCurrentBand;
  2003. nScansInCurrentBand = nScansInBand;
  2004. if (nBands != 1)
  2005. {
  2006. RestoreDC(hdc, -1);
  2007. }
  2008. }
  2009. if (nBands != 1)
  2010. {
  2011. ASSERTGDI(pbmiSave!=NULL, "StretchDIBits: pbmiSave==NULL\n");
  2012. ASSERTGDI(pbmiNew!=NULL, "StretchDIBits: pbmiNew==NULL\n");
  2013. LOCALFREE(pbmiNew);
  2014. pbmiNew = pbmiSave;
  2015. //
  2016. // pbmiNew will be cleaned up in the
  2017. // regular cleanup code below.
  2018. //
  2019. }
  2020. //
  2021. // We do our own NtGdiSetDIBitsToDeviceInternal
  2022. // So we need to fall through to cleanup at this point.
  2023. //
  2024. iRet=cScanCount;
  2025. goto Exit;
  2026. }
  2027. }
  2028. if (bStatus)
  2029. {
  2030. iRet = NtGdiStretchDIBitsInternal(hdc,
  2031. xDest,
  2032. yDest,
  2033. nDestWidth,
  2034. nDestHeight,
  2035. xSrc,
  2036. ySrc,
  2037. nSrcWidth,
  2038. nSrcHeight,
  2039. (LPBYTE) pj,
  2040. (LPBITMAPINFO) pbmiNew,
  2041. iUsage,
  2042. lRop,
  2043. cjHeader,
  2044. cjBits,
  2045. hcmTempXform);
  2046. }
  2047. Exit:
  2048. if (pulBits)
  2049. {
  2050. LOCALFREE(pulBits);
  2051. }
  2052. if (pbmiNew && (pbmiNew != pbmi))
  2053. {
  2054. LOCALFREE(pbmiNew);
  2055. }
  2056. return (iRet);
  2057. }
  2058. /******************************Public*Routine******************************\
  2059. *
  2060. * History:
  2061. * 27-Oct-2000 -by- Pravin Santiago [pravins]
  2062. * Wrote it.
  2063. \**************************************************************************/
  2064. HBITMAP SetBitmapAttributes(HBITMAP hbm, DWORD dwFlags)
  2065. {
  2066. FIXUP_HANDLE(hbm);
  2067. if ((dwFlags & ~SBA_STOCK) != 0)
  2068. return (HBITMAP)0;
  2069. return (HBITMAP)NtGdiSetBitmapAttributes(hbm,dwFlags);
  2070. }
  2071. /******************************Public*Routine******************************\
  2072. *
  2073. * History:
  2074. * 27-Oct-2000 -by- Pravin Santiago [pravins]
  2075. * Wrote it.
  2076. \**************************************************************************/
  2077. HBITMAP ClearBitmapAttributes(HBITMAP hbm, DWORD dwFlags)
  2078. {
  2079. FIXUP_HANDLE(hbm);
  2080. if ((dwFlags & ~SBA_STOCK) != 0)
  2081. return (HBITMAP)0;
  2082. return (HBITMAP)NtGdiClearBitmapAttributes(hbm,dwFlags);
  2083. }
  2084. /******************************Public*Routine******************************\
  2085. *
  2086. * History:
  2087. * 27-Oct-2000 -by- Pravin Santiago [pravins]
  2088. * Wrote it.
  2089. \**************************************************************************/
  2090. DWORD GetBitmapAttributes(HBITMAP hbm)
  2091. {
  2092. DWORD dwRet = 0;
  2093. FIXUP_HANDLE(hbm);
  2094. if (IS_STOCKOBJ(hbm))
  2095. dwRet |= SBA_STOCK;
  2096. return dwRet;
  2097. }
  2098. /******************************Public*Routine******************************\
  2099. *
  2100. * History:
  2101. * 27-Oct-2000 -by- Pravin Santiago [pravins]
  2102. * Wrote it.
  2103. \**************************************************************************/
  2104. HBRUSH SetBrushAttributes(HBRUSH hbr, DWORD dwFlags)
  2105. {
  2106. FIXUP_HANDLE(hbr);
  2107. if ((dwFlags & ~SBA_STOCK) != 0)
  2108. return (HBRUSH)0;
  2109. return (HBRUSH)NtGdiSetBrushAttributes(hbr,dwFlags);
  2110. }
  2111. /******************************Public*Routine******************************\
  2112. *
  2113. * History:
  2114. * 27-Oct-2000 -by- Pravin Santiago [pravins]
  2115. * Wrote it.
  2116. \**************************************************************************/
  2117. HBRUSH ClearBrushAttributes(HBRUSH hbr, DWORD dwFlags)
  2118. {
  2119. FIXUP_HANDLE(hbr);
  2120. if ((dwFlags & ~SBA_STOCK) != 0)
  2121. return (HBRUSH)0;
  2122. return (HBRUSH)NtGdiClearBrushAttributes(hbr,dwFlags);
  2123. }
  2124. /******************************Public*Routine******************************\
  2125. *
  2126. * History:
  2127. * 27-Oct-2000 -by- Pravin Santiago [pravins]
  2128. * Wrote it.
  2129. \**************************************************************************/
  2130. DWORD GetBrushAttributes(HBRUSH hbr)
  2131. {
  2132. DWORD dwRet = 0;
  2133. FIXUP_HANDLE(hbr);
  2134. if (IS_STOCKOBJ(hbr))
  2135. dwRet |= SBA_STOCK;
  2136. return dwRet;
  2137. }
  2138. /******************************Public*Routine******************************\
  2139. *
  2140. * History:
  2141. * 28-May-1991 -by- Eric Kutter [erick]
  2142. * Wrote it.
  2143. \**************************************************************************/
  2144. HBITMAP CreateBitmap(
  2145. int nWidth,
  2146. int nHeight,
  2147. UINT nPlanes,
  2148. UINT nBitCount,
  2149. CONST VOID *lpBits)
  2150. {
  2151. LONG cj;
  2152. HBITMAP hbm = (HBITMAP)0;
  2153. INT ii;
  2154. // check if it is an empty bitmap
  2155. if ((nWidth == 0) || (nHeight == 0))
  2156. {
  2157. return(GetStockObject(PRIV_STOCK_BITMAP));
  2158. }
  2159. // Pass call to the server
  2160. if (lpBits == (VOID *) NULL)
  2161. cj = 0;
  2162. else
  2163. {
  2164. cj = (((nWidth*nPlanes*nBitCount + 15) >> 4) << 1) * nHeight;
  2165. if (cj < 0)
  2166. {
  2167. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2168. return((HBITMAP)0);
  2169. }
  2170. }
  2171. hbm = NtGdiCreateBitmap(nWidth,
  2172. nHeight,
  2173. nPlanes,
  2174. nBitCount,
  2175. (LPBYTE) lpBits);
  2176. #if TRACE_SURFACE_ALLOCS
  2177. {
  2178. PULONG pUserAlloc;
  2179. PSHARED_GET_VALIDATE(pUserAlloc, hbm, SURF_TYPE);
  2180. if (pUserAlloc != NULL)
  2181. {
  2182. pUserAlloc[1] = RtlWalkFrameChain((PVOID *)&pUserAlloc[2], pUserAlloc[0], 0);
  2183. }
  2184. }
  2185. #endif
  2186. return(hbm);
  2187. }
  2188. /******************************Public*Routine******************************\
  2189. * HBITMAP CreateBitmapIndirect(CONST BITMAP * pbm)
  2190. *
  2191. * NOTE: if the bmWidthBytes is larger than it needs to be, GetBitmapBits
  2192. * will return different info than the set.
  2193. *
  2194. * History:
  2195. * Tue 18-Jan-1994 -by- Bodin Dresevic [BodinD]
  2196. * update: added bmWidthBytes support
  2197. * 28-May-1991 -by- Eric Kutter [erick]
  2198. * Wrote it.
  2199. \**************************************************************************/
  2200. HBITMAP CreateBitmapIndirect(CONST BITMAP * pbm)
  2201. {
  2202. HBITMAP hbm = (HBITMAP)0;
  2203. LPBYTE lpBits = (LPBYTE)NULL; // important to zero init
  2204. BOOL bAlloc = FALSE; // indicates that tmp bitmap was allocated
  2205. // compute minimal word aligned scan width in bytes given the number of
  2206. // pixels in x. The width refers to one plane only. Our multi - planar
  2207. // support is broken anyway. I believe that we should take an early
  2208. // exit if bmPlanes != 1. [bodind].
  2209. LONG cjWidthWordAligned = ((pbm->bmWidth * pbm->bmBitsPixel + 15) >> 4) << 1;
  2210. // Win 31 requires at least WORD alinged scans, have to reject inconsistent
  2211. // input, this is what win31 does
  2212. if
  2213. (
  2214. (pbm->bmWidthBytes & 1) ||
  2215. (pbm->bmWidthBytes == 0) ||
  2216. (pbm->bmWidthBytes < cjWidthWordAligned)
  2217. )
  2218. {
  2219. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2220. return (HBITMAP)0;
  2221. }
  2222. // take an early exit if this is not the case we know how to handle:
  2223. if (pbm->bmPlanes != 1)
  2224. {
  2225. WARNING("gdi32: can not handle bmPlanes != 1\n");
  2226. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2227. return (HBITMAP)0;
  2228. }
  2229. // if bmBits is nonzero and bmWidthBytes is bigger than the minimal required
  2230. // word aligned width we will first convert the bitmap to one that
  2231. // has the rows that are minimally word aligned:
  2232. if (pbm->bmBits)
  2233. {
  2234. if (pbm->bmWidthBytes > cjWidthWordAligned)
  2235. {
  2236. PBYTE pjSrc, pjDst, pjDstEnd;
  2237. ULONGLONG lrg;
  2238. lrg = UInt32x32To64(
  2239. (ULONG)cjWidthWordAligned,
  2240. (ULONG)pbm->bmHeight
  2241. );
  2242. if (lrg > ULONG_MAX ||
  2243. !(lpBits = (LPBYTE)LOCALALLOC((size_t) lrg)))
  2244. {
  2245. // the result does not fit in 32 bits, alloc memory will fail
  2246. // this is too big to digest
  2247. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2248. return (HBITMAP)0;
  2249. }
  2250. // flag that we have allocated memory so that we can free it later
  2251. bAlloc = TRUE;
  2252. // convert bitmap to minimally word aligned format
  2253. pjSrc = (LPBYTE)pbm->bmBits;
  2254. pjDst = lpBits;
  2255. pjDstEnd = lpBits + (size_t) lrg;
  2256. while (pjDst < pjDstEnd)
  2257. {
  2258. RtlCopyMemory(pjDst,pjSrc, cjWidthWordAligned);
  2259. pjDst += cjWidthWordAligned, pjSrc += pbm->bmWidthBytes;
  2260. }
  2261. }
  2262. else
  2263. {
  2264. // bits already in minimally aligned format, do nothing
  2265. ASSERTGDI(
  2266. pbm->bmWidthBytes == cjWidthWordAligned,
  2267. "pbm->bmWidthBytes != cjWidthWordAligned\n"
  2268. );
  2269. lpBits = (LPBYTE)pbm->bmBits;
  2270. }
  2271. }
  2272. hbm = CreateBitmap(
  2273. pbm->bmWidth,
  2274. pbm->bmHeight,
  2275. (UINT) pbm->bmPlanes,
  2276. (UINT) pbm->bmBitsPixel,
  2277. lpBits);
  2278. #if TRACE_SURFACE_ALLOCS
  2279. {
  2280. PULONG pUserAlloc;
  2281. PSHARED_GET_VALIDATE(pUserAlloc, hbm, SURF_TYPE);
  2282. if (pUserAlloc != NULL)
  2283. {
  2284. pUserAlloc[1] = RtlWalkFrameChain((PVOID *)&pUserAlloc[2], pUserAlloc[0], 0);
  2285. }
  2286. }
  2287. #endif
  2288. if (bAlloc)
  2289. LOCALFREE(lpBits);
  2290. return(hbm);
  2291. }
  2292. /******************************Public*Routine******************************\
  2293. * CreateDIBSection
  2294. *
  2295. * Allocate a file mapping object for a DIB. Return the pointer to it
  2296. * and the handle of the bitmap.
  2297. *
  2298. * History:
  2299. *
  2300. * 25-Aug-1993 -by- Wendy Wu [wendywu]
  2301. * Wrote it.
  2302. \**************************************************************************/
  2303. HBITMAP
  2304. WINAPI
  2305. CreateDIBSection(
  2306. HDC hdc,
  2307. CONST BITMAPINFO *pbmi,
  2308. UINT iUsage,
  2309. VOID **ppvBits,
  2310. HANDLE hSectionApp,
  2311. DWORD dwOffset)
  2312. {
  2313. HBITMAP hbm = NULL;
  2314. PVOID pjBits = NULL;
  2315. BITMAPINFO * pbmiNew = NULL;
  2316. INT cjHdr;
  2317. FIXUP_HANDLE(hdc);
  2318. pbmiNew = pbmiConvertInfo(pbmi, iUsage, &cjHdr ,FALSE);
  2319. //
  2320. // Does not support passthrough image (BI_JPEG or BI_PNG).
  2321. // Return NULL for error.
  2322. //
  2323. if (IS_BMI_PASSTHROUGH_IMAGE(pbmiNew))
  2324. {
  2325. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2326. return hbm;
  2327. }
  2328. //
  2329. // dwOffset has to be a multiple of 4 (sizeof(DWORD))
  2330. // if there is a section. If the section is NULL we do
  2331. // not care
  2332. //
  2333. if ( (hSectionApp == NULL) ||
  2334. ((dwOffset & 3) == 0) )
  2335. {
  2336. PCACHED_COLORSPACE pBitmapColorSpace = NULL;
  2337. BOOL bCreatedColorSpace = FALSE;
  2338. LOGCOLORSPACEW LogColorSpace;
  2339. PROFILE ColorProfile;
  2340. DWORD dwFlags = 0;
  2341. //
  2342. // Check they has thier own color space or not.
  2343. //
  2344. if (pbmiNew && IcmGetBitmapColorSpace(pbmiNew,&LogColorSpace,&ColorProfile,&dwFlags))
  2345. {
  2346. //
  2347. // Find ColorSpace from cache.
  2348. //
  2349. pBitmapColorSpace = IcmGetColorSpaceByColorSpace(
  2350. (HGDIOBJ)hdc,
  2351. &LogColorSpace,
  2352. &ColorProfile,
  2353. dwFlags);
  2354. if (pBitmapColorSpace == NULL)
  2355. {
  2356. //
  2357. // If we can not find the color space for this DIBSection from existing color space.
  2358. // create new one for this, but we mark it as DIBSECTION_COLORSPACE, then associated
  2359. // to this hdc (later hbm), so that we can make sure this color space get deleted
  2360. // when hbm is deleted.
  2361. //
  2362. dwFlags |= DIBSECTION_COLORSPACE;
  2363. //
  2364. // Mark we will create new colorspace for this bitmap.
  2365. //
  2366. bCreatedColorSpace = TRUE;
  2367. //
  2368. // Create new cache.
  2369. //
  2370. pBitmapColorSpace = IcmCreateColorSpaceByColorSpace(
  2371. (HGDIOBJ)hdc,
  2372. &LogColorSpace,
  2373. &ColorProfile,
  2374. dwFlags);
  2375. }
  2376. }
  2377. hbm = NtGdiCreateDIBSection(
  2378. hdc,
  2379. hSectionApp,
  2380. dwOffset,
  2381. (LPBITMAPINFO) pbmiNew,
  2382. iUsage,
  2383. cjHdr,
  2384. 0,
  2385. (ULONG_PTR)pBitmapColorSpace,
  2386. (PVOID *)&pjBits);
  2387. if ((hbm == NULL) || (pjBits == NULL))
  2388. {
  2389. hbm = 0;
  2390. pjBits = NULL;
  2391. if (pBitmapColorSpace)
  2392. {
  2393. IcmReleaseColorSpace(NULL,pBitmapColorSpace,FALSE);
  2394. }
  2395. }
  2396. else
  2397. {
  2398. #if TRACE_SURFACE_ALLOCS
  2399. PULONG pUserAlloc;
  2400. PSHARED_GET_VALIDATE(pUserAlloc, hbm, SURF_TYPE);
  2401. if (pUserAlloc != NULL)
  2402. {
  2403. pUserAlloc[1] = RtlWalkFrameChain((PVOID *)&pUserAlloc[2], pUserAlloc[0], 0);
  2404. }
  2405. #endif
  2406. if (pBitmapColorSpace && bCreatedColorSpace)
  2407. {
  2408. //
  2409. // if we created new color space for this bitmap,
  2410. // set owner of this colorspace to the created bitmap.
  2411. //
  2412. pBitmapColorSpace->hObj = hbm;
  2413. }
  2414. }
  2415. }
  2416. //
  2417. // Assign the appropriate value to the caller's pointer
  2418. //
  2419. if (ppvBits != NULL)
  2420. {
  2421. *ppvBits = pjBits;
  2422. }
  2423. if (pbmiNew && (pbmiNew != pbmi))
  2424. {
  2425. LOCALFREE(pbmiNew);
  2426. }
  2427. return(hbm);
  2428. }