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.

5046 lines
175 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: dibapi.cxx
  3. *
  4. * This contains all the functions relating to DIBs
  5. *
  6. * Created: 12-Mar-1991 13:53:29
  7. * Author: Patrick Haluptzok patrickh
  8. *
  9. * Copyright (c) 1990-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. BOOL bIdenticalFormat (XEPALOBJ, INT);
  13. //
  14. // This is to convert BMF constants into max # of palette entries
  15. //
  16. ULONG gacPalEntries[7] =
  17. {
  18. 0,
  19. 2,
  20. 16,
  21. 256,
  22. 0,
  23. 0,
  24. 0
  25. };
  26. extern PAL_ULONG aPalVGA[16];
  27. //
  28. // IS_BMI_JPEG
  29. //
  30. // Checks if the header pointed to by pv is a BITMAPINFO for a JPEG.
  31. // Evaluates to TRUE if JPEG, FALSE otherwise.
  32. //
  33. #define IS_BMI_JPEG(pv) \
  34. ((pv) && \
  35. (((BITMAPINFO *)(pv))->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && \
  36. (((BITMAPINFO *)(pv))->bmiHeader.biCompression == BI_JPEG))
  37. //
  38. // IS_BMI_PNG
  39. //
  40. // Checks if the header pointed to by pv is a BITMAPINFO for a PNG.
  41. // Evaluates to TRUE if PNG, FALSE otherwise.
  42. //
  43. #define IS_BMI_PNG(pv) \
  44. ((pv) && \
  45. (((BITMAPINFO *)(pv))->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && \
  46. (((BITMAPINFO *)(pv))->bmiHeader.biCompression == BI_PNG))
  47. //
  48. // IS_PASSTHROUGH_IMAGE
  49. //
  50. // Checks if the biCompression value is one of the passthrough formats that
  51. // can be passed to devices (BI_JPEG or BI_PNG).
  52. //
  53. #define IS_PASSTHROUGH_IMAGE(biCompression) \
  54. (((biCompression) == BI_JPEG) || ((biCompression) == BI_PNG))
  55. //
  56. // IS_BMI_PASSTHROUGH_IMAGE
  57. //
  58. // Checks if the header pointed to by pv is a BITMAPINFO for a JPEG or PNG.
  59. // Evaluates to TRUE if JPEG or PNG, FALSE otherwise.
  60. //
  61. #define IS_BMI_PASSTHROUGH_IMAGE(pv) \
  62. ((pv) && \
  63. (((BITMAPINFO *)(pv))->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && \
  64. IS_PASSTHROUGH_IMAGE(((BITMAPINFO *)(pv))->bmiHeader.biCompression))
  65. //
  66. // IS_CMYK_BITMAP
  67. //
  68. // Checks if the bitmap uses CMYK color data either in color table or bitmap
  69. // itself.
  70. //
  71. #define IS_CMYK_BITMAP(biCompression) \
  72. (((biCompression) == BI_CMYK) || \
  73. ((biCompression) == BI_CMYKRLE4) || \
  74. ((biCompression) == BI_CMYKRLE8))
  75. /******************************Public*Routine******************************\
  76. * vCopyCoreToInfoHeader
  77. *
  78. * Copy a BITMAPCOREINFOHEADER to BITMAPINFOHEADER
  79. *
  80. * 06-Mar-1995 -by- Lingyun Wang [lingyunw]
  81. * Wrote it.
  82. \**************************************************************************/
  83. VOID vCopyCoreToInfoHeader(LPBITMAPINFOHEADER pbmih, LPBITMAPCOREHEADER pbmch)
  84. {
  85. pbmih->biSize = sizeof(BITMAPINFOHEADER);
  86. pbmih->biWidth = pbmch->bcWidth;
  87. pbmih->biHeight = pbmch->bcHeight;
  88. pbmih->biPlanes = pbmch->bcPlanes;
  89. pbmih->biBitCount = pbmch->bcBitCount;
  90. pbmih->biCompression = BI_RGB;
  91. pbmih->biSizeImage = 0;
  92. pbmih->biXPelsPerMeter = 0;
  93. pbmih->biYPelsPerMeter = 0;
  94. pbmih->biClrUsed = 0;
  95. pbmih->biClrImportant = 0;
  96. }
  97. /******************************Public*Routine******************************\
  98. * vCopyCoreToInfoColorTable
  99. *
  100. * Copy a RGBTRIPLE color table to a RGBQUAD color table
  101. *
  102. * 06-Mar-1995 -by- Lingyun Wang [lingyunw]
  103. * Wrote it.
  104. \**************************************************************************/
  105. VOID vCopyCoreToInfoColorTable(RGBQUAD *pQuad, RGBTRIPLE *pTri, INT cEntries, INT iUsage)
  106. {
  107. INT cj;
  108. cj = cEntries;
  109. if (iUsage != DIB_PAL_COLORS)
  110. {
  111. while (cj--)
  112. {
  113. pQuad->rgbRed = pTri->rgbtRed;
  114. pQuad->rgbGreen = pTri->rgbtGreen;
  115. pQuad->rgbBlue = pTri->rgbtBlue;
  116. pQuad->rgbReserved = 0;
  117. pQuad++;
  118. pTri++;
  119. }
  120. }
  121. else
  122. // DIB_PAL_COLORS
  123. {
  124. RtlCopyMemory((LPBYTE)pQuad,(LPBYTE)pTri,cEntries * sizeof(USHORT));
  125. }
  126. }
  127. /******************************Public*Routine******************************\
  128. * GreCreateDIBitmapComp
  129. *
  130. * Only called by CreateDIBitmap from client - when CREATEDIB is not set
  131. *
  132. * History:
  133. *
  134. * 03-Mar-1995 -by- Lingyun Wang [lingyunw]
  135. * Changed from GreCreateDIBitmapInternal.
  136. \**************************************************************************/
  137. HBITMAP
  138. APIENTRY
  139. GreCreateDIBitmapComp(
  140. HDC hdc,
  141. INT cx,
  142. INT cy,
  143. DWORD fInit,
  144. LPBYTE pInitBits,
  145. LPBITMAPINFO pInitInfo,
  146. DWORD iUsage,
  147. UINT cjMaxInitInfo,
  148. UINT cjMaxBits,
  149. FLONG fl,
  150. HANDLE hcmXform)
  151. {
  152. DEVBITMAPINFO dbmi;
  153. //
  154. // It is old style call so do the compatible thing.
  155. // Let's validate some of the parameters
  156. //
  157. if ((iUsage != DIB_PAL_INDICES) &&
  158. (iUsage != DIB_PAL_COLORS) &&
  159. (iUsage != DIB_RGB_COLORS))
  160. {
  161. WARNING1("GreCreateDIBitmapComp failed because of invalid parameters\n");
  162. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  163. return(0);
  164. }
  165. //
  166. // Cannot support the device passthrough formats (BI_JPEG, BI_PNG).
  167. //
  168. if (IS_BMI_PASSTHROUGH_IMAGE(pInitInfo))
  169. {
  170. WARNING1("GreCreateDIBitmapComp invalid pInitInfo (BITMAPINFOHEADER)\n");
  171. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  172. return(0);
  173. }
  174. dbmi.cxBitmap = cx;
  175. //
  176. // Check for the upside down bitmaps.
  177. //
  178. if (cy < 0)
  179. {
  180. dbmi.cyBitmap = -cy;
  181. }
  182. else
  183. {
  184. dbmi.cyBitmap = cy;
  185. }
  186. HBITMAP hbmReturn = GreCreateCompatibleBitmap(hdc, (int) dbmi.cxBitmap, (int) dbmi.cyBitmap);
  187. if (hbmReturn)
  188. {
  189. if ((fInit & CBM_INIT) &&
  190. (pInitBits != NULL) &&
  191. (pInitInfo != NULL))
  192. {
  193. if (GreSetDIBitsInternal(
  194. hdc,
  195. hbmReturn,
  196. 0,
  197. (UINT) dbmi.cyBitmap,
  198. pInitBits,
  199. pInitInfo,
  200. (UINT) iUsage,
  201. cjMaxBits,
  202. cjMaxInitInfo,
  203. hcmXform
  204. ))
  205. {
  206. return(hbmReturn);
  207. }
  208. else
  209. {
  210. WARNING1("CreateDIBitmapComp failed SetDIBits compat\n");
  211. }
  212. }
  213. else
  214. {
  215. return(hbmReturn);
  216. }
  217. GreDeleteObject(hbmReturn);
  218. }
  219. WARNING1("CreateDIBitmapComp failed CreateCompatBitmap\n");
  220. return(0);
  221. }
  222. /******************************Public*Routine******************************\
  223. * GreCreateDIBitmapReal
  224. *
  225. * Called by CreateDIBitmap from client when CREATEDIB is set and
  226. * CreateDIBSection
  227. *
  228. * hdc - handle of device context
  229. * pInfoHeader - bitmap size and format
  230. * fInit - initialization flag
  231. * pInitBits - initialization data
  232. * pInitInfo - initialization color info
  233. * iUsage - color-data usage
  234. * cjMaxInitInfo - size of bitmapinfo
  235. * cjMaxBits - size of bitmap
  236. * hSection - For DIBSECTION, Section or NULL
  237. * dwOffset - For DIBSECTION
  238. * hSecure - For DIBSECTION, VM Secure handle
  239. * fl - creation flags
  240. * dwColorSpace - identifier of client side color space data
  241. * ppvBits - receives pointer to the bitmap bits
  242. *
  243. * History:
  244. *
  245. * 07-Apr-1995 -by- Mark Enstrom [marke]
  246. * add DIBSection support
  247. * 03-Mar-1995 -by- Lingyun Wang [lingyunw]
  248. * Changed from GreCreateDIBitmapInternal.
  249. * 04-Dec-1990 -by- Patrick Haluptzok patrickh
  250. \**************************************************************************/
  251. HBITMAP
  252. APIENTRY
  253. GreCreateDIBitmapReal(
  254. HDC hdc,
  255. DWORD fInit,
  256. LPBYTE pInitBits,
  257. LPBITMAPINFO pInitInfo,
  258. DWORD iUsage,
  259. UINT cjMaxInitInfo,
  260. UINT cjMaxBits,
  261. HANDLE hSection,
  262. DWORD dwOffset,
  263. HANDLE hSecure,
  264. FLONG fl,
  265. ULONG_PTR dwColorSpace,
  266. PVOID *ppvBits)
  267. {
  268. ULONG ulSize;
  269. DEVBITMAPINFO dbmi;
  270. //
  271. // It is a new DIB bitmap creation. This code can essentially
  272. // be used as the base for CreateDIBSection when it is written.
  273. //
  274. // Let's validate some of the parameters.
  275. //
  276. if (((iUsage != DIB_PAL_COLORS) &&
  277. (iUsage != DIB_PAL_NONE) &&
  278. (iUsage != DIB_RGB_COLORS)) ||
  279. ((iUsage == DIB_PAL_NONE) && ((fl & CDBI_INTERNAL) == 0)) ||
  280. (pInitInfo == (LPBITMAPINFO) NULL) ||
  281. (cjMaxInitInfo < sizeof(BITMAPINFOHEADER)) || // Check first so we can access biSize.
  282. (cjMaxInitInfo < (ulSize = pInitInfo->bmiHeader.biSize)) ||
  283. (IS_BMI_PASSTHROUGH_IMAGE(pInitInfo)) ||
  284. (ulSize < sizeof(BITMAPINFOHEADER)) ||
  285. (pInitInfo->bmiHeader.biWidth < 0))
  286. {
  287. WARNING1("GreCreateDIBitmapReal failed new DIB because of invalid parameters\n");
  288. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  289. return(0);
  290. }
  291. UINT uiCompression;
  292. dbmi.fl = 0;
  293. PULONG pulColors;
  294. ULONG ulClrUsed;
  295. cjMaxInitInfo -= ((UINT) ulSize);
  296. dbmi.cxBitmap = pInitInfo->bmiHeader.biWidth;
  297. if (pInitInfo->bmiHeader.biHeight < 0)
  298. {
  299. dbmi.cyBitmap = -(pInitInfo->bmiHeader.biHeight);
  300. dbmi.fl = BMF_TOPDOWN;
  301. }
  302. else
  303. {
  304. dbmi.cyBitmap = pInitInfo->bmiHeader.biHeight;
  305. }
  306. dbmi.iFormat = (UINT) pInitInfo->bmiHeader.biBitCount;
  307. uiCompression = (UINT) pInitInfo->bmiHeader.biCompression;
  308. ulClrUsed = (ULONG) pInitInfo->bmiHeader.biClrUsed;
  309. pulColors = (PULONG) ((LPBYTE)pInitInfo+ulSize);
  310. //
  311. // Figure out what this guy is asking for
  312. //
  313. ULONG cColors;
  314. FLONG iPalMode = PAL_INDEXED;
  315. FLONG iPalType;
  316. FLONG flRed;
  317. FLONG flGre;
  318. FLONG flBlu;
  319. if (uiCompression == BI_RGB)
  320. {
  321. switch (dbmi.iFormat)
  322. {
  323. case 1:
  324. dbmi.iFormat = BMF_1BPP;
  325. cColors = 2;
  326. iPalMode = PAL_INDEXED;
  327. iPalType = PAL_FREE;
  328. break;
  329. case 4:
  330. dbmi.iFormat = BMF_4BPP;
  331. cColors = 16;
  332. iPalMode = PAL_INDEXED;
  333. iPalType = PAL_FREE;
  334. break;
  335. case 8:
  336. dbmi.iFormat = BMF_8BPP;
  337. cColors = 256;
  338. iPalMode = PAL_INDEXED;
  339. iPalType = PAL_FREE;
  340. break;
  341. default:
  342. if (iUsage == DIB_PAL_COLORS)
  343. {
  344. iUsage = DIB_RGB_COLORS;
  345. }
  346. cColors = 0;
  347. iPalType = PAL_FIXED;
  348. switch (dbmi.iFormat)
  349. {
  350. case 16:
  351. dbmi.iFormat = BMF_16BPP;
  352. flRed = 0x7c00;
  353. flGre = 0x03e0;
  354. flBlu = 0x001f;
  355. iPalMode = PAL_BITFIELDS;
  356. break;
  357. case 24:
  358. dbmi.iFormat = BMF_24BPP;
  359. iPalMode = PAL_BGR;
  360. break;
  361. case 32:
  362. dbmi.iFormat = BMF_32BPP;
  363. iPalMode = PAL_BGR;
  364. break;
  365. default:
  366. WARNING1("CreateDIBitmapReal failed invalid bitcount in bmi for BI_RGB\n");
  367. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  368. return(0);
  369. }
  370. }
  371. }
  372. else if (uiCompression == BI_BITFIELDS)
  373. {
  374. if (
  375. (
  376. (ulSize <= sizeof(BITMAPINFOHEADER)) &&
  377. (cjMaxInitInfo < (sizeof(ULONG) * 3))
  378. ) ||
  379. (iUsage != DIB_RGB_COLORS)
  380. )
  381. {
  382. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  383. WARNING1("CreateDIBitmapReal 16bpp failed - no room for flags\n");
  384. return((HBITMAP) 0);
  385. }
  386. //
  387. // if BITMAPV4 or greater then masks are stored in info header
  388. //
  389. if (ulSize >= sizeof(BITMAPINFOHEADER))
  390. {
  391. pulColors = (PULONG) ((LPBYTE)pInitInfo+sizeof(BITMAPINFOHEADER));
  392. }
  393. flRed = pulColors[0];
  394. flGre = pulColors[1];
  395. flBlu = pulColors[2];
  396. cColors = 0;
  397. iPalMode = PAL_BITFIELDS;
  398. iPalType = PAL_FIXED;
  399. switch (dbmi.iFormat)
  400. {
  401. case 16:
  402. dbmi.iFormat = BMF_16BPP;
  403. break;
  404. case 32:
  405. dbmi.iFormat = BMF_32BPP;
  406. break;
  407. default:
  408. WARNING1("CreateDIBitmap failed invalid bitcount in bmi in BI_BITFIELDS\n");
  409. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  410. return(0);
  411. }
  412. }
  413. else if (uiCompression == BI_CMYK)
  414. {
  415. ASSERTGDI(iUsage == DIB_RGB_COLORS,
  416. "CreateDIBitmap(BI_CMYK):iUsage should be DIB_RGB_COLORS\n");
  417. DCOBJ dco(hdc);
  418. //
  419. // Current device context accept CMYK color ?
  420. //
  421. if (!dco.bValid() || !dco.pdc->bIsCMYKColor())
  422. {
  423. WARNING1("CreateDIBitmapReal:DC is not in CMYK color mode for BI_CMYK\n");
  424. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  425. return(0);
  426. }
  427. switch (dbmi.iFormat)
  428. {
  429. case 1:
  430. dbmi.iFormat = BMF_1BPP;
  431. cColors = 2;
  432. iPalMode = PAL_INDEXED;
  433. iPalType = PAL_FREE;
  434. break;
  435. case 4:
  436. dbmi.iFormat = BMF_4BPP;
  437. cColors = 16;
  438. iPalMode = PAL_INDEXED;
  439. iPalType = PAL_FREE;
  440. break;
  441. case 8:
  442. dbmi.iFormat = BMF_8BPP;
  443. cColors = 256;
  444. iPalMode = PAL_INDEXED;
  445. iPalType = PAL_FREE;
  446. break;
  447. case 32:
  448. dbmi.iFormat = BMF_32BPP;
  449. cColors = 0;
  450. iPalMode = PAL_CMYK;
  451. iPalType = PAL_FIXED;
  452. break;
  453. default:
  454. WARNING1("CreateDIBitmapReal failed invalid bitcount in bmi for BI_CMYK\n");
  455. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  456. return(0);
  457. }
  458. }
  459. else
  460. {
  461. WARNING1("CreateDIBitmap failed - invalid Compression\n");
  462. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  463. return(0);
  464. }
  465. //
  466. // Allocate a palette for this bitmap.
  467. //
  468. PALMEMOBJ palPerm;
  469. if (!palPerm.bCreatePalette(iPalMode, cColors, (PULONG) NULL,
  470. flRed, flGre, flBlu, iPalType))
  471. {
  472. WARNING1("Failed palette creation in GreCreateBitmap\n");
  473. return(0);
  474. }
  475. dbmi.hpal = (HPALETTE) palPerm.hpal();
  476. //
  477. // Attempt to allocate the bitmap from handle manager.
  478. //
  479. SURFMEM SurfDimo;
  480. PBYTE pDIB = (PBYTE) NULL;
  481. HANDLE hDIB = NULL;
  482. if (fl & CDBI_DIBSECTION)
  483. {
  484. //
  485. // Let's mark the palette created as being a DIBSECTION palette
  486. // so when we attempt to map it to another palette we try to
  487. // make it identity before going through the closest match search.
  488. //
  489. palPerm.flPal(PAL_DIBSECTION);
  490. //
  491. // In kernel mode, pInitBits contains the DIBSection address
  492. //
  493. pDIB = pInitBits;
  494. hDIB = hSection;
  495. if (pDIB == (PVOID)NULL)
  496. {
  497. return(0);
  498. }
  499. //
  500. // Clear pInitBits so we can fall through nicely later.
  501. //
  502. pInitBits = (LPBYTE) NULL;
  503. }
  504. else if (hdc)
  505. {
  506. DCOBJ dco(hdc);
  507. if (dco.bValid() && dco.bUMPD())
  508. dbmi.fl |= UMPD_SURFACE;
  509. }
  510. if (!SurfDimo.bCreateDIB(&dbmi, pDIB, hDIB, dwOffset, hSecure, dwColorSpace) ||
  511. (SurfDimo.ps->bDIBSection() && (SurfDimo.ps->cjBits() != cjMaxBits)))
  512. {
  513. WARNING("GreCreateDIBitmap failed bCreateDIB or size mismatch\n");
  514. return(0);
  515. }
  516. //
  517. // Initialize bits if provided.
  518. //
  519. if (pInitBits != (LPBYTE) NULL)
  520. {
  521. ASSERTGDI(fInit & CBM_INIT, "CreateDIBitmap bits sent but no CBM_INIT set");
  522. if (SurfDimo.ps->cjBits() > cjMaxBits)
  523. {
  524. WARNING1("CreateDIBitmap failed because invalid bitmap buffer size CBM_CREATEDIB\n");
  525. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  526. return(0);
  527. }
  528. RtlCopyMemory(SurfDimo.ps->pvBits(), (PVOID) pInitBits, (UINT) SurfDimo.ps->cjBits());
  529. }
  530. //
  531. // Check if it is not equal to 0. If it is not 0 use that as the number
  532. // of palette entries to initialize. If it is 0 then cPalEntries has the
  533. // correct number already computed in it.
  534. //
  535. if (ulClrUsed != 0)
  536. {
  537. if (ulClrUsed < cColors)
  538. {
  539. cColors = ulClrUsed;
  540. }
  541. }
  542. //
  543. // Intitialize the palette
  544. //
  545. if (cColors)
  546. {
  547. ASSERTGDI(iUsage != DIB_PAL_INDICES, "ERROR logic error, should have returned FALSE");
  548. switch (iUsage)
  549. {
  550. case DIB_RGB_COLORS:
  551. if (cjMaxInitInfo < (cColors * 4))
  552. {
  553. WARNING1("CreateDIBitmap failed DIB_RGB_COLORS size buffer RGBQUAD\n");
  554. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  555. return(0);
  556. }
  557. //
  558. // Copy bitmap color table into palette
  559. //
  560. if (IS_CMYK_BITMAP(uiCompression))
  561. {
  562. palPerm.vCopy_cmykquad(pulColors, 0, cColors);
  563. }
  564. else
  565. {
  566. palPerm.vCopy_rgbquad((RGBQUAD *) pulColors, 0, cColors);
  567. }
  568. //
  569. // NOPALETTE is a private option for DirectDraw to permit the
  570. // DIBSection to share its colour table with the display.
  571. //
  572. if ((fl & CDBI_NOPALETTE) && (dbmi.iFormat == BMF_8BPP))
  573. {
  574. BOOL b;
  575. DCOBJ dco(hdc);
  576. b = FALSE;
  577. if (dco.bValid())
  578. {
  579. PDEVOBJ po(dco.hdev());
  580. //
  581. // Acquire the devlock to protect us from a dynamic mode
  582. // change while we muck with po.ppalSurf():
  583. //
  584. DEVLOCKOBJ dlo(po);
  585. if ((po.iDitherFormat() == BMF_8BPP) &&
  586. (po.bIsPalManaged()) &&
  587. (po.bDisplayPDEV()))
  588. {
  589. b = TRUE;
  590. palPerm.apalColorSet(po.ppalSurf());
  591. }
  592. }
  593. if (!b)
  594. {
  595. WARNING("Display not 8bpp, failing CreateDIBSection(CDBI_NOPALETTE)");
  596. return(0);
  597. }
  598. }
  599. break;
  600. case DIB_PAL_COLORS:
  601. {
  602. PUSHORT pusIndices;
  603. if (cjMaxInitInfo < (cColors * sizeof(USHORT)))
  604. {
  605. WARNING1("CreateDIBitmap failed DIB_PAL_COLORS size buffer USHORT\n");
  606. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  607. return(0);
  608. }
  609. pusIndices = (PUSHORT) pulColors;
  610. //
  611. // Validate the DC.
  612. //
  613. DCOBJ dco(hdc);
  614. if (!dco.bValid())
  615. {
  616. WARNING1("CreateDIBitmap failed CBM_CREATEDIB because DIB_PAL_COLORS and invalid DC\n");
  617. return(0);
  618. }
  619. {
  620. //
  621. // Hold the Devlock while munging around in the
  622. // surface to protect against dynamic mode changing.
  623. //
  624. DEVLOCKOBJ dlo;
  625. dlo.vLockNoDrawing(dco);
  626. SURFACE *pSurf = dco.pSurfaceEff();
  627. PDEVOBJ po(dco.hdev());
  628. XEPALOBJ palSurf(pSurf->ppal() ? pSurf->ppal() : po.ppalSurf());
  629. XEPALOBJ palDC(dco.ppal());
  630. palPerm.vGetEntriesFrom(palDC, palSurf, pusIndices, cColors);
  631. }
  632. }
  633. break;
  634. case DIB_PAL_NONE:
  635. //
  636. // This is so CreateDIBPatternBrush can call off to this to do the
  637. // work and then init the palette himself.
  638. //
  639. break;
  640. }
  641. }
  642. if (ppvBits)
  643. {
  644. *ppvBits = SurfDimo.ps->pvBits();
  645. }
  646. //
  647. // Make the palette a keeper and return.
  648. //
  649. SurfDimo.ps->vSetApiBitmap();
  650. SurfDimo.vKeepIt();
  651. palPerm.vKeepIt();
  652. return((HBITMAP)SurfDimo.ps->hsurf());
  653. }
  654. /******************************Public*Routine******************************\
  655. * GreSetDIBitsInternal
  656. *
  657. * API function - Sets the bits of a DIB to a bitmap.
  658. *
  659. * Arguments:
  660. *
  661. * hdc - handle of device context
  662. * hbmp - handle of bitmap
  663. * iStartScan - starting scan line
  664. * cNumScans - number of scan lines
  665. * pInitBits - array of bitmap bits
  666. * pInitInfo - address of structure with bitmap data
  667. * iUsage - type of color indices to use
  668. * cjMaxBits - maximum size of pInitBits
  669. * cjMaxInfo - maximum size of cjMaxInfo
  670. * hcmXform - handle of color transformation (optional)
  671. *
  672. * History:
  673. *
  674. * 12-Mar-1991 -by- Patrick Haluptzok patrickh
  675. \**************************************************************************/
  676. int
  677. APIENTRY
  678. GreSetDIBits(
  679. HDC hdc,
  680. HBITMAP hbm,
  681. UINT iStartScans,
  682. UINT cNumScans,
  683. LPBYTE pInitBits,
  684. LPBITMAPINFO pInitInfo,
  685. UINT iUsage)
  686. {
  687. PBITMAPINFO pbmi = pInitInfo;
  688. INT iRet;
  689. //
  690. // if it is a COREHEADER, covert it
  691. //
  692. if (pInitInfo && (pInitInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)))
  693. {
  694. pbmi = pbmiConvertInfo (pInitInfo, iUsage);
  695. }
  696. //
  697. // Cannot support the device passthrough formats (BI_JPEG, BI_PNG).
  698. //
  699. if (IS_BMI_PASSTHROUGH_IMAGE(pInitInfo))
  700. {
  701. WARNING1("GreSetDIBits invalid pInitBits\n");
  702. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  703. return(0);
  704. }
  705. iRet = GreSetDIBitsInternal(
  706. hdc,
  707. hbm,
  708. iStartScans,
  709. cNumScans,
  710. pInitBits,
  711. pbmi,
  712. iUsage,
  713. (UINT)~0,
  714. (UINT)~0,
  715. NULL);
  716. if (pbmi && (pbmi != pInitInfo))
  717. {
  718. VFREEMEM (pbmi);
  719. }
  720. return (iRet);
  721. }
  722. int
  723. APIENTRY
  724. GreSetDIBitsInternal(
  725. HDC hdc,
  726. HBITMAP hbm,
  727. UINT iStartScans,
  728. UINT cNumScans,
  729. LPBYTE pInitBits,
  730. LPBITMAPINFO pInitInfo,
  731. UINT iUsage,
  732. UINT cjMaxBits,
  733. UINT cjMaxInfo,
  734. HANDLE hcmXform)
  735. {
  736. //
  737. // Lock down and validate the bitmap. Make sure it's a bitmap.
  738. //
  739. HDC hdcTemp;
  740. HPALETTE hpalTemp = (HPALETTE) 0;
  741. HBITMAP hbmTemp;
  742. int iReturn = 0;
  743. BOOL bMakeDC = FALSE;
  744. ULONG cx;
  745. ULONG cy;
  746. //
  747. // Validate header and cannot support the device
  748. // passthrough formats (BI_JPEG, BI_PNG).
  749. //
  750. if ((pInitInfo == (LPBITMAPINFO) NULL) ||
  751. IS_BMI_PASSTHROUGH_IMAGE(pInitInfo))
  752. {
  753. WARNING1("GreSetDIBitsInternal failed - pInitInfo is invalid\n");
  754. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  755. }
  756. else
  757. {
  758. ASSERTGDI (pInitInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER), "setdibitstodevice,bad size\n");
  759. cx = pInitInfo->bmiHeader.biWidth;
  760. if (pInitInfo->bmiHeader.biHeight < 0)
  761. {
  762. cy = -pInitInfo->bmiHeader.biHeight;
  763. }
  764. else
  765. {
  766. cy = pInitInfo->bmiHeader.biHeight;
  767. }
  768. SURFREF soDest((HSURF)hbm);
  769. if ((!soDest.bValid()) || (!soDest.ps->bApiBitmap()))
  770. {
  771. WARNING1("SetDIBits failed - Bitmap is not valid\n");
  772. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  773. }
  774. else
  775. {
  776. if (soDest.ps->cRef() != 0)
  777. {
  778. hdcTemp = soDest.ps->hdc();
  779. }
  780. else
  781. {
  782. hdcTemp = (HDC) NULL;
  783. }
  784. if (hdcTemp == (HDC) NULL)
  785. {
  786. hdcTemp = GreCreateCompatibleDC(hdc);
  787. bMakeDC = TRUE;
  788. if (hdcTemp == (HDC) NULL)
  789. {
  790. WARNING1("GreSetDIBits failed CreateCompatibleDC, is hdc valid?\n");
  791. }
  792. }
  793. if (hdcTemp != (HDC)NULL)
  794. {
  795. BOOL bSuccess = TRUE;
  796. if (hdc != (HDC) NULL)
  797. {
  798. DCOBJ dco(hdc);
  799. if (!dco.bValid())
  800. {
  801. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  802. WARNING1("SetDIBits failed - hdc is invalid\n");
  803. bSuccess = FALSE;
  804. }
  805. else
  806. {
  807. hpalTemp = (HPALETTE) GreSelectPalette(hdcTemp, (HPALETTE)dco.hpal(), (BOOL)TRUE);
  808. }
  809. }
  810. if (bSuccess)
  811. {
  812. hbmTemp = (HBITMAP)GreSelectBitmap(hdcTemp, (HBITMAP)hbm);
  813. if (hbmTemp == (HBITMAP) 0)
  814. {
  815. WARNING1("GreSetDIBits failed to Select, is bitmap valid?\n");
  816. }
  817. else
  818. {
  819. iReturn = GreSetDIBitsToDeviceInternal(
  820. hdcTemp,
  821. 0,
  822. 0,
  823. cx,
  824. cy,
  825. 0,
  826. 0,
  827. iStartScans,
  828. cNumScans,
  829. pInitBits,
  830. pInitInfo,
  831. iUsage,
  832. cjMaxBits,
  833. cjMaxInfo,
  834. FALSE,
  835. hcmXform
  836. );
  837. if (hpalTemp != (HPALETTE) 0)
  838. {
  839. GreSelectPalette(hdcTemp, hpalTemp, TRUE);
  840. }
  841. GreSelectBitmap(hdcTemp, (HBITMAP)hbmTemp);
  842. }
  843. }
  844. if (bMakeDC)
  845. {
  846. bDeleteDCInternal(hdcTemp,TRUE,FALSE);
  847. }
  848. }
  849. }
  850. }
  851. return(iReturn);
  852. }
  853. /******************************Public*Routine******************************\
  854. * GreSetDIBitsToDevice
  855. *
  856. * API entry point for blting DIBS to a DC.
  857. *
  858. * Arguments:
  859. *
  860. * hdcDest - handle of device context
  861. * xDst - x-coordinate of upper-left corner of dest. rect.
  862. * yDst - y-coordinate of upper-left corner of dest. rect.
  863. * cx - source rectangle width
  864. * cy - source rectangle height
  865. * xSrc - x-coordinate of lower-left corner of source rect.
  866. * ySrc - y-coordinate of lower-left corner of source rect.
  867. * iStartScan - first scan line in array
  868. * cNumScan - number of scan lines
  869. * pInitBits - address of array with DIB bits
  870. * pInfoHeader - address of structure with bitmap info.
  871. * iUsage - RGB or palette indices
  872. * cjMaxBits - maximum soace of pInitBits
  873. * cjMaxInfo - maximum soace ofpInfoHeader
  874. * bTransformCoordinates - Transform necessary
  875. *
  876. * Return Value:
  877. *
  878. * Number of scan lines set or 0 for error
  879. *
  880. * History:
  881. *
  882. * 12-Mar-1991 -by- Patrick Haluptzok patrickh
  883. \**************************************************************************/
  884. // I believe nobody should be calling this, but just in case... (erick)
  885. // The internal version is called by server.c
  886. int
  887. APIENTRY
  888. GreSetDIBitsToDevice(
  889. HDC hdcDest,
  890. int xDst,
  891. int yDst,
  892. DWORD cx,
  893. DWORD cy,
  894. int xSrc,
  895. int ySrc,
  896. DWORD iStartScan,
  897. DWORD cNumScan,
  898. LPBYTE pInitBits,
  899. LPBITMAPINFO pInfoHeader,
  900. DWORD iUsage)
  901. {
  902. return(GreSetDIBitsToDeviceInternal(
  903. hdcDest,
  904. xDst,
  905. yDst,
  906. cx,
  907. cy,
  908. xSrc,
  909. ySrc,
  910. iStartScan,
  911. cNumScan,
  912. pInitBits,
  913. pInfoHeader,
  914. iUsage,
  915. (UINT)~0,
  916. (UINT)~0,
  917. TRUE,
  918. NULL));
  919. }
  920. int
  921. APIENTRY
  922. GreSetDIBitsToDeviceInternal(
  923. HDC hdcDest,
  924. int xDst,
  925. int yDst,
  926. DWORD cx,
  927. DWORD cy,
  928. int xSrc,
  929. int ySrc,
  930. DWORD iStartScan,
  931. DWORD cNumScan,
  932. LPBYTE pInitBits,
  933. LPBITMAPINFO pInfoHeader,
  934. DWORD iUsage,
  935. UINT cjMaxBits,
  936. UINT cjMaxInfo,
  937. BOOL bTransformCoordinates,
  938. HANDLE hcmXform)
  939. {
  940. // If the dc is mirrored then make x point to the most left point.
  941. if (GreGetLayout(hdcDest) & LAYOUT_RTL) {
  942. xDst += (cx - 1);
  943. }
  944. //
  945. // Size of bitmap info header, copy out, it can change async.
  946. //
  947. ULONG ulSize;
  948. //
  949. // Let's validate the parameters so we don't gp-fault ourselves and
  950. // to save checks later on.
  951. //
  952. if ((pInfoHeader == (LPBITMAPINFO) NULL) ||
  953. (pInitBits == (LPBYTE) NULL) ||
  954. ((iUsage != DIB_RGB_COLORS) &&
  955. (iUsage != DIB_PAL_COLORS) &&
  956. (iUsage != DIB_PAL_INDICES)) ||
  957. (cjMaxInfo < sizeof(BITMAPINFOHEADER)) ||
  958. ( pInfoHeader->bmiHeader.biSize < sizeof(BITMAPINFOHEADER)))
  959. {
  960. WARNING1("GreSetDIBitsToDevice failed because 1 of last 3 params is invalid\n");
  961. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  962. return(0);
  963. }
  964. ulSize = pInfoHeader->bmiHeader.biSize;
  965. //
  966. // Get the info from the Header depending upon what kind it is.
  967. //
  968. UINT uiBitCount, uiCompression, uiWidth, uiPalUsed;
  969. LONG lHeight;
  970. PULONG pulColors;
  971. DEVBITMAPINFO dbmi;
  972. dbmi.fl = 0;
  973. dbmi.hpal = 0;
  974. uiBitCount = (UINT) pInfoHeader->bmiHeader.biBitCount;
  975. uiCompression = (UINT) pInfoHeader->bmiHeader.biCompression;
  976. uiWidth = (UINT) pInfoHeader->bmiHeader.biWidth;
  977. lHeight = pInfoHeader->bmiHeader.biHeight;
  978. uiPalUsed = (UINT) pInfoHeader->bmiHeader.biClrUsed;
  979. pulColors = (PULONG) ((LPBYTE)pInfoHeader+ulSize);
  980. if (lHeight < 0)
  981. {
  982. dbmi.fl = BMF_TOPDOWN;
  983. if ((uiCompression != BI_RGB) && (uiCompression != BI_BITFIELDS) &&
  984. (uiCompression != BI_JPEG) && (uiCompression != BI_PNG) &&
  985. (uiCompression != BI_CMYK) && (uiCompression != BI_CMYKRLE4) &&
  986. (uiCompression != BI_CMYKRLE8))
  987. {
  988. WARNING1("GreSetDIBits: TOP_DOWN RLE not allowed\n");
  989. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  990. return (0);
  991. }
  992. lHeight = -lHeight;
  993. }
  994. //
  995. // Now that cjMaxInfo has been validated for the header, adjust it to refer to
  996. // the color table
  997. //
  998. cjMaxInfo -= (UINT)ulSize;
  999. //
  1000. // Figure out what this guy is blting from.
  1001. //
  1002. ULONG cColorsMax;
  1003. FLONG iPalMode;
  1004. FLONG iPalType;
  1005. FLONG flRed;
  1006. FLONG flGre;
  1007. FLONG flBlu;
  1008. BOOL bRLE = FALSE;
  1009. if (uiCompression == BI_BITFIELDS)
  1010. {
  1011. //
  1012. // Handle 16 and 32 bit per pel bitmaps.
  1013. //
  1014. if ((ulSize <= sizeof(BITMAPINFOHEADER)) && (cjMaxInfo < (sizeof(ULONG) * 3)))
  1015. {
  1016. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1017. WARNING1("SetDIBitsToDevice 16/32bpp failed - not room for flags\n");
  1018. return(0);
  1019. }
  1020. if (iUsage == DIB_PAL_COLORS)
  1021. {
  1022. iUsage = DIB_RGB_COLORS;
  1023. }
  1024. switch (uiBitCount)
  1025. {
  1026. case 16:
  1027. dbmi.iFormat = BMF_16BPP;
  1028. break;
  1029. case 32:
  1030. dbmi.iFormat = BMF_32BPP;
  1031. break;
  1032. default:
  1033. WARNING1("SetDIBitsToDevice failed for BI_BITFIELDS\n");
  1034. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1035. return(0);
  1036. }
  1037. //
  1038. // if BITMAPV4 or greater then masks are stored in info header
  1039. //
  1040. if (ulSize > sizeof(BITMAPINFOHEADER))
  1041. {
  1042. pulColors = (PULONG) ((LPBYTE)pInfoHeader+sizeof(BITMAPINFOHEADER));
  1043. }
  1044. flRed = pulColors[0];
  1045. flGre = pulColors[1];
  1046. flBlu = pulColors[2];
  1047. cColorsMax = 0;
  1048. iPalMode = PAL_BITFIELDS;
  1049. iPalType = PAL_FIXED;
  1050. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * cNumScan;
  1051. }
  1052. else if (uiCompression == BI_RGB)
  1053. {
  1054. switch (uiBitCount)
  1055. {
  1056. case 1:
  1057. dbmi.iFormat = BMF_1BPP;
  1058. cColorsMax = 2;
  1059. iPalMode = PAL_INDEXED;
  1060. iPalType = PAL_FREE;
  1061. break;
  1062. case 4:
  1063. dbmi.iFormat = BMF_4BPP;
  1064. cColorsMax = 16;
  1065. iPalMode = PAL_INDEXED;
  1066. iPalType = PAL_FREE;
  1067. break;
  1068. case 8:
  1069. dbmi.iFormat = BMF_8BPP;
  1070. cColorsMax = 256;
  1071. iPalMode = PAL_INDEXED;
  1072. iPalType = PAL_FREE;
  1073. break;
  1074. default:
  1075. if (iUsage == DIB_PAL_COLORS)
  1076. {
  1077. iUsage = DIB_RGB_COLORS;
  1078. }
  1079. cColorsMax = 0;
  1080. iPalType = PAL_FIXED;
  1081. switch (uiBitCount)
  1082. {
  1083. case 16:
  1084. dbmi.iFormat = BMF_16BPP;
  1085. flRed = 0x7c00;
  1086. flGre = 0x03e0;
  1087. flBlu = 0x001f;
  1088. iPalMode = PAL_BITFIELDS;
  1089. break;
  1090. case 24:
  1091. dbmi.iFormat = BMF_24BPP;
  1092. iPalMode = PAL_BGR;
  1093. break;
  1094. case 32:
  1095. dbmi.iFormat = BMF_32BPP;
  1096. iPalMode = PAL_BGR;
  1097. break;
  1098. default:
  1099. WARNING1("SetDIBitsToDevice failed invalid bitcount in bmi BI_RGB\n");
  1100. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1101. return(0);
  1102. }
  1103. }
  1104. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * cNumScan;
  1105. }
  1106. else if (uiCompression == BI_CMYK)
  1107. {
  1108. ASSERTGDI(iUsage == DIB_RGB_COLORS,
  1109. "SetDIBitsToDevice(BI_CMYK):iUsage should be DIB_RGB_COLORS\n");
  1110. DCOBJ dcoDest(hdcDest);
  1111. //
  1112. // Current device context accept CMYK color ?
  1113. //
  1114. if (!dcoDest.bValid() || !dcoDest.pdc->bIsCMYKColor())
  1115. {
  1116. WARNING1("SetDIBitsToDevice:DC is not in CMYK color mode for BI_CMYK\n");
  1117. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1118. return(0);
  1119. }
  1120. switch (uiBitCount)
  1121. {
  1122. case 1:
  1123. dbmi.iFormat = BMF_1BPP;
  1124. cColorsMax = 2;
  1125. iPalMode = PAL_INDEXED;
  1126. iPalType = PAL_FREE;
  1127. break;
  1128. case 4:
  1129. dbmi.iFormat = BMF_4BPP;
  1130. cColorsMax = 16;
  1131. iPalMode = PAL_INDEXED;
  1132. iPalType = PAL_FREE;
  1133. break;
  1134. case 8:
  1135. dbmi.iFormat = BMF_8BPP;
  1136. cColorsMax = 256;
  1137. iPalMode = PAL_INDEXED;
  1138. iPalType = PAL_FREE;
  1139. break;
  1140. case 32:
  1141. dbmi.iFormat = BMF_32BPP;
  1142. cColorsMax = 0;
  1143. iPalMode = PAL_CMYK;
  1144. iPalType = PAL_FIXED;
  1145. break;
  1146. default:
  1147. WARNING1("SetDIBitsToDevice failed invalid bitcount in bmi BI_CMYK\n");
  1148. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1149. return(0);
  1150. }
  1151. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * cNumScan;
  1152. }
  1153. else if ((uiCompression == BI_RLE4) || (uiCompression == BI_CMYKRLE4))
  1154. {
  1155. if (uiCompression == BI_CMYKRLE4)
  1156. {
  1157. ASSERTGDI(iUsage == DIB_RGB_COLORS,
  1158. "SetDIBitsToDevice(BI_CMYKRLE4):iUsage should be DIB_RGB_COLORS\n");
  1159. DCOBJ dcoDest(hdcDest);
  1160. //
  1161. // Current device context accept CMYK color ?
  1162. //
  1163. if (!dcoDest.bValid() || !dcoDest.pdc->bIsCMYKColor())
  1164. {
  1165. WARNING1("SetDIBitsToDevice:DC is not in CMYK color mode for BI_CMYKRLE4\n");
  1166. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1167. return(0);
  1168. }
  1169. }
  1170. if (uiBitCount != 4)
  1171. {
  1172. WARNING1("SetDIBitsToDevice invalid bitcount BI_RLE4\n");
  1173. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1174. return(0);
  1175. }
  1176. dbmi.iFormat = BMF_4RLE;
  1177. cColorsMax = 16;
  1178. iPalMode = PAL_INDEXED;
  1179. iPalType = PAL_FREE;
  1180. iStartScan = 0;
  1181. cNumScan = lHeight;
  1182. dbmi.cjBits = pInfoHeader->bmiHeader.biSizeImage;
  1183. bRLE = TRUE;
  1184. }
  1185. else if ((uiCompression == BI_RLE8) || (uiCompression == BI_CMYKRLE8))
  1186. {
  1187. if (uiCompression == BI_CMYKRLE8)
  1188. {
  1189. ASSERTGDI(iUsage == DIB_RGB_COLORS,
  1190. "SetDIBitsToDevice(BI_CMYKRLE8):iUsage should be DIB_RGB_COLORS\n");
  1191. DCOBJ dcoDest(hdcDest);
  1192. //
  1193. // Current dc context accept CMYK color ?
  1194. //
  1195. if (!dcoDest.bValid() || !dcoDest.pdc->bIsCMYKColor())
  1196. {
  1197. WARNING1("SetDIBitsToDevice:DC is not in CMYK color mode for BI_CMYKRLE8\n");
  1198. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1199. return(0);
  1200. }
  1201. }
  1202. if (uiBitCount != 8)
  1203. {
  1204. WARNING1("SetDIBitsToDevice invalid bitcount BI_RLE8\n");
  1205. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1206. return(0);
  1207. }
  1208. dbmi.iFormat = BMF_8RLE;
  1209. cColorsMax = 256;
  1210. iPalMode = PAL_INDEXED;
  1211. iPalType = PAL_FREE;
  1212. iStartScan = 0;
  1213. cNumScan = lHeight;
  1214. dbmi.cjBits = pInfoHeader->bmiHeader.biSizeImage;
  1215. bRLE = TRUE;
  1216. }
  1217. else if (uiCompression == BI_JPEG)
  1218. {
  1219. //
  1220. // The XLATEOBJ we setup for BI_JPEG is only valid for
  1221. // querying the ICM flags in the flXlate member.
  1222. //
  1223. dbmi.iFormat = BMF_JPEG;
  1224. cColorsMax = 0;
  1225. iPalMode = PAL_BGR;
  1226. iPalType = PAL_FIXED;
  1227. iStartScan = 0;
  1228. //cNumScan = lHeight;
  1229. dbmi.cjBits = pInfoHeader->bmiHeader.biSizeImage;
  1230. }
  1231. else if (uiCompression == BI_PNG)
  1232. {
  1233. //
  1234. // The XLATEOBJ we setup for BI_PNG is only valid for
  1235. // querying the ICM flags in the flXlate member.
  1236. //
  1237. dbmi.iFormat = BMF_PNG;
  1238. cColorsMax = 0;
  1239. iPalMode = PAL_BGR;
  1240. iPalType = PAL_FIXED;
  1241. iStartScan = 0;
  1242. //cNumScan = lHeight;
  1243. dbmi.cjBits = pInfoHeader->bmiHeader.biSizeImage;
  1244. }
  1245. else
  1246. {
  1247. WARNING1("GreSetDIBitsToDevice failed invalid Compression in header\n");
  1248. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1249. return(0);
  1250. }
  1251. ULONG cColors;
  1252. if (uiPalUsed != 0)
  1253. {
  1254. if (uiPalUsed <= cColorsMax)
  1255. {
  1256. cColors = uiPalUsed;
  1257. }
  1258. else
  1259. {
  1260. cColors = cColorsMax;
  1261. }
  1262. }
  1263. else
  1264. {
  1265. cColors = cColorsMax;
  1266. }
  1267. if (cjMaxBits < dbmi.cjBits)
  1268. {
  1269. WARNING1("GreSetDIBitsToDevice failed because of invalid cjMaxBits\n");
  1270. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1271. return(0);
  1272. }
  1273. dbmi.cxBitmap = uiWidth;
  1274. dbmi.cyBitmap = (IS_PASSTHROUGH_IMAGE(uiCompression)) ? lHeight
  1275. : cNumScan;
  1276. //
  1277. // Lock the destination DC.
  1278. //
  1279. // This is our first constructor/destructor so from here on out
  1280. // we need to minimize the number of returns. Each return generates
  1281. // a bunch of destructors, bloating the code size.
  1282. //
  1283. DCOBJ dcoDest(hdcDest);
  1284. if (dcoDest.bValid())
  1285. {
  1286. PDEVOBJ po(dcoDest.hdev());
  1287. EPOINTL eptlDst(xDst,yDst);
  1288. //
  1289. // Check for state incompatible with BI_JPEG or BI_PNG support.
  1290. //
  1291. if (IS_PASSTHROUGH_IMAGE(pInfoHeader->bmiHeader.biCompression))
  1292. {
  1293. //
  1294. // Device must support image format
  1295. // No rotations allowed (checked below)
  1296. // DIB_RGB_COLORS only
  1297. // No hcmXform
  1298. //
  1299. if (!dcoDest.bSupportsPassthroughImage(pInfoHeader->bmiHeader.biCompression) ||
  1300. (iUsage != DIB_RGB_COLORS) || hcmXform)
  1301. {
  1302. //
  1303. // Return 0 for error.
  1304. //
  1305. WARNING("SetDIBitsToDevice -- invalid BI_JPEG/BI_PNG operation\n");
  1306. cNumScan = 0;
  1307. }
  1308. }
  1309. if (bTransformCoordinates)
  1310. {
  1311. EXFORMOBJ xoDest(dcoDest, WORLD_TO_DEVICE);
  1312. //
  1313. // Transform the dest point to DEVICE coordinates.
  1314. //
  1315. xoDest.bXform(eptlDst);
  1316. //
  1317. // Check for state incompatible with BI_JPEG or BI_PNG support.
  1318. //
  1319. if (cNumScan &&
  1320. IS_PASSTHROUGH_IMAGE(pInfoHeader->bmiHeader.biCompression))
  1321. {
  1322. //
  1323. // No rotations allowed
  1324. //
  1325. if (xoDest.bRotation())
  1326. {
  1327. //
  1328. // Return 0 for error.
  1329. //
  1330. WARNING("SetDIBitsToDevice -- invalid BI_JPEG/BI_PNG operation\n");
  1331. cNumScan = 0;
  1332. }
  1333. }
  1334. }
  1335. //
  1336. // Make the rectangle well ordered.
  1337. //
  1338. ERECTL erclDest(eptlDst.x, eptlDst.y, eptlDst.x + cx, eptlDst.y + cy);
  1339. erclDest.vOrder();
  1340. if (!erclDest.bEmpty() && cNumScan)
  1341. {
  1342. //
  1343. // Accumulate bounds. We can do this before knowing if the operation is
  1344. // successful because bounds can be loose.
  1345. //
  1346. if (dcoDest.fjAccum())
  1347. {
  1348. dcoDest.vAccumulate(erclDest);
  1349. }
  1350. //
  1351. // Lock the Rao region if we are drawing on a display surface. The Rao
  1352. // region might otherwise change asynchronously. The DEVLOCKOBJ also makes
  1353. // sure that the VisRgn is up to date, calling the window manager if
  1354. // necessary to recompute it. It also protects us from having the
  1355. // surface change asynchronously by a dynamic mode change.
  1356. //
  1357. DEVLOCKOBJ dlo(dcoDest);
  1358. SURFACE *pSurfDest = dcoDest.pSurface();
  1359. //
  1360. // Return null operations.
  1361. //
  1362. if (pSurfDest != NULL)
  1363. {
  1364. //
  1365. // if color transform is not specified, use DC's color transform.
  1366. //
  1367. if (hcmXform == NULL)
  1368. {
  1369. hcmXform = dcoDest.pdc->hcmXform();
  1370. }
  1371. else
  1372. {
  1373. ICMMSG(("GreSetDIBitsToDeviceInternal():Bitmap has thier own colorspace\n"));
  1374. }
  1375. ULONG lIcmMode = dcoDest.pdc->lIcmMode();
  1376. if (IS_CMYK_COLOR(lIcmMode)) /* DC is CMYK color mode ? */
  1377. {
  1378. if ((hcmXform == NULL) || !IS_CMYK_BITMAP(uiCompression))
  1379. {
  1380. //
  1381. // DC mode is CMYK color, but bitmap itself is not.
  1382. // so clear CMYK color bit, so that XLATEOBJ will not
  1383. // have XO_FROM_CMYK
  1384. //
  1385. CLEAR_COLORTYPE(lIcmMode);
  1386. //
  1387. // then it's RGB.
  1388. //
  1389. lIcmMode |= DC_ICM_RGB_COLOR;
  1390. }
  1391. }
  1392. //
  1393. // Allocate a palette for this bitmap
  1394. //
  1395. PALMEMOBJ palTemp;
  1396. XEPALOBJ palDest(pSurfDest->ppal());
  1397. XEPALOBJ palDestDC(dcoDest.ppal());
  1398. //
  1399. // Associate the DC's palette with the bitmap for use when
  1400. // converting DDBs to DIBs for dynamic mode changes.
  1401. //
  1402. if (!palDestDC.bIsPalDefault())
  1403. {
  1404. pSurfDest->hpalHint(palDestDC.hpal());
  1405. }
  1406. //
  1407. // bSuccess gets set to FALSE only if the following switch
  1408. // executes with error. We do this to avoid doing a
  1409. // return from the switch statement.
  1410. //
  1411. BOOL bSuccess = TRUE;
  1412. BOOL bNeedAssociatePalette = FALSE;
  1413. XLATEOBJ *pxlo;
  1414. EXLATEOBJ xlo;
  1415. switch (iUsage)
  1416. {
  1417. case DIB_RGB_COLORS:
  1418. if (palTemp.bCreatePalette(iPalMode, cColorsMax, (PULONG) NULL,
  1419. flRed, flGre, flBlu, iPalType))
  1420. {
  1421. if (cColors)
  1422. {
  1423. if (cjMaxInfo < (cColors * 4))
  1424. {
  1425. WARNING1("SetDIBitsToDevice failed DIB_RGB_COLORS bmi invalid size\n");
  1426. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1427. bSuccess = FALSE;
  1428. }
  1429. else
  1430. {
  1431. //
  1432. // Copy bitmap color table into palette
  1433. //
  1434. if (IS_CMYK_BITMAP(uiCompression))
  1435. {
  1436. palTemp.vCopy_cmykquad(pulColors, 0, cColors);
  1437. }
  1438. else
  1439. {
  1440. palTemp.vCopy_rgbquad((RGBQUAD *) pulColors, 0, cColors);
  1441. }
  1442. }
  1443. if (bSuccess)
  1444. {
  1445. //
  1446. // This is a special version of the constructor that doesn't search the
  1447. // cache and doesn't put it in the cache when it's done.
  1448. //
  1449. if (xlo.pInitXlateNoCache(
  1450. hcmXform,
  1451. lIcmMode,
  1452. palTemp,
  1453. palDest,
  1454. palDestDC,
  1455. 0,
  1456. 0,
  1457. 0x00FFFFFF
  1458. )
  1459. )
  1460. {
  1461. pxlo = xlo.pxlo();
  1462. }
  1463. else
  1464. {
  1465. //
  1466. // Error is logged by bMakeXlate.
  1467. //
  1468. WARNING1("GreSetDIBitsToDevice failed XLATE init because of low memory\n");
  1469. bSuccess = FALSE;
  1470. }
  1471. }
  1472. }
  1473. else
  1474. {
  1475. //
  1476. // This is a special version of the constructor that doesn't search the
  1477. // cache and doesn't put it in the cache when it's done.
  1478. //
  1479. if (bSuccess)
  1480. {
  1481. if (xlo.pInitXlateNoCache(
  1482. hcmXform,
  1483. lIcmMode,
  1484. palTemp,
  1485. palDest,
  1486. palDestDC,
  1487. 0,
  1488. 0,
  1489. 0x00FFFFFF
  1490. )
  1491. )
  1492. {
  1493. pxlo = xlo.pxlo();
  1494. }
  1495. else
  1496. {
  1497. //
  1498. // Error is logged by bMakeXlate.
  1499. //
  1500. WARNING1("GreSetDIBitsToDevice failed XLATE init because of low memory\n");
  1501. bSuccess = FALSE;
  1502. }
  1503. }
  1504. }
  1505. }
  1506. else
  1507. {
  1508. WARNING1("Failed palette creation in SetDIBitsToDevice\n");
  1509. bSuccess = FALSE;
  1510. }
  1511. break;
  1512. case DIB_PAL_COLORS:
  1513. if (cjMaxInfo < (cColors * sizeof(USHORT)))
  1514. {
  1515. WARNING1("SetDIBitsToDevice failed DIB_PAL_COLORS is invalid\n");
  1516. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1517. bSuccess = FALSE;
  1518. }
  1519. else
  1520. {
  1521. if (!xlo.bMakeXlate((PUSHORT) pulColors, palDestDC, pSurfDest, cColors, cColorsMax))
  1522. {
  1523. WARNING1("GDISRV GreSetDIBitsToDevice failed bMakeXlate\n");
  1524. bSuccess = FALSE;
  1525. }
  1526. else
  1527. {
  1528. pxlo = xlo.pxlo();
  1529. //
  1530. // If we are drawing to display meta-screen with multi-monitor system
  1531. // and it's colour-depth is not same for all those monitor.
  1532. // we need to create palette to map color to other-than primary
  1533. // monitor(s).
  1534. //
  1535. if (gbMultiMonMismatchColor && po.bDisplayPDEV())
  1536. {
  1537. if (palTemp.bCreatePalette(iPalMode, cColorsMax, (PULONG) NULL,
  1538. flRed, flGre, flBlu, iPalType))
  1539. {
  1540. XEPALOBJ palSurfEff(pSurfDest->ppal() ? pSurfDest->ppal() : po.ppalSurf());
  1541. //
  1542. // Keep DC (or Surface) palette entry to temporay palette.
  1543. //
  1544. palTemp.vGetEntriesFrom(palDestDC, palSurfEff, (PUSHORT)pulColors, cColors);
  1545. bNeedAssociatePalette = TRUE;
  1546. }
  1547. }
  1548. }
  1549. }
  1550. break;
  1551. case DIB_PAL_INDICES:
  1552. ULONG iFormatDC = pSurfDest->iFormat();
  1553. if ((iFormatDC == dbmi.iFormat) ||
  1554. ((iFormatDC == BMF_4BPP) && (dbmi.iFormat == BMF_4RLE)) ||
  1555. ((iFormatDC == BMF_8BPP) && (dbmi.iFormat == BMF_8RLE)))
  1556. {
  1557. pxlo = &xloIdent;
  1558. }
  1559. else
  1560. {
  1561. WARNING1("SetDIBitsToDevice failed - DIB_PAL_INDICES used - DIB not format of Dst\n");
  1562. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1563. bSuccess = FALSE;
  1564. }
  1565. }
  1566. //
  1567. // Attempt to allocate the bitmap from handle manager.
  1568. //
  1569. SURFMEM SurfDimoTemp;
  1570. SurfDimoTemp.bCreateDIB(&dbmi, (PVOID) pInitBits);
  1571. if (bSuccess && (SurfDimoTemp.bValid()))
  1572. {
  1573. //
  1574. // Bug #69739
  1575. //
  1576. // Set uniqueness to zero so that it will not be cached by
  1577. // a driver (NetMeeting for example) down below.
  1578. //
  1579. SurfDimoTemp.ps->iUniq(0);
  1580. if (dlo.bValid())
  1581. {
  1582. //
  1583. // With a fixed DC origin we can change the destination to SCREEN coordinates.
  1584. //
  1585. erclDest += dcoDest.eptlOrigin();
  1586. if (bNeedAssociatePalette)
  1587. {
  1588. ASSERTGDI(SurfDimoTemp.ps->ppal() == NULL,
  1589. "SetDIBitsToDevice():Surface has palette already\n");
  1590. SurfDimoTemp.ps->ppal(palTemp.ppalGet());
  1591. }
  1592. //
  1593. // Lock the dest ldev.
  1594. //
  1595. PDEVOBJ pdo(pSurfDest->hdev());
  1596. //
  1597. // Handle RLE bitmaps here. We don't need to adjust src origin or dst rect
  1598. // since we must enumerate through the entire RLE.
  1599. //
  1600. if (bRLE)
  1601. {
  1602. //
  1603. // Compute the clipping complexity and maybe reduce the exclusion rectangle.
  1604. //
  1605. EPOINTL eptlSrc;
  1606. eptlSrc.x = xSrc;
  1607. eptlSrc.y = lHeight - ySrc - cy;
  1608. ECLIPOBJ co(dcoDest.prgnEffRao(), erclDest);
  1609. //
  1610. // Check the destination which is reduced by clipping.
  1611. //
  1612. if (!co.erclExclude().bEmpty())
  1613. {
  1614. //
  1615. // Exclude the pointer.
  1616. //
  1617. DEVEXCLUDEOBJ dxo(dcoDest,&co.erclExclude(),&co);
  1618. //
  1619. // Inc the target surface uniqueness
  1620. //
  1621. INC_SURF_UNIQ(pSurfDest);
  1622. //
  1623. // Dispatch the call. Give it no mask.
  1624. //
  1625. (*PPFNGET(pdo,CopyBits,pSurfDest->flags()))
  1626. (
  1627. pSurfDest->pSurfobj(), // Destination surface.
  1628. SurfDimoTemp.pSurfobj(), // Source surface.
  1629. (CLIPOBJ *)&co, // Clip object.
  1630. pxlo, // Palette translation object.
  1631. (RECTL *) &erclDest, // Destination rectangle.
  1632. (POINTL *) &eptlSrc // Source origin.
  1633. );
  1634. }
  1635. }
  1636. else
  1637. {
  1638. //
  1639. // Handle BitBlts that have a source. Create a rect bounding the
  1640. // src and the bits that have been supplied.
  1641. //
  1642. EPOINTL eptlSrc;
  1643. ERECTL erclReduced;
  1644. eptlSrc.x = xSrc;
  1645. erclReduced.left = 0;
  1646. erclReduced.right = uiWidth;
  1647. eptlSrc.y = lHeight - ySrc - cy;
  1648. //
  1649. // When we are here lHeight is positive. The destination dimensions are
  1650. // determined from the height, iStartScan, and cNumScan.
  1651. //
  1652. erclReduced.top = lHeight - (iStartScan + cNumScan);
  1653. erclReduced.bottom = lHeight - iStartScan;
  1654. EPOINTL eptlOffset;
  1655. eptlOffset.x = erclDest.left - eptlSrc.x;
  1656. eptlOffset.y = erclDest.top - eptlSrc.y;
  1657. //
  1658. // First make sure it doesn't go off the edge of the src bitmap if we had
  1659. // the whole thing.
  1660. //
  1661. erclReduced += eptlOffset;
  1662. erclReduced *= erclDest;
  1663. if (!erclReduced.bEmpty())
  1664. {
  1665. //
  1666. // Compute the clipping complexity and maybe reduce the exclusion rectangle.
  1667. //
  1668. ECLIPOBJ co(dcoDest.prgnEffRao(), erclReduced);
  1669. //
  1670. // Check the destination which is reduced by clipping.
  1671. //
  1672. if (!co.erclExclude().bEmpty())
  1673. {
  1674. erclReduced = co.erclExclude();
  1675. //
  1676. // Compute the (reduced) origin.
  1677. //
  1678. eptlSrc.x = erclReduced.left - eptlOffset.x;
  1679. eptlSrc.y = erclReduced.top - eptlOffset.y;
  1680. //
  1681. // Transform the source point to DEVICE coordinates of the bitmap we
  1682. // have allocated.
  1683. //
  1684. eptlSrc.y -= lHeight - (iStartScan + cNumScan);
  1685. //
  1686. // Exclude the pointer.
  1687. //
  1688. DEVEXCLUDEOBJ dxo(dcoDest,&erclReduced,&co);
  1689. //
  1690. // Inc the target surface uniqueness
  1691. //
  1692. INC_SURF_UNIQ(pSurfDest);
  1693. BOOL bRes = (*PPFNGET(pdo,CopyBits,pSurfDest->flags()))
  1694. (pSurfDest->pSurfobj(), // Destination surface.
  1695. SurfDimoTemp.pSurfobj(), // Source surface.
  1696. (CLIPOBJ *)&co, // Clip object.
  1697. pxlo, // Palette translation object.
  1698. (RECTL *) &erclReduced, // Destination rectangle.
  1699. (POINTL *) &eptlSrc // Source origin.
  1700. );
  1701. if (!bRes)
  1702. {
  1703. WARNING1("GreSetDIBitsToDevice failed DrvCopyBits\n");
  1704. cNumScan = 0;
  1705. }
  1706. }
  1707. }
  1708. }
  1709. if (bNeedAssociatePalette)
  1710. {
  1711. SurfDimoTemp.ps->ppal(NULL);
  1712. }
  1713. }
  1714. }
  1715. else // if (bSuccess && (SurfDimoTemp.bValid()))
  1716. {
  1717. #if DBG
  1718. if (bSuccess)
  1719. {
  1720. WARNING1("Some silly switch failure in SetDIBitsToDevice\n");
  1721. }
  1722. else
  1723. {
  1724. WARNING1("GreSetDIBitsToDevice failed to allocate temporary bitmap\n");
  1725. }
  1726. #endif
  1727. cNumScan = 0;
  1728. }
  1729. }
  1730. else // if (pSurfDest != NULL)
  1731. {
  1732. WARNING1("SetDIBitsToDevice failed - pSurfDst == NULL\n");
  1733. }
  1734. }
  1735. else // if (!erclDest.bEmpty())
  1736. {
  1737. WARNING1("SetDIBitsToDevice failed - empty dst rect\n");
  1738. }
  1739. }
  1740. else // if (!dcoDest.bValid())
  1741. {
  1742. WARNING1("GreSetDIBitsToDevice failed because of invalid hdc parameter\n");
  1743. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1744. cNumScan = 0;
  1745. }
  1746. return(cNumScan);
  1747. }
  1748. /******************************Public*Routine******************************\
  1749. * BOOL bIdenticalFormat
  1750. *
  1751. * checks if the Source surface pal format is the same as the DIB pal format
  1752. * when DIB format is BI_RGB
  1753. *
  1754. * History:
  1755. * 3-Nov-1995 -by- Lingyun Wang [lingyunw]
  1756. * Wrote it.
  1757. \**************************************************************************/
  1758. BOOL bIdenticalFormat (XEPALOBJ palSrc, INT iFormat)
  1759. {
  1760. FLONG flRedSrc, flGreSrc, flBluSrc;
  1761. FLONG flRedDst, flGreDst, flBluDst;
  1762. BOOL bRet = TRUE;
  1763. if (palSrc.bIsBitfields())
  1764. {
  1765. flRedSrc = palSrc.flRed();
  1766. flGreSrc = palSrc.flGre();
  1767. flBluSrc = palSrc.flBlu();
  1768. }
  1769. else
  1770. //
  1771. // RGB, BGR
  1772. //
  1773. {
  1774. ASSERTGDI (iFormat == BMF_32BPP, "bIdenticalFormat-16bpp non bitfield surf?\n");
  1775. flGreSrc = 0x0000FF00;
  1776. if (palSrc.bIsRGB())
  1777. {
  1778. flRedSrc = 0x000000FF;
  1779. flBluSrc = 0x00FF0000;
  1780. }
  1781. else
  1782. {
  1783. ASSERTGDI(palSrc.bIsBGR(), "What is it then?");
  1784. flRedSrc = 0x00FF0000;
  1785. flBluSrc = 0x000000FF;
  1786. }
  1787. }
  1788. if (iFormat == BMF_16BPP)
  1789. {
  1790. flRedDst = 0x7c00;
  1791. flGreDst = 0x03e0;
  1792. flBluDst = 0x001f;
  1793. }
  1794. //
  1795. // BMF_32BPP
  1796. //
  1797. else
  1798. {
  1799. flRedDst = 0x00FF0000;
  1800. flGreDst = 0x0000FF00;
  1801. flBluDst = 0x000000FF;
  1802. }
  1803. if ((flRedSrc != flRedDst) ||
  1804. (flGreSrc != flGreDst) ||
  1805. (flBluSrc != flBluDst))
  1806. {
  1807. bRet = FALSE;
  1808. }
  1809. return (bRet);
  1810. }
  1811. /******************************Public*Routine******************************\
  1812. * GreGetDIBits
  1813. *
  1814. * API entry point geting the DIB bits out of a bitmap.
  1815. *
  1816. * If they ask for the bits in the same format as they are stored
  1817. * internally we give them the exact same palette entries and bits.
  1818. * If they ask for a format NBPP different than they are internally
  1819. * stored we :
  1820. *
  1821. * for 1BPP give them black,white and blt to it.
  1822. * for 4BPP give them VGA colors and blt to it.
  1823. * for 8BPP give them a good spread of colors and blt to it.
  1824. * for 16BPP give them 5-5-5
  1825. * for 24BPP give them RGB.
  1826. * for 32BPP give them RGB.
  1827. *
  1828. * Arguments:
  1829. *
  1830. * hdc - handle of device context
  1831. * hBitmap - handle of bitmap
  1832. * iStartScan - first scan line to set in destination bitmap
  1833. * cNumScan - number of scan lines to copy
  1834. * pjBits - address of array for bitmap bits
  1835. * pBitsInfo - address of structure with bitmap data
  1836. * iUsage - RGB or palette index
  1837. * cjMaxBits - Maximum for pjBits
  1838. * cjMaxInfo - Maximum for pBitsInfo
  1839. *
  1840. * Returns:
  1841. *
  1842. * Number of scan lines copied, 0 for failure
  1843. *
  1844. *
  1845. * History:
  1846. * 12-Mar-1991 -by- Patrick Haluptzok patrickh
  1847. * Wrote it.
  1848. \**************************************************************************/
  1849. int
  1850. APIENTRY
  1851. GreGetDIBitsInternal(
  1852. HDC hdc,
  1853. HBITMAP hBitmap,
  1854. UINT iStartScan,
  1855. UINT cNumScan,
  1856. LPBYTE pjBits,
  1857. LPBITMAPINFO pBitsInfo,
  1858. UINT iUsage,
  1859. UINT cjMaxBits,
  1860. UINT cjMaxInfo)
  1861. {
  1862. //
  1863. // Let's make sure we are given valid input.
  1864. //
  1865. if (pBitsInfo == (LPBITMAPINFO) NULL)
  1866. {
  1867. WARNING1("GreGetDIBits failed with NULL BITMAPINFO parameter\n");
  1868. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1869. return(0);
  1870. }
  1871. switch(iUsage)
  1872. {
  1873. case DIB_PAL_INDICES:
  1874. case DIB_PAL_COLORS:
  1875. case DIB_RGB_COLORS:
  1876. break;
  1877. default:
  1878. WARNING1("GreGetDIBits failed with invalid DIB_ iUsage type\n");
  1879. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1880. return(0);
  1881. }
  1882. //
  1883. // check to make sure that at least the minimum sized header will fit
  1884. //
  1885. if (cjMaxInfo < sizeof(BITMAPCOREHEADER))
  1886. {
  1887. WARNING1("GreGetDIBits failed cjMaxInfo\n");
  1888. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1889. return(0);
  1890. }
  1891. //
  1892. // Because of CS we must set pjBits to NULL if it should be NULL
  1893. // This is indicated by cNumScan being 0.
  1894. //
  1895. if (cNumScan == 0)
  1896. {
  1897. pjBits = (PBYTE) NULL;
  1898. }
  1899. //
  1900. // Validate the bitmap.
  1901. //
  1902. SURFREF SurfBM((HSURF)hBitmap);
  1903. if (!SurfBM.bValid())
  1904. {
  1905. WARNING1("GreGetDIBits failed to lock down the bitmap\n");
  1906. return(0);
  1907. }
  1908. ULONG ulSize = pBitsInfo->bmiHeader.biSize;
  1909. //
  1910. // First check if they just want us to fill in the bmiinfo, no color
  1911. // table, no bits. This is indicated by NULL bits and 0 for bitcount.
  1912. //
  1913. if (pjBits == (PBYTE) NULL)
  1914. {
  1915. if (ulSize == sizeof(BITMAPCOREHEADER))
  1916. {
  1917. //
  1918. // If bitcount is 0 they want to know what we have.
  1919. //
  1920. if (((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcBitCount == 0)
  1921. {
  1922. ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcWidth = (USHORT) SurfBM.ps->sizl().cx;
  1923. ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcHeight = (USHORT) SurfBM.ps->sizl().cy;
  1924. ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcPlanes = 1;
  1925. ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcBitCount = (USHORT) gaulConvert[SurfBM.ps->iFormat()];
  1926. //
  1927. // the core header does not support 16/32 bpp bitmaps
  1928. //
  1929. if (((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcBitCount >= 16)
  1930. {
  1931. ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcBitCount = 24;
  1932. }
  1933. return(TRUE);
  1934. }
  1935. }
  1936. else
  1937. {
  1938. if (cjMaxInfo < sizeof(BITMAPINFOHEADER))
  1939. return(0);
  1940. //
  1941. // If bitcount is 0 they want to know what we have.
  1942. //
  1943. if (pBitsInfo->bmiHeader.biBitCount == 0)
  1944. {
  1945. //
  1946. // zero out extra fields that are not going to be filled up later
  1947. //
  1948. if (ulSize > sizeof(BITMAPINFOHEADER))
  1949. RtlZeroMemory((PVOID)pBitsInfo, ulSize);
  1950. pBitsInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1951. pBitsInfo->bmiHeader.biWidth = SurfBM.ps->sizl().cx;
  1952. pBitsInfo->bmiHeader.biHeight = SurfBM.ps->sizl().cy;
  1953. pBitsInfo->bmiHeader.biPlanes = 1;
  1954. pBitsInfo->bmiHeader.biCompression = BI_RGB;
  1955. pBitsInfo->bmiHeader.biBitCount = (USHORT) gaulConvert[SurfBM.ps->iFormat()];
  1956. //
  1957. // If it is a 16 bpp or 32 bpp bitmap, set the compression field
  1958. //
  1959. if ((pBitsInfo->bmiHeader.biBitCount == 16) ||
  1960. (pBitsInfo->bmiHeader.biBitCount == 32))
  1961. {
  1962. pBitsInfo->bmiHeader.biCompression = BI_BITFIELDS;
  1963. }
  1964. pBitsInfo->bmiHeader.biSizeImage = pBitsInfo->bmiHeader.biHeight *
  1965. ((((pBitsInfo->bmiHeader.biBitCount * pBitsInfo->bmiHeader.biWidth)
  1966. + 31) >> 5) << 2);
  1967. pBitsInfo->bmiHeader.biXPelsPerMeter = 0;
  1968. pBitsInfo->bmiHeader.biYPelsPerMeter = 0;
  1969. pBitsInfo->bmiHeader.biClrUsed =
  1970. pBitsInfo->bmiHeader.biClrImportant = gacPalEntries[SurfBM.ps->iFormat()];
  1971. //
  1972. // top down -vs- bottom up
  1973. // We need to put this at the end because we use the positive
  1974. // height to compute the size (above).
  1975. //
  1976. // On Win95/98, negative height is returned if it's top-down
  1977. // DIBSECTION. #196691 [lingyunw]
  1978. //
  1979. // We should flip the height here, but too much stuff already
  1980. // depends on the bad NT4 compatible behaviour of this code.
  1981. // Win9x has fixed this, so we should return and fix this in
  1982. // a later release.
  1983. //
  1984. //if ((SurfBM.ps->bDIBSection()||SurfBM.ps->bDirectDraw()) &&
  1985. // (SurfBM.ps->fjBitmap() & BMF_TOPDOWN))
  1986. //{
  1987. // pBitsInfo->bmiHeader.biHeight = -pBitsInfo->bmiHeader.biHeight;
  1988. //}
  1989. //
  1990. return(TRUE);
  1991. }
  1992. }
  1993. }
  1994. //
  1995. // Ok they want us to pay attention to what is in the bmBitmapInfo.
  1996. //
  1997. //
  1998. // Cannot support the device passthrough formats (BI_JPEG, BI_PNG).
  1999. //
  2000. if (IS_BMI_PASSTHROUGH_IMAGE(pBitsInfo))
  2001. {
  2002. WARNING1("GreGetDIBits failed -- invalid pBitsInfo (BITMAPINFOHEADER)\n");
  2003. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2004. return(0);
  2005. }
  2006. DCOBJ dco(hdc);
  2007. if (!dco.bValid())
  2008. {
  2009. WARNING1("GreGetDIBits failed because invalid hdc\n");
  2010. return(0);
  2011. }
  2012. PDEVOBJ po(dco.hdev());
  2013. ASSERTGDI(po.bValid(), "ERROR po is invalid");
  2014. XEPALOBJ palDC(dco.ppal());
  2015. ASSERTGDI(palDC.bValid(), "ERROR palDC is invalid");
  2016. //
  2017. // Acquire the devlock here to protect against dynamic mode changes
  2018. // that affect the device palette. This also protects us if the
  2019. // bitmap is a Device Format Bitmap that is owned by the display
  2020. // driver.
  2021. //
  2022. DEVLOCKOBJ dlo(po);
  2023. PPALETTE ppalSrc;
  2024. if (!bIsCompatible(&ppalSrc, SurfBM.ps->ppal(), SurfBM.ps, dco.hdev()))
  2025. {
  2026. WARNING1("GreGetDIBits failed - bitmap not compatible with surface\n");
  2027. return(0);
  2028. }
  2029. XEPALOBJ palBM(ppalSrc);
  2030. PUSHORT pusIndices;
  2031. BOOL bCoreInfo;
  2032. DEVBITMAPINFO dbmi;
  2033. dbmi.fl = 0;
  2034. UINT uiWidth, uiHeight, uiBitCount, uiSizeScan, uiCompression;
  2035. if (ulSize == sizeof(BITMAPCOREHEADER))
  2036. {
  2037. bCoreInfo = TRUE;
  2038. pusIndices = (PUSHORT) ((LPBITMAPCOREINFO) pBitsInfo)->bmciColors;
  2039. uiWidth = (UINT) ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcWidth;
  2040. uiHeight = (UINT) ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcHeight;
  2041. ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcPlanes = 1;
  2042. uiBitCount = (UINT) ((LPBITMAPCOREINFO) pBitsInfo)->bmciHeader.bcBitCount;
  2043. uiSizeScan = ((((uiBitCount * uiWidth) + 31) >> 5) << 2);
  2044. uiCompression = BI_RGB;
  2045. }
  2046. else
  2047. {
  2048. //
  2049. // make sure the header is large enough for a full INFOHEADER
  2050. //
  2051. if (cjMaxInfo < sizeof(BITMAPINFOHEADER))
  2052. {
  2053. return(0);
  2054. }
  2055. //
  2056. // zero out extra fields
  2057. //
  2058. if (ulSize > sizeof(BITMAPINFOHEADER))
  2059. {
  2060. RtlZeroMemory((PVOID)((BYTE *)pBitsInfo+sizeof(BITMAPINFOHEADER)),
  2061. ulSize-sizeof(BITMAPINFOHEADER));
  2062. }
  2063. //
  2064. // First fill in bmiHeader
  2065. //
  2066. bCoreInfo = FALSE;
  2067. pusIndices = (PUSHORT) (pBitsInfo->bmiColors);
  2068. pBitsInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  2069. pBitsInfo->bmiHeader.biPlanes = 1;
  2070. uiBitCount = (UINT) pBitsInfo->bmiHeader.biBitCount;
  2071. uiCompression = pBitsInfo->bmiHeader.biCompression;
  2072. uiWidth = (UINT) pBitsInfo->bmiHeader.biWidth;
  2073. if (pBitsInfo->bmiHeader.biHeight < 0)
  2074. {
  2075. dbmi.fl = BMF_TOPDOWN;
  2076. if ((uiCompression != BI_RGB) && (uiCompression != BI_BITFIELDS))
  2077. {
  2078. WARNING1("GreGetDIBits: TOP_DOWN RLE not allowed\n");
  2079. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2080. return (0);
  2081. }
  2082. uiHeight = (UINT) -pBitsInfo->bmiHeader.biHeight;
  2083. }
  2084. else
  2085. {
  2086. uiHeight = (UINT) pBitsInfo->bmiHeader.biHeight;
  2087. }
  2088. //
  2089. // Get a valid compression set in.
  2090. //
  2091. if (uiCompression == BI_BITFIELDS)
  2092. {
  2093. //
  2094. // We only give BI_BITFIELDS if they want 16 or 32 bpp.
  2095. //
  2096. if ((uiBitCount != 16) &&
  2097. (uiBitCount != 32))
  2098. {
  2099. uiCompression = pBitsInfo->bmiHeader.biCompression = BI_RGB;
  2100. }
  2101. }
  2102. else if (uiCompression == BI_RLE8)
  2103. {
  2104. //
  2105. // We only give BI_RLE8 if they want 8 bpp data.
  2106. //
  2107. if (uiBitCount != 8)
  2108. {
  2109. uiCompression = pBitsInfo->bmiHeader.biCompression = BI_RGB;
  2110. }
  2111. }
  2112. else if (uiCompression == BI_RLE4)
  2113. {
  2114. //
  2115. // We only give BI_RLE4 if they want 4 bpp data.
  2116. //
  2117. if (uiBitCount != 4)
  2118. {
  2119. uiCompression = pBitsInfo->bmiHeader.biCompression = BI_RGB;
  2120. }
  2121. }
  2122. else if (uiCompression == BI_CMYK)
  2123. {
  2124. //
  2125. // We will give BI_CMYK, if dc allowed.
  2126. //
  2127. if (dco.pdc->bIsCMYKColor())
  2128. {
  2129. uiCompression = pBitsInfo->bmiHeader.biCompression = BI_CMYK;
  2130. }
  2131. }
  2132. else
  2133. {
  2134. //
  2135. // We give them BI_RGB.
  2136. //
  2137. uiCompression = pBitsInfo->bmiHeader.biCompression = BI_RGB;
  2138. }
  2139. uiSizeScan = ((((uiBitCount * uiWidth) + 31) >> 5) << 2);
  2140. if ((uiCompression == BI_RGB) || (uiCompression == BI_BITFIELDS))
  2141. {
  2142. pBitsInfo->bmiHeader.biSizeImage = uiSizeScan * uiHeight;
  2143. }
  2144. pBitsInfo->bmiHeader.biClrUsed = 0;
  2145. pBitsInfo->bmiHeader.biClrImportant = 0;
  2146. }
  2147. BOOL bRLE = (uiCompression == BI_RLE4) ||
  2148. (uiCompression == BI_RLE8);
  2149. //
  2150. // Get iStartScan and cNumScan in a valid range.
  2151. //
  2152. iStartScan = MIN(uiHeight, iStartScan);
  2153. cNumScan = MIN((uiHeight - iStartScan), cNumScan);
  2154. //
  2155. // check to see if all scans will fit in the passed buffer
  2156. //
  2157. if (!bRLE)
  2158. {
  2159. if (cjMaxBits < (uiSizeScan * cNumScan))
  2160. {
  2161. #if DBG
  2162. DbgPrint("ERROR GreGetDIBitsInternal %lu %lu %lu %lu %lu\n", cjMaxBits, uiSizeScan, cNumScan, iStartScan, uiHeight);
  2163. #endif
  2164. WARNING1("GreGetDIBits: cjMaxBits is to small\n");
  2165. return(0);
  2166. }
  2167. }
  2168. //
  2169. // Find out what they are asking for
  2170. //
  2171. ULONG cColors;
  2172. dbmi.hpal = (HPALETTE) 0;
  2173. if (uiCompression == BI_BITFIELDS)
  2174. {
  2175. //
  2176. // Handle 16 and 32 bit per pel bitmaps.
  2177. //
  2178. if ((ulSize <= sizeof(BITMAPINFO)) && (cjMaxInfo < (sizeof(ULONG) * 3)))
  2179. {
  2180. WARNING1("GetDIBits 16/32bpp failed - not room for flags\n");
  2181. return(0);
  2182. }
  2183. }
  2184. switch (uiBitCount)
  2185. {
  2186. case 1:
  2187. dbmi.iFormat = BMF_1BPP;
  2188. cColors = 2;
  2189. break;
  2190. case 4:
  2191. dbmi.iFormat = BMF_4BPP;
  2192. cColors = 16;
  2193. break;
  2194. case 8:
  2195. dbmi.iFormat = BMF_8BPP;
  2196. cColors = 256;
  2197. break;
  2198. default:
  2199. if (iUsage == DIB_PAL_COLORS)
  2200. {
  2201. iUsage = DIB_RGB_COLORS;
  2202. }
  2203. cColors = 0;
  2204. switch (uiBitCount)
  2205. {
  2206. case 16:
  2207. dbmi.iFormat = BMF_16BPP;
  2208. break;
  2209. case 24:
  2210. dbmi.iFormat = BMF_24BPP;
  2211. break;
  2212. case 32:
  2213. dbmi.iFormat = BMF_32BPP;
  2214. break;
  2215. default:
  2216. WARNING1("GetDIBits failed invalid bitcount in bmi BI_RGB\n");
  2217. return(0);
  2218. }
  2219. }
  2220. //
  2221. // Initialize a DIB and palette for them.
  2222. //
  2223. PALMEMOBJ palMem;
  2224. XEPALOBJ palTarg;
  2225. ULONG cEntryTemp;
  2226. if (iUsage == DIB_PAL_COLORS)
  2227. {
  2228. //
  2229. // We are guranteed to be getting for just the 1,4,8 BPP case here.
  2230. //
  2231. ASSERTGDI(palDC.cEntries() != 0, "Created 0 entry DC palette");
  2232. //
  2233. // Make sure the color table will fit in the BITMAPINFO
  2234. //
  2235. if (cjMaxInfo < (ulSize + cColors * sizeof(USHORT)))
  2236. {
  2237. WARNING1("GreGetDIBits: not enough memory for the color table DIB_PAL_COLORS\n");
  2238. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2239. return(0);
  2240. }
  2241. //
  2242. // For a palette managed device we need to do special work
  2243. // to get the color table correct for 8bpp get. Grab sem
  2244. // so we can look at ptransFore.
  2245. //
  2246. SEMOBJ semo(ghsemPalette);
  2247. if ((!palBM.bValid()) && (dbmi.iFormat == BMF_8BPP) && (palDC.ptransFore() != NULL))
  2248. {
  2249. ASSERTGDI(po.bIsPalManaged(), "ERROR not palmanaged on invalid palbm");
  2250. palTarg.ppalSet(palBM.ppalGet());
  2251. //
  2252. // 0 it out like windows
  2253. //
  2254. for (cEntryTemp = 0; cEntryTemp < 256; cEntryTemp++)
  2255. {
  2256. pusIndices[cEntryTemp] = 0;
  2257. }
  2258. USHORT usTemp;
  2259. ASSERTGDI(palDC.cEntries() <= USHRT_MAX, "palDC.cEntries too large\n");
  2260. for (cEntryTemp = 0; cEntryTemp < 256; cEntryTemp++)
  2261. {
  2262. for (usTemp = 0; usTemp < (USHORT)palDC.cEntries(); usTemp++)
  2263. {
  2264. if (palDC.ptransFore()->ajVector[usTemp] == cEntryTemp)
  2265. {
  2266. pusIndices[cEntryTemp] = usTemp;
  2267. break;
  2268. }
  2269. }
  2270. }
  2271. }
  2272. else
  2273. {
  2274. //
  2275. // We need to create a palette to blt to.
  2276. //
  2277. if (!palMem.bCreatePalette(PAL_INDEXED, cColors,
  2278. (PULONG) NULL,
  2279. 0, 0, 0, PAL_FIXED))
  2280. {
  2281. WARNING1("GetDIBits failed bCreatePalette for DIB_PAL_COLORS\n");
  2282. return(0);
  2283. }
  2284. palTarg.ppalSet(palMem.ppalGet());
  2285. //
  2286. // Initialize the pusIndices field.
  2287. //
  2288. for (cEntryTemp = 0; cEntryTemp < cColors; cEntryTemp++)
  2289. {
  2290. pusIndices[cEntryTemp] = (USHORT) cEntryTemp;
  2291. }
  2292. //
  2293. // We need to copy the RGB's in from the logical DC palette, reaching down when
  2294. // necessary.
  2295. //
  2296. XEPALOBJ palTemp(po.ppalSurf());
  2297. palTarg.vGetEntriesFrom(palDC, palBM.bValid() ? palBM : palTemp, pusIndices, cColors);
  2298. }
  2299. }
  2300. else if (iUsage == DIB_RGB_COLORS)
  2301. {
  2302. BOOL bCopyPal = FALSE;
  2303. if ((SurfBM.ps->iFormat() == dbmi.iFormat) && (palBM.bValid()))
  2304. {
  2305. bCopyPal = TRUE;
  2306. //
  2307. // for 16/32, do more checking
  2308. //
  2309. if ((uiCompression != BI_BITFIELDS) &&
  2310. ((dbmi.iFormat == BMF_16BPP) || (dbmi.iFormat == BMF_32BPP)))
  2311. {
  2312. bCopyPal = bIdenticalFormat (palBM, dbmi.iFormat);
  2313. }
  2314. //
  2315. // for 24, check RGB order.
  2316. //
  2317. else if ((dbmi.iFormat == BMF_24BPP) && (palBM.bIsRGB()))
  2318. {
  2319. //
  2320. // Bitmap palette is PAL_RGB, but we need PAL_BGR.
  2321. //
  2322. bCopyPal = FALSE;
  2323. }
  2324. }
  2325. //
  2326. // We can just use palBM, no temporary needed.
  2327. //
  2328. if (bCopyPal)
  2329. {
  2330. palTarg.ppalSet(palBM.ppalGet());
  2331. }
  2332. else
  2333. {
  2334. //
  2335. // We need a temporary palette to fill in with the correct mix of colors and then to
  2336. // use in the xlateobj construction.
  2337. //
  2338. if (!palMem.bCreatePalette(cColors ? PAL_INDEXED :
  2339. ((dbmi.iFormat == BMF_16BPP) ? PAL_BITFIELDS : PAL_BGR),
  2340. cColors,
  2341. (PULONG) NULL,
  2342. 0x00007C00, 0x000003E0, 0x0000001F, PAL_FIXED))
  2343. {
  2344. WARNING1("GetDIBits failed bCreatePalette\n");
  2345. return(0);
  2346. }
  2347. palTarg.ppalSet(palMem.ppalGet());
  2348. if ((SurfBM.ps->iFormat() == dbmi.iFormat) && (dbmi.iFormat == BMF_8BPP))
  2349. {
  2350. //
  2351. // This is the 8BPP palette managed bitmap case. There is no palette and
  2352. // we need to construct the correct colors based on the DC's logical palette.
  2353. //
  2354. //
  2355. // We init the pusIndices to just point into the DC palette and then pull the
  2356. // RGB's out with the same logic we use in CreateDIBitmap. Then we fill the
  2357. // pusIndices with the correct RGB's.
  2358. //
  2359. // Initialize the pusIndices field.
  2360. //
  2361. for (cEntryTemp = 0; cEntryTemp < cColors; cEntryTemp++)
  2362. {
  2363. pusIndices[cEntryTemp] = (USHORT) cEntryTemp;
  2364. }
  2365. //
  2366. // Get the correct palette setup
  2367. //
  2368. XEPALOBJ palTemp(po.ppalSurf());
  2369. palTarg.vGetEntriesFrom(palDC, palTemp, pusIndices, cColors);
  2370. palTarg.vInit256Default();
  2371. }
  2372. else
  2373. {
  2374. //
  2375. // Fill in a general mix of colors. Don't use more colors
  2376. // than the source bitmap has.
  2377. //
  2378. // Actually use as many colors as the destination has. To be
  2379. // Compatible with Windows Millenium.
  2380. //
  2381. switch(dbmi.iFormat)
  2382. {
  2383. case BMF_1BPP:
  2384. palTarg.vInitMono();
  2385. break;
  2386. case BMF_4BPP:
  2387. palTarg.vInitVGA();
  2388. break;
  2389. case BMF_8BPP:
  2390. palTarg.vInit256Rainbow();
  2391. }
  2392. }
  2393. }
  2394. //
  2395. // Fill in the color table.
  2396. //
  2397. if (bCoreInfo)
  2398. {
  2399. if (cjMaxInfo < (sizeof(BITMAPCOREHEADER) + cColors * 3))
  2400. {
  2401. WARNING1("GreGetDIBits: not enough memory for the color table2\n");
  2402. return(0);
  2403. }
  2404. if ((uiBitCount != 16) &&
  2405. (uiBitCount != 24) &&
  2406. (uiBitCount != 32))
  2407. {
  2408. //
  2409. // It's the 1,4,8 bpp case in which case we have to write
  2410. // out information.
  2411. //
  2412. palTarg.vFill_triples((RGBTRIPLE *) pusIndices,
  2413. 0, cColors);
  2414. }
  2415. }
  2416. else
  2417. {
  2418. if (uiCompression == BI_BITFIELDS)
  2419. {
  2420. // If uiCompression == BI_BITFIELDS we should have space for
  2421. // 3 DWORD color masks which will be filled in below. Do
  2422. // this only if we have enough space for 3 masks.
  2423. ASSERTGDI(cColors == 0,"GreGetDIBits: BI_BITFIELDS & cColors != 0\n");
  2424. if (cjMaxInfo >= sizeof(BITMAPINFOHEADER) + 3*sizeof(DWORD))
  2425. cColors = 3;
  2426. }
  2427. if (cjMaxInfo < (sizeof(BITMAPINFOHEADER) + cColors * 4))
  2428. {
  2429. WARNING1("GreGetDIBits: not enough memory for the color table33\n");
  2430. return(0);
  2431. }
  2432. if (palTarg.flPal() & PAL_BRUSHHACK)
  2433. {
  2434. RtlCopyMemory(pusIndices,(PUSHORT) palTarg.apalColorGet(),
  2435. cColors * sizeof(SHORT));
  2436. }
  2437. else if ((uiCompression == BI_BITFIELDS) ||
  2438. (uiBitCount == 1) ||
  2439. (uiBitCount == 4) ||
  2440. (uiBitCount == 8))
  2441. {
  2442. //
  2443. // We don't fill it in if it's BI_RGB and 16/24/32.
  2444. //
  2445. palTarg.vFill_rgbquads((RGBQUAD *) pusIndices,
  2446. 0, cColors);
  2447. }
  2448. }
  2449. }
  2450. else
  2451. {
  2452. //
  2453. // This is the DIB_PAL_INDICES case
  2454. //
  2455. if (dbmi.iFormat != SurfBM.ps->iFormat())
  2456. {
  2457. WARNING1("GetDIBits failed DIB_PAL_INDICES - incompat DIB/bitmap format\n");
  2458. return(0);
  2459. }
  2460. palTarg.ppalSet(palBM.ppalGet());
  2461. }
  2462. //
  2463. // Now get the xlate ready.
  2464. //
  2465. XLATEOBJ *pxlo;
  2466. EXLATEOBJ xlo;
  2467. if (xlo.bInitXlateObj(
  2468. dco.pdc->hcmXform(),
  2469. dco.pdc->lIcmMode(),
  2470. palBM,
  2471. palTarg,
  2472. palDC,
  2473. palDC,
  2474. 0,
  2475. 0x00FFFFFF,
  2476. 0))
  2477. {
  2478. pxlo = xlo.pxlo();
  2479. }
  2480. else
  2481. {
  2482. //
  2483. // bInitXlateObj will log the correct error.
  2484. //
  2485. WARNING1("GreGetDIBits failed bInitXlateObj\n");
  2486. return(0);
  2487. }
  2488. //
  2489. // If they just want the color table leave now.
  2490. //
  2491. if ((pjBits == (PBYTE) NULL) &&
  2492. (!bRLE))
  2493. {
  2494. return(TRUE);
  2495. }
  2496. LPBYTE pjCompressionBits;
  2497. if (bRLE)
  2498. {
  2499. if (cNumScan == 0)
  2500. cNumScan = uiHeight;
  2501. pjCompressionBits = NULL;
  2502. }
  2503. else
  2504. {
  2505. pjCompressionBits = pjBits;
  2506. }
  2507. //
  2508. // Attempt to allocate the bitmap from handle manager.
  2509. //
  2510. dbmi.cxBitmap = uiWidth;
  2511. dbmi.cyBitmap = cNumScan;
  2512. //
  2513. // Create the dest surface.
  2514. //
  2515. SURFMEM SurfDimoTemp;
  2516. SurfDimoTemp.bCreateDIB(&dbmi, (PVOID) pjCompressionBits);
  2517. if (!SurfDimoTemp.bValid())
  2518. {
  2519. return(0);
  2520. }
  2521. ASSERTGDI((pjCompressionBits == NULL) ||
  2522. (pjCompressionBits == SurfDimoTemp.ps->pvBits()),
  2523. "ERROR compression invalid bits");
  2524. //
  2525. // For non-RLE the assignment below does nothing. For RLE we have
  2526. // it gets the pointer to the bits we allocated.
  2527. //
  2528. pjCompressionBits = (PBYTE) SurfDimoTemp.ps->pvBits();
  2529. SurfDimoTemp.ps->hdev(dco.hdev());
  2530. //
  2531. // Zero fill the memory allocated.
  2532. //
  2533. RtlZeroMemory(SurfDimoTemp.ps->pvBits(), (UINT) SurfDimoTemp.ps->cjBits());
  2534. //
  2535. // Fill in pjBits
  2536. //
  2537. ERECTL erclDest(0, 0, dbmi.cxBitmap, dbmi.cyBitmap);
  2538. EPOINTL eptlSrc(0, uiHeight -
  2539. (iStartScan + cNumScan));
  2540. //
  2541. // Compute the offset between source and dest, in screen coordinates.
  2542. //
  2543. EPOINTL eptlOffset;
  2544. ERECTL erclReduced;
  2545. eptlOffset.x = erclDest.left - eptlSrc.x; // == -eptlSrc
  2546. eptlOffset.y = erclDest.top - eptlSrc.y;
  2547. erclReduced.left = 0 + eptlOffset.x;
  2548. erclReduced.top = eptlOffset.y;
  2549. erclReduced.right = SurfBM.ps->sizl().cx + eptlOffset.x;
  2550. erclReduced.bottom = SurfBM.ps->sizl().cy + eptlOffset.y;
  2551. //
  2552. // Intersect the dest with the source.
  2553. //
  2554. erclDest *= erclReduced;
  2555. if (erclDest.bEmpty())
  2556. {
  2557. return(0);
  2558. }
  2559. //
  2560. // The bitmap may be a DFB. Synchronization should have been taken
  2561. // care by the devlock that we already acquired.
  2562. //
  2563. ASSERTGDI(!(SurfBM.ps->bUseDevlock()) ||
  2564. (SurfBM.ps->hdev() == po.hdev()), "Devlock not acquired");
  2565. EngCopyBits(SurfDimoTemp.pSurfobj(),
  2566. SurfBM.pSurfobj(),
  2567. (CLIPOBJ *) NULL,
  2568. pxlo,
  2569. (PRECTL) &erclDest,
  2570. (PPOINTL) &eptlSrc);
  2571. if (bRLE)
  2572. {
  2573. //
  2574. // If pjBits is NULL we want these to write the size to hold the
  2575. // compressed bits in the header. If pjBits is not NULL we want
  2576. // to compress the data into the buffer and fail returning 0 if
  2577. // the buffer is not big enough.
  2578. //
  2579. if (uiCompression == BI_RLE4)
  2580. {
  2581. pBitsInfo->bmiHeader.biSizeImage = EncodeRLE4(
  2582. pjCompressionBits,
  2583. pjBits,
  2584. uiWidth,
  2585. cNumScan,
  2586. pBitsInfo->bmiHeader.biSizeImage
  2587. );
  2588. }
  2589. else if (uiCompression == BI_RLE8)
  2590. {
  2591. pBitsInfo->bmiHeader.biSizeImage = EncodeRLE8(
  2592. pjCompressionBits,
  2593. pjBits,
  2594. uiWidth,
  2595. cNumScan,
  2596. pBitsInfo->bmiHeader.biSizeImage
  2597. );
  2598. }
  2599. //
  2600. // if the encoded data doesn't fit into the buffer
  2601. // the encode routines return 0 and we do the same
  2602. if (pBitsInfo->bmiHeader.biSizeImage == 0)
  2603. {
  2604. return(0);
  2605. }
  2606. }
  2607. return(erclDest.bottom - erclDest.top);
  2608. }
  2609. /******************************Public*Routine******************************\
  2610. * GreSetBitmapDimension
  2611. *
  2612. * API entry point for setting the sizlDim of the bitmap.
  2613. * sizlDim is not used by GDI, but is kept around for the user to query.
  2614. *
  2615. * Returns: TRUE if successful, FALSE for failure.
  2616. *
  2617. * History:
  2618. * 02-May-1991 -by- Patrick Haluptzok patrickh
  2619. * Wrote it.
  2620. \**************************************************************************/
  2621. BOOL
  2622. APIENTRY
  2623. GreSetBitmapDimension(
  2624. HBITMAP hbm,
  2625. int ulX,
  2626. int ulY,
  2627. LPSIZE pSize)
  2628. {
  2629. BOOL bReturn = FALSE;
  2630. SURFREF Surf((HSURF)hbm);
  2631. if (Surf.bValid())
  2632. {
  2633. if (Surf.ps->bApiBitmap())
  2634. {
  2635. SIZEL sizl;
  2636. if (pSize != (LPSIZE) NULL)
  2637. {
  2638. *pSize = Surf.ps->sizlDim();
  2639. }
  2640. sizl.cx = ulX;
  2641. sizl.cy = ulY;
  2642. Surf.ps->sizlDim(sizl);
  2643. bReturn = TRUE;
  2644. }
  2645. }
  2646. else
  2647. {
  2648. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2649. }
  2650. return(bReturn);
  2651. }
  2652. /******************************Public*Routine******************************\
  2653. * GreGetBitmapDimension
  2654. *
  2655. * API entry point for getting the sizlDim of the bitmap.
  2656. * sizlDim is not used by GDI, but is kept around for the user to query.
  2657. *
  2658. * Returns: TRUE if successful, FALSE for failure.
  2659. *
  2660. * History:
  2661. * 02-May-1991 -by- Patrick Haluptzok patrickh
  2662. * Wrote it.
  2663. \**************************************************************************/
  2664. BOOL
  2665. APIENTRY
  2666. GreGetBitmapDimension(
  2667. HBITMAP hbm,
  2668. LPSIZE pSize)
  2669. {
  2670. BOOL bReturn = FALSE;
  2671. SURFREF Surf((HSURF)hbm);
  2672. if (Surf.bValid())
  2673. {
  2674. if (Surf.ps->bApiBitmap())
  2675. {
  2676. if (pSize != (LPSIZE) NULL)
  2677. {
  2678. *pSize = Surf.ps->sizlDim();
  2679. bReturn = TRUE;
  2680. }
  2681. else
  2682. {
  2683. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2684. }
  2685. }
  2686. }
  2687. else
  2688. {
  2689. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  2690. }
  2691. return(bReturn);
  2692. }
  2693. /******************************Public*Routine******************************\
  2694. * GreStretchDIBits
  2695. *
  2696. * API entry for stretching a DIB to a DC.
  2697. *
  2698. * Arguments:
  2699. *
  2700. * hdc - handle of device context
  2701. * xDst - x-coordinate of upper-left corner of dest. rect.
  2702. * yDst - y-coordinate of upper-left corner of dest. rect.
  2703. * cWidthDest - width of destination rectangle
  2704. * cHeightDest - height of destination rectangle
  2705. * xSrc - x-coordinate of upper-left corner of source rect.
  2706. * ySrc - y-coordinate of upper-left corner of source rect.
  2707. * cWidthSrc - width of source rectangle
  2708. * cHeightSrc - height of source rectangle
  2709. * pInitBits - address of bitmap bits
  2710. * pInfoHeader - address of bitmap data
  2711. * iUsage - usage
  2712. * rop4 - raster operation code
  2713. * cjMaxInfo - maximum size of pInfoHeader
  2714. * cjMaxBits - maximum size of pIintBits
  2715. *
  2716. * Return Value:
  2717. *
  2718. * Number of scan lines copied or 0 for error
  2719. *
  2720. * History:
  2721. *
  2722. * 10-May-1991 -by- Patrick Haluptzok patrickh
  2723. \**************************************************************************/
  2724. int
  2725. APIENTRY
  2726. GreStretchDIBits(
  2727. HDC hdc,
  2728. int xDst,
  2729. int yDst,
  2730. int cWidthDest,
  2731. int cHeightDest,
  2732. int xSrc,
  2733. int ySrc,
  2734. int cWidthSrc,
  2735. int cHeightSrc,
  2736. LPBYTE pjBits,
  2737. LPBITMAPINFO pInfoHeader,
  2738. DWORD iUsage,
  2739. DWORD Rop)
  2740. {
  2741. PBITMAPINFO pbmi = pInfoHeader;
  2742. INT iRet = 0;
  2743. //
  2744. // if it is a COREHEADER, covert it
  2745. //
  2746. if (pInfoHeader && (pInfoHeader->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)))
  2747. {
  2748. pbmi = pbmiConvertInfo (pInfoHeader, iUsage);
  2749. }
  2750. iRet = GreStretchDIBitsInternal(hdc,
  2751. xDst,
  2752. yDst,
  2753. cWidthDest,
  2754. cHeightDest,
  2755. xSrc,
  2756. ySrc,
  2757. cWidthSrc,
  2758. cHeightSrc,
  2759. pjBits,
  2760. pbmi,
  2761. iUsage,
  2762. Rop,
  2763. (UINT)~0,
  2764. (UINT)~0,
  2765. NULL);
  2766. if (pbmi && (pbmi != pInfoHeader))
  2767. {
  2768. VFREEMEM (pbmi);
  2769. }
  2770. return (iRet);
  2771. }
  2772. #define DIB_FLIP_X 1
  2773. #define DIB_FLIP_Y 2
  2774. int
  2775. APIENTRY
  2776. GreStretchDIBitsInternal(
  2777. HDC hdc,
  2778. int xDst,
  2779. int yDst,
  2780. int cWidthDest,
  2781. int cHeightDest,
  2782. int xSrc,
  2783. int ySrc,
  2784. int cWidthSrc,
  2785. int cHeightSrc,
  2786. LPBYTE pInitBits,
  2787. LPBITMAPINFO pInfoHeader,
  2788. DWORD iUsage,
  2789. DWORD rop4,
  2790. UINT cjMaxInfo,
  2791. UINT cjMaxBits,
  2792. HANDLE hcmXform)
  2793. {
  2794. int iRetHeight = 0;
  2795. #if DBG
  2796. if (pInfoHeader)
  2797. {
  2798. ASSERTGDI (pInfoHeader->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER), "bad header\n");
  2799. }
  2800. #endif
  2801. //
  2802. // Process the rop and get the A-vector notation.
  2803. //
  2804. int ropCode = (rop4 >> 16) & 0x000000FF;
  2805. ULONG ulAvec = (ULONG) gajRop3[ropCode];
  2806. //
  2807. // Check for no source required.
  2808. //
  2809. if (!(ulAvec & AVEC_NEED_SOURCE))
  2810. {
  2811. iRetHeight = NtGdiPatBlt(hdc,xDst,yDst,cWidthDest,cHeightDest, rop4);
  2812. }
  2813. else
  2814. {
  2815. //
  2816. // Validate the hdc.
  2817. //
  2818. DCOBJ dcoDest(hdc);
  2819. if (!dcoDest.bValid())
  2820. {
  2821. WARNING1("StretchDIBits failed - invalid DC\n");
  2822. }
  2823. else
  2824. {
  2825. //
  2826. // Let's validate the parameters so we don't gp-fault ourselves.
  2827. //
  2828. // Size in header, copy it out, it can change.
  2829. //
  2830. ULONG ulSize;
  2831. if ((pInfoHeader == (LPBITMAPINFO) NULL) ||
  2832. (pInitBits == (LPBYTE) NULL) ||
  2833. ((iUsage != DIB_RGB_COLORS) &&
  2834. (iUsage != DIB_PAL_COLORS) &&
  2835. (iUsage != DIB_PAL_INDICES)) ||
  2836. (cjMaxInfo < sizeof(BITMAPCOREHEADER)) || // Check first that we can access biSize.
  2837. (cjMaxInfo < (ulSize = pInfoHeader->bmiHeader.biSize)) ||
  2838. (ulSize < sizeof(BITMAPINFOHEADER)))
  2839. {
  2840. WARNING1("GreStretchDIBits failed because 1 of 3 params is invalid\n");
  2841. }
  2842. else
  2843. {
  2844. ULONG jStretchBltMode = dcoDest.pdc->jStretchBltMode();
  2845. //
  2846. // This is used to hold the height of the bitmap in.
  2847. //
  2848. int yHeight;
  2849. //
  2850. // Get the transform now, we'll need it later
  2851. //
  2852. EXFORMOBJ exo(dcoDest, WORLD_TO_DEVICE);
  2853. //
  2854. // Check for state incompatible with BI_JPEG or BI_PNG support.
  2855. //
  2856. if (IS_PASSTHROUGH_IMAGE(pInfoHeader->bmiHeader.biCompression))
  2857. {
  2858. //
  2859. // Device must support image format
  2860. // Only support rop 0xCCCC
  2861. // No rotations allowed
  2862. // DIB_RGB_COLORS only
  2863. // No hcmXform
  2864. //
  2865. if (!dcoDest.bSupportsPassthroughImage(pInfoHeader->bmiHeader.biCompression) ||
  2866. (ropCode != 0xcc) || exo.bRotation() ||
  2867. (iUsage != DIB_RGB_COLORS) || hcmXform)
  2868. {
  2869. //
  2870. // Return 0 for error.
  2871. //
  2872. WARNING("StretchDIBits -- invalid BI_JPEG/BI_PNG operation\n");
  2873. return iRetHeight;
  2874. }
  2875. }
  2876. //
  2877. // if it is one to one mapping, lets just call SetDIBitsToDevice
  2878. //
  2879. if ((cWidthDest == cWidthSrc) &&
  2880. (cHeightDest == cHeightSrc) &&
  2881. (cHeightSrc > 0) &&
  2882. (cWidthSrc > 0) &&
  2883. ((xSrc | ySrc) == 0) &&
  2884. (ropCode == 0xcc) &&
  2885. (jStretchBltMode != HALFTONE))
  2886. {
  2887. if (exo.bTranslationsOnly())
  2888. {
  2889. yHeight = (int)ABS(pInfoHeader->bmiHeader.biHeight);
  2890. cHeightSrc = min(cHeightSrc, yHeight);
  2891. return(GreSetDIBitsToDeviceInternal(
  2892. hdc,
  2893. xDst,
  2894. yDst,
  2895. cWidthDest,
  2896. cHeightDest,
  2897. xSrc,
  2898. ySrc,
  2899. ySrc,
  2900. cHeightSrc,
  2901. pInitBits,
  2902. pInfoHeader,
  2903. iUsage,
  2904. cjMaxBits,
  2905. cjMaxInfo,
  2906. TRUE,
  2907. hcmXform));
  2908. }
  2909. }
  2910. //
  2911. // We really just want to blt it into a temporary DIB and then
  2912. // blt it out.
  2913. //
  2914. // Calls with DIB_PAL_COLORS will fail HTBlt since there is no
  2915. // src pal. On mono printers, this looks really bad with no gray scale.
  2916. // Make it go thru GreStretchBlt so we won't lose HALFTONE here.
  2917. // [lingyunw]
  2918. //
  2919. BOOL bForceHalftone = FALSE;
  2920. if ((iUsage == DIB_PAL_COLORS))
  2921. {
  2922. DEVLOCKOBJ dlo(dcoDest);
  2923. if (dcoDest.pSurface() && dcoDest.pSurface()->iFormat() == BMF_1BPP)
  2924. {
  2925. bForceHalftone = TRUE;
  2926. }
  2927. }
  2928. if ((ropCode != 0xcc) || (exo.bRotation()) || bForceHalftone)
  2929. {
  2930. //
  2931. // Set up src rectangle in upper-left coordinates.
  2932. //
  2933. yHeight = (int)pInfoHeader->bmiHeader.biHeight;
  2934. int ySrcNew;
  2935. if (yHeight > 0)
  2936. {
  2937. ySrcNew = yHeight - ySrc - cHeightSrc;
  2938. }
  2939. else
  2940. {
  2941. ySrcNew = ySrc;
  2942. }
  2943. //
  2944. // We have to decompress it first and then call StretchBlt
  2945. //
  2946. HDC hdcTemp = GreCreateCompatibleDC(hdc);
  2947. UINT uiCompression = (UINT) pInfoHeader->bmiHeader.biCompression;
  2948. HBITMAP hbm;
  2949. //
  2950. // Let GreCreateDIBitmapComp to decompress RLEs
  2951. //
  2952. if ((uiCompression != BI_RLE8) && (uiCompression != BI_RLE4))
  2953. {
  2954. hbm = GreCreateDIBitmapReal(hdc,
  2955. CBM_INIT,
  2956. pInitBits,
  2957. pInfoHeader,
  2958. iUsage,
  2959. cjMaxInfo,
  2960. cjMaxBits,
  2961. (HANDLE)0,
  2962. 0,
  2963. (HANDLE)0,
  2964. 0,
  2965. 0,
  2966. NULL);
  2967. }
  2968. else
  2969. {
  2970. hbm = GreCreateDIBitmapComp(hdc,
  2971. ((BITMAPINFOHEADER *) pInfoHeader)->biWidth,
  2972. ((BITMAPINFOHEADER *) pInfoHeader)->biHeight,
  2973. CBM_INIT,
  2974. pInitBits,
  2975. pInfoHeader,
  2976. iUsage,
  2977. cjMaxInfo,
  2978. cjMaxBits,
  2979. CDBI_INTERNAL,
  2980. hcmXform
  2981. );
  2982. }
  2983. if ((hdcTemp == (HDC) NULL) || (hbm == (HBITMAP) NULL))
  2984. {
  2985. //
  2986. // The creation calls will log the correct errors.
  2987. //
  2988. WARNING1("StretchDIBits failed to allocate temp DC and temp bitmap\n");
  2989. bDeleteDCInternal(hdcTemp,TRUE,FALSE);
  2990. GreDeleteObject(hbm);
  2991. }
  2992. else
  2993. {
  2994. HBITMAP hbmTemp = (HBITMAP)GreSelectBitmap(hdcTemp, (HBITMAP)hbm);
  2995. ASSERTGDI(hbmTemp == STOCKOBJ_BITMAP, "ERROR GDI SetDIBits");
  2996. //
  2997. // Send them off to someone we know can do it.
  2998. //
  2999. BOOL bReturn = GreStretchBltInternal
  3000. (
  3001. hdc,
  3002. xDst,
  3003. yDst,
  3004. cWidthDest,
  3005. cHeightDest,
  3006. hdcTemp,
  3007. xSrc,ySrcNew,
  3008. cWidthSrc,
  3009. cHeightSrc,
  3010. rop4,
  3011. (DWORD) 0x00FFFFFF,
  3012. STRETCHBLT_ENABLE_ICM
  3013. );
  3014. bDeleteDCInternal(hdcTemp,TRUE,FALSE);
  3015. GreDeleteObject(hbm);
  3016. if (bReturn)
  3017. {
  3018. iRetHeight = yHeight;
  3019. }
  3020. }
  3021. return(iRetHeight);
  3022. }
  3023. //
  3024. // Get the info from the Header depending upon what kind it is.
  3025. //
  3026. UINT uiBitCount, uiCompression, uiWidth, uiPalUsed;
  3027. PULONG pulColors;
  3028. DEVBITMAPINFO dbmi;
  3029. dbmi.fl = 0;
  3030. BOOL bSuccess = TRUE;
  3031. uiBitCount = (UINT) pInfoHeader->bmiHeader.biBitCount;
  3032. uiCompression = (UINT) pInfoHeader->bmiHeader.biCompression;
  3033. uiWidth = (UINT) pInfoHeader->bmiHeader.biWidth;
  3034. yHeight = (int) pInfoHeader->bmiHeader.biHeight;
  3035. uiPalUsed = (UINT) pInfoHeader->bmiHeader.biClrUsed;
  3036. pulColors = (PULONG) ((LPBYTE)pInfoHeader+ulSize);
  3037. if (yHeight < 0)
  3038. {
  3039. dbmi.fl = BMF_TOPDOWN;
  3040. yHeight = -yHeight;
  3041. }
  3042. //
  3043. // Now that cjMaxInfo has been validated for the header, adjust it to refer to
  3044. // the color table
  3045. //
  3046. cjMaxInfo -= (UINT)ulSize;
  3047. //
  3048. // Figure out what this guy is blting from.
  3049. //
  3050. ULONG cColorsMax;
  3051. FLONG iPalMode;
  3052. FLONG iPalType;
  3053. FLONG flRed;
  3054. FLONG flGre;
  3055. FLONG flBlu;
  3056. BOOL bRLE = FALSE;
  3057. if (uiCompression == BI_BITFIELDS)
  3058. {
  3059. //
  3060. // Handle 16 and 32 bit per pel bitmaps.
  3061. //
  3062. if ((ulSize <= sizeof(BITMAPINFO)) && (cjMaxInfo < (sizeof(ULONG) * 3)))
  3063. {
  3064. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3065. WARNING1("SetDIBitsToDevice 16/32bpp failed - not room for flags\n");
  3066. bSuccess = FALSE;
  3067. }
  3068. else
  3069. {
  3070. if (iUsage == DIB_PAL_COLORS)
  3071. {
  3072. iUsage = DIB_RGB_COLORS;
  3073. }
  3074. switch (uiBitCount)
  3075. {
  3076. case 16:
  3077. dbmi.iFormat = BMF_16BPP;
  3078. break;
  3079. case 32:
  3080. dbmi.iFormat = BMF_32BPP;
  3081. break;
  3082. default:
  3083. WARNING1("SetDIBitsToDevice failed for BI_BITFIELDS\n");
  3084. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3085. bSuccess = FALSE;
  3086. }
  3087. //
  3088. // if BITMAPV4 or greater then masks are stored in info header
  3089. //
  3090. if (ulSize >= sizeof(BITMAPINFOHEADER))
  3091. {
  3092. pulColors = (PULONG) ((LPBYTE)pInfoHeader+sizeof(BITMAPINFOHEADER));
  3093. }
  3094. flRed = pulColors[0];
  3095. flGre = pulColors[1];
  3096. flBlu = pulColors[2];
  3097. cColorsMax = 0;
  3098. iPalMode = PAL_BITFIELDS;
  3099. iPalType = PAL_FIXED;
  3100. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * yHeight;
  3101. }
  3102. }
  3103. else if (uiCompression == BI_RGB)
  3104. {
  3105. switch (uiBitCount)
  3106. {
  3107. case 1:
  3108. dbmi.iFormat = BMF_1BPP;
  3109. cColorsMax = 2;
  3110. iPalMode = PAL_INDEXED;
  3111. iPalType = PAL_FREE;
  3112. break;
  3113. case 4:
  3114. dbmi.iFormat = BMF_4BPP;
  3115. cColorsMax = 16;
  3116. iPalMode = PAL_INDEXED;
  3117. iPalType = PAL_FREE;
  3118. break;
  3119. case 8:
  3120. dbmi.iFormat = BMF_8BPP;
  3121. cColorsMax = 256;
  3122. iPalMode = PAL_INDEXED;
  3123. iPalType = PAL_FREE;
  3124. break;
  3125. default:
  3126. if (iUsage == DIB_PAL_COLORS)
  3127. {
  3128. iUsage = DIB_RGB_COLORS;
  3129. }
  3130. switch (uiBitCount)
  3131. {
  3132. case 16:
  3133. dbmi.iFormat = BMF_16BPP;
  3134. flRed = 0x7c00;
  3135. flGre = 0x03e0;
  3136. flBlu = 0x001f;
  3137. cColorsMax = 0;
  3138. iPalMode = PAL_BITFIELDS;
  3139. iPalType = PAL_FIXED;
  3140. break;
  3141. case 24:
  3142. dbmi.iFormat = BMF_24BPP;
  3143. cColorsMax = 0;
  3144. iPalMode = PAL_BGR;
  3145. iPalType = PAL_FIXED;
  3146. break;
  3147. case 32:
  3148. dbmi.iFormat = BMF_32BPP;
  3149. cColorsMax = 0;
  3150. iPalMode = PAL_BGR;
  3151. iPalType = PAL_FIXED;
  3152. break;
  3153. default:
  3154. WARNING1("SetDIBitsToDevice failed invalid bitcount in bmi BI_RGB\n");
  3155. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3156. bSuccess = FALSE;
  3157. }
  3158. }
  3159. if (bSuccess)
  3160. {
  3161. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * yHeight;
  3162. }
  3163. }
  3164. else if (uiCompression == BI_CMYK)
  3165. {
  3166. ASSERTGDI(iUsage == DIB_RGB_COLORS,
  3167. "StretchDIBits(BI_CMYK):iUsage should be DIB_RGB_COLORS\n");
  3168. DCOBJ dco(hdc);
  3169. //
  3170. // Current device context accept CMYK color ?
  3171. //
  3172. if (!dco.bValid() || !dco.pdc->bIsCMYKColor())
  3173. {
  3174. WARNING1("SetDIBitsToDevice:DC is not in CMYK color mode for BI_CMYK\n");
  3175. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3176. bSuccess = FALSE;
  3177. }
  3178. else
  3179. {
  3180. switch (uiBitCount)
  3181. {
  3182. case 1:
  3183. dbmi.iFormat = BMF_1BPP;
  3184. cColorsMax = 2;
  3185. iPalMode = PAL_INDEXED;
  3186. iPalType = PAL_FREE;
  3187. break;
  3188. case 4:
  3189. dbmi.iFormat = BMF_4BPP;
  3190. cColorsMax = 16;
  3191. iPalMode = PAL_INDEXED;
  3192. iPalType = PAL_FREE;
  3193. break;
  3194. case 8:
  3195. dbmi.iFormat = BMF_8BPP;
  3196. cColorsMax = 256;
  3197. iPalMode = PAL_INDEXED;
  3198. iPalType = PAL_FREE;
  3199. break;
  3200. case 32:
  3201. dbmi.iFormat = BMF_32BPP;
  3202. cColorsMax = 0;
  3203. iPalMode = PAL_CMYK;
  3204. iPalType = PAL_FIXED;
  3205. break;
  3206. default:
  3207. WARNING1("SetDIBitsToDevice failed invalid bitcount in bmi BI_CMYK\n");
  3208. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3209. bSuccess = FALSE;
  3210. }
  3211. }
  3212. if (bSuccess)
  3213. {
  3214. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * yHeight;
  3215. }
  3216. }
  3217. else if ((uiCompression == BI_RLE4) || (uiCompression == BI_CMYKRLE4))
  3218. {
  3219. if (uiCompression == BI_CMYKRLE4)
  3220. {
  3221. ASSERTGDI(iUsage == DIB_RGB_COLORS,
  3222. "StretchDIBits(BI_CMYKRLE4):iUsage should be DIB_RGB_COLORS\n");
  3223. DCOBJ dco(hdc);
  3224. //
  3225. // Current device context accept CMYK color ?
  3226. //
  3227. if (!dco.bValid() || !dco.pdc->bIsCMYKColor())
  3228. {
  3229. WARNING1("SetDIBitsToDevice:DC is not in CMYK color mode for BI_CMYKRLE4\n");
  3230. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3231. bSuccess = FALSE;
  3232. }
  3233. }
  3234. if (bSuccess)
  3235. {
  3236. if (uiBitCount != 4)
  3237. {
  3238. WARNING1("StretchDIBits invalid bitcount BI_RLE4\n");
  3239. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3240. bSuccess = FALSE;
  3241. }
  3242. dbmi.iFormat = BMF_4RLE;
  3243. cColorsMax = 16;
  3244. iPalMode = PAL_INDEXED;
  3245. iPalType = PAL_FREE;
  3246. dbmi.cjBits = pInfoHeader->bmiHeader.biSizeImage;
  3247. bRLE = TRUE;
  3248. }
  3249. }
  3250. else if ((uiCompression == BI_RLE8) || (uiCompression == BI_CMYKRLE8))
  3251. {
  3252. if (uiCompression == BI_CMYKRLE8)
  3253. {
  3254. ASSERTGDI(iUsage == DIB_RGB_COLORS,
  3255. "StretchDIBits(BI_CMYKRLE8):iUsage should be DIB_RGB_COLORS\n");
  3256. DCOBJ dco(hdc);
  3257. //
  3258. // Current device context accept CMYK color ?
  3259. //
  3260. if (!dco.bValid() || !dco.pdc->bIsCMYKColor())
  3261. {
  3262. WARNING1("SetDIBitsToDevice:DC is not in CMYK color mode for BI_CMYKRLE8\n");
  3263. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3264. bSuccess = FALSE;
  3265. }
  3266. }
  3267. if (bSuccess)
  3268. {
  3269. if (uiBitCount != 8)
  3270. {
  3271. WARNING1("StretchDIBits invalid bitcount BI_RLE8\n");
  3272. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3273. bSuccess = FALSE;
  3274. }
  3275. dbmi.iFormat = BMF_8RLE;
  3276. cColorsMax = 256;
  3277. iPalMode = PAL_INDEXED;
  3278. iPalType = PAL_FREE;
  3279. dbmi.cjBits = pInfoHeader->bmiHeader.biSizeImage;
  3280. bRLE = TRUE;
  3281. }
  3282. }
  3283. else if (uiCompression == BI_JPEG)
  3284. {
  3285. //
  3286. // The XLATEOBJ we setup for BI_JPEG is only valid for
  3287. // querying the ICM flags in the flXlate member.
  3288. //
  3289. dbmi.iFormat = BMF_JPEG;
  3290. cColorsMax = 0;
  3291. iPalMode = PAL_BGR;
  3292. iPalType = PAL_FIXED;
  3293. dbmi.cjBits = pInfoHeader->bmiHeader.biSizeImage;
  3294. }
  3295. else if (uiCompression == BI_PNG)
  3296. {
  3297. //
  3298. // The XLATEOBJ we setup for BI_PNG is only valid for
  3299. // querying the ICM flags in the flXlate member.
  3300. //
  3301. dbmi.iFormat = BMF_PNG;
  3302. cColorsMax = 0;
  3303. iPalMode = PAL_BGR;
  3304. iPalType = PAL_FIXED;
  3305. dbmi.cjBits = pInfoHeader->bmiHeader.biSizeImage;
  3306. }
  3307. else
  3308. {
  3309. WARNING1("GreStretchDIBits failed invalid Compression in header\n");
  3310. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3311. bSuccess = FALSE;
  3312. }
  3313. if (bSuccess)
  3314. {
  3315. //
  3316. // if color transform is not specified, use DC's color transform.
  3317. //
  3318. if (hcmXform == NULL)
  3319. {
  3320. hcmXform = dcoDest.pdc->hcmXform();
  3321. }
  3322. else
  3323. {
  3324. ICMMSG(("GreStretchDIBitsInternal():Bitmap has thier own colorspace\n"));
  3325. }
  3326. ULONG lIcmMode = dcoDest.pdc->lIcmMode();
  3327. if (IS_CMYK_COLOR(lIcmMode)) /* DC is CMYK color mode ? */
  3328. {
  3329. if ((hcmXform == NULL) || !IS_CMYK_BITMAP(uiCompression))
  3330. {
  3331. //
  3332. // DC mode is CMYK color, but bitmap itself is not.
  3333. // so clear CMYK color bit, so that XLATEOBJ will not
  3334. // have XO_FROM_CMYK
  3335. //
  3336. CLEAR_COLORTYPE(lIcmMode);
  3337. //
  3338. // then it's RGB.
  3339. //
  3340. lIcmMode |= DC_ICM_RGB_COLOR;
  3341. }
  3342. }
  3343. dbmi.cxBitmap = uiWidth;
  3344. dbmi.cyBitmap = yHeight;
  3345. ULONG cColors;
  3346. if (uiPalUsed != 0)
  3347. {
  3348. if (uiPalUsed <= cColorsMax)
  3349. {
  3350. cColors = uiPalUsed;
  3351. }
  3352. else
  3353. {
  3354. cColors = cColorsMax;
  3355. }
  3356. }
  3357. else
  3358. {
  3359. cColors = cColorsMax;
  3360. }
  3361. if (cjMaxBits < dbmi.cjBits)
  3362. {
  3363. WARNING1("GreStretchDIBits failed because of invalid cjMaxBits\n");
  3364. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3365. }
  3366. else
  3367. {
  3368. PDEVOBJ po(dcoDest.hdev());
  3369. ERECTL erclTrg(xDst, yDst, xDst + cWidthDest, yDst + cHeightDest);
  3370. //
  3371. // Transform the dest point to DEVICE coordinates.
  3372. //
  3373. EXFORMOBJ xoDest(dcoDest, WORLD_TO_DEVICE);
  3374. if (!xoDest.bXform(erclTrg))
  3375. {
  3376. WARNING1("StretchDIBits failed to transform coordinates\n");
  3377. }
  3378. else
  3379. {
  3380. //
  3381. // Return null operations.
  3382. //
  3383. if (erclTrg.bEmpty())
  3384. {
  3385. iRetHeight = cHeightSrc;
  3386. }
  3387. else
  3388. {
  3389. //
  3390. // Windows uses 'last point' exclusion on StretchBlt calls.
  3391. // This means we can't simply 'order' a rectangle, we must
  3392. // Flip it, remember that it has flipped and adjust the
  3393. // coordinates to match Windows, this is sick and twisted
  3394. // but it's compatible. [donalds] 03-Jun-1993
  3395. //
  3396. FLONG flFlip = 0;
  3397. LONG lTmp;
  3398. if (erclTrg.left > erclTrg.right)
  3399. {
  3400. lTmp = erclTrg.left, erclTrg.left = erclTrg.right, erclTrg.right = lTmp;
  3401. //
  3402. // WINBUG #274633 3-19-2000 andarsov. When the transformation has the
  3403. // bMirrored flag, it does the increment of left, right itself.
  3404. // The check below prevents the double increment, and losing of a pixel column.
  3405. //
  3406. if (!xoDest.bMirrored)
  3407. {
  3408. erclTrg.left++;
  3409. erclTrg.right++;
  3410. }
  3411. flFlip ^= DIB_FLIP_X;
  3412. }
  3413. if (erclTrg.top > erclTrg.bottom)
  3414. {
  3415. lTmp = erclTrg.top, erclTrg.top = erclTrg.bottom, erclTrg.bottom = lTmp;
  3416. erclTrg.top++;
  3417. erclTrg.bottom++;
  3418. flFlip ^= DIB_FLIP_Y;
  3419. }
  3420. //
  3421. // We need a well ordered rectangle to compute clipping and exclusion with.
  3422. //
  3423. PALMEMOBJ palTemp;
  3424. if (iUsage == DIB_RGB_COLORS)
  3425. {
  3426. //
  3427. // Allocate a palette for this bitmap.
  3428. //
  3429. if (!palTemp.bCreatePalette(iPalMode,
  3430. cColorsMax,
  3431. (PULONG) NULL,
  3432. flRed,
  3433. flGre,
  3434. flBlu,
  3435. iPalType
  3436. )
  3437. )
  3438. {
  3439. WARNING1("Failed palette creation in StretchDIBits\n");
  3440. bSuccess = FALSE;
  3441. }
  3442. }
  3443. if (bSuccess)
  3444. {
  3445. DEVLOCKOBJ dlo(dcoDest);
  3446. SURFACE *pSurfDst = dcoDest.pSurfaceEff();
  3447. dbmi.fl |= dcoDest.bUMPD() ? UMPD_SURFACE : 0;
  3448. dbmi.hpal = 0;
  3449. //
  3450. // Attempt to allocate the bitmap.
  3451. //
  3452. SURFMEM SurfDimoTemp;
  3453. if (bRLE)
  3454. {
  3455. DEVBITMAPINFO dbmiRLE;
  3456. SURFMEM SurfDimoRLE;
  3457. dbmiRLE = dbmi;
  3458. if (!SurfDimoRLE.bCreateDIB(&dbmiRLE, pInitBits))
  3459. {
  3460. WARNING("GreStretchDIBits failed SurfDimoRLE alloc\n");
  3461. bSuccess = FALSE;
  3462. }
  3463. else
  3464. {
  3465. //
  3466. // Well StretchBlt can't handle RLE's, so we unpack it into
  3467. // SurfDimoTemp which must be an uncompressed format.
  3468. //
  3469. if (dbmi.iFormat == BMF_4RLE)
  3470. {
  3471. dbmi.iFormat = BMF_4BPP;
  3472. }
  3473. else
  3474. {
  3475. dbmi.iFormat = BMF_8BPP;
  3476. }
  3477. if (!SurfDimoTemp.bCreateDIB(&dbmi, NULL))
  3478. {
  3479. WARNING("GreStretchDIBits failed\n");
  3480. bSuccess = FALSE;
  3481. }
  3482. else
  3483. {
  3484. ERECTL erclTemp(0,0, dbmi.cxBitmap, dbmi.cyBitmap);
  3485. EngCopyBits(SurfDimoTemp.pSurfobj(),
  3486. SurfDimoRLE.pSurfobj(),
  3487. (CLIPOBJ *) NULL,
  3488. NULL,
  3489. (PRECTL) &erclTemp,
  3490. (PPOINTL) &gptl00
  3491. );
  3492. }
  3493. }
  3494. }
  3495. else
  3496. {
  3497. if (!SurfDimoTemp.bCreateDIB(&dbmi,pInitBits))
  3498. {
  3499. WARNING("GreStretchDIBits failed\n");
  3500. bSuccess = FALSE;
  3501. }
  3502. }
  3503. if (bSuccess)
  3504. {
  3505. //
  3506. // Lock the Rao region if we are drawing on a display surface. The Rao
  3507. // region might otherwise change asynchronously. The DEVLOCKOBJ also makes
  3508. // sure that the VisRgn is up to date, calling the window manager if
  3509. // necessary to recompute it. It also protects us from pSurfDest
  3510. // being changed asynchronously by a dynamic mode change.
  3511. //
  3512. DEVLOCKOBJ dlo(dcoDest);
  3513. SURFACE *pSurfDest = dcoDest.pSurfaceEff();
  3514. XEPALOBJ palDest(pSurfDest->ppal());
  3515. XEPALOBJ palDestDC(dcoDest.ppal());
  3516. XLATEOBJ *pxlo;
  3517. EXLATEOBJ xlo;
  3518. BOOL bNeedAssociatePalette = FALSE;
  3519. //
  3520. // Associate the DC's palette with the bitmap for use when
  3521. // converting DDBs to DIBs for dynamic mode changes.
  3522. //
  3523. if (!palDestDC.bIsPalDefault())
  3524. {
  3525. pSurfDest->hpalHint(palDestDC.hpal());
  3526. }
  3527. switch (iUsage)
  3528. {
  3529. case DIB_RGB_COLORS:
  3530. if (cColors)
  3531. {
  3532. if (cjMaxInfo < (cColors * 4))
  3533. {
  3534. WARNING1("StretchDIBits failed DIB_RGB_COLORS bmi invalid size\n");
  3535. bSuccess = FALSE;
  3536. //
  3537. // break out of case
  3538. //
  3539. break;
  3540. }
  3541. else
  3542. {
  3543. //
  3544. // Copy bitmap color table into palette
  3545. //
  3546. if (IS_CMYK_BITMAP(uiCompression))
  3547. {
  3548. palTemp.vCopy_cmykquad(pulColors, 0, cColors);
  3549. }
  3550. else
  3551. {
  3552. palTemp.vCopy_rgbquad((RGBQUAD *) pulColors, 0, cColors);
  3553. }
  3554. }
  3555. //
  3556. // This is a special version of the constructor that doesn't search the
  3557. // cache and doesn't put it in the cache when it's done.
  3558. //
  3559. if (NULL == xlo.pInitXlateNoCache(
  3560. hcmXform,
  3561. lIcmMode,
  3562. palTemp,
  3563. palDest,
  3564. palDestDC,
  3565. 0,
  3566. 0,
  3567. 0x00FFFFFF
  3568. )
  3569. )
  3570. {
  3571. //
  3572. // Error message is already logged.
  3573. //
  3574. WARNING1("GreStretchDIBits failed XLATE init\n");
  3575. bSuccess = FALSE;
  3576. }
  3577. }
  3578. else
  3579. {
  3580. //
  3581. // This is a special version of the constructor that doesn't search the
  3582. // cache and doesn't put it in the cache when it's done.
  3583. //
  3584. if (NULL == xlo.pInitXlateNoCache(
  3585. hcmXform,
  3586. lIcmMode,
  3587. palTemp,
  3588. palDest,
  3589. palDestDC,
  3590. 0,
  3591. 0,
  3592. 0x00FFFFFF
  3593. )
  3594. )
  3595. {
  3596. //
  3597. // Error message is already logged.
  3598. //
  3599. WARNING1("GreStretchDIBits failed XLATE init\n");
  3600. bSuccess = FALSE;
  3601. }
  3602. }
  3603. pxlo = xlo.pxlo();
  3604. break;
  3605. case DIB_PAL_COLORS:
  3606. if (cjMaxInfo < (cColors * sizeof(USHORT)))
  3607. {
  3608. WARNING1("StretchDIBits failed DIB_PAL_COLORS is invalid\n");
  3609. bSuccess = FALSE;
  3610. }
  3611. else
  3612. {
  3613. if (!xlo.bMakeXlate(
  3614. (PUSHORT) pulColors,
  3615. palDestDC,
  3616. pSurfDest,
  3617. cColors,
  3618. cColorsMax))
  3619. {
  3620. WARNING1("GDISRV GreStretchDIBits failed bMakeXlate\n");
  3621. bSuccess = FALSE;
  3622. }
  3623. else
  3624. {
  3625. pxlo = xlo.pxlo();
  3626. //
  3627. // If we are drawing to display meta-screen with multi-monitor
  3628. // system and it's colour-depth is not same for all those monitor.
  3629. // we need to create palette to map color to other-than primary
  3630. // monitor(s).
  3631. //
  3632. if (gbMultiMonMismatchColor && po.bDisplayPDEV())
  3633. {
  3634. if (palTemp.bCreatePalette(iPalMode, cColorsMax, (PULONG) NULL,
  3635. flRed, flGre, flBlu, iPalType))
  3636. {
  3637. XEPALOBJ palSurfEff(pSurfDest->ppal() ? \
  3638. pSurfDest->ppal() : po.ppalSurf());
  3639. //
  3640. // Keep DC (or Surface) palette entry to temporay palette.
  3641. //
  3642. palTemp.vGetEntriesFrom(palDestDC, palSurfEff,
  3643. (PUSHORT)pulColors, cColors);
  3644. bNeedAssociatePalette = TRUE;
  3645. }
  3646. else
  3647. {
  3648. WARNING1("GreStretchDIBitsInternal: Failed to create temporary palette");
  3649. bSuccess = FALSE;
  3650. }
  3651. }
  3652. }
  3653. }
  3654. break;
  3655. case DIB_PAL_INDICES:
  3656. if (pSurfDest->iFormat() != dbmi.iFormat)
  3657. {
  3658. WARNING1("StretchDIBits failed - DIB_PAL_INDICES used - DIB not format of Dst\n");
  3659. bSuccess = FALSE;
  3660. }
  3661. pxlo = &xloIdent;
  3662. }
  3663. if (bSuccess)
  3664. {
  3665. //
  3666. // Accumulate bounds. We can do this before knowing if the operation is
  3667. // successful because bounds can be loose.
  3668. //
  3669. if (dcoDest.fjAccum())
  3670. {
  3671. dcoDest.vAccumulate(erclTrg);
  3672. }
  3673. //
  3674. // Bail out if this is an INFO_DC, but only after we have the attempted to grab devlock
  3675. //
  3676. if (dcoDest.bFullScreen())
  3677. {
  3678. iRetHeight = yHeight;
  3679. }
  3680. else
  3681. {
  3682. //
  3683. // now bail out if the devlock failed for any other reason
  3684. //
  3685. if (!dlo.bValid())
  3686. {
  3687. WARNING1("GreStretchDIBits failed the DEVLOCK\n");
  3688. }
  3689. else
  3690. {
  3691. //
  3692. // With a fixed DC origin we can change the destination to SCREEN coordinates.
  3693. //
  3694. erclTrg += dcoDest.eptlOrigin();
  3695. //
  3696. // Handle BitBlts that have a source. Create a rect bounding the
  3697. // src and the bits that have been supplied.
  3698. //
  3699. EPOINTL eptlSrc;
  3700. ERECTL erclSrc;
  3701. erclSrc.left = xSrc;
  3702. //
  3703. // If the DIB is regular PM DIB the coordinates are lower-left and need
  3704. // to adjusted to upper left.
  3705. //
  3706. //
  3707. // fix a bug for JPEG/TOPDOWN case
  3708. // the same problem occurs for general DIBs but it's too risky
  3709. // to fix now
  3710. //
  3711. if ((uiCompression == BI_JPEG) && (dbmi.fl & BMF_TOPDOWN))
  3712. {
  3713. erclSrc.top = ySrc;
  3714. }
  3715. else
  3716. {
  3717. erclSrc.top = yHeight - ySrc - cHeightSrc;
  3718. }
  3719. erclSrc.bottom = erclSrc.top + cHeightSrc;
  3720. erclSrc.right = erclSrc.left + cWidthSrc;
  3721. //
  3722. // Order the Src rectangle, flipping Dst to reflect it.
  3723. //
  3724. if (erclSrc.left > erclSrc.right)
  3725. {
  3726. lTmp = erclSrc.left, erclSrc.left = erclSrc.right, erclSrc.right = lTmp;
  3727. erclSrc.left++;
  3728. erclSrc.right++;
  3729. flFlip ^= DIB_FLIP_X;
  3730. }
  3731. if (erclSrc.top > erclSrc.bottom)
  3732. {
  3733. lTmp = erclSrc.top, erclSrc.top = erclSrc.bottom, erclSrc.bottom = lTmp;
  3734. erclSrc.top++;
  3735. erclSrc.bottom++;
  3736. flFlip ^= DIB_FLIP_Y;
  3737. }
  3738. //
  3739. // Make sure some portion of the source is on the src surface.
  3740. //
  3741. if ((erclSrc.right <= 0) ||
  3742. (erclSrc.bottom <= 0) ||
  3743. (erclSrc.left >= SurfDimoTemp.ps->sizl().cx) ||
  3744. (erclSrc.top >= SurfDimoTemp.ps->sizl().cy) ||
  3745. (erclSrc.bEmpty()))
  3746. {
  3747. //
  3748. // Well nothing is visible, let's get out of here.
  3749. //
  3750. WARNING1("GreStretchDIBits nothing visible in SRC rectangle\n");
  3751. }
  3752. else
  3753. {
  3754. //
  3755. // Compute the clipping complexity and maybe reduce the exclusion rectangle.
  3756. //
  3757. ECLIPOBJ co(dcoDest.prgnEffRao(), erclTrg);
  3758. //
  3759. // Check the destination which is reduced by clipping.
  3760. //
  3761. if (co.erclExclude().bEmpty())
  3762. {
  3763. iRetHeight = yHeight;
  3764. }
  3765. else
  3766. {
  3767. if (bNeedAssociatePalette)
  3768. {
  3769. ASSERTGDI(SurfDimoTemp.ps->ppal() == NULL,
  3770. "SetDIBitsToDevice():Surface has palette already\n");
  3771. SurfDimoTemp.ps->ppal(palTemp.ppalGet());
  3772. }
  3773. //
  3774. // Exclude the pointer.
  3775. //
  3776. DEVEXCLUDEOBJ dxo(dcoDest,&erclTrg,&co);
  3777. //
  3778. // Get the function pointer.
  3779. //
  3780. PFN_DrvStretchBlt pfn;
  3781. //
  3782. // There are a bunch of conditions that we don't want to
  3783. // call the driver, so we make pfn point to the Eng
  3784. // function. But if the destination is a meta, we want it
  3785. // to actually call the Mul layer.
  3786. //
  3787. // WINBUG #357937 4-3-2001 jasonha Meta DEVBITMAPs must go thru Mul layer
  3788. // Don't check iType:
  3789. // DEVICE/DEVBITMAP -> MulStretchBlt
  3790. // BITMAP (not hooked) -> EngStretchBlt
  3791. PDEVOBJ pdoDest(pSurfDest->hdev());
  3792. pfn = PPFNGET(pdoDest, StretchBlt, pSurfDest->flags());
  3793. if ((pSurfDest->flags() & HOOK_StretchBlt) && !pdoDest.bMetaDriver())
  3794. {
  3795. // Don't call the driver if it doesn't do halftone.
  3796. if (jStretchBltMode == HALFTONE)
  3797. {
  3798. if (!(dcoDest.flGraphicsCaps() & GCAPS_HALFTONE))
  3799. pfn = (PFN_DrvStretchBlt)EngStretchBlt;
  3800. }
  3801. //
  3802. // Don't call the driver if the source rectangle exceeds
  3803. // the source surface. Some drivers punt using a duplicate
  3804. // of the source SURFOBJ, but without preserving its
  3805. // sizlBitmap member.
  3806. // This causes a source clipping bug (77102).
  3807. //
  3808. if((erclSrc.left < 0) ||
  3809. (erclSrc.top < 0) ||
  3810. (erclSrc.right > SurfDimoTemp.ps->sizl().cx) ||
  3811. (erclSrc.bottom > SurfDimoTemp.ps->sizl().cy))
  3812. {
  3813. pfn = (PFN_DrvStretchBlt)EngStretchBlt;
  3814. }
  3815. }
  3816. //
  3817. // Reflect the accumulated flipping on the target
  3818. //
  3819. if (flFlip & DIB_FLIP_X)
  3820. {
  3821. lTmp = erclTrg.left, erclTrg.left = erclTrg.right, erclTrg.right = lTmp;
  3822. }
  3823. if (flFlip & DIB_FLIP_Y)
  3824. {
  3825. lTmp = erclTrg.top, erclTrg.top = erclTrg.bottom, erclTrg.bottom = lTmp;
  3826. }
  3827. //
  3828. // Inc the target surface uniqueness
  3829. //
  3830. INC_SURF_UNIQ(pSurfDest);
  3831. //
  3832. // Dispatch the call.
  3833. //
  3834. BOOL bRes = (*pfn)(pSurfDest->pSurfobj(),
  3835. SurfDimoTemp.pSurfobj(),
  3836. (SURFOBJ *) NULL,
  3837. (CLIPOBJ *)&co,
  3838. pxlo,
  3839. (dcoDest.pColorAdjustment()->caFlags & CA_DEFAULT) ?
  3840. (PCOLORADJUSTMENT)NULL : dcoDest.pColorAdjustment(),
  3841. &dcoDest.pdc->ptlFillOrigin(),
  3842. &erclTrg,
  3843. &erclSrc,
  3844. NULL,
  3845. (ULONG) jStretchBltMode
  3846. );
  3847. if (bRes)
  3848. {
  3849. iRetHeight = yHeight;
  3850. }
  3851. else
  3852. {
  3853. WARNING1("GreStretchDIBits failed DrvStretchBlt\n");
  3854. }
  3855. if (bNeedAssociatePalette)
  3856. {
  3857. SurfDimoTemp.ps->ppal(NULL);
  3858. }
  3859. }
  3860. }
  3861. }
  3862. }
  3863. }
  3864. }
  3865. }
  3866. }
  3867. }
  3868. }
  3869. }
  3870. }
  3871. }
  3872. }
  3873. return(iRetHeight);
  3874. }
  3875. /**************************************************************************\
  3876. * psurfCreateDIBSurfaceAndXform
  3877. *
  3878. * Create Surface and Palette from DIB input
  3879. *
  3880. * Arguments:
  3881. *
  3882. *
  3883. *
  3884. * Return Value:
  3885. *
  3886. *
  3887. *
  3888. * History:
  3889. *
  3890. * 2/18/1997 Mark Enstrom [marke]
  3891. *
  3892. \**************************************************************************/
  3893. PSURFACE
  3894. psurfCreateDIBSurface(
  3895. HDC hdcDest,
  3896. LPBYTE pInitBits,
  3897. LPBITMAPINFO pInfoHeader,
  3898. DWORD iUsage,
  3899. UINT cjMaxInfo,
  3900. UINT cjMaxBits
  3901. )
  3902. {
  3903. SURFMEM SurfDimoTemp;
  3904. BOOL bSuccess = TRUE;
  3905. #if DBG
  3906. if (pInfoHeader)
  3907. {
  3908. ASSERTGDI (pInfoHeader->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER), "bad header\n");
  3909. }
  3910. #endif
  3911. //
  3912. // Validate the hdc.
  3913. //
  3914. DCOBJ dcoDest(hdcDest);
  3915. if (!dcoDest.bValid())
  3916. {
  3917. WARNING1("psurfCreateDIBSurfaceAndXform failed - invalid DC\n");
  3918. }
  3919. else
  3920. {
  3921. //
  3922. // Let's validate the parameters so we don't gp-fault ourselves.
  3923. //
  3924. // Size in header, copy it out, it can change.
  3925. //
  3926. ULONG ulSize;
  3927. if ((pInfoHeader == (LPBITMAPINFO) NULL) ||
  3928. (pInitBits == (LPBYTE) NULL) ||
  3929. ((iUsage != DIB_RGB_COLORS) &&
  3930. (iUsage != DIB_PAL_COLORS) &&
  3931. (iUsage != DIB_PAL_INDICES)) ||
  3932. (cjMaxInfo < sizeof(BITMAPCOREHEADER)) || // Check first that we can access biSize.
  3933. (cjMaxInfo < (ulSize = pInfoHeader->bmiHeader.biSize)) ||
  3934. (ulSize < sizeof(BITMAPINFOHEADER)))
  3935. {
  3936. WARNING1("psurfCreateDIBSurfaceAndXform failed input parameter validation\n");
  3937. }
  3938. else
  3939. {
  3940. //
  3941. // This is used to hold the height of the bitmap in.
  3942. //
  3943. int yHeight;
  3944. //
  3945. // Get the info from the Header depending upon what kind it is.
  3946. //
  3947. BOOL bSuccess = TRUE;
  3948. UINT uiBitCount, uiCompression, uiWidth, uiPalUsed;
  3949. PULONG pulColors;
  3950. DEVBITMAPINFO dbmi;
  3951. dbmi.fl = 0;
  3952. uiBitCount = (UINT) pInfoHeader->bmiHeader.biBitCount;
  3953. uiCompression = (UINT) pInfoHeader->bmiHeader.biCompression;
  3954. uiWidth = (UINT) pInfoHeader->bmiHeader.biWidth;
  3955. yHeight = (int) pInfoHeader->bmiHeader.biHeight;
  3956. uiPalUsed = (UINT) pInfoHeader->bmiHeader.biClrUsed;
  3957. pulColors = (PULONG) ((LPBYTE)pInfoHeader+ulSize);
  3958. if (yHeight < 0)
  3959. {
  3960. dbmi.fl = BMF_TOPDOWN;
  3961. yHeight = -yHeight;
  3962. }
  3963. //
  3964. // Now that cjMaxInfo has been validated for the header, adjust it to refer to
  3965. // the color table
  3966. //
  3967. cjMaxInfo -= (UINT)ulSize;
  3968. //
  3969. // Figure out what this guy is blting from.
  3970. //
  3971. ULONG cColorsMax;
  3972. FLONG iPalMode;
  3973. FLONG iPalType;
  3974. FLONG flRed;
  3975. FLONG flGre;
  3976. FLONG flBlu;
  3977. BOOL bRLE = FALSE;
  3978. if (uiCompression == BI_BITFIELDS)
  3979. {
  3980. //
  3981. // Handle 16 and 32 bit per pel bitmaps.
  3982. //
  3983. if ((ulSize <= sizeof(BITMAPINFO)) && (cjMaxInfo < (sizeof(ULONG) * 3)))
  3984. {
  3985. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  3986. WARNING1("psurfCreateDIBSurfaceAndXform failed - not room for flags\n");
  3987. bSuccess = FALSE;
  3988. }
  3989. else
  3990. {
  3991. //
  3992. // if BITMAPV4 or greater then masks are stored in info header
  3993. //
  3994. if (ulSize >= sizeof(BITMAPINFOHEADER))
  3995. {
  3996. pulColors = (PULONG) ((LPBYTE)pInfoHeader+sizeof(BITMAPINFOHEADER));
  3997. }
  3998. flRed = pulColors[0];
  3999. flGre = pulColors[1];
  4000. flBlu = pulColors[2];
  4001. if (iUsage == DIB_PAL_COLORS)
  4002. {
  4003. iUsage = DIB_RGB_COLORS;
  4004. }
  4005. switch (uiBitCount)
  4006. {
  4007. case 16:
  4008. dbmi.iFormat = BMF_16BPP;
  4009. break;
  4010. case 32:
  4011. dbmi.iFormat = BMF_32BPP;
  4012. break;
  4013. default:
  4014. WARNING1("SetDIBitsToDevice failed for BI_BITFIELDS\n");
  4015. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  4016. bSuccess = FALSE;
  4017. }
  4018. cColorsMax = 0;
  4019. iPalMode = PAL_BITFIELDS;
  4020. iPalType = PAL_FIXED;
  4021. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * yHeight;
  4022. }
  4023. }
  4024. else if (uiCompression == BI_RGB)
  4025. {
  4026. switch (uiBitCount)
  4027. {
  4028. case 1:
  4029. dbmi.iFormat = BMF_1BPP;
  4030. cColorsMax = 2;
  4031. iPalMode = PAL_INDEXED;
  4032. iPalType = PAL_FREE;
  4033. break;
  4034. case 4:
  4035. dbmi.iFormat = BMF_4BPP;
  4036. cColorsMax = 16;
  4037. iPalMode = PAL_INDEXED;
  4038. iPalType = PAL_FREE;
  4039. break;
  4040. case 8:
  4041. dbmi.iFormat = BMF_8BPP;
  4042. cColorsMax = 256;
  4043. iPalMode = PAL_INDEXED;
  4044. iPalType = PAL_FREE;
  4045. break;
  4046. default:
  4047. if (iUsage == DIB_PAL_COLORS)
  4048. {
  4049. iUsage = DIB_RGB_COLORS;
  4050. }
  4051. switch (uiBitCount)
  4052. {
  4053. case 16:
  4054. dbmi.iFormat = BMF_16BPP;
  4055. flRed = 0x7c00;
  4056. flGre = 0x03e0;
  4057. flBlu = 0x001f;
  4058. cColorsMax = 0;
  4059. iPalMode = PAL_BITFIELDS;
  4060. iPalType = PAL_FIXED;
  4061. break;
  4062. case 24:
  4063. dbmi.iFormat = BMF_24BPP;
  4064. cColorsMax = 0;
  4065. iPalMode = PAL_BGR;
  4066. iPalType = PAL_FIXED;
  4067. break;
  4068. case 32:
  4069. //
  4070. // This is for alpha API, assume
  4071. // 32 bpp BGR input is BGRA
  4072. //
  4073. dbmi.iFormat = BMF_32BPP;
  4074. cColorsMax = 0;
  4075. iPalMode = PAL_BGR;
  4076. iPalType = PAL_FIXED;
  4077. break;
  4078. default:
  4079. WARNING1("psurfCreateDIBSurfaceAndXform failed invalid bitcount in bmi BI_RGB\n");
  4080. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  4081. bSuccess = FALSE;
  4082. }
  4083. }
  4084. if (bSuccess)
  4085. {
  4086. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * yHeight;
  4087. }
  4088. }
  4089. else if (uiCompression == BI_CMYK)
  4090. {
  4091. ASSERTGDI(iUsage == DIB_RGB_COLORS,
  4092. "psurfCreateDIBSurface(BI_CMYK):iUsage should be DIB_RGB_COLORS\n");
  4093. DCOBJ dcoDest(hdcDest);
  4094. //
  4095. // Current dc context accept CMYK color ?
  4096. //
  4097. if (!dcoDest.bValid() || !dcoDest.pdc->bIsCMYKColor())
  4098. {
  4099. WARNING1("psurfCreateDIBSurface:DC is not in CMYK color mode for BI_CMYK\n");
  4100. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  4101. bSuccess = FALSE;
  4102. }
  4103. else
  4104. {
  4105. switch (uiBitCount)
  4106. {
  4107. case 1:
  4108. dbmi.iFormat = BMF_1BPP;
  4109. cColorsMax = 2;
  4110. iPalMode = PAL_INDEXED;
  4111. iPalType = PAL_FREE;
  4112. break;
  4113. case 4:
  4114. dbmi.iFormat = BMF_4BPP;
  4115. cColorsMax = 16;
  4116. iPalMode = PAL_INDEXED;
  4117. iPalType = PAL_FREE;
  4118. break;
  4119. case 8:
  4120. dbmi.iFormat = BMF_8BPP;
  4121. cColorsMax = 256;
  4122. iPalMode = PAL_INDEXED;
  4123. iPalType = PAL_FREE;
  4124. break;
  4125. case 32:
  4126. dbmi.iFormat = BMF_32BPP;
  4127. cColorsMax = 0;
  4128. iPalMode = PAL_CMYK;
  4129. iPalType = PAL_FIXED;
  4130. break;
  4131. default:
  4132. WARNING1("psurfCreateDIBSurfaceAndXform failed invalid bitcount in bmi BI_RGB\n");
  4133. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  4134. bSuccess = FALSE;
  4135. }
  4136. }
  4137. if (bSuccess)
  4138. {
  4139. dbmi.cjBits = ((((uiBitCount * uiWidth) + 31) >> 5) << 2) * yHeight;
  4140. }
  4141. }
  4142. else
  4143. {
  4144. //
  4145. // rle not supported
  4146. //
  4147. WARNING1("psurfCreateDIBSurfaceAndXform does not support RLE\n");
  4148. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  4149. bSuccess = FALSE;
  4150. }
  4151. if (bSuccess)
  4152. {
  4153. dbmi.cxBitmap = uiWidth;
  4154. dbmi.cyBitmap = yHeight;
  4155. ULONG cColors;
  4156. if (uiPalUsed != 0)
  4157. {
  4158. if (uiPalUsed <= cColorsMax)
  4159. {
  4160. cColors = uiPalUsed;
  4161. }
  4162. else
  4163. {
  4164. cColors = cColorsMax;
  4165. }
  4166. }
  4167. else
  4168. {
  4169. cColors = cColorsMax;
  4170. }
  4171. if (cjMaxBits < dbmi.cjBits)
  4172. {
  4173. WARNING1("psurfCreateDIBSurfaceAndXform failed because of invalid cjMaxBits\n");
  4174. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  4175. }
  4176. else
  4177. {
  4178. PALMEMOBJ palTemp;
  4179. //
  4180. // Allocate a palette for this bitmap.
  4181. //
  4182. if (!palTemp.bCreatePalette(iPalMode,
  4183. cColorsMax,
  4184. (PULONG) NULL,
  4185. flRed,
  4186. flGre,
  4187. flBlu,
  4188. iPalType
  4189. )
  4190. )
  4191. {
  4192. WARNING1("psurfCreateDIBSurfaceAndXform: Failed palette creation\n");
  4193. bSuccess = FALSE;
  4194. }
  4195. if (bSuccess && palTemp.bValid())
  4196. {
  4197. //
  4198. // need palette, is not locked in!
  4199. //
  4200. palTemp.vKeepIt();
  4201. dbmi.hpal = palTemp.hpal();
  4202. //
  4203. // Attempt to allocate the bitmap.
  4204. //
  4205. if (!SurfDimoTemp.bCreateDIB(&dbmi,pInitBits))
  4206. {
  4207. WARNING("psurfCreateDIBSurfaceAndXform failed bCreateDIB\n");
  4208. bSuccess = FALSE;
  4209. }
  4210. if (bSuccess)
  4211. {
  4212. //
  4213. // Lock the Rao region if we are drawing on a display surface. The Rao
  4214. // region might otherwise change asynchronously. The DEVLOCKOBJ also makes
  4215. // sure that the VisRgn is up to date, calling the window manager if
  4216. // necessary to recompute it. It also protects us from pSurfDest
  4217. // being changed asynchronously by a dynamic mode change.
  4218. //
  4219. DEVLOCKOBJ dlo(dcoDest);
  4220. SURFACE *pSurfDest = dcoDest.pSurfaceEff();
  4221. XEPALOBJ palDest(pSurfDest->ppal());
  4222. XEPALOBJ palDestDC(dcoDest.ppal());
  4223. switch (iUsage)
  4224. {
  4225. case DIB_RGB_COLORS:
  4226. if (cColors)
  4227. {
  4228. if (cjMaxInfo < (cColors * 4))
  4229. {
  4230. WARNING1("psurfCreateDIBSurfaceAndXform: failed DIB_RGB_COLORS bmi invalid size\n");
  4231. bSuccess = FALSE;
  4232. //
  4233. // break out of case
  4234. //
  4235. break;
  4236. }
  4237. else
  4238. {
  4239. //
  4240. // Copy bitmap color table into palette
  4241. //
  4242. if (IS_CMYK_BITMAP(uiCompression))
  4243. {
  4244. palTemp.vCopy_cmykquad(pulColors, 0, cColors);
  4245. }
  4246. else
  4247. {
  4248. palTemp.vCopy_rgbquad((RGBQUAD *) pulColors, 0, cColors);
  4249. }
  4250. }
  4251. }
  4252. break;
  4253. case DIB_PAL_COLORS:
  4254. {
  4255. //
  4256. // translate PAL_INDICIES into colors
  4257. // from dc palette
  4258. //
  4259. ULONG palIndex;
  4260. PUSHORT pDibPalColor = (PUSHORT)pulColors;
  4261. //
  4262. // DIB_PAL_COLOR array is direct user input, verify
  4263. //
  4264. for (palIndex=0;palIndex<cColors;palIndex++)
  4265. {
  4266. PALETTEENTRY PalEntry;
  4267. ULONG TempIndex = pDibPalColor[palIndex];
  4268. if (TempIndex > 256)
  4269. {
  4270. TempIndex = 0;
  4271. }
  4272. PalEntry = palDestDC.palentryGet(TempIndex);
  4273. PalEntry.peFlags = 0;
  4274. palTemp.palentrySet(palIndex,PalEntry);
  4275. }
  4276. palTemp.vUpdateTime();
  4277. }
  4278. break;
  4279. //
  4280. // error case, don't support DIB_PAL_INDICIES
  4281. //
  4282. default:
  4283. bSuccess = FALSE;
  4284. }
  4285. }
  4286. }
  4287. }
  4288. }
  4289. }
  4290. }
  4291. if (bSuccess)
  4292. {
  4293. //
  4294. // keep but ref count is 0
  4295. //
  4296. SurfDimoTemp.vKeepIt();
  4297. return(SurfDimoTemp.ps);
  4298. }
  4299. else
  4300. {
  4301. return(NULL);
  4302. }
  4303. }