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.

11798 lines
363 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: icm.c
  3. *
  4. * Created: 4-Jun-1996
  5. * Author: Mark Enstrom [marke]
  6. *
  7. * Copyright (c) 1996-1999 Microsoft Corporation
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. #include "winuserk.h"
  12. #if DBG_ICM
  13. ULONG DbgIcm = 0x0;
  14. #endif
  15. //
  16. // Instance of MSCMS.DLL
  17. //
  18. HINSTANCE ghICM;
  19. //
  20. // Color Profile Directory
  21. //
  22. WCHAR ColorDirectory[MAX_PATH];
  23. DWORD ColorDirectorySize;
  24. //
  25. // Primary display DC color profile filename.
  26. //
  27. WCHAR PrimaryDisplayProfile[MAX_PATH];
  28. //
  29. // List of ICMINFO
  30. //
  31. LIST_ENTRY ListIcmInfo;
  32. //
  33. // Semaphore to protect ICMINFO list
  34. //
  35. RTL_CRITICAL_SECTION semListIcmInfo;
  36. //
  37. // Per process color space and color transform cache list
  38. //
  39. LIST_ENTRY ListCachedColorSpace;
  40. LIST_ENTRY ListCachedColorTransform;
  41. ULONG cCachedColorSpace = 0;
  42. ULONG cCachedColorTransform = 0;
  43. //
  44. // Semaphore to protect Cache list
  45. //
  46. RTL_CRITICAL_SECTION semColorTransformCache;
  47. RTL_CRITICAL_SECTION semColorSpaceCache;
  48. BOOL gbICMEnabledOnceBefore = FALSE;
  49. //
  50. // ANSI version function in MSCMS.DLL will not called.
  51. //
  52. // FPOPENCOLORPROFILEA fpOpenColorProfileA;
  53. // FPCREATECOLORTRANSFORMA fpCreateColorTransformA;
  54. // FPREGISTERCMMA fpRegisterCMMA;
  55. // FPUNREGISTERCMMA fpUnregisterCMMA;
  56. // FPINSTALLCOLORPROFILEA fpInstallColorProfileA;
  57. // FPUNINSTALLCOLORPROFILEA fpUninstallColorProfileA;
  58. // FPGETSTANDARDCOLORSPACEPROFILEA fpGetStandardColorSpaceProfileA;
  59. // FPENUMCOLORPROFILESA fpEnumColorProfilesA;
  60. // FPGETCOLORDIRECTORYA fpGetColorDirectoryA;
  61. //
  62. // And Following function does not used from gdi32.dll
  63. //
  64. // FPISCOLORPROFILEVALID fpIsColorProfileValid;
  65. // FPCREATEDEVICELINKPROFILE fpCreateDeviceLinkProfile;
  66. // FPTRANSLATECOLORS fpTranslateColors;
  67. // FPCHECKCOLORS fpCheckColors;
  68. // FPGETCMMINFO fpGetCMMInfo;
  69. // FPSELECTCMM fpSelectCMM;
  70. //
  71. FPOPENCOLORPROFILEW fpOpenColorProfileW;
  72. FPCLOSECOLORPROFILE fpCloseColorProfile;
  73. FPCREATECOLORTRANSFORMW fpCreateColorTransformW;
  74. FPDELETECOLORTRANSFORM fpDeleteColorTransform;
  75. FPTRANSLATEBITMAPBITS fpTranslateBitmapBits;
  76. FPTRANSLATECOLORS fpTranslateColors;
  77. FPCHECKBITMAPBITS fpCheckBitmapBits;
  78. FPREGISTERCMMW fpRegisterCMMW;
  79. FPUNREGISTERCMMW fpUnregisterCMMW;
  80. FPINSTALLCOLORPROFILEW fpInstallColorProfileW;
  81. FPUNINSTALLCOLORPROFILEW fpUninstallColorProfileW;
  82. FPENUMCOLORPROFILESW fpEnumColorProfilesW;
  83. FPGETSTANDARDCOLORSPACEPROFILEW fpGetStandardColorSpaceProfileW;
  84. FPGETCOLORPROFILEHEADER fpGetColorProfileHeader;
  85. FPGETCOLORDIRECTORYW fpGetColorDirectoryW;
  86. FPCREATEPROFILEFROMLOGCOLORSPACEW fpCreateProfileFromLogColorSpaceW;
  87. FPCREATEMULTIPROFILETRANSFORM fpCreateMultiProfileTransform;
  88. FPINTERNALGETDEVICECONFIG fpInternalGetDeviceConfig;
  89. //
  90. // MS COLOR MATCH DLL name
  91. //
  92. #define MSCMS_DLL_NAME L"mscms.dll"
  93. //
  94. // Misc. macros
  95. //
  96. #define ALIGN_DWORD(nBytes) (((nBytes) + 3) & ~3)
  97. //
  98. // sRGB color profile name
  99. //
  100. #define sRGB_PROFILENAME L"sRGB Color Space Profile.icm"
  101. //
  102. // DWORD 0x12345678 ---> 0x78563412
  103. //
  104. #define IcmSwapBytes(x) ((((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | \
  105. (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24))
  106. //
  107. // Macro to check color DC or not.
  108. //
  109. // LATER: We can improve performance by caching this in client, since
  110. // GetDeviceCaps() goes to kernel in most cases.
  111. //
  112. #define IsColorDeviceContext(hdcThis) \
  113. (2 < (unsigned) GetDeviceCaps((hdcThis), NUMCOLORS))
  114. //
  115. // Macro to check the color space is GDI object dependent.
  116. //
  117. #define IsColorSpaceOwnedByGDIObject(pColorSpace,hGDIObj) \
  118. ((pColorSpace) ? \
  119. (((pColorSpace)->hObj == (hGDIObj)) ? TRUE : FALSE) \
  120. : FALSE)
  121. //
  122. // Macro to get current color tranform in DC.
  123. //
  124. #define GetColorTransformInDC(pdcattr) ((pdcattr)->hcmXform)
  125. //
  126. // if the color space has DEVICE_CALIBRATE_COLORSPACE flag, returns TRUE, otherwise FALSE.
  127. //
  128. #define bDeviceCalibrate(pColorSpace) \
  129. ((pColorSpace) ? \
  130. (((pColorSpace)->flInfo & DEVICE_CALIBRATE_COLORSPACE) ? TRUE : FALSE) \
  131. : FALSE)
  132. //
  133. // Increment reference count of colorpsace/colortransform.
  134. //
  135. #define IcmReferenceColorSpace(pColorSpace) \
  136. if ((pColorSpace)) \
  137. { \
  138. ENTERCRITICALSECTION(&semColorSpaceCache); \
  139. (pColorSpace)->cRef++; \
  140. LEAVECRITICALSECTION(&semColorSpaceCache); \
  141. }
  142. #define IcmReferenceColorTransform(pCXfrom) \
  143. if ((pCXform)) \
  144. { \
  145. ENTERCRITICALSECTION(&semColorTransformCache); \
  146. (pCXform)->cRef++; \
  147. LEAVECRITICALSECTION(&semColorTransformCache); \
  148. }
  149. //
  150. // Invalid color space handle
  151. //
  152. #define INVALID_COLORSPACE ((HCOLORSPACE)-1)
  153. //
  154. // Maximum number of cached color transform in list.
  155. //
  156. #define MAX_COLORTRANSFORM_CACHE 10
  157. //
  158. // Maximum size of "on memory profile" which be able to cache.
  159. //
  160. #define MAX_SIZE_OF_COLORPROFILE_TO_CACHE (1024*3)
  161. /******************************Public*Routine******************************\
  162. * GDI initialization routine called from dll init
  163. *
  164. * Arguments:
  165. *
  166. * None
  167. *
  168. * Return Value:
  169. *
  170. * Status
  171. *
  172. * History:
  173. *
  174. * 3-Jul-1996 -by- Mark Enstrom [marke]
  175. *
  176. \**************************************************************************/
  177. BOOL
  178. IcmInitialize()
  179. {
  180. BOOL bStatus = TRUE;
  181. ICMAPI(("gdi32: IcmInitialize\n"));
  182. ENTERCRITICALSECTION(&semLocal);
  183. //
  184. // load MCSCM.DLL and get function addresses
  185. //
  186. if (ghICM == NULL)
  187. {
  188. HANDLE hmscms = LoadLibraryW(MSCMS_DLL_NAME);
  189. if (hmscms != NULL)
  190. {
  191. fpOpenColorProfileW =
  192. (FPOPENCOLORPROFILEW)GetProcAddress(hmscms,"OpenColorProfileW");
  193. fpCloseColorProfile =
  194. (FPCLOSECOLORPROFILE)GetProcAddress(hmscms,"CloseColorProfile");
  195. fpCreateColorTransformW =
  196. (FPCREATECOLORTRANSFORMW)GetProcAddress(hmscms,"CreateColorTransformW");
  197. fpDeleteColorTransform =
  198. (FPDELETECOLORTRANSFORM)GetProcAddress(hmscms,"DeleteColorTransform");
  199. fpTranslateBitmapBits =
  200. (FPTRANSLATEBITMAPBITS)GetProcAddress(hmscms,"TranslateBitmapBits");
  201. fpTranslateColors =
  202. (FPTRANSLATECOLORS)GetProcAddress(hmscms,"TranslateColors");
  203. fpCheckBitmapBits =
  204. (FPCHECKBITMAPBITS)GetProcAddress(hmscms,"CheckBitmapBits");
  205. fpRegisterCMMW =
  206. (FPREGISTERCMMW)GetProcAddress(hmscms,"RegisterCMMW");
  207. fpUnregisterCMMW =
  208. (FPUNREGISTERCMMW)GetProcAddress(hmscms,"UnregisterCMMW");
  209. fpInstallColorProfileW =
  210. (FPINSTALLCOLORPROFILEW)GetProcAddress(hmscms,"InstallColorProfileW");
  211. fpUninstallColorProfileW =
  212. (FPUNINSTALLCOLORPROFILEW)GetProcAddress(hmscms,"UninstallColorProfileW");
  213. fpEnumColorProfilesW =
  214. (FPENUMCOLORPROFILESW)GetProcAddress(hmscms,"EnumColorProfilesW");
  215. fpGetStandardColorSpaceProfileW =
  216. (FPGETSTANDARDCOLORSPACEPROFILEW)GetProcAddress(hmscms,"GetStandardColorSpaceProfileW");
  217. fpGetColorProfileHeader =
  218. (FPGETCOLORPROFILEHEADER)GetProcAddress(hmscms,"GetColorProfileHeader");
  219. fpGetColorDirectoryW =
  220. (FPGETCOLORDIRECTORYW)GetProcAddress(hmscms,"GetColorDirectoryW");
  221. fpCreateProfileFromLogColorSpaceW =
  222. (FPCREATEPROFILEFROMLOGCOLORSPACEW)GetProcAddress(hmscms,"CreateProfileFromLogColorSpaceW");
  223. fpCreateMultiProfileTransform =
  224. (FPCREATEMULTIPROFILETRANSFORM)GetProcAddress(hmscms,"CreateMultiProfileTransform");
  225. fpInternalGetDeviceConfig =
  226. (FPINTERNALGETDEVICECONFIG)GetProcAddress(hmscms,"InternalGetDeviceConfig");
  227. if ((fpOpenColorProfileW == NULL) ||
  228. (fpCloseColorProfile == NULL) ||
  229. (fpCreateColorTransformW == NULL) ||
  230. (fpDeleteColorTransform == NULL) ||
  231. (fpTranslateBitmapBits == NULL) ||
  232. (fpTranslateColors == NULL) ||
  233. (fpCheckBitmapBits == NULL) ||
  234. (fpRegisterCMMW == NULL) ||
  235. (fpUnregisterCMMW == NULL) ||
  236. (fpInstallColorProfileW == NULL) ||
  237. (fpUninstallColorProfileW == NULL) ||
  238. (fpEnumColorProfilesW == NULL) ||
  239. (fpGetStandardColorSpaceProfileW == NULL) ||
  240. (fpGetColorProfileHeader == NULL) ||
  241. (fpGetColorDirectoryW == NULL) ||
  242. (fpCreateProfileFromLogColorSpaceW == NULL) ||
  243. (fpCreateMultiProfileTransform == NULL) ||
  244. (fpInternalGetDeviceConfig == NULL)
  245. )
  246. {
  247. WARNING("LoadLibrary of mscms.dll failed to associate all proc addresses\n");
  248. FreeLibrary(hmscms);
  249. hmscms = NULL;
  250. }
  251. else
  252. {
  253. //
  254. // Initialize Color Directory
  255. //
  256. ColorDirectorySize = sizeof(ColorDirectory) / sizeof(WCHAR);
  257. bStatus = (*fpGetColorDirectoryW)(NULL,ColorDirectory,&ColorDirectorySize);
  258. if (bStatus)
  259. {
  260. ColorDirectorySize = wcslen(ColorDirectory);
  261. }
  262. if (bStatus && ColorDirectorySize)
  263. {
  264. ICMMSG(("IcmInitialize():ColorDirectory = %ws\n",ColorDirectory));
  265. //
  266. // Counts null-terminated char.
  267. //
  268. ColorDirectorySize += 1;
  269. //
  270. // Initialize Primary display color profile.
  271. //
  272. PrimaryDisplayProfile[0] = UNICODE_NULL;
  273. }
  274. else
  275. {
  276. WARNING("LoadLibrary of mscms.dll failed to obtain color directory\n");
  277. FreeLibrary(hmscms);
  278. hmscms = NULL;
  279. }
  280. }
  281. //
  282. // Keep the handle to global veriable.
  283. //
  284. ghICM = hmscms;
  285. }
  286. }
  287. LEAVECRITICALSECTION(&semLocal);
  288. if (ghICM == NULL)
  289. {
  290. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  291. bStatus = FALSE;
  292. }
  293. return(bStatus);
  294. }
  295. /******************************Public*Routine******************************\
  296. *
  297. * SetIcmMode - turn ICM on or off in a DC
  298. *
  299. * Arguments:
  300. *
  301. * hdc - device context
  302. * mode - ICM_ON,ICM_OFF,ICM_QUERY
  303. *
  304. * Return Value:
  305. *
  306. * status
  307. *
  308. * History:
  309. *
  310. * Rewrite it:
  311. * 20-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  312. * Write it:
  313. * 4-Jun-1996 -by- Mark Enstrom [marke]
  314. *
  315. \**************************************************************************/
  316. int META WINAPI
  317. SetICMMode(
  318. HDC hdc,
  319. int mode
  320. )
  321. {
  322. int iRet = (int)FALSE;
  323. PDC_ATTR pdcattr;
  324. ICMAPI(("gdi32: SetICMMode\n"));
  325. FIXUP_HANDLE(hdc);
  326. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  327. //
  328. // metafile (only for ICM_ON and ICM_OFF)
  329. //
  330. if (IS_ALTDC_TYPE(hdc))
  331. {
  332. PLDC pldc;
  333. //
  334. // No ICM with Windows MetaFile.
  335. //
  336. if (IS_METADC16_TYPE(hdc))
  337. return(iRet);
  338. DC_PLDC(hdc,pldc,iRet)
  339. #if DBG_ICM
  340. ICMMSG(("SetICMMode():%s ICM for %s\n", \
  341. ((mode == ICM_ON) ? "Enable" : \
  342. ((mode == ICM_OFF) ? "Disable" : "Query")), \
  343. ((pldc->iType == LO_METADC) ? "Enhanced Metafile" : \
  344. (!IsColorDeviceContext(hdc) ? "Monochrome Printer" : "Color Printer")) \
  345. ));
  346. #endif
  347. //
  348. // If this is Enhanced Metafile, OR non-color printer device, don't enable ICM "really".
  349. //
  350. if (pldc->iType == LO_METADC || (!IsColorDeviceContext(hdc)))
  351. {
  352. switch (mode)
  353. {
  354. case ICM_ON:
  355. case ICM_OFF:
  356. case ICM_DONE_OUTSIDEDC:
  357. //
  358. // Record ICM ON/OFF only to metafile.
  359. //
  360. if (pldc->iType == LO_METADC)
  361. {
  362. if (!MF_SetD(hdc,(DWORD)mode,EMR_SETICMMODE))
  363. {
  364. return((int)FALSE);
  365. }
  366. }
  367. //
  368. // We don't "really" turn-on ICM for metafile, metafile
  369. // should be device-independent, thus, non-ICMed color/images
  370. // will be metafiled. But still need to keep its status for ICM_QUERY.
  371. // And "real" image correction happen at play-back time.
  372. //
  373. if(pdcattr)
  374. {
  375. if (mode == ICM_ON)
  376. {
  377. pdcattr->lIcmMode |= DC_ICM_METAFILING_ON;
  378. }
  379. else if (mode == ICM_DONE_OUTSIDEDC)
  380. {
  381. pdcattr->lIcmMode |= (DC_ICM_METAFILING_ON |
  382. CTX_ICM_METAFILING_OUTSIDEDC);
  383. }
  384. else // if ((mode == ICM_OFF)
  385. {
  386. pdcattr->lIcmMode &= ~(DC_ICM_METAFILING_ON |
  387. CTX_ICM_METAFILING_OUTSIDEDC);
  388. }
  389. iRet = (int)TRUE;
  390. }
  391. break;
  392. case ICM_QUERY:
  393. if (pdcattr)
  394. {
  395. if (IS_ICM_METAFILING_ON(pdcattr->lIcmMode))
  396. {
  397. iRet = ((pdcattr->lIcmMode & CTX_ICM_METAFILING_OUTSIDEDC) ? \
  398. ICM_DONE_OUTSIDEDC : ICM_ON);
  399. }
  400. else
  401. {
  402. iRet = ICM_OFF;
  403. }
  404. }
  405. break;
  406. default:
  407. iRet = (int)FALSE;
  408. break;
  409. }
  410. return (iRet);
  411. }
  412. }
  413. if (pdcattr)
  414. {
  415. ULONG iPrevMode;
  416. //
  417. // Before change ICM mode, we need to flush batched gdi functions.
  418. //
  419. CHECK_AND_FLUSH(hdc,pdcattr);
  420. //
  421. // Get current mode.
  422. //
  423. iPrevMode = pdcattr->lIcmMode;
  424. //
  425. // validate input parameter
  426. //
  427. switch (ICM_MODE(mode))
  428. {
  429. case ICM_QUERY:
  430. //
  431. // return current mode
  432. //
  433. if (IS_ICM_INSIDEDC(iPrevMode))
  434. {
  435. iRet = ICM_ON;
  436. }
  437. else if (IS_ICM_OUTSIDEDC(iPrevMode))
  438. {
  439. iRet = ICM_DONE_OUTSIDEDC;
  440. }
  441. else
  442. {
  443. iRet = ICM_OFF;
  444. }
  445. break;
  446. case ICM_ON:
  447. if (!IS_ICM_INSIDEDC(iPrevMode))
  448. {
  449. //
  450. // As default, ICM will be done on HOST.
  451. //
  452. ULONG lReqMode = REQ_ICM_HOST;
  453. PGDI_ICMINFO pIcmInfo = INIT_ICMINFO(hdc,pdcattr);
  454. //
  455. // Initialize ICMINFO
  456. //
  457. if (pIcmInfo == NULL)
  458. {
  459. WARNING("gdi32: SetICMMode: Can't init icm info\n");
  460. return((int)FALSE);
  461. }
  462. //
  463. // Load external ICM dlls.
  464. //
  465. LOAD_ICMDLL((int)FALSE);
  466. //
  467. // ICM is not enabled,yet. Let's enable ICM.
  468. //
  469. ASSERTGDI(GetColorTransformInDC(pdcattr) == NULL,"SetIcmMode: hcmXform is not NULL\n");
  470. if (IS_DEVICE_ICM_DEVMODE(iPrevMode))
  471. {
  472. ICMMSG(("SetIcmMode: Device ICM is requested\n"));
  473. //
  474. // if ICM on Device was requested by CreateDC(), let force do
  475. // ICM on device, if possible.
  476. //
  477. lReqMode = REQ_ICM_DEVICE;
  478. }
  479. else
  480. {
  481. ICMMSG(("SetIcmMode: Host ICM is requested\n"));
  482. }
  483. //
  484. // Turn ICM on for this DC.
  485. //
  486. if (!NtGdiSetIcmMode(hdc,ICM_SET_MODE,lReqMode))
  487. {
  488. //
  489. // something wrong... we are fail to enable ICM.
  490. //
  491. iRet = (int)FALSE;
  492. break;
  493. }
  494. //
  495. // If we have cached transform and it is not dirty, we can use that.
  496. //
  497. if ((pIcmInfo->pCXform == NULL) || (pdcattr->ulDirty_ & DIRTY_COLORTRANSFORM))
  498. {
  499. if (IcmUpdateDCColorInfo(hdc,pdcattr))
  500. {
  501. //
  502. // Mark this process has experience about ICM ON.
  503. //
  504. gbICMEnabledOnceBefore = TRUE;
  505. iRet = (int)TRUE;
  506. }
  507. else
  508. {
  509. WARNING("SetIcmMode():IcmUpdateDCInfo failed\n");
  510. //
  511. // Fail to create new transform
  512. //
  513. NtGdiSetIcmMode(hdc,ICM_SET_MODE,REQ_ICM_OFF);
  514. iRet = (int)FALSE;
  515. }
  516. }
  517. else
  518. {
  519. ICMMSG(("SetIcmMode: Use cached Color Transform\n"));
  520. //
  521. // Use cached transform, because since last time when we disabled ICM,
  522. // NO profile(s) and logical color space has been changed.
  523. //
  524. if (IcmSelectColorTransform(
  525. hdc,pdcattr,pIcmInfo->pCXform,
  526. bDeviceCalibrate(pIcmInfo->pCXform->DestinationColorSpace)))
  527. {
  528. //
  529. // Translate all DC objects to ICM colors. Must
  530. // force brush/pens to be re-realized when used next
  531. //
  532. IcmTranslateColorObjects(hdc,pdcattr,TRUE);
  533. iRet = (int)TRUE;
  534. }
  535. else
  536. {
  537. //
  538. // Fail to select cached transform to the DC.
  539. //
  540. NtGdiSetIcmMode(hdc,ICM_SET_MODE,REQ_ICM_OFF);
  541. iRet = (int)FALSE;
  542. }
  543. }
  544. }
  545. else
  546. {
  547. ICMMSG(("SetIcmMode: ICM has been enabled already\n"));
  548. iRet = (int)TRUE;
  549. }
  550. break;
  551. case ICM_DONE_OUTSIDEDC:
  552. if (!IS_ICM_OUTSIDEDC(iPrevMode))
  553. {
  554. //
  555. // if inside-DC ICM is enabled, turned off it.
  556. //
  557. if (IS_ICM_INSIDEDC(iPrevMode))
  558. {
  559. //
  560. // Invalidate current color tansform (but the cache in ICMINFO is still valid).
  561. //
  562. IcmSelectColorTransform(hdc,pdcattr,NULL,FALSE);
  563. //
  564. // Restore color data for ICM disable.
  565. //
  566. IcmTranslateColorObjects(hdc,pdcattr,FALSE);
  567. }
  568. //
  569. // Tell the kernel to disable color adjustment during halftone.
  570. //
  571. NtGdiSetIcmMode(hdc,ICM_SET_MODE,REQ_ICM_OUTSIDEDC);
  572. }
  573. else
  574. {
  575. ICMMSG(("SetIcmMode: OutsideDC ICM has been enabled already\n"));
  576. }
  577. iRet = (int)TRUE;
  578. break;
  579. case ICM_OFF:
  580. //
  581. // Is there any kind of ICM is enabled ?
  582. //
  583. if (IS_ICM_ON(iPrevMode))
  584. {
  585. if (IS_ICM_INSIDEDC(iPrevMode))
  586. {
  587. //
  588. // Invalidate current color tansform (but the cache in ICMINFO is still valid).
  589. //
  590. IcmSelectColorTransform(hdc,pdcattr,NULL,TRUE);
  591. //
  592. // Restore color data for ICM disable.
  593. //
  594. IcmTranslateColorObjects(hdc,pdcattr,FALSE);
  595. }
  596. //
  597. // Tell the kernel to disable ICM.
  598. //
  599. NtGdiSetIcmMode(hdc,ICM_SET_MODE,REQ_ICM_OFF);
  600. }
  601. else
  602. {
  603. ICMMSG(("SetIcmMode: ICM has been disabled already\n"));
  604. }
  605. iRet = (int)TRUE;
  606. break;
  607. default:
  608. GdiSetLastError(ERROR_INVALID_PARAMETER);
  609. iRet = (int)FALSE;
  610. break;
  611. }
  612. }
  613. else
  614. {
  615. GdiSetLastError(ERROR_INVALID_PARAMETER);
  616. iRet = (int)FALSE;
  617. }
  618. return((int)iRet);
  619. }
  620. /******************************Public*Routine******************************\
  621. * CreateColorSpaceA
  622. *
  623. * Arguments:
  624. *
  625. * lpLogColorSpace - apps log color space
  626. *
  627. * Return Value:
  628. *
  629. * handle of color space or NULL
  630. *
  631. * History:
  632. *
  633. * 4-Jun-1996 -by- Mark Enstrom [marke]
  634. *
  635. \**************************************************************************/
  636. HCOLORSPACE WINAPI
  637. CreateColorSpaceA(
  638. LPLOGCOLORSPACEA lpLogColorSpace
  639. )
  640. {
  641. HCOLORSPACE hRet;
  642. LOGCOLORSPACEW LogColorSpaceW;
  643. ICMAPI(("gdi32: CreateColorSpaceA\n"));
  644. if (lpLogColorSpace == NULL)
  645. {
  646. GdiSetLastError(ERROR_INVALID_PARAMETER);
  647. return(NULL);
  648. }
  649. //
  650. // convert ascii to long character version
  651. //
  652. if ((lpLogColorSpace->lcsSignature != LCS_SIGNATURE) ||
  653. (lpLogColorSpace->lcsVersion != 0x400) ||
  654. (lpLogColorSpace->lcsSize != sizeof(LOGCOLORSPACEA)))
  655. {
  656. ICMWRN(("CreateColorSpaceA: Incorrect signature,version or size \n"));
  657. GdiSetLastError(ERROR_INVALID_COLORSPACE);
  658. return(NULL);
  659. }
  660. RtlZeroMemory(&LogColorSpaceW,sizeof(LOGCOLORSPACEW));
  661. LogColorSpaceW.lcsSignature = lpLogColorSpace->lcsSignature;
  662. LogColorSpaceW.lcsVersion = lpLogColorSpace->lcsVersion;
  663. LogColorSpaceW.lcsCSType = lpLogColorSpace->lcsCSType;
  664. LogColorSpaceW.lcsIntent = lpLogColorSpace->lcsIntent;
  665. LogColorSpaceW.lcsEndpoints = lpLogColorSpace->lcsEndpoints;
  666. LogColorSpaceW.lcsGammaRed = lpLogColorSpace->lcsGammaRed;
  667. LogColorSpaceW.lcsGammaGreen = lpLogColorSpace->lcsGammaGreen;
  668. LogColorSpaceW.lcsGammaBlue = lpLogColorSpace->lcsGammaBlue;
  669. LogColorSpaceW.lcsSize = sizeof(LOGCOLORSPACEW);
  670. vToUnicodeN(
  671. LogColorSpaceW.lcsFilename,MAX_PATH,
  672. lpLogColorSpace->lcsFilename,strlen(lpLogColorSpace->lcsFilename)+1
  673. );
  674. hRet = CreateColorSpaceInternalW(&LogColorSpaceW,LCSEX_ANSICREATED);
  675. return(hRet);
  676. }
  677. /******************************Public*Routine******************************\
  678. * CreateColorSpaceW
  679. *
  680. * ColorSpace is a KERNEL mode object
  681. *
  682. * Arguments:
  683. *
  684. * lpLogColorSpace - apps log color space
  685. *
  686. * Return Value:
  687. *
  688. * Handle of color space or NULL
  689. *
  690. * History:
  691. *
  692. * 18-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  693. *
  694. \**************************************************************************/
  695. HCOLORSPACE WINAPI
  696. CreateColorSpaceW(
  697. LPLOGCOLORSPACEW lpLogColorSpace
  698. )
  699. {
  700. return (CreateColorSpaceInternalW(lpLogColorSpace,0));
  701. }
  702. HCOLORSPACE WINAPI
  703. CreateColorSpaceInternalW(
  704. LPLOGCOLORSPACEW lpLogColorSpace,
  705. DWORD dwCreateFlags
  706. )
  707. {
  708. HCOLORSPACE hRet = NULL;
  709. LOGCOLORSPACEEXW LogColorSpaceExOnStack;
  710. ICMAPI(("gdi32: CreateColorSpaceW\n"));
  711. if (lpLogColorSpace == NULL)
  712. {
  713. GdiSetLastError(ERROR_INVALID_PARAMETER);
  714. return(NULL);
  715. }
  716. //
  717. // validate color space
  718. //
  719. if ((lpLogColorSpace->lcsSignature != LCS_SIGNATURE) ||
  720. (lpLogColorSpace->lcsVersion != 0x400) ||
  721. (lpLogColorSpace->lcsSize != sizeof(LOGCOLORSPACEW)))
  722. {
  723. goto InvalidColorSpaceW;
  724. }
  725. //
  726. // validate lcsIntent
  727. //
  728. if ((lpLogColorSpace->lcsIntent != LCS_GM_BUSINESS) &&
  729. (lpLogColorSpace->lcsIntent != LCS_GM_GRAPHICS) &&
  730. (lpLogColorSpace->lcsIntent != LCS_GM_IMAGES) &&
  731. (lpLogColorSpace->lcsIntent != LCS_GM_ABS_COLORIMETRIC))
  732. {
  733. goto InvalidColorSpaceW;
  734. }
  735. //
  736. // We can not modify apps LOGCOLORSPACEW, so that make a copy on stack.
  737. //
  738. LogColorSpaceExOnStack.lcsColorSpace = *lpLogColorSpace;
  739. LogColorSpaceExOnStack.dwFlags = dwCreateFlags;
  740. //
  741. // validate lcsCSTYPE
  742. //
  743. if ((lpLogColorSpace->lcsCSType == LCS_CALIBRATED_RGB) ||
  744. (lpLogColorSpace->lcsCSType == PROFILE_LINKED))
  745. {
  746. //
  747. // Replace CSType in case PROFILE_LINKED.
  748. //
  749. LogColorSpaceExOnStack.lcsColorSpace.lcsCSType = LCS_CALIBRATED_RGB;
  750. if (lpLogColorSpace->lcsFilename[0] != L'\0')
  751. {
  752. HANDLE hFile;
  753. //
  754. // Normalize profile filename. but we will not over-write app's
  755. // path with our normalized path.
  756. //
  757. BuildIcmProfilePath(lpLogColorSpace->lcsFilename,
  758. LogColorSpaceExOnStack.lcsColorSpace.lcsFilename,
  759. MAX_PATH);
  760. //
  761. // profile name given, verify it exists
  762. //
  763. hFile = CreateFileW(
  764. LogColorSpaceExOnStack.lcsColorSpace.lcsFilename,
  765. GENERIC_READ,
  766. FILE_SHARE_READ,
  767. NULL,
  768. OPEN_EXISTING,
  769. FILE_ATTRIBUTE_NORMAL,
  770. NULL);
  771. if (hFile != INVALID_HANDLE_VALUE)
  772. {
  773. //
  774. // Yes, file is really exits.
  775. //
  776. CloseHandle(hFile);
  777. }
  778. else
  779. {
  780. ICMWRN(("CreateColorSpaceW: Couldn't open file specified by lcsFilename\n"));
  781. GdiSetLastError(ERROR_PROFILE_NOT_FOUND);
  782. return(NULL);
  783. }
  784. }
  785. }
  786. else // any other CSType
  787. {
  788. ULONG ulSize = MAX_PATH;
  789. //
  790. // Load external ICM dlls.
  791. //
  792. LOAD_ICMDLL(NULL);
  793. //
  794. // if CSType is not LCS_CALIBRATED_RGB, we should go to MSCMS.DLL to get color profile
  795. // for corresponding LCSType, then any given profile name from application is IGNORED.
  796. //
  797. if (!(*fpGetStandardColorSpaceProfileW)(
  798. NULL, lpLogColorSpace->lcsCSType,
  799. LogColorSpaceExOnStack.lcsColorSpace.lcsFilename, &ulSize))
  800. {
  801. ICMWRN(("CreateColorSpaceW:Error CSType = %x\n",lpLogColorSpace->lcsCSType));
  802. goto InvalidColorSpaceW;
  803. }
  804. }
  805. //
  806. // Call kernel to create this colorspace.
  807. //
  808. hRet = NtGdiCreateColorSpace(&LogColorSpaceExOnStack);
  809. return(hRet);
  810. InvalidColorSpaceW:
  811. ICMWRN(("CreateColorSpaceW: Incorrect ColorSpace parameter\n"));
  812. GdiSetLastError(ERROR_INVALID_COLORSPACE);
  813. return(NULL);
  814. }
  815. /******************************Public*Routine******************************\
  816. * DeleteColorSpace - delete user object
  817. *
  818. * Arguments:
  819. *
  820. * hColorSpace - color space handle
  821. *
  822. * Return Value:
  823. *
  824. * status
  825. *
  826. * History:
  827. *
  828. * 5-Jun-1996 -by- Mark Enstrom [marke]
  829. *
  830. \**************************************************************************/
  831. BOOL WINAPI
  832. DeleteColorSpace(
  833. HCOLORSPACE hColorSpace
  834. )
  835. {
  836. ICMAPI(("gdi32: DeleteColorSpace\n"));
  837. FIXUP_HANDLE(hColorSpace);
  838. //
  839. // validate handle, delete
  840. //
  841. return (NtGdiDeleteColorSpace(hColorSpace));
  842. }
  843. /******************************Public*Routine******************************\
  844. * SetColorSpace - set logical color space into DC, force new xform to be
  845. * created and all objects re-realized
  846. *
  847. * Arguments:
  848. *
  849. * hdc - dc handle
  850. * hColorSpace - logical color space handle
  851. *
  852. * Return Value:
  853. *
  854. * Status
  855. *
  856. * History:
  857. *
  858. * 5-Jun-1996 -by- Mark Enstrom [marke]
  859. *
  860. \**************************************************************************/
  861. HCOLORSPACE META WINAPI
  862. SetColorSpace(
  863. HDC hdc,
  864. HCOLORSPACE hColorSpace
  865. )
  866. {
  867. HANDLE hRet = NULL;
  868. ICMAPI(("gdi32: SetColorSpace\n"));
  869. FIXUP_HANDLE(hdc);
  870. FIXUP_HANDLE(hColorSpace);
  871. if (IS_ALTDC_TYPE(hdc))
  872. {
  873. PLDC pldc;
  874. if (IS_METADC16_TYPE(hdc))
  875. return(hRet);
  876. DC_PLDC(hdc,pldc,hRet);
  877. if (pldc->iType == LO_METADC)
  878. {
  879. if (!MF_SelectAnyObject(hdc,(HANDLE)hColorSpace,EMR_SETCOLORSPACE))
  880. return(hRet);
  881. }
  882. }
  883. //
  884. // Update source color space
  885. //
  886. hRet = IcmSetSourceColorSpace(hdc,hColorSpace,NULL,0);
  887. return(hRet);
  888. }
  889. /******************************Public*Routine******************************\
  890. * GetColorSpace - return color space from DC
  891. *
  892. * Arguments:
  893. *
  894. * hdc
  895. *
  896. * Return Value:
  897. *
  898. * hColorSpace or NULL
  899. *
  900. * History:
  901. *
  902. * 5-Jun-1996 -by- Mark Enstrom [marke]
  903. *
  904. \**************************************************************************/
  905. HCOLORSPACE WINAPI
  906. GetColorSpace(
  907. HDC hdc
  908. )
  909. {
  910. HANDLE hRet = NULL;
  911. PDC_ATTR pdcattr;
  912. ICMAPI(("gdi32: GetColorSpace\n"));
  913. FIXUP_HANDLE(hdc);
  914. //
  915. // validate and access hdc
  916. //
  917. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  918. if (pdcattr)
  919. {
  920. //
  921. // get hColorSpace
  922. //
  923. hRet = (HANDLE)pdcattr->hColorSpace;
  924. }
  925. else
  926. {
  927. GdiSetLastError(ERROR_INVALID_PARAMETER);
  928. }
  929. return(hRet);
  930. }
  931. /******************************Public*Routine******************************\
  932. * GetLogColorSpaceA - get colorspace and convert to ASCII
  933. *
  934. * typedef struct tagLOGCOLORSPACEW {
  935. * DWORD lcsSignature;
  936. * DWORD lcsVersion;
  937. * DWORD lcsSize;
  938. * LCSCSTYPE lcsCSType;
  939. * LCSGAMUTMATCH lcsIntent;
  940. * CIEXYZTRIPLE lcsEndpoints;
  941. * DWORD lcsGammaRed;
  942. * DWORD lcsGammaGreen;
  943. * DWORD lcsGammaBlue;
  944. * WCHAR lcsFilename[MAX_PATH];
  945. * } LOGCOLORSPACEW, *LPLOGCOLORSPACEW;
  946. *
  947. * Arguments:
  948. *
  949. * hColorSpace - handle to color space
  950. * lpBuffer - buffer to hold logcolorspace
  951. * nSize - buffer size
  952. *
  953. * Return Value:
  954. *
  955. * status
  956. *
  957. * History:
  958. *
  959. * 5-Jun-1996 -by- Mark Enstrom [marke]
  960. *
  961. \**************************************************************************/
  962. BOOL WINAPI
  963. GetLogColorSpaceA(
  964. HCOLORSPACE hColorSpace,
  965. LPLOGCOLORSPACEA lpBuffer,
  966. DWORD nSize
  967. )
  968. {
  969. BOOL bRet = FALSE;
  970. LOGCOLORSPACEW LogColorSpaceW;
  971. ICMAPI(("gdi32: GetLogColorSpaceA\n"));
  972. if ((lpBuffer != NULL) && (nSize >= sizeof(LOGCOLORSPACEA)))
  973. {
  974. //
  975. // get info using W version
  976. //
  977. bRet = GetLogColorSpaceW(hColorSpace,&LogColorSpaceW,sizeof(LOGCOLORSPACEW));
  978. if (bRet)
  979. {
  980. //
  981. // copy to user buffer
  982. //
  983. lpBuffer->lcsSignature = LogColorSpaceW.lcsSignature;
  984. lpBuffer->lcsVersion = LogColorSpaceW.lcsVersion;
  985. lpBuffer->lcsSize = sizeof(LOGCOLORSPACEA);
  986. lpBuffer->lcsCSType = LogColorSpaceW.lcsCSType;
  987. lpBuffer->lcsIntent = LogColorSpaceW.lcsIntent;
  988. lpBuffer->lcsEndpoints = LogColorSpaceW.lcsEndpoints;
  989. lpBuffer->lcsGammaRed = LogColorSpaceW.lcsGammaRed;
  990. lpBuffer->lcsGammaGreen = LogColorSpaceW.lcsGammaGreen;
  991. lpBuffer->lcsGammaBlue = LogColorSpaceW.lcsGammaBlue;
  992. //
  993. // convert W to A
  994. //
  995. bRet = bToASCII_N(lpBuffer->lcsFilename,
  996. MAX_PATH,
  997. LogColorSpaceW.lcsFilename,
  998. wcslen(LogColorSpaceW.lcsFilename)+1);
  999. }
  1000. else
  1001. {
  1002. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1003. }
  1004. }
  1005. else
  1006. {
  1007. GdiSetLastError(ERROR_INSUFFICIENT_BUFFER);
  1008. }
  1009. return(bRet);
  1010. }
  1011. /******************************Public*Routine******************************\
  1012. * GetLogColorSpaceW - return logical color space info.
  1013. *
  1014. * Arguments:
  1015. *
  1016. * hColorSpace - handle to color space
  1017. * lpBuffer - buffer to hold logcolorspace
  1018. * nSize - buffer size
  1019. *
  1020. * Return Value:
  1021. *
  1022. * status
  1023. *
  1024. * History:
  1025. *
  1026. * 5-Jun-1996 -by- Mark Enstrom [marke]
  1027. *
  1028. \**************************************************************************/
  1029. BOOL WINAPI
  1030. GetLogColorSpaceW(
  1031. HCOLORSPACE hColorSpace,
  1032. LPLOGCOLORSPACEW lpBuffer,
  1033. DWORD nSize
  1034. )
  1035. {
  1036. BOOL bRet = FALSE;
  1037. ICMAPI(("gdi32: GetLogColorSpaceW\n"));
  1038. if ((lpBuffer != NULL) && (nSize >= sizeof(LOGCOLORSPACEW)))
  1039. {
  1040. FIXUP_HANDLE(hColorSpace);
  1041. //
  1042. // Call kernel to get contents
  1043. //
  1044. if (NtGdiExtGetObjectW(hColorSpace,sizeof(LOGCOLORSPACEW),lpBuffer)
  1045. == sizeof(LOGCOLORSPACEW))
  1046. {
  1047. //
  1048. // Only for stock color space object.
  1049. //
  1050. if ((hColorSpace == GetStockObject(PRIV_STOCK_COLORSPACE)) &&
  1051. (lpBuffer->lcsCSType != LCS_CALIBRATED_RGB))
  1052. {
  1053. ULONG ulSize = MAX_PATH;
  1054. //
  1055. // Load ICM DLL.
  1056. //
  1057. LOAD_ICMDLL(FALSE);
  1058. //
  1059. // Get corresponding profile name from CSType.
  1060. //
  1061. if (!(*fpGetStandardColorSpaceProfileW)(
  1062. NULL,
  1063. lpBuffer->lcsCSType,
  1064. lpBuffer->lcsFilename,
  1065. &ulSize))
  1066. {
  1067. ICMMSG(("GetLogColorSpaceW():Fail to SCS(%x), leave it as is\n",
  1068. lpBuffer->lcsCSType));
  1069. }
  1070. }
  1071. bRet = TRUE;
  1072. }
  1073. else
  1074. {
  1075. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1076. }
  1077. }
  1078. else
  1079. {
  1080. GdiSetLastError(ERROR_INSUFFICIENT_BUFFER);
  1081. }
  1082. return(bRet);
  1083. }
  1084. /******************************Public*Routine******************************\
  1085. * CheckColorsInGamut
  1086. *
  1087. * Arguments:
  1088. *
  1089. * hdc - DC
  1090. * lpRGBQuad - Buffer of colors to check
  1091. * dlpBuffer - result buffer
  1092. * nCount - number of colors
  1093. *
  1094. * Return Value:
  1095. *
  1096. * status
  1097. *
  1098. * History:
  1099. *
  1100. * Rewrite it:
  1101. * 26-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  1102. * Write it:
  1103. * 5-Jun-1996 -by- Mark Enstrom [marke]
  1104. *
  1105. \**************************************************************************/
  1106. BOOL WINAPI
  1107. CheckColorsInGamut(
  1108. HDC hdc,
  1109. LPVOID lpRGBTriple,
  1110. LPVOID dlpBuffer,
  1111. DWORD nCount
  1112. )
  1113. {
  1114. BOOL bRet = FALSE;
  1115. PDC_ATTR pdcattr;
  1116. ICMAPI(("gdi32: CheckColorsInGamut\n"));
  1117. FIXUP_HANDLE(hdc);
  1118. //
  1119. // Check parameter
  1120. //
  1121. if ((lpRGBTriple == NULL) || (dlpBuffer == NULL) || (nCount == 0))
  1122. {
  1123. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1124. return (FALSE);
  1125. }
  1126. //
  1127. // validate and access hdc
  1128. //
  1129. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  1130. if (pdcattr)
  1131. {
  1132. if (IS_ICM_HOST(pdcattr->lIcmMode) ||
  1133. IS_ICM_DEVICE(pdcattr->lIcmMode))
  1134. {
  1135. ASSERTGDI(ghICM,"CheckColorsInGamut(): mscms.dll is not loaded\n");
  1136. if (GetColorTransformInDC(pdcattr))
  1137. {
  1138. //
  1139. // The input buffer may not be DWORD-aligned, And it buffer size
  1140. // might be exactly nCount * sizeof(RGBTRIPLE).
  1141. // So that, allocate DWORD-aligned buffer here.
  1142. //
  1143. PVOID pvBuf = LOCALALLOC(ALIGN_DWORD(nCount*sizeof(RGBTRIPLE)));
  1144. if (!pvBuf)
  1145. {
  1146. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1147. return (FALSE);
  1148. }
  1149. //
  1150. // Make a copy, here
  1151. //
  1152. RtlZeroMemory(pvBuf,ALIGN_DWORD(nCount*sizeof(RGBTRIPLE)));
  1153. RtlCopyMemory(pvBuf,lpRGBTriple,nCount*sizeof(RGBTRIPLE));
  1154. if (IS_ICM_HOST(pdcattr->lIcmMode))
  1155. {
  1156. //
  1157. // we handle RGBTRIPLE array as nCount x 1 pixel bitmap.
  1158. //
  1159. bRet = (*fpCheckBitmapBits)(
  1160. (HANDLE)GetColorTransformInDC(pdcattr),
  1161. pvBuf,
  1162. BM_RGBTRIPLETS,
  1163. nCount,1,
  1164. ALIGN_DWORD(nCount*sizeof(RGBTRIPLE)),
  1165. dlpBuffer,
  1166. NULL,0);
  1167. }
  1168. else // if (IS_ICM_DEVICE(pdcattr->lIcmMode))
  1169. {
  1170. //
  1171. // Call device driver via kernel.
  1172. //
  1173. bRet = NtGdiCheckBitmapBits(
  1174. hdc,
  1175. (HANDLE)GetColorTransformInDC(pdcattr),
  1176. (PVOID)lpRGBTriple,
  1177. (ULONG)BM_RGBTRIPLETS,
  1178. nCount,1,
  1179. ALIGN_DWORD(nCount*sizeof(RGBTRIPLE)),
  1180. dlpBuffer);
  1181. }
  1182. LOCALFREE(pvBuf);
  1183. }
  1184. else
  1185. {
  1186. //
  1187. // There is no valid color transform,
  1188. // so it is assume ident. color transform,
  1189. // then that every color in the gamut.
  1190. //
  1191. RtlZeroMemory(dlpBuffer,nCount);
  1192. bRet = TRUE;
  1193. }
  1194. }
  1195. else
  1196. {
  1197. WARNING("CheckColorsInGamut():ICM mode is invalid\n");
  1198. GdiSetLastError(ERROR_ICM_NOT_ENABLED);
  1199. }
  1200. }
  1201. else
  1202. {
  1203. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1204. }
  1205. return(bRet);
  1206. }
  1207. /******************************Public*Routine******************************\
  1208. * ColorMatchToTarget
  1209. *
  1210. * Arguments:
  1211. *
  1212. * hdc,
  1213. * hdcTarget
  1214. * uiAction
  1215. *
  1216. * Return Value:
  1217. *
  1218. * status
  1219. *
  1220. * History:
  1221. *
  1222. * Rewrite it:
  1223. * 26-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  1224. * Write it:
  1225. * 5-Jun-1996 -by- Mark Enstrom [marke]
  1226. *
  1227. \**************************************************************************/
  1228. BOOL META WINAPI
  1229. ColorMatchToTarget(
  1230. HDC hdc,
  1231. HDC hdcTarget,
  1232. DWORD uiAction
  1233. )
  1234. {
  1235. BOOL bRet = FALSE;
  1236. PDC_ATTR pdcattrTarget;
  1237. ICMAPI(("gdi32: ColorMatchToTarget\n"));
  1238. FIXUP_HANDLE(hdcTarget);
  1239. //
  1240. // Verify Target DC. No ICM with Windows MetaFile.
  1241. //
  1242. if (IS_METADC16_TYPE(hdcTarget))
  1243. {
  1244. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1245. return(bRet);
  1246. }
  1247. PSHARED_GET_VALIDATE(pdcattrTarget,hdcTarget,DC_TYPE);
  1248. if (pdcattrTarget != NULL)
  1249. {
  1250. PCACHED_COLORSPACE pTargetColorSpace = NULL;
  1251. PLDC pldcTarget = (PLDC)(pdcattrTarget->pvLDC);
  1252. if (!IS_ICM_INSIDEDC(pdcattrTarget->lIcmMode))
  1253. {
  1254. GdiSetLastError(ERROR_ICM_NOT_ENABLED);
  1255. return (FALSE);
  1256. }
  1257. //
  1258. // No Enhanced metafile DC as target DC.
  1259. //
  1260. if (pldcTarget && pldcTarget->iType == LO_METADC)
  1261. {
  1262. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1263. return(bRet);
  1264. }
  1265. //
  1266. // ICMINFO should be exist.
  1267. //
  1268. if (!BEXIST_ICMINFO(pdcattrTarget))
  1269. {
  1270. GdiSetLastError(ERROR_ICM_NOT_ENABLED);
  1271. return(bRet);
  1272. }
  1273. if (uiAction == CS_ENABLE)
  1274. {
  1275. //
  1276. // Hold critical section for color space to make sure pTargetColorSpace won't be deleted
  1277. //
  1278. ENTERCRITICALSECTION(&semColorSpaceCache);
  1279. //
  1280. // Target DC has LDC and ICMINFO, pick up colorspace data from there.
  1281. //
  1282. pTargetColorSpace = ((PGDI_ICMINFO)(pdcattrTarget->pvICM))->pDestColorSpace;
  1283. //
  1284. // Select it to target. the ref count of pTargetColorSpace will be incremented
  1285. // if we suceed to select.
  1286. //
  1287. bRet = ColorMatchToTargetInternal(hdc,pTargetColorSpace,uiAction);
  1288. LEAVECRITICALSECTION(&semColorSpaceCache);
  1289. }
  1290. else
  1291. {
  1292. bRet = ColorMatchToTargetInternal(hdc,NULL,uiAction);
  1293. }
  1294. }
  1295. else
  1296. {
  1297. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1298. }
  1299. return (bRet);
  1300. }
  1301. BOOL WINAPI
  1302. ColorMatchToTargetInternal(
  1303. HDC hdc,
  1304. PCACHED_COLORSPACE pTargetColorSpace,
  1305. DWORD uiAction
  1306. )
  1307. {
  1308. BOOL bRet = FALSE;
  1309. BOOL bEhnMetafile = FALSE;
  1310. PDC_ATTR pdcattr;
  1311. FIXUP_HANDLE(hdc);
  1312. //
  1313. // Verify destination DC. No ICM with Windows MetaFile.
  1314. //
  1315. if (IS_METADC16_TYPE(hdc))
  1316. {
  1317. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1318. return(FALSE);
  1319. }
  1320. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  1321. if (pdcattr != NULL)
  1322. {
  1323. PLDC pldc = (PLDC)(pdcattr->pvLDC);
  1324. //
  1325. // Check ICM is enabled on hdc properly.
  1326. //
  1327. if (pldc && (pldc->iType == LO_METADC))
  1328. {
  1329. //
  1330. // ICM should be turned on "fakely" on metafile hdc
  1331. //
  1332. if (!IS_ICM_METAFILING_ON(pdcattr->lIcmMode))
  1333. {
  1334. GdiSetLastError(ERROR_ICM_NOT_ENABLED);
  1335. return (FALSE);
  1336. }
  1337. //
  1338. // Mark we are recording into Enhanced metafile.
  1339. //
  1340. bEhnMetafile = TRUE;
  1341. }
  1342. else
  1343. {
  1344. if (!IS_ICM_INSIDEDC(pdcattr->lIcmMode))
  1345. {
  1346. GdiSetLastError(ERROR_ICM_NOT_ENABLED);
  1347. return (FALSE);
  1348. }
  1349. }
  1350. switch (uiAction)
  1351. {
  1352. case CS_ENABLE:
  1353. //
  1354. // Fail, if we are in proofing mode, already.
  1355. //
  1356. if (!IS_ICM_PROOFING(pdcattr->lIcmMode))
  1357. {
  1358. if (pTargetColorSpace)
  1359. {
  1360. if (bEhnMetafile)
  1361. {
  1362. //
  1363. // Set the data to metafile.
  1364. //
  1365. bRet = MF_ColorMatchToTarget(
  1366. hdc, uiAction,
  1367. (PVOID) pTargetColorSpace,
  1368. EMR_COLORMATCHTOTARGETW);
  1369. }
  1370. else
  1371. {
  1372. //
  1373. // Set Target color space.
  1374. //
  1375. // (this increments ref count of pTargetColorSpace)
  1376. //
  1377. bRet = IcmSetTargetColorSpace(hdc,pTargetColorSpace,uiAction);
  1378. }
  1379. }
  1380. }
  1381. else
  1382. {
  1383. WARNING("ColorMatchToTargetInternal(): DC is proofing mode already\n");
  1384. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1385. }
  1386. break;
  1387. case CS_DISABLE:
  1388. case CS_DELETE_TRANSFORM:
  1389. if (IS_ICM_PROOFING(pdcattr->lIcmMode))
  1390. {
  1391. if (bEhnMetafile)
  1392. {
  1393. //
  1394. // Set the data to metafile.
  1395. //
  1396. bRet = MF_ColorMatchToTarget(
  1397. hdc, uiAction, NULL,
  1398. EMR_COLORMATCHTOTARGETW);
  1399. }
  1400. else
  1401. {
  1402. //
  1403. // Reset Target color space
  1404. //
  1405. bRet = IcmSetTargetColorSpace(hdc,NULL,uiAction);
  1406. }
  1407. }
  1408. else
  1409. {
  1410. //
  1411. // we are not in proofing mode, never called with CS_ENABLE before.
  1412. //
  1413. WARNING("ColorMatchToTarget: DC is not proofing mode\n");
  1414. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1415. }
  1416. break;
  1417. default:
  1418. WARNING("ColorMatchToTarget: uiAction is invalid\n");
  1419. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1420. }
  1421. }
  1422. else
  1423. {
  1424. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1425. WARNING("ColorMatchToTarget: invalid DC\n");
  1426. }
  1427. return(bRet);
  1428. }
  1429. /******************************Public*Routine******************************\
  1430. * GetICMProfileA - get current profile from DC
  1431. *
  1432. * Arguments:
  1433. *
  1434. * hdc - DC
  1435. * szBuffer - size of buffer
  1436. * pBuffer - user buffer
  1437. *
  1438. * Return Value:
  1439. *
  1440. * status
  1441. *
  1442. * History:
  1443. *
  1444. * Rewrite it:
  1445. * 05-Feb-1996 -by- Hideyuki Nagase [hideyukn]
  1446. * Write it:
  1447. * 5-Jun-1996 -by- Mark Enstrom [marke]
  1448. *
  1449. \**************************************************************************/
  1450. BOOL WINAPI
  1451. GetICMProfileA(
  1452. HDC hdc,
  1453. LPDWORD pBufSize,
  1454. LPSTR pszFilename
  1455. )
  1456. {
  1457. BOOL bRet = FALSE;
  1458. WCHAR wchProfile[MAX_PATH];
  1459. DWORD BufSizeW = MAX_PATH;
  1460. ICMAPI(("gdi32: GetICMProfileA\n"));
  1461. if (pBufSize == NULL)
  1462. {
  1463. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1464. return(FALSE);
  1465. }
  1466. //
  1467. // Call W version.
  1468. //
  1469. if (GetICMProfileW(hdc,&BufSizeW,wchProfile))
  1470. {
  1471. CHAR chProfile[MAX_PATH];
  1472. DWORD BufSizeA = MAX_PATH;
  1473. if (BufSizeW)
  1474. {
  1475. //
  1476. // Unicode to Ansi convertion
  1477. //
  1478. BufSizeA = WideCharToMultiByte(CP_ACP,0,
  1479. wchProfile,BufSizeW,
  1480. chProfile,BufSizeA,
  1481. NULL,NULL);
  1482. if ((pszFilename == NULL) || (*pBufSize < BufSizeA))
  1483. {
  1484. //
  1485. // if the buffer is not given or not enough, return nessesary buffer size and error.
  1486. //
  1487. *pBufSize = BufSizeA;
  1488. GdiSetLastError(ERROR_INSUFFICIENT_BUFFER);
  1489. }
  1490. else
  1491. {
  1492. //
  1493. // copy converted string to buffer.
  1494. //
  1495. lstrcpyA(pszFilename,chProfile);
  1496. *pBufSize = BufSizeA;
  1497. bRet = TRUE;
  1498. }
  1499. }
  1500. }
  1501. return(bRet);
  1502. }
  1503. /******************************Public*Routine******************************\
  1504. * GetICMProfileW - read icm profile from DC
  1505. *
  1506. * Arguments:
  1507. *
  1508. * hdc - DC
  1509. * szBuffer - size of user buffer
  1510. * pszFilename - user W buffer
  1511. *
  1512. * Return Value:
  1513. *
  1514. * Boolean
  1515. *
  1516. * History:
  1517. *
  1518. * 5-Jun-1996 -by- Mark Enstrom [marke]
  1519. *
  1520. \**************************************************************************/
  1521. BOOL WINAPI
  1522. GetICMProfileW(
  1523. HDC hdc,
  1524. LPDWORD pBufSize,
  1525. LPWSTR pszFilename
  1526. )
  1527. {
  1528. PDC_ATTR pdcattr;
  1529. ICMAPI(("gdi32: GetICMProfileW\n"));
  1530. FIXUP_HANDLE(hdc);
  1531. if (pBufSize == NULL)
  1532. {
  1533. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1534. return(FALSE);
  1535. }
  1536. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  1537. if (pdcattr)
  1538. {
  1539. PGDI_ICMINFO pIcmInfo;
  1540. PWSZ pwszProfile = NULL;
  1541. ULONG ulSize = 0;
  1542. //
  1543. // Initialize ICMINFO
  1544. //
  1545. if ((pIcmInfo = INIT_ICMINFO(hdc,pdcattr)) == NULL)
  1546. {
  1547. WARNING("gdi32: GetICMProfileW: Can't init icm info\n");
  1548. return(FALSE);
  1549. }
  1550. if (IsColorDeviceContext(hdc))
  1551. {
  1552. //
  1553. // Load external ICM dll
  1554. //
  1555. LOAD_ICMDLL(FALSE);
  1556. //
  1557. // if there is no destination profile for the DC, then load
  1558. // the defualt
  1559. //
  1560. IcmUpdateLocalDCColorSpace(hdc,pdcattr);
  1561. if (pIcmInfo->pDestColorSpace)
  1562. {
  1563. //
  1564. // Get profile name in destination colorspace.
  1565. //
  1566. pwszProfile = pIcmInfo->pDestColorSpace->LogColorSpace.lcsFilename;
  1567. }
  1568. }
  1569. else
  1570. {
  1571. ICMMSG(("GetICMProfile(): for Mono-device\n"));
  1572. //
  1573. // There is no destination profile AS default,
  1574. // *BUT* if Apps set it by calling SetICMProfile(), return it.
  1575. //
  1576. if (pIcmInfo->flInfo & ICM_VALID_CURRENT_PROFILE)
  1577. {
  1578. pwszProfile = pIcmInfo->DefaultDstProfile;
  1579. }
  1580. }
  1581. if (pwszProfile)
  1582. {
  1583. ulSize = lstrlenW(pwszProfile) + 1; // + 1 for null-terminated
  1584. }
  1585. if (ulSize <= 1)
  1586. {
  1587. //
  1588. // No profile, Or only NULL character.
  1589. //
  1590. GdiSetLastError(ERROR_PROFILE_NOT_FOUND);
  1591. return(FALSE);
  1592. }
  1593. else if (*pBufSize >= ulSize)
  1594. {
  1595. //
  1596. // There is enough buffer, copy filename.
  1597. //
  1598. lstrcpyW(pszFilename,pwszProfile);
  1599. *pBufSize = ulSize;
  1600. return (TRUE);
  1601. }
  1602. else
  1603. {
  1604. //
  1605. // if buffer is not presented or it's too small,
  1606. // returns the nessesary buffer size.
  1607. //
  1608. GdiSetLastError(ERROR_INSUFFICIENT_BUFFER);
  1609. *pBufSize = ulSize;
  1610. return (FALSE);
  1611. }
  1612. }
  1613. //
  1614. // something error.
  1615. //
  1616. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1617. return(FALSE);
  1618. }
  1619. /******************************Public*Routine******************************\
  1620. * SetICMProfileA - convert the profile string to WCHAR and save in DC
  1621. *
  1622. * Arguments:
  1623. *
  1624. * hdc - DC
  1625. * pszFileName - Profile name
  1626. *
  1627. * Return Value:
  1628. *
  1629. * status
  1630. *
  1631. * History:
  1632. *
  1633. * Rewrite it:
  1634. * 23-Jan-1996 -by- Hideyuki Nagase [hideyukn]
  1635. * Write it:
  1636. * 5-Jun-1996 -by- Mark Enstrom [marke]
  1637. *
  1638. \**************************************************************************/
  1639. BOOL META WINAPI
  1640. SetICMProfileA(
  1641. HDC hdc,
  1642. LPSTR pszFileName
  1643. )
  1644. {
  1645. ICMAPI(("gdi32: SetICMProfileA\n"));
  1646. return (SetICMProfileInternalA(hdc,pszFileName,NULL,0));
  1647. }
  1648. BOOL
  1649. SetICMProfileInternalA(
  1650. HDC hdc,
  1651. LPSTR pszFileName,
  1652. PCACHED_COLORSPACE pColorSpace,
  1653. DWORD dwFlags
  1654. )
  1655. {
  1656. BOOL bRet = FALSE;
  1657. //
  1658. // Check parameter either pColorSpace or pszFilename should be given.
  1659. //
  1660. if (pColorSpace)
  1661. {
  1662. ICMAPI(("gdi32: SetICMProfileA by ColorSpace (%ws):dwFlags - %d\n",
  1663. pColorSpace->LogColorSpace.lcsFilename,dwFlags));
  1664. }
  1665. else if (pszFileName)
  1666. {
  1667. ICMAPI(("gdi32: SetICMProfileA by profile name (%s):dwFlags - %x\n",
  1668. pszFileName,dwFlags));
  1669. }
  1670. else
  1671. {
  1672. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1673. return (FALSE);
  1674. }
  1675. if (IS_ALTDC_TYPE(hdc))
  1676. {
  1677. PLDC pldc;
  1678. if (IS_METADC16_TYPE(hdc))
  1679. return(bRet);
  1680. DC_PLDC(hdc,pldc,bRet)
  1681. if (pldc->iType == LO_METADC)
  1682. {
  1683. if (!MF_SetICMProfile(hdc,
  1684. (LPBYTE)pszFileName,
  1685. (PVOID)pColorSpace,
  1686. EMR_SETICMPROFILEA))
  1687. {
  1688. return((int)FALSE);
  1689. }
  1690. }
  1691. }
  1692. if (pColorSpace)
  1693. {
  1694. //
  1695. // Select the given profile into DC.
  1696. //
  1697. // (this increments ref count of pColorSpace)
  1698. //
  1699. bRet = IcmSetDestinationColorSpace(hdc,NULL,pColorSpace,dwFlags);
  1700. }
  1701. else if (pszFileName)
  1702. {
  1703. ULONG ulSize = lstrlenA(pszFileName);
  1704. if (ulSize && (ulSize < MAX_PATH))
  1705. {
  1706. WCHAR pwszCapt[MAX_PATH];
  1707. //
  1708. // let me count null-terminate char.
  1709. //
  1710. ulSize += 1;
  1711. //
  1712. // Convert to Unicode.
  1713. //
  1714. vToUnicodeN(pwszCapt,MAX_PATH,pszFileName,ulSize);
  1715. //
  1716. // Select the given profile into DC.
  1717. //
  1718. bRet = IcmSetDestinationColorSpace(hdc,pwszCapt,NULL,dwFlags);
  1719. }
  1720. else
  1721. {
  1722. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1723. }
  1724. }
  1725. return(bRet);
  1726. }
  1727. /******************************Public*Routine******************************\
  1728. * SetICMProfileW - set profile name into DC
  1729. *
  1730. * Arguments:
  1731. *
  1732. * Return Value:
  1733. *
  1734. * History:
  1735. *
  1736. * 5-Jun-1996 -by- Mark Enstrom [marke]
  1737. *
  1738. \**************************************************************************/
  1739. BOOL META WINAPI
  1740. SetICMProfileW(
  1741. HDC hdc,
  1742. LPWSTR pwszFileName
  1743. )
  1744. {
  1745. ICMAPI(("gdi32: SetICMProfileW\n"));
  1746. return (SetICMProfileInternalW(hdc,pwszFileName,NULL,0));
  1747. }
  1748. BOOL
  1749. SetICMProfileInternalW(
  1750. HDC hdc,
  1751. LPWSTR pwszFileName,
  1752. PCACHED_COLORSPACE pColorSpace,
  1753. DWORD dwFlags
  1754. )
  1755. {
  1756. BOOL bRet = FALSE;
  1757. //
  1758. // Check parameter either pColorSpace or pszFilename should be given.
  1759. //
  1760. if (pColorSpace)
  1761. {
  1762. ICMAPI(("gdi32: SetICMProfileW by ColorSpace (%ws):dwFlags - %x\n",
  1763. pColorSpace->LogColorSpace.lcsFilename,dwFlags));
  1764. }
  1765. else if (pwszFileName)
  1766. {
  1767. ICMAPI(("gdi32: SetICMProfileW by profile name (%ws):dwFlags - %d\n",
  1768. pwszFileName,dwFlags));
  1769. }
  1770. else
  1771. {
  1772. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1773. return (FALSE);
  1774. }
  1775. FIXUP_HANDLE(hdc);
  1776. if (IS_ALTDC_TYPE(hdc))
  1777. {
  1778. PLDC pldc;
  1779. if (IS_METADC16_TYPE(hdc))
  1780. return(bRet);
  1781. DC_PLDC(hdc,pldc,bRet)
  1782. if (pldc->iType == LO_METADC)
  1783. {
  1784. if (!MF_SetICMProfile(hdc,
  1785. (LPBYTE)pwszFileName,
  1786. (PVOID)pColorSpace,
  1787. EMR_SETICMPROFILEW))
  1788. {
  1789. return((int)FALSE);
  1790. }
  1791. }
  1792. }
  1793. //
  1794. // Select the given profile into DC.
  1795. //
  1796. // (this increments ref count of pColorSpace)
  1797. //
  1798. bRet = IcmSetDestinationColorSpace(hdc,pwszFileName,pColorSpace,dwFlags);
  1799. return (bRet);
  1800. }
  1801. /******************************Public*Routine******************************\
  1802. * EnumICMProfilesA
  1803. *
  1804. * Arguments:
  1805. *
  1806. * hdc
  1807. * lpEnumGamutMatchProc
  1808. * lParam
  1809. *
  1810. * Return Value:
  1811. *
  1812. * History:
  1813. *
  1814. * Write it:
  1815. * 13-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  1816. *
  1817. \**************************************************************************/
  1818. int WINAPI
  1819. EnumICMProfilesA(
  1820. HDC hdc,
  1821. ICMENUMPROCA lpEnumGamutMatchProc,
  1822. LPARAM lParam
  1823. )
  1824. {
  1825. int iRet = -1;
  1826. BOOL bRet;
  1827. ICMAPI(("gdi32: EnumICMProfileA\n"));
  1828. FIXUP_HANDLE(hdc);
  1829. VALIDATE_HANDLE(bRet,hdc,DC_TYPE);
  1830. if (bRet && (lpEnumGamutMatchProc != NULL))
  1831. {
  1832. iRet = IcmEnumColorProfile(hdc,lpEnumGamutMatchProc,lParam,TRUE,NULL,NULL);
  1833. }
  1834. else
  1835. {
  1836. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1837. }
  1838. return(iRet);
  1839. }
  1840. /******************************Public*Routine******************************\
  1841. * EnumICMProfilesW
  1842. *
  1843. * Arguments:
  1844. *
  1845. * hdc
  1846. * lpEnumGamutMatchProc
  1847. * lParam
  1848. *
  1849. * Return Value:
  1850. *
  1851. * History:
  1852. *
  1853. * Write it:
  1854. * 13-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  1855. *
  1856. \**************************************************************************/
  1857. int WINAPI
  1858. EnumICMProfilesW(
  1859. HDC hdc,
  1860. ICMENUMPROCW lpEnumGamutMatchProc,
  1861. LPARAM lParam
  1862. )
  1863. {
  1864. int iRet = -1;
  1865. BOOL bRet;
  1866. ICMAPI(("gdi32: EnumICMProfileW\n"));
  1867. FIXUP_HANDLE(hdc);
  1868. VALIDATE_HANDLE(bRet,hdc,DC_TYPE);
  1869. if (bRet && (lpEnumGamutMatchProc != NULL))
  1870. {
  1871. iRet = IcmEnumColorProfile(hdc,lpEnumGamutMatchProc,lParam,FALSE,NULL,NULL);
  1872. }
  1873. else
  1874. {
  1875. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1876. }
  1877. return(iRet);
  1878. }
  1879. /******************************Public*Routine******************************\
  1880. * UpdateICMRegKeyW()
  1881. *
  1882. * History:
  1883. * 8-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  1884. \**************************************************************************/
  1885. BOOL WINAPI
  1886. UpdateICMRegKeyW(
  1887. DWORD Reserved,
  1888. PWSTR pwszICMMatcher,
  1889. PWSTR pwszFileName,
  1890. UINT Command
  1891. )
  1892. {
  1893. BOOL bRet = FALSE;
  1894. int iRet;
  1895. ICMAPI(("gdi32: UpdateICMRegKeyW\n"));
  1896. if (Reserved != 0)
  1897. {
  1898. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1899. return(FALSE);
  1900. }
  1901. //
  1902. // Load external ICM dlls
  1903. //
  1904. LOAD_ICMDLL(FALSE);
  1905. switch (Command)
  1906. {
  1907. case ICM_ADDPROFILE:
  1908. if (pwszFileName)
  1909. {
  1910. //
  1911. // Call InstallColorProfileA() in mscms.dll
  1912. //
  1913. bRet = (*fpInstallColorProfileW)(NULL, pwszFileName);
  1914. }
  1915. else
  1916. {
  1917. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1918. }
  1919. break;
  1920. case ICM_DELETEPROFILE:
  1921. if (pwszFileName)
  1922. {
  1923. //
  1924. // Call UninstallColorProfileW() in mscms.dll
  1925. //
  1926. bRet = (*fpUninstallColorProfileW)(NULL, pwszFileName, FALSE);
  1927. }
  1928. else
  1929. {
  1930. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1931. }
  1932. break;
  1933. case ICM_QUERYPROFILE:
  1934. if (pwszFileName)
  1935. {
  1936. PROFILECALLBACK_DATA QueryProfile;
  1937. QueryProfile.pwszFileName = GetFileNameFromPath(pwszFileName);
  1938. QueryProfile.bFound = FALSE;
  1939. if (QueryProfile.pwszFileName != NULL)
  1940. {
  1941. //
  1942. // Enumrate all registered profile to find this profile.
  1943. //
  1944. IcmEnumColorProfile(NULL,IcmQueryProfileCallBack,(LPARAM)(&QueryProfile),FALSE,NULL,NULL);
  1945. //
  1946. // Is that found ?
  1947. //
  1948. bRet = QueryProfile.bFound;
  1949. }
  1950. }
  1951. else
  1952. {
  1953. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1954. }
  1955. break;
  1956. case ICM_SETDEFAULTPROFILE:
  1957. //
  1958. // Not supported.
  1959. //
  1960. GdiSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1961. break;
  1962. case ICM_REGISTERICMATCHER:
  1963. if (pwszICMMatcher && pwszFileName)
  1964. {
  1965. DWORD dwCMM = *((DWORD *)pwszICMMatcher);
  1966. //
  1967. // Call RegisterCMMW() in mscms.dll
  1968. //
  1969. bRet = (*fpRegisterCMMW)(NULL, IcmSwapBytes(dwCMM), pwszFileName);
  1970. }
  1971. else
  1972. {
  1973. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1974. }
  1975. break;
  1976. case ICM_UNREGISTERICMATCHER:
  1977. if (pwszICMMatcher)
  1978. {
  1979. DWORD dwCMM = *((DWORD *)pwszICMMatcher);
  1980. //
  1981. // Call UnregisterCMMW() in mscms.dll
  1982. //
  1983. bRet = (*fpUnregisterCMMW)(NULL, IcmSwapBytes(dwCMM));
  1984. }
  1985. else
  1986. {
  1987. GdiSetLastError(ERROR_INVALID_PARAMETER);
  1988. }
  1989. break;
  1990. case ICM_QUERYMATCH:
  1991. if (pwszFileName)
  1992. {
  1993. //
  1994. // Find match profile.
  1995. //
  1996. iRet = IcmEnumColorProfile(NULL,NULL,0,FALSE,(PDEVMODEW)pwszFileName,NULL);
  1997. //
  1998. // Adjust return value, because IcmEnumColorProfile returns -1 if not found.
  1999. // and 0 for error (since no callback function)
  2000. //
  2001. if (iRet > 0)
  2002. {
  2003. bRet = TRUE;
  2004. }
  2005. }
  2006. else
  2007. {
  2008. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2009. }
  2010. break;
  2011. default:
  2012. WARNING("gdi32!UpdateICMRegKeyW():Invalid Command\n");
  2013. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2014. break;
  2015. }
  2016. return bRet;
  2017. }
  2018. /******************************Public*Routine******************************\
  2019. * UpdateICMRegKeyA
  2020. *
  2021. * Arguments:
  2022. *
  2023. * Reserved
  2024. * szICMMatcher
  2025. * szFileName
  2026. * Command
  2027. *
  2028. * Return Value:
  2029. *
  2030. * Status
  2031. *
  2032. * History:
  2033. *
  2034. * 8-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  2035. *
  2036. \**************************************************************************/
  2037. BOOL WINAPI
  2038. UpdateICMRegKeyA(
  2039. DWORD Reserved,
  2040. PSTR szICMMatcher,
  2041. PSTR szFileName,
  2042. UINT Command
  2043. )
  2044. {
  2045. BOOL bRet = FALSE;
  2046. BOOL bError = FALSE;
  2047. PWSTR pwszFileName = NULL;
  2048. //
  2049. // szICMMatcher points to 4 bytes CMM ID, actually it is not "string".
  2050. // Ansi to Unicode conversion is not needed.
  2051. //
  2052. PWSTR pwszICMMatcher = (PWSTR) szICMMatcher;
  2053. ULONG cjSize;
  2054. ICMAPI(("gdi32: UpdateICMRegKeyA\n"));
  2055. if (Reserved != 0)
  2056. {
  2057. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2058. return(FALSE);
  2059. }
  2060. switch (Command)
  2061. {
  2062. case ICM_ADDPROFILE:
  2063. case ICM_DELETEPROFILE:
  2064. case ICM_QUERYPROFILE:
  2065. case ICM_REGISTERICMATCHER:
  2066. //
  2067. // szFileName should be presented.
  2068. //
  2069. if (szFileName)
  2070. {
  2071. //
  2072. // szFileName points to ansi string, just convert to Unicode.
  2073. //
  2074. cjSize = lstrlenA(szFileName)+1;
  2075. pwszFileName = LOCALALLOC((cjSize)*sizeof(WCHAR));
  2076. if (pwszFileName == NULL)
  2077. {
  2078. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2079. return (bRet);
  2080. }
  2081. vToUnicodeN(pwszFileName,cjSize,szFileName,cjSize);
  2082. }
  2083. else
  2084. {
  2085. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2086. bError = TRUE;
  2087. }
  2088. break;
  2089. case ICM_QUERYMATCH:
  2090. //
  2091. // szFileName should be presented.
  2092. //
  2093. if (szFileName)
  2094. {
  2095. //
  2096. // szFileName points to DEVMODEA structure, convert it to DEVMODEW
  2097. //
  2098. pwszFileName = (PWSTR) GdiConvertToDevmodeW((DEVMODEA *)szFileName);
  2099. }
  2100. else
  2101. {
  2102. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2103. bError = TRUE;
  2104. }
  2105. break;
  2106. case ICM_SETDEFAULTPROFILE:
  2107. GdiSetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2108. bError = TRUE;
  2109. break;
  2110. case ICM_UNREGISTERICMATCHER:
  2111. //
  2112. // Nothing to convert to Unicode.
  2113. //
  2114. ASSERTGDI(szFileName==NULL,"UpdateICMRegKeyA():szFileName is not null\n");
  2115. break;
  2116. default:
  2117. WARNING("GDI:UpdateICMRegKeyA():Command is invalid\n");
  2118. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2119. bError = TRUE;
  2120. break;
  2121. }
  2122. if (!bError)
  2123. {
  2124. //
  2125. // Call W version.
  2126. //
  2127. bRet = UpdateICMRegKeyW(Reserved,pwszICMMatcher,pwszFileName,Command);
  2128. }
  2129. if (pwszFileName)
  2130. {
  2131. LOCALFREE(pwszFileName);
  2132. }
  2133. return(bRet);
  2134. }
  2135. /******************************Public*Routine******************************\
  2136. * GetDeviceGammaRamp
  2137. *
  2138. * Arguments:
  2139. *
  2140. * hdc
  2141. * lpGammaRamp
  2142. *
  2143. * Return Value:
  2144. *
  2145. * Status
  2146. *
  2147. * History:
  2148. *
  2149. * 5-Jun-1996 -by- Mark Enstrom [marke]
  2150. *
  2151. \**************************************************************************/
  2152. BOOL WINAPI
  2153. GetDeviceGammaRamp(
  2154. HDC hdc,
  2155. LPVOID lpGammaRamp
  2156. )
  2157. {
  2158. BOOL bRet = FALSE;
  2159. ICMAPI(("gdi32: GetDeviceGammaRamp\n"));
  2160. if (lpGammaRamp == NULL)
  2161. {
  2162. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2163. }
  2164. else
  2165. {
  2166. //
  2167. // Call kernel to get current Gamma ramp array for this DC.
  2168. //
  2169. bRet = NtGdiGetDeviceGammaRamp(hdc,lpGammaRamp);
  2170. }
  2171. return(bRet);
  2172. }
  2173. /******************************Public*Routine******************************\
  2174. * SetDeviceGammaRamp
  2175. *
  2176. * Arguments:
  2177. *
  2178. * hdc
  2179. * lpGammaRamp
  2180. *
  2181. * Return Value:
  2182. *
  2183. * Status
  2184. *
  2185. * History:
  2186. *
  2187. * 5-Jun-1996 -by- Mark Enstrom [marke]
  2188. *
  2189. \**************************************************************************/
  2190. BOOL WINAPI
  2191. SetDeviceGammaRamp(
  2192. HDC hdc,
  2193. LPVOID lpGammaRamp
  2194. )
  2195. {
  2196. BOOL bRet = FALSE;
  2197. ICMAPI(("gdi32: SetDeviceGammaRamp\n"));
  2198. if (lpGammaRamp == NULL)
  2199. {
  2200. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2201. }
  2202. else
  2203. {
  2204. //
  2205. // Call kernel to set new Gamma ramp array for this DC.
  2206. //
  2207. bRet = NtGdiSetDeviceGammaRamp(hdc,lpGammaRamp);
  2208. }
  2209. return(bRet);
  2210. }
  2211. /******************************Public*Routine******************************\
  2212. * ColorCorrectPalette
  2213. *
  2214. * If this is not the default palette and ICM is turned on in the DC
  2215. * then translate the specified palette entries according to the color
  2216. * transform in the DC
  2217. *
  2218. * Arguments:
  2219. *
  2220. * hdc - DC handle
  2221. * hpal - PALETTE handle
  2222. * FirsrEntry - first entry in palette to translate
  2223. * NumberOfEntries - number of entries to translate
  2224. *
  2225. * Return Value:
  2226. *
  2227. * Status
  2228. *
  2229. * History:
  2230. *
  2231. * Write it:
  2232. * 13-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  2233. *
  2234. \**************************************************************************/
  2235. BOOL META WINAPI
  2236. ColorCorrectPalette(
  2237. HDC hdc,
  2238. HPALETTE hpal,
  2239. ULONG FirstEntry,
  2240. ULONG NumberOfEntries
  2241. )
  2242. {
  2243. BOOL bStatus = FALSE;
  2244. PDC_ATTR pdcattr = NULL;
  2245. ICMAPI(("gdi32: ColorCorrectPalette\n"));
  2246. //
  2247. // Parameter check (max entry of log palette is 0x65536)
  2248. //
  2249. if ((hdc == NULL) || (hpal == NULL) ||
  2250. (NumberOfEntries == 0) || (NumberOfEntries > 65536) ||
  2251. (FirstEntry >= 65536) || (65536 - NumberOfEntries < FirstEntry))
  2252. {
  2253. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2254. return (FALSE);
  2255. }
  2256. //
  2257. // default palette could not be changed...
  2258. //
  2259. if (hpal != (HPALETTE)GetStockObject(DEFAULT_PALETTE))
  2260. {
  2261. //
  2262. // metafile call
  2263. //
  2264. if (IS_ALTDC_TYPE(hdc))
  2265. {
  2266. PLDC pldc;
  2267. if (IS_METADC16_TYPE(hdc))
  2268. return(bStatus);
  2269. DC_PLDC(hdc,pldc,bStatus);
  2270. if (pldc->iType == LO_METADC)
  2271. {
  2272. if (!MF_ColorCorrectPalette(hdc,hpal,FirstEntry,NumberOfEntries))
  2273. {
  2274. return(FALSE);
  2275. }
  2276. }
  2277. }
  2278. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  2279. if (pdcattr)
  2280. {
  2281. //
  2282. // Load external ICM dlls
  2283. //
  2284. LOAD_ICMDLL(FALSE);
  2285. if (IS_ICM_HOST(pdcattr->lIcmMode))
  2286. {
  2287. if (bNeedTranslateColor(pdcattr))
  2288. {
  2289. PPALETTEENTRY ppalEntrySrc = NULL;
  2290. PPALETTEENTRY ppalEntryDst = NULL;
  2291. ULONG NumEntriesRetrieved = 0;
  2292. //
  2293. // Make sure palette can be color corrected, get requested entries
  2294. //
  2295. ULONG Index;
  2296. ppalEntrySrc = LOCALALLOC((NumberOfEntries * sizeof(PALETTEENTRY)) * 2);
  2297. if (ppalEntrySrc == NULL)
  2298. {
  2299. WARNING("ColorCorrectPalette: ppalEntry = NULL\n");
  2300. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2301. return(bStatus);
  2302. }
  2303. NumEntriesRetrieved = NtGdiColorCorrectPalette(hdc,
  2304. hpal,
  2305. FirstEntry,
  2306. NumberOfEntries,
  2307. ppalEntrySrc,
  2308. ColorPaletteQuery);
  2309. if (NumEntriesRetrieved > 0)
  2310. {
  2311. ppalEntryDst = ppalEntrySrc + NumberOfEntries;
  2312. //
  2313. // Translate palette entry colors
  2314. //
  2315. IcmTranslatePaletteEntry(hdc,pdcattr,ppalEntrySrc,ppalEntryDst,NumEntriesRetrieved);
  2316. //
  2317. // set new palette entries
  2318. //
  2319. NumEntriesRetrieved = NtGdiColorCorrectPalette(hdc,
  2320. hpal,
  2321. FirstEntry,
  2322. NumEntriesRetrieved,
  2323. ppalEntryDst,
  2324. ColorPaletteSet);
  2325. if (NumEntriesRetrieved > 0)
  2326. {
  2327. bStatus = TRUE;
  2328. }
  2329. }
  2330. else
  2331. {
  2332. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2333. }
  2334. LOCALFREE(ppalEntrySrc);
  2335. }
  2336. else
  2337. {
  2338. //
  2339. // Don't need to translate color.
  2340. //
  2341. bStatus = TRUE;
  2342. }
  2343. }
  2344. else if (IS_ICM_DEVICE(pdcattr->lIcmMode))
  2345. {
  2346. //
  2347. // for device ICM, don't need to do anything.
  2348. //
  2349. bStatus = TRUE;
  2350. }
  2351. else
  2352. {
  2353. WARNING("ColorCorrectPalette():ICM mode is not enabled\n");
  2354. GdiSetLastError(ERROR_ICM_NOT_ENABLED);
  2355. }
  2356. }
  2357. else
  2358. {
  2359. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2360. }
  2361. }
  2362. else
  2363. {
  2364. GdiSetLastError(ERROR_INVALID_PARAMETER);
  2365. }
  2366. return bStatus;
  2367. }
  2368. /******************************Public*Routine******************************\
  2369. * IcmTranslateColorObjects - called when there is a change in ICM color transfrom
  2370. * state
  2371. *
  2372. * Arguments:
  2373. *
  2374. * hdc - input DC
  2375. * pdcattr - DC's attrs
  2376. *
  2377. * Return Value:
  2378. *
  2379. * status
  2380. *
  2381. * History:
  2382. *
  2383. * Rewrite it:
  2384. * 13-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  2385. * Write it:
  2386. * 9-Jul-1996 -by- Mark Enstrom [marke]
  2387. *
  2388. \**************************************************************************/
  2389. BOOL
  2390. IcmTranslateColorObjects(
  2391. HDC hdc,
  2392. PDC_ATTR pdcattr,
  2393. BOOL bICMEnable
  2394. )
  2395. {
  2396. BOOL bStatus = TRUE;
  2397. COLORREF OldColor;
  2398. COLORREF NewColor;
  2399. ICMAPI(("gdi32: IcmTranslateColorObjects\n"));
  2400. //
  2401. // Invalidate IcmPenColor/IcmBrushColor
  2402. //
  2403. pdcattr->ulDirty_ &= ~(ICM_PEN_TRANSLATED | ICM_BRUSH_TRANSLATED);
  2404. if (bICMEnable)
  2405. {
  2406. if(bNeedTranslateColor(pdcattr))
  2407. {
  2408. if (GetColorTransformInDC(pdcattr) == NULL)
  2409. {
  2410. WARNING("Error in IcmTranslateColorObjects: called when hcmXform == NULL");
  2411. return FALSE;
  2412. }
  2413. //
  2414. // translate Foreground to new icm mode if not paletteindex
  2415. //
  2416. if (!(pdcattr->ulForegroundClr & 0x01000000))
  2417. {
  2418. OldColor = pdcattr->ulForegroundClr;
  2419. bStatus = IcmTranslateCOLORREF(hdc,
  2420. pdcattr,
  2421. OldColor,
  2422. &NewColor,
  2423. ICM_FORWARD);
  2424. if (bStatus)
  2425. {
  2426. pdcattr->crForegroundClr = NewColor;
  2427. }
  2428. else
  2429. {
  2430. pdcattr->crForegroundClr = OldColor;
  2431. }
  2432. }
  2433. //
  2434. // translate Background to new icm mode if not paletteindex
  2435. //
  2436. if (!(pdcattr->ulBackgroundClr & 0x01000000))
  2437. {
  2438. OldColor = pdcattr->ulBackgroundClr;
  2439. bStatus = IcmTranslateCOLORREF(hdc,
  2440. pdcattr,
  2441. OldColor,
  2442. &NewColor,
  2443. ICM_FORWARD);
  2444. if (bStatus)
  2445. {
  2446. pdcattr->crBackgroundClr = NewColor;
  2447. }
  2448. else
  2449. {
  2450. pdcattr->crBackgroundClr = OldColor;
  2451. }
  2452. }
  2453. //
  2454. // translate DCBrush to new icm mode if not paletteindex
  2455. //
  2456. if (!(pdcattr->ulDCBrushClr & 0x01000000))
  2457. {
  2458. OldColor = pdcattr->ulDCBrushClr;
  2459. bStatus = IcmTranslateCOLORREF(hdc,
  2460. pdcattr,
  2461. OldColor,
  2462. &NewColor,
  2463. ICM_FORWARD);
  2464. if (bStatus)
  2465. {
  2466. pdcattr->crDCBrushClr = NewColor;
  2467. }
  2468. else
  2469. {
  2470. pdcattr->crDCBrushClr = OldColor;
  2471. }
  2472. }
  2473. //
  2474. // translate DCPen to new icm mode if not paletteindex
  2475. //
  2476. if (!(pdcattr->ulDCPenClr & 0x01000000))
  2477. {
  2478. OldColor = pdcattr->ulDCPenClr;
  2479. bStatus = IcmTranslateCOLORREF(hdc,
  2480. pdcattr,
  2481. OldColor,
  2482. &NewColor,
  2483. ICM_FORWARD);
  2484. if (bStatus)
  2485. {
  2486. pdcattr->crDCPenClr = NewColor;
  2487. }
  2488. else
  2489. {
  2490. pdcattr->crDCPenClr = OldColor;
  2491. }
  2492. }
  2493. //
  2494. // set icm color of selected logical brush
  2495. //
  2496. IcmTranslateBrushColor(hdc,pdcattr,(HANDLE)pdcattr->hbrush);
  2497. //
  2498. // set icm color of selected logical pen/extpen
  2499. //
  2500. if (LO_TYPE(pdcattr->hpen) == LO_EXTPEN_TYPE)
  2501. {
  2502. IcmTranslateExtPenColor(hdc,pdcattr,(HANDLE)pdcattr->hpen);
  2503. }
  2504. else
  2505. {
  2506. IcmTranslatePenColor(hdc,pdcattr,(HANDLE)pdcattr->hpen);
  2507. }
  2508. }
  2509. }
  2510. else
  2511. {
  2512. PBRUSHATTR pbrushattr;
  2513. //
  2514. // ICM is off, restore colors (non device icm only)
  2515. //
  2516. pdcattr->crForegroundClr = pdcattr->ulForegroundClr & 0x13ffffff;
  2517. pdcattr->crBackgroundClr = pdcattr->ulBackgroundClr & 0x13ffffff;
  2518. pdcattr->crDCBrushClr = pdcattr->ulDCBrushClr & 0x13ffffff;
  2519. pdcattr->crDCPenClr = pdcattr->ulDCPenClr & 0x13ffffff;
  2520. //
  2521. // set icm color of selected logical brush
  2522. //
  2523. PSHARED_GET_VALIDATE(pbrushattr,pdcattr->hbrush,BRUSH_TYPE);
  2524. if (pbrushattr)
  2525. {
  2526. pdcattr->IcmBrushColor = pbrushattr->lbColor;
  2527. }
  2528. //
  2529. // set icm color of selected logical pen
  2530. //
  2531. PSHARED_GET_VALIDATE(pbrushattr,pdcattr->hpen,BRUSH_TYPE);
  2532. if (pbrushattr)
  2533. {
  2534. pdcattr->IcmPenColor = pbrushattr->lbColor;
  2535. }
  2536. }
  2537. //
  2538. // set DC dirty flags to force re-realization of color objects
  2539. //
  2540. pdcattr->ulDirty_ |= (DIRTY_BRUSHES|DC_BRUSH_DIRTY|DC_PEN_DIRTY);
  2541. return(bStatus);
  2542. }
  2543. /******************************Public*Routine******************************\
  2544. * IcmCreateTemporaryColorProfile()
  2545. *
  2546. * History:
  2547. *
  2548. * Wrote it:
  2549. * 7.May.1997 -by- Hideyuki Nagase [hideyukn]
  2550. \**************************************************************************/
  2551. BOOL
  2552. IcmCreateTemporaryColorProfile(
  2553. LPWSTR TemporaryColorProfile,
  2554. LPBYTE ProfileData,
  2555. DWORD ProfileDataSize
  2556. )
  2557. {
  2558. BOOL bRet = FALSE;
  2559. WCHAR TempPath[MAX_PATH];
  2560. WCHAR TempFile[MAX_PATH];
  2561. //
  2562. // make temp file for profile, include name in lcspw
  2563. //
  2564. if (GetTempPathW(MAX_PATH,(LPWSTR)TempPath))
  2565. {
  2566. BOOL bPathOK = TRUE;
  2567. if (TemporaryColorProfile[0] != UNICODE_NULL)
  2568. {
  2569. wcscpy(TempFile,TempPath);
  2570. wcscat(TempFile,TemporaryColorProfile);
  2571. }
  2572. else
  2573. {
  2574. bPathOK = GetTempFileNameW((LPWSTR)TempPath,L"ICM",0,(LPWSTR)TempFile);
  2575. }
  2576. if (bPathOK)
  2577. {
  2578. if (ProfileDataSize == 0)
  2579. {
  2580. //
  2581. // Nothing needs to save, just return with created filename
  2582. //
  2583. lstrcpyW(TemporaryColorProfile,TempFile);
  2584. bRet = TRUE;
  2585. }
  2586. else
  2587. {
  2588. HANDLE hFile = CreateFileW((LPWSTR)TempFile,
  2589. GENERIC_READ | GENERIC_WRITE,
  2590. 0,
  2591. NULL,
  2592. CREATE_ALWAYS,
  2593. FILE_ATTRIBUTE_NORMAL,
  2594. NULL);
  2595. if (hFile != INVALID_HANDLE_VALUE)
  2596. {
  2597. ULONG ulWritten;
  2598. if (WriteFile(hFile,ProfileData,ProfileDataSize,&ulWritten,NULL))
  2599. {
  2600. //
  2601. // Put the created file name into LOGCOLORSPACE
  2602. //
  2603. lstrcpyW(TemporaryColorProfile,TempFile);
  2604. //
  2605. // Close file handle
  2606. //
  2607. CloseHandle(hFile);
  2608. //
  2609. // Everything O.K.
  2610. //
  2611. bRet = TRUE;
  2612. }
  2613. else
  2614. {
  2615. ICMWRN(("IcmCreateTemporaryColorProfile(): Failed WriteFile\n"));
  2616. //
  2617. // Failed, close handle and delete it.
  2618. //
  2619. CloseHandle(hFile);
  2620. DeleteFileW(TempFile);
  2621. }
  2622. }
  2623. else
  2624. {
  2625. ICMWRN(("IcmCreateTemporaryColorProfile(): Failed CreateFile\n"));
  2626. }
  2627. }
  2628. }
  2629. else
  2630. {
  2631. ICMWRN(("IcmCreateTemporaryColorProfile(): Failed CreateTempFileName\n"));
  2632. }
  2633. }
  2634. else
  2635. {
  2636. ICMWRN(("IcmCreateTemporayColorProfile(): Failed GetTempPath\n"));
  2637. }
  2638. return (bRet);
  2639. }
  2640. /******************************Public*Routine******************************\
  2641. * IcmGetBitmapColorSpace()
  2642. *
  2643. * History:
  2644. *
  2645. * Wrote it:
  2646. * 13.March.1997 -by- Hideyuki Nagase [hideyukn]
  2647. \**************************************************************************/
  2648. BOOL
  2649. IcmGetBitmapColorSpace(
  2650. LPBITMAPINFO pbmi,
  2651. LPLOGCOLORSPACEW plcspw,
  2652. PPROFILE pColorProfile,
  2653. PDWORD pdwFlags
  2654. )
  2655. {
  2656. BOOL bBitmapColorSpace = FALSE;
  2657. ICMAPI(("gdi32: IcmGetBitmapColorSpace\n"));
  2658. //
  2659. // Init output buffers with zero.
  2660. //
  2661. *pdwFlags = 0;
  2662. ZeroMemory(plcspw,sizeof(LOGCOLORSPACE));
  2663. ZeroMemory(pColorProfile,sizeof(PROFILE));
  2664. //
  2665. // check for BITMAPV4 OR BITMAPV5
  2666. //
  2667. if (pbmi->bmiHeader.biSize == sizeof(BITMAPV4HEADER))
  2668. {
  2669. PBITMAPV4HEADER pbmih4 = (PBITMAPV4HEADER)&pbmi->bmiHeader;
  2670. ICMMSG(("IcmGetBitmapColorSpace: BITMAPV4HEADER\n"));
  2671. //
  2672. // if CIEXYZ endpoints are given, create a new color transform
  2673. // to use.
  2674. //
  2675. plcspw->lcsSignature = LCS_SIGNATURE;
  2676. plcspw->lcsVersion = 0x400;
  2677. plcspw->lcsSize = sizeof(LOGCOLORSPACEW);
  2678. plcspw->lcsCSType = pbmih4->bV4CSType;
  2679. plcspw->lcsIntent = LCS_GM_IMAGES;
  2680. plcspw->lcsEndpoints = pbmih4->bV4Endpoints;
  2681. plcspw->lcsGammaRed = pbmih4->bV4GammaRed;
  2682. plcspw->lcsGammaGreen = pbmih4->bV4GammaGreen;
  2683. plcspw->lcsGammaBlue = pbmih4->bV4GammaBlue;
  2684. if (pbmih4->bV4CSType == LCS_CALIBRATED_RGB)
  2685. {
  2686. ICMMSG(("IcmGetBitmapColorSpace: BITMAPv4 CALIBRATED RGB\n"));
  2687. ICMMSG((" lcspw.lcsCSType = %x\n",pbmih4->bV4CSType));
  2688. ICMMSG((" lcspw.lcsIntent = %d\n",LCS_GM_IMAGES));
  2689. ICMMSG((" lcspw.lcsGammaRed = %d\n",pbmih4->bV4GammaRed));
  2690. ICMMSG((" lcspw.lcsGammaGreen = %d\n",pbmih4->bV4GammaGreen));
  2691. //
  2692. // There is no profile specified.
  2693. //
  2694. plcspw->lcsFilename[0] = UNICODE_NULL;
  2695. bBitmapColorSpace = TRUE;
  2696. }
  2697. else // any other CSType
  2698. {
  2699. DWORD dwSize = MAX_PATH;
  2700. ICMMSG(("IcmGetBitmapColorSpace: BITMAPv4 lcsType = %x\n",pbmih4->bV4CSType));
  2701. //
  2702. // Load external ICM dlls.
  2703. //
  2704. LOAD_ICMDLL((int)FALSE);
  2705. //
  2706. // Get corresponding colorspace profile.
  2707. //
  2708. bBitmapColorSpace =
  2709. (*fpGetStandardColorSpaceProfileW)(NULL,
  2710. pbmih4->bV4CSType,
  2711. plcspw->lcsFilename,
  2712. &dwSize);
  2713. }
  2714. }
  2715. else if (pbmi->bmiHeader.biSize == sizeof(BITMAPV5HEADER))
  2716. {
  2717. PBITMAPV5HEADER pbmih5 = (PBITMAPV5HEADER)&pbmi->bmiHeader;
  2718. ICMMSG(("IcmGetBitmapColorSpace: BITMAPV5HEADER\n"));
  2719. ICMMSG((" lcspw.lcsCSType = %x\n",pbmih5->bV5CSType));
  2720. ICMMSG((" lcspw.lcsIntent = %d\n",pbmih5->bV5Intent));
  2721. //
  2722. // fill in common logcolorspace info
  2723. //
  2724. plcspw->lcsSignature = LCS_SIGNATURE;
  2725. plcspw->lcsVersion = 0x400;
  2726. plcspw->lcsSize = sizeof(LOGCOLORSPACEW);
  2727. plcspw->lcsCSType = pbmih5->bV5CSType;
  2728. plcspw->lcsIntent = pbmih5->bV5Intent;
  2729. plcspw->lcsEndpoints = pbmih5->bV5Endpoints;
  2730. plcspw->lcsGammaRed = pbmih5->bV5GammaRed;
  2731. plcspw->lcsGammaGreen = pbmih5->bV5GammaGreen;
  2732. plcspw->lcsGammaBlue = pbmih5->bV5GammaBlue;
  2733. //
  2734. // validate Intent
  2735. //
  2736. if ((plcspw->lcsIntent != LCS_GM_BUSINESS) &&
  2737. (plcspw->lcsIntent != LCS_GM_GRAPHICS) &&
  2738. (plcspw->lcsIntent != LCS_GM_IMAGES) &&
  2739. (plcspw->lcsIntent != LCS_GM_ABS_COLORIMETRIC))
  2740. {
  2741. //
  2742. // Intent is invalid, just use LCS_GM_IMAGES
  2743. //
  2744. plcspw->lcsIntent = LCS_GM_IMAGES;
  2745. }
  2746. //
  2747. // If a profile is linked or embedded then use it.
  2748. // otherwise:
  2749. // If CIEXYZ endpoints are given, create a new color transform
  2750. // to use.
  2751. //
  2752. if (pbmih5->bV5CSType == PROFILE_EMBEDDED)
  2753. {
  2754. PVOID pProfileEmbedded = NULL;
  2755. ICMMSG(("IcmGetBitmapColorSpace: Embedded profile\n"));
  2756. //
  2757. // Update CSType to Calibrated_RGB from Profile_Embedded
  2758. //
  2759. plcspw->lcsCSType = LCS_CALIBRATED_RGB;
  2760. //
  2761. // Get pointer to embeded profile.
  2762. //
  2763. pProfileEmbedded = (PVOID)((PBYTE)pbmi + pbmih5->bV5ProfileData);
  2764. if (pProfileEmbedded)
  2765. {
  2766. //
  2767. // Fill up PROFILE structure for "on memory" profile.
  2768. //
  2769. pColorProfile->dwType = PROFILE_MEMBUFFER;
  2770. pColorProfile->pProfileData = pProfileEmbedded;
  2771. pColorProfile->cbDataSize = pbmih5->bV5ProfileSize;
  2772. //
  2773. // Mark as on memory profile.
  2774. //
  2775. *pdwFlags |= ON_MEMORY_PROFILE;
  2776. }
  2777. else
  2778. {
  2779. //
  2780. // This bitmap marked as "Embedded", but no profile there, just go with LOGCOLORSPACE.
  2781. //
  2782. ICMWRN(("IcmGetBitmapColorSpace(): Embedded profile, but no profile embedded\n"));
  2783. }
  2784. bBitmapColorSpace = TRUE;
  2785. }
  2786. else if (pbmih5->bV5CSType == PROFILE_LINKED)
  2787. {
  2788. WCHAR LinkedProfile[MAX_PATH];
  2789. ICMMSG(("IcmGetBitmapColorSpace(): linked profile\n"));
  2790. //
  2791. // Update CSType to Calibrated_RGB from Profile_Linked
  2792. //
  2793. plcspw->lcsCSType = LCS_CALIBRATED_RGB;
  2794. //
  2795. // Convert profile name to Unicode.
  2796. //
  2797. vToUnicodeN(
  2798. LinkedProfile, MAX_PATH,
  2799. (CONST CHAR *)((PBYTE)pbmih5 + pbmih5->bV5ProfileData),
  2800. strlen((CONST CHAR *)((PBYTE)pbmih5 + pbmih5->bV5ProfileData))+1
  2801. );
  2802. //
  2803. // Normalize profile path.
  2804. //
  2805. BuildIcmProfilePath(LinkedProfile,plcspw->lcsFilename,MAX_PATH);
  2806. ICMMSG(("lcspw.lcsFilename = %ws\n",plcspw->lcsFilename));
  2807. bBitmapColorSpace = TRUE;
  2808. }
  2809. else if (pbmih5->bV5CSType == LCS_CALIBRATED_RGB)
  2810. {
  2811. ICMMSG(("IcmGetBitmapColorSpace(): calibrated RGB\n"));
  2812. ICMMSG((" lcspw.lcsGammaRed = %d\n",pbmih5->bV5GammaRed));
  2813. ICMMSG((" lcspw.lcsGammaGreen = %d\n",pbmih5->bV5GammaGreen));
  2814. ICMMSG((" lcspw.lcsGammaBlue = %d\n",pbmih5->bV5GammaBlue));
  2815. //
  2816. // There is profile specified.
  2817. //
  2818. plcspw->lcsFilename[0] = UNICODE_NULL;
  2819. bBitmapColorSpace = TRUE;
  2820. }
  2821. else // any other CSType
  2822. {
  2823. DWORD dwSize = MAX_PATH;
  2824. ICMMSG(("IcmGetBitmapColorSpace: BITMAPv5 lcsType = %x\n",pbmih5->bV5CSType));
  2825. //
  2826. // Load external ICM dlls.
  2827. //
  2828. LOAD_ICMDLL((int)FALSE);
  2829. //
  2830. // Get corresponding colorspace profile.
  2831. //
  2832. bBitmapColorSpace =
  2833. (*fpGetStandardColorSpaceProfileW)(NULL,
  2834. pbmih5->bV5CSType,
  2835. plcspw->lcsFilename,
  2836. &dwSize);
  2837. }
  2838. }
  2839. else
  2840. {
  2841. ICMMSG(("IcmGetBitmapColorSpace(): no color space specified\n"));
  2842. }
  2843. return (bBitmapColorSpace);
  2844. }
  2845. /******************************Public*Routine******************************\
  2846. * IcmGetTranslateInfo()
  2847. *
  2848. * History:
  2849. *
  2850. * Wrote it:
  2851. * 13.March.1997 -by- Hideyuki Nagase [hideyukn]
  2852. \**************************************************************************/
  2853. BOOL
  2854. IcmGetTranslateInfo(
  2855. PDC_ATTR pdcattr,
  2856. LPBITMAPINFO pbmi,
  2857. PVOID pvBits,
  2858. ULONG cjBits,
  2859. DWORD dwNumScan,
  2860. PDIB_TRANSLATE_INFO pdti,
  2861. DWORD dwFlags
  2862. )
  2863. {
  2864. BMFORMAT ColorType;
  2865. PVOID pOutput;
  2866. ULONG nColors;
  2867. ULONG cjTranslateBits;
  2868. PBITMAPINFO pbmiNew = NULL;
  2869. BOOL bCMYKColor = IS_CMYK_COLOR(pdcattr->lIcmMode);
  2870. ICMAPI(("gdi32: IcmGetTranslateInfo\n"));
  2871. ICMAPI(("-----: CMYK Color = %s\n",(bCMYKColor ? "Yes" : "No")));
  2872. ICMAPI(("-----: Backward = %s\n",((dwFlags & ICM_BACKWARD) ? "Yes" : "No")));
  2873. UNREFERENCED_PARAMETER(dwFlags);
  2874. if (dwNumScan == (DWORD)-1)
  2875. {
  2876. dwNumScan = ABS(pbmi->bmiHeader.biHeight);
  2877. }
  2878. //
  2879. // determine whether this is a palettized DIB
  2880. //
  2881. if (pbmi->bmiHeader.biCompression == BI_RGB)
  2882. {
  2883. if (pbmi->bmiHeader.biBitCount > 8)
  2884. {
  2885. //
  2886. // we will translate bitmap, pvBits should be presented.
  2887. //
  2888. if (pvBits == NULL)
  2889. {
  2890. return (FALSE);
  2891. }
  2892. //
  2893. // must translate DIB, standard 16,24,32 format
  2894. //
  2895. if (pbmi->bmiHeader.biBitCount == 16)
  2896. {
  2897. ICMMSG(("IcmGetTranslateInfo():BI_RGB 16 bpp\n"));
  2898. ColorType = BM_x555RGB;
  2899. }
  2900. else if (pbmi->bmiHeader.biBitCount == 24)
  2901. {
  2902. ICMMSG(("IcmGetTranslateInfo():BI_RGB 24 bpp\n"));
  2903. ColorType = BM_RGBTRIPLETS;
  2904. }
  2905. else if (pbmi->bmiHeader.biBitCount == 32)
  2906. {
  2907. ICMMSG(("IcmGetTranslateInfo():BI_RGB 32 bpp\n"));
  2908. ColorType = BM_xRGBQUADS;
  2909. }
  2910. else
  2911. {
  2912. ICMMSG(("IcmGetTranslateInfo():BI_RGB Invalid bpp\n"));
  2913. return (FALSE);
  2914. }
  2915. //
  2916. // Fill up source bitmap information.
  2917. //
  2918. pdti->SourceWidth = pbmi->bmiHeader.biWidth;
  2919. pdti->SourceHeight = dwNumScan;
  2920. pdti->SourceBitCount = pbmi->bmiHeader.biBitCount;
  2921. pdti->SourceColorType = ColorType;
  2922. pdti->pvSourceBits = pvBits;
  2923. pdti->cjSourceBits = cjBits;
  2924. //
  2925. // CMYK Color ?
  2926. //
  2927. if (bCMYKColor)
  2928. {
  2929. pdti->TranslateType = (TRANSLATE_BITMAP|TRANSLATE_HEADER);
  2930. //
  2931. // CMYK bitmap color bitmap is 32 BPP (4 bytes per pixel).
  2932. //
  2933. cjTranslateBits = (pdti->SourceWidth * 4) * pdti->SourceHeight;
  2934. //
  2935. // We need new bitmap info header for CMYK.
  2936. //
  2937. pbmiNew = LOCALALLOC(pbmi->bmiHeader.biSize);
  2938. if (!pbmiNew)
  2939. {
  2940. WARNING("IcmGetTranslateInfo():LOCALALLOC() failed\n");
  2941. return (FALSE);
  2942. }
  2943. //
  2944. // Make a copy of source, first.
  2945. //
  2946. RtlCopyMemory(pbmiNew,pbmi,pbmi->bmiHeader.biSize);
  2947. //
  2948. // Update header for CMYK color.
  2949. //
  2950. pbmiNew->bmiHeader.biBitCount = 32;
  2951. pbmiNew->bmiHeader.biCompression = BI_CMYK;
  2952. pbmiNew->bmiHeader.biSizeImage = cjTranslateBits;
  2953. pbmiNew->bmiHeader.biClrUsed = 0;
  2954. pbmiNew->bmiHeader.biClrImportant = 0;
  2955. //
  2956. // We have new BITMAPINFO header
  2957. //
  2958. pdti->TranslateBitmapInfo = pbmiNew;
  2959. pdti->TranslateBitmapInfoSize = pbmi->bmiHeader.biSize;
  2960. //
  2961. // Translate bitmap color type is CMYK.
  2962. //
  2963. pdti->TranslateColorType = BM_KYMCQUADS;
  2964. }
  2965. else
  2966. {
  2967. pdti->TranslateType = TRANSLATE_BITMAP;
  2968. //
  2969. // Translate bitmap size is same as source.
  2970. //
  2971. cjTranslateBits = cjBits;
  2972. //
  2973. // Translate bitmap color type is same source.
  2974. //
  2975. pdti->TranslateColorType = ColorType;
  2976. pdti->TranslateBitmapInfo = NULL;
  2977. pdti->TranslateBitmapInfoSize = 0;
  2978. }
  2979. //
  2980. // Allocate translate buffer
  2981. //
  2982. pOutput = LOCALALLOC(cjTranslateBits);
  2983. if (!pOutput)
  2984. {
  2985. if (pbmiNew)
  2986. {
  2987. LOCALFREE(pbmiNew);
  2988. }
  2989. WARNING("IcmGetTranslateInfo():LOCALALLOC() failed\n");
  2990. return (FALSE);
  2991. }
  2992. //
  2993. // Setup translation buffer.
  2994. //
  2995. pdti->pvTranslateBits = pOutput;
  2996. pdti->cjTranslateBits = cjTranslateBits;
  2997. }
  2998. else if (
  2999. ((pbmi->bmiHeader.biBitCount == 8) ||
  3000. (pbmi->bmiHeader.biBitCount == 4) ||
  3001. (pbmi->bmiHeader.biBitCount == 1))
  3002. )
  3003. {
  3004. ULONG nMaxColors = (1 << pbmi->bmiHeader.biBitCount);
  3005. ICMMSG(("IcmGetTranslateInfo():BI_RGB 8/4/1 bpp\n"));
  3006. //
  3007. // validate number of colors
  3008. //
  3009. nColors = pbmi->bmiHeader.biClrUsed;
  3010. if ((nColors == 0) || (nColors > nMaxColors))
  3011. {
  3012. nColors = nMaxColors;
  3013. }
  3014. //
  3015. // Allocate new bitmap info header and color table.
  3016. //
  3017. pbmiNew = LOCALALLOC(pbmi->bmiHeader.biSize + (nColors * sizeof(RGBQUAD)));
  3018. if (!pbmiNew)
  3019. {
  3020. WARNING("IcmGetTranslateInfo():LOCALALLOC() failed\n");
  3021. return (FALSE);
  3022. }
  3023. //
  3024. // Copy source BITMAPINFO to new
  3025. //
  3026. RtlCopyMemory(pbmiNew,pbmi,pbmi->bmiHeader.biSize);
  3027. pdti->TranslateType = TRANSLATE_HEADER;
  3028. pdti->SourceColorType = BM_xRGBQUADS;
  3029. pdti->SourceWidth = nColors;
  3030. pdti->SourceHeight = 1;
  3031. pdti->SourceBitCount = sizeof(RGBQUAD);
  3032. pdti->TranslateBitmapInfo = pbmiNew;
  3033. pdti->TranslateBitmapInfoSize = 0; // size will not change from original
  3034. pdti->pvSourceBits = (PBYTE)pbmi + pbmi->bmiHeader.biSize;
  3035. pdti->cjSourceBits = nColors;
  3036. pdti->pvTranslateBits = (PBYTE)pbmiNew + pbmiNew->bmiHeader.biSize;
  3037. pdti->cjTranslateBits = nColors * sizeof(RGBQUAD);
  3038. if (bCMYKColor)
  3039. {
  3040. pdti->TranslateColorType = BM_KYMCQUADS;
  3041. //
  3042. // Update header for CMYK color.
  3043. //
  3044. pbmiNew->bmiHeader.biCompression = BI_CMYK;
  3045. }
  3046. else
  3047. {
  3048. pdti->TranslateColorType = BM_xRGBQUADS;
  3049. }
  3050. }
  3051. else
  3052. {
  3053. ICMWRN(("IcmGetTranslateInfo: Illegal biBitCount\n"));
  3054. return (FALSE);
  3055. }
  3056. }
  3057. else if (
  3058. (pbmi->bmiHeader.biCompression == BI_BITFIELDS) &&
  3059. (
  3060. (pbmi->bmiHeader.biBitCount == 16) ||
  3061. (pbmi->bmiHeader.biBitCount == 32)
  3062. )
  3063. )
  3064. {
  3065. PULONG pulColors = (PULONG)pbmi->bmiColors;
  3066. ICMMSG(("IcmGetTranslateInfo():BI_BITFIELDS 16/32 bpp\n"));
  3067. //
  3068. // we will translate bitmap, pvBits should be presented.
  3069. //
  3070. if (pvBits == NULL)
  3071. {
  3072. return (FALSE);
  3073. }
  3074. if (pbmi->bmiHeader.biBitCount == 32)
  3075. {
  3076. if ((pulColors[0] == 0x0000ff) && /* Red */
  3077. (pulColors[1] == 0x00ff00) && /* Green */
  3078. (pulColors[2] == 0xff0000)) /* Blue */
  3079. {
  3080. ColorType = BM_xBGRQUADS;
  3081. }
  3082. else if ((pulColors[0] == 0xff0000) && /* Red */
  3083. (pulColors[1] == 0x00ff00) && /* Green */
  3084. (pulColors[2] == 0x0000ff)) /* Blue */
  3085. {
  3086. ColorType = BM_xRGBQUADS;
  3087. }
  3088. else
  3089. {
  3090. ICMWRN(("IcmGetTranslateInfo: Illegal Bitfields fields for 32 bpp\n"));
  3091. return (FALSE);
  3092. }
  3093. }
  3094. else
  3095. {
  3096. if ((pulColors[0] == 0x007c00) &&
  3097. (pulColors[1] == 0x0003e0) &&
  3098. (pulColors[2] == 0x00001f))
  3099. {
  3100. ColorType = BM_x555RGB;
  3101. }
  3102. else if ((pulColors[0] == 0x00f800) &&
  3103. (pulColors[1] == 0x0007e0) &&
  3104. (pulColors[2] == 0x00001f))
  3105. {
  3106. ColorType = BM_565RGB;
  3107. }
  3108. else
  3109. {
  3110. ICMWRN(("IcmGetTranslateInfo: Illegal Bitfields fields for 16 bpp\n"));
  3111. return (FALSE);
  3112. }
  3113. }
  3114. //
  3115. // Fill up source bitmap information.
  3116. //
  3117. pdti->SourceWidth = pbmi->bmiHeader.biWidth;
  3118. pdti->SourceHeight = dwNumScan;
  3119. pdti->SourceBitCount = pbmi->bmiHeader.biBitCount;
  3120. pdti->SourceColorType = ColorType;
  3121. pdti->pvSourceBits = pvBits;
  3122. pdti->cjSourceBits = cjBits;
  3123. //
  3124. // CMYK Color ?
  3125. //
  3126. if (bCMYKColor)
  3127. {
  3128. pdti->TranslateType = (TRANSLATE_BITMAP|TRANSLATE_HEADER);
  3129. //
  3130. // CMYK bitmap color bitmap is 32 BPP (4 bytes per pixel).
  3131. //
  3132. cjTranslateBits = (pdti->SourceWidth * 4) * pdti->SourceHeight;
  3133. //
  3134. // We need new bitmap info header for CMYK.
  3135. //
  3136. pbmiNew = LOCALALLOC(pbmi->bmiHeader.biSize);
  3137. if (!pbmiNew)
  3138. {
  3139. WARNING("IcmGetTranslateInfo():LOCALALLOC() failed\n");
  3140. return (FALSE);
  3141. }
  3142. //
  3143. // Make a copy of source, first.
  3144. //
  3145. RtlCopyMemory(pbmiNew,pbmi,pbmi->bmiHeader.biSize);
  3146. //
  3147. // Update header for CMYK color.
  3148. //
  3149. pbmiNew->bmiHeader.biBitCount = 32;
  3150. pbmiNew->bmiHeader.biCompression = BI_CMYK;
  3151. pbmiNew->bmiHeader.biSizeImage = cjTranslateBits;
  3152. pbmiNew->bmiHeader.biClrUsed = 0;
  3153. pbmiNew->bmiHeader.biClrImportant = 0;
  3154. //
  3155. // We have new BITMAPINFO header
  3156. //
  3157. pdti->TranslateBitmapInfo = pbmiNew;
  3158. pdti->TranslateBitmapInfoSize = pbmi->bmiHeader.biSize;
  3159. //
  3160. // Translate bitmap color type is CMYK.
  3161. //
  3162. pdti->TranslateColorType = BM_KYMCQUADS;
  3163. }
  3164. else
  3165. {
  3166. pdti->TranslateType = TRANSLATE_BITMAP;
  3167. //
  3168. // Translate bitmap size is same as source.
  3169. //
  3170. cjTranslateBits = cjBits;
  3171. //
  3172. // Translate bitmap color type is same source.
  3173. //
  3174. pdti->TranslateColorType = ColorType;
  3175. pdti->TranslateBitmapInfo = NULL;
  3176. pdti->TranslateBitmapInfoSize = 0;
  3177. }
  3178. //
  3179. // Allocate translate buffer
  3180. //
  3181. pOutput = LOCALALLOC(cjTranslateBits);
  3182. if (!pOutput)
  3183. {
  3184. if (pbmiNew)
  3185. {
  3186. LOCALFREE(pbmiNew);
  3187. }
  3188. WARNING("IcmGetTranslateInfo():LOCALALLOC() failed\n");
  3189. return (FALSE);
  3190. }
  3191. //
  3192. // Setup translation buffer.
  3193. //
  3194. pdti->pvTranslateBits = pOutput;
  3195. pdti->cjTranslateBits = cjTranslateBits;
  3196. }
  3197. else if (
  3198. (pbmi->bmiHeader.biCompression == BI_RLE8) ||
  3199. (pbmi->bmiHeader.biCompression == BI_RLE4)
  3200. )
  3201. {
  3202. //
  3203. // translate 256 for RLE8, 16 for RLE4 entry color palette
  3204. //
  3205. ULONG nMaxColors;
  3206. if (pbmi->bmiHeader.biCompression == BI_RLE8)
  3207. {
  3208. ICMMSG(("IcmGetTranslateInfo():BI_RLE 8\n"));
  3209. nMaxColors = 256;
  3210. }
  3211. else
  3212. {
  3213. ICMMSG(("IcmGetTranslateInfo():BI_RLE 4\n"));
  3214. nMaxColors = 16;
  3215. }
  3216. //
  3217. // validate number of colors
  3218. //
  3219. nColors = pbmi->bmiHeader.biClrUsed;
  3220. if ((nColors == 0) || (nColors > nMaxColors))
  3221. {
  3222. nColors = nMaxColors;
  3223. }
  3224. //
  3225. // Allocate new bitmap info header and color table.
  3226. //
  3227. pbmiNew = LOCALALLOC(pbmi->bmiHeader.biSize + (nColors * sizeof(RGBQUAD)));
  3228. if (!pbmiNew)
  3229. {
  3230. WARNING("IcmGetTranslateInfo():LOCALALLOC() failed\n");
  3231. return (FALSE);
  3232. }
  3233. //
  3234. // Copy source BITMAPINFO to new
  3235. //
  3236. RtlCopyMemory(pbmiNew,pbmi,pbmi->bmiHeader.biSize);
  3237. pdti->TranslateType = TRANSLATE_HEADER;
  3238. pdti->SourceColorType = BM_xRGBQUADS;
  3239. pdti->SourceWidth = nColors;
  3240. pdti->SourceHeight = 1;
  3241. pdti->SourceBitCount = sizeof(RGBQUAD);
  3242. pdti->TranslateBitmapInfo = pbmiNew;
  3243. pdti->TranslateBitmapInfoSize = 0; // size will not change from original
  3244. pdti->pvSourceBits = (PBYTE)pbmi + pbmi->bmiHeader.biSize;
  3245. pdti->cjSourceBits = nColors;
  3246. pdti->pvTranslateBits = (PBYTE)pbmiNew + pbmiNew->bmiHeader.biSize;
  3247. pdti->cjTranslateBits = nColors * sizeof(RGBQUAD);
  3248. if (bCMYKColor)
  3249. {
  3250. pdti->TranslateColorType = BM_KYMCQUADS;
  3251. //
  3252. // Update header for CMYK color.
  3253. //
  3254. if (pbmi->bmiHeader.biCompression == BI_RLE8)
  3255. {
  3256. ICMMSG(("IcmGetTranslateInfo():BI_CMYKRLE 8\n"));
  3257. pbmiNew->bmiHeader.biCompression = BI_CMYKRLE8;
  3258. }
  3259. else
  3260. {
  3261. ICMMSG(("IcmGetTranslateInfo():BI_CMYKRLE 4\n"));
  3262. pbmiNew->bmiHeader.biCompression = BI_CMYKRLE4;
  3263. }
  3264. }
  3265. else
  3266. {
  3267. pdti->TranslateColorType = BM_xRGBQUADS;
  3268. }
  3269. }
  3270. else
  3271. {
  3272. WARNING("IcmGetTranslateInfo():Illegal bitmap format\n");
  3273. return (FALSE);
  3274. }
  3275. return (TRUE);
  3276. }
  3277. /******************************Public*Routine******************************\
  3278. * IcmTranslateDIB
  3279. *
  3280. * History:
  3281. *
  3282. * Rewrote it for CMYK color support:
  3283. * 13-Mar-1997 -by- Hideyuki Nagase [hideyukn]
  3284. * Wrote it:
  3285. * 3-Jul-1996 -by- Mark Enstrom [marke]
  3286. *
  3287. \**************************************************************************/
  3288. BOOL
  3289. IcmTranslateDIB(
  3290. HDC hdc,
  3291. PDC_ATTR pdcattr,
  3292. ULONG cjBits,
  3293. PVOID pBitsIn,
  3294. PVOID *ppBitsOut,
  3295. PBITMAPINFO pbmi,
  3296. PBITMAPINFO *ppbmiNew,
  3297. DWORD *pcjbmiNew,
  3298. DWORD dwNumScan,
  3299. UINT iUsage,
  3300. DWORD dwFlags,
  3301. PCACHED_COLORSPACE *ppColorSpace, // used only for device ICM case.
  3302. PCACHED_COLORTRANSFORM *ppCXform // used only for device ICM case.
  3303. )
  3304. {
  3305. //
  3306. // translate DIB or color table
  3307. //
  3308. BOOL bStatus = TRUE;
  3309. DWORD dwColorSpaceFlags = 0;
  3310. PCACHED_COLORSPACE pBitmapColorSpace = NULL;
  3311. LOGCOLORSPACEW LogColorSpace;
  3312. PROFILE ColorProfile;
  3313. DIB_TRANSLATE_INFO TranslateInfo;
  3314. PCACHED_COLORTRANSFORM pCXform;
  3315. PGDI_ICMINFO pIcmInfo;
  3316. UNREFERENCED_PARAMETER(iUsage);
  3317. ICMAPI(("gdi32: IcmTranslateDIB\n"));
  3318. //
  3319. // Parameter check
  3320. //
  3321. if (pbmi == NULL)
  3322. {
  3323. WARNING("gdi32: IcmTranslateDIB(): pbmi is NULL\n");
  3324. return FALSE;
  3325. }
  3326. //
  3327. // Load external ICM dlls.
  3328. //
  3329. LOAD_ICMDLL(FALSE);
  3330. //
  3331. // Initialize ICMINFO
  3332. //
  3333. if ((pIcmInfo = GET_ICMINFO(pdcattr)) == NULL)
  3334. {
  3335. WARNING("gdi32: IcmTranslateDIB: Can't init icm info\n");
  3336. return FALSE;
  3337. }
  3338. //
  3339. // Initialized returned info.
  3340. //
  3341. if (ppColorSpace)
  3342. *ppColorSpace = NULL;
  3343. if (ppCXform)
  3344. *ppCXform = NULL;
  3345. //
  3346. // Get LOGCOLORSPACE from bitmap if specified.
  3347. //
  3348. if (IcmGetBitmapColorSpace(pbmi,&LogColorSpace,&ColorProfile,&dwColorSpaceFlags))
  3349. {
  3350. //
  3351. // Find ColorSpace from cache.
  3352. //
  3353. pBitmapColorSpace = IcmGetColorSpaceByColorSpace(
  3354. (HGDIOBJ)hdc,
  3355. &LogColorSpace,
  3356. &ColorProfile,
  3357. dwColorSpaceFlags);
  3358. if (pBitmapColorSpace == NULL)
  3359. {
  3360. //
  3361. // Create new cache.
  3362. //
  3363. pBitmapColorSpace = IcmCreateColorSpaceByColorSpace(
  3364. (HGDIOBJ)hdc,
  3365. &LogColorSpace,
  3366. &ColorProfile,
  3367. dwColorSpaceFlags);
  3368. }
  3369. }
  3370. //
  3371. // Create Color Transform, if nessesary.
  3372. //
  3373. if (IS_ICM_DEVICE(pdcattr->lIcmMode))
  3374. {
  3375. //
  3376. // just create a new hcmXform for use with BITMAPV4 AND BITMAPV5s.
  3377. //
  3378. if (pBitmapColorSpace)
  3379. {
  3380. ICMMSG(("IcmTranslateDIB():Bitmap color space used for DEVICE ICM\n"));
  3381. if ((ppCXform != NULL) && (ppColorSpace != NULL))
  3382. {
  3383. //
  3384. // for DEVICE managed ICM, call device driver to create a temp xform
  3385. //
  3386. pCXform = IcmCreateColorTransform(hdc,pdcattr,pBitmapColorSpace,dwFlags);
  3387. if (pCXform == NULL)
  3388. {
  3389. WARNING("IcmTranslateDIB():Fail to create temporay Xfrom with V4V5 Bitmap\n");
  3390. //
  3391. // Failed to create color transfrom, release bitmap color space,
  3392. // and null-color transform.
  3393. //
  3394. IcmReleaseColorSpace(NULL,pBitmapColorSpace,FALSE);
  3395. bStatus = FALSE;
  3396. }
  3397. else
  3398. {
  3399. if (pCXform == IDENT_COLORTRANSFORM)
  3400. {
  3401. //
  3402. // Source and destination color space are same, so no color transform is
  3403. // required, and of course we don't need to keep bitmap color space.
  3404. //
  3405. IcmReleaseColorSpace(NULL,pBitmapColorSpace,FALSE);
  3406. }
  3407. else
  3408. {
  3409. //
  3410. // Return to the color transform to callee...
  3411. // (these should be deleted by callee)
  3412. //
  3413. *ppCXform = pCXform;
  3414. *ppColorSpace = pBitmapColorSpace;
  3415. }
  3416. bStatus = TRUE;
  3417. }
  3418. }
  3419. else
  3420. {
  3421. WARNING("IcmTranslateDIB():No device ICM will happen for this V4V5 Bitmap\n");
  3422. IcmReleaseColorSpace(NULL,pBitmapColorSpace,FALSE);
  3423. bStatus = TRUE;
  3424. }
  3425. return (bStatus);
  3426. }
  3427. else
  3428. {
  3429. ICMMSG(("IcmTranslateDIB():DC color space used for DEVICE ICM\n"));
  3430. //
  3431. // We don't need to create new transform, just use the transform in DC.
  3432. //
  3433. return (TRUE);
  3434. }
  3435. }
  3436. else if (IS_ICM_HOST(pdcattr->lIcmMode))
  3437. {
  3438. HANDLE hcmXform = NULL;
  3439. if (pBitmapColorSpace)
  3440. {
  3441. ICMMSG(("IcmTranslateDIB():Bitmap color space used for HOST ICM\n"));
  3442. pCXform = IcmCreateColorTransform(hdc,pdcattr,pBitmapColorSpace,dwFlags);
  3443. if ((pCXform == IDENT_COLORTRANSFORM) || (pCXform == NULL))
  3444. {
  3445. //
  3446. // unable or not nessesary to translate DIB
  3447. //
  3448. ICMWRN(("Bitmap V4 or V5: CreateColorTransform failed or ident.\n"));
  3449. goto TranslateDIB_Cleanup;
  3450. }
  3451. else
  3452. {
  3453. hcmXform = pCXform->ColorTransform;
  3454. }
  3455. }
  3456. else
  3457. {
  3458. ICMMSG(("IcmTranslateDIB():DC color space used for HOST ICM\n"));
  3459. if (dwFlags & ICM_BACKWARD)
  3460. {
  3461. ICMMSG(("IcmTranslateDIB():Backward Color transform\n"));
  3462. //
  3463. // If there is cached handle, use that.
  3464. //
  3465. if (pIcmInfo->pBackCXform)
  3466. {
  3467. ICMMSG(("IcmTranslateDIB():Use cached transform for Backward Color transform\n"));
  3468. hcmXform = pIcmInfo->pBackCXform->ColorTransform;
  3469. }
  3470. else
  3471. {
  3472. PCACHED_COLORTRANSFORM pCXform;
  3473. ICMMSG(("IcmTranslateDIB():Create cached transform for Backward Color transform\n"));
  3474. //
  3475. // Create backward color transform.
  3476. //
  3477. pCXform = IcmCreateColorTransform(hdc,
  3478. pdcattr,
  3479. NULL,
  3480. ICM_BACKWARD);
  3481. if ((pCXform == NULL) || (pCXform == IDENT_COLORTRANSFORM))
  3482. {
  3483. ICMWRN(("IcmTranslateDIB():ColorTransform is NULL or ident.\n"));
  3484. goto TranslateDIB_Cleanup;
  3485. }
  3486. //
  3487. // Cache created color transform.
  3488. //
  3489. pIcmInfo->pBackCXform = pCXform;
  3490. //
  3491. // We will delete this cached transform, when we don't need this anymore.
  3492. //
  3493. hcmXform = pCXform->ColorTransform;
  3494. }
  3495. }
  3496. else
  3497. {
  3498. //
  3499. // Use DC's colortransform
  3500. //
  3501. hcmXform = pdcattr->hcmXform;
  3502. }
  3503. }
  3504. if (hcmXform == NULL)
  3505. {
  3506. //
  3507. // if we don't have any colortransform, we will not translate anything.
  3508. // just fail and let use original image.
  3509. //
  3510. ICMWRN(("IcmTranslateDIB():No colortransform, might be ident.\n"));
  3511. goto TranslateDIB_Cleanup;
  3512. }
  3513. //
  3514. // Get bitmap translate information.
  3515. //
  3516. bStatus = IcmGetTranslateInfo(pdcattr,pbmi,pBitsIn,cjBits,dwNumScan,&TranslateInfo,dwFlags);
  3517. if (bStatus)
  3518. {
  3519. LONG nLineBytes = ((TranslateInfo.SourceWidth *
  3520. TranslateInfo.SourceBitCount) + 7) / 8;
  3521. bStatus = (*fpTranslateBitmapBits)(
  3522. hcmXform,
  3523. TranslateInfo.pvSourceBits,
  3524. TranslateInfo.SourceColorType,
  3525. TranslateInfo.SourceWidth,
  3526. TranslateInfo.SourceHeight,
  3527. ALIGN_DWORD(nLineBytes),
  3528. TranslateInfo.pvTranslateBits,
  3529. TranslateInfo.TranslateColorType,
  3530. //
  3531. 0, // We need pass 0 here, to let Kodak CMM works
  3532. //
  3533. NULL,0);
  3534. if (bStatus)
  3535. {
  3536. //
  3537. // Pass new bitmap and/or header to caller.
  3538. //
  3539. if (TranslateInfo.TranslateType & TRANSLATE_BITMAP)
  3540. {
  3541. if (ppBitsOut)
  3542. {
  3543. *ppBitsOut = TranslateInfo.pvTranslateBits;
  3544. }
  3545. else
  3546. {
  3547. //
  3548. // Overwrite original (when input color and output color type is same)
  3549. //
  3550. if (TranslateInfo.SourceColorType == TranslateInfo.TranslateColorType)
  3551. {
  3552. RtlCopyMemory(TranslateInfo.pvSourceBits,
  3553. TranslateInfo.pvTranslateBits,
  3554. TranslateInfo.cjTranslateBits);
  3555. }
  3556. else
  3557. {
  3558. WARNING("IcmTranslateDIB():Input color != Output color\n");
  3559. }
  3560. LOCALFREE(TranslateInfo.pvTranslateBits);
  3561. }
  3562. }
  3563. if (TranslateInfo.TranslateType & TRANSLATE_HEADER)
  3564. {
  3565. if (ppbmiNew)
  3566. {
  3567. *ppbmiNew = TranslateInfo.TranslateBitmapInfo;
  3568. }
  3569. else
  3570. {
  3571. //
  3572. // Overwrite original (when input color and output color type is same)
  3573. //
  3574. if (TranslateInfo.SourceColorType == TranslateInfo.TranslateColorType)
  3575. {
  3576. RtlCopyMemory(TranslateInfo.pvSourceBits,
  3577. TranslateInfo.pvTranslateBits,
  3578. TranslateInfo.cjTranslateBits);
  3579. }
  3580. else
  3581. {
  3582. WARNING("IcmTranslateDIB():Input color != Output color\n");
  3583. }
  3584. LOCALFREE(TranslateInfo.TranslateBitmapInfo);
  3585. }
  3586. if (pcjbmiNew)
  3587. {
  3588. *pcjbmiNew = TranslateInfo.TranslateBitmapInfoSize;
  3589. }
  3590. }
  3591. }
  3592. else
  3593. {
  3594. WARNING("IcmTranslateDIB():Fail TranslateBitmapBits\n");
  3595. //
  3596. // Free memory which allocated inside IcmGetTranslateInfo().
  3597. //
  3598. if (TranslateInfo.TranslateType & TRANSLATE_BITMAP)
  3599. {
  3600. LOCALFREE(TranslateInfo.pvTranslateBits);
  3601. }
  3602. if (TranslateInfo.TranslateType & TRANSLATE_HEADER)
  3603. {
  3604. LOCALFREE(TranslateInfo.TranslateBitmapInfo);
  3605. }
  3606. }
  3607. }
  3608. TranslateDIB_Cleanup:
  3609. //
  3610. // Free temp transform and temp file
  3611. //
  3612. // Only delete hcmXform when it based on bitmap colorspace.
  3613. //
  3614. if (pBitmapColorSpace)
  3615. {
  3616. if (hcmXform)
  3617. {
  3618. IcmDeleteColorTransform(pCXform,FALSE);
  3619. }
  3620. IcmReleaseColorSpace(NULL,pBitmapColorSpace,FALSE);
  3621. }
  3622. }
  3623. return(bStatus);
  3624. }
  3625. /******************************Public*Routine******************************\
  3626. * IcmGetFirstNonUsedColorTransform()
  3627. *
  3628. * History:
  3629. *
  3630. * Write it:
  3631. * 12-Mar-1998 -by- Hideyuki Nagase [hideyukn]
  3632. \**************************************************************************/
  3633. PCACHED_COLORTRANSFORM
  3634. IcmGetFirstNonUsedColorTransform(
  3635. VOID
  3636. )
  3637. {
  3638. PCACHED_COLORTRANSFORM pCXform = NULL;
  3639. PLIST_ENTRY p;
  3640. ICMAPI(("gdi32: IcmGetFirstNonUsedColorTransform\n"));
  3641. ENTERCRITICALSECTION(&semColorTransformCache);
  3642. p = ListCachedColorTransform.Flink;
  3643. while(p != &ListCachedColorTransform)
  3644. {
  3645. pCXform = CONTAINING_RECORD(p,CACHED_COLORTRANSFORM,ListEntry);
  3646. if (pCXform->cRef == 0)
  3647. {
  3648. ICMMSG(("IcmGetFirstNonUsedColorTransform():Find non-used color transform in cache !\n"));
  3649. //
  3650. // No one use this color transform at this moment.
  3651. //
  3652. break;
  3653. }
  3654. p = p->Flink;
  3655. pCXform = NULL;
  3656. }
  3657. LEAVECRITICALSECTION(&semColorTransformCache);
  3658. return (pCXform);
  3659. }
  3660. /******************************Public*Routine******************************\
  3661. * IcmGetColorTransform()
  3662. *
  3663. * History:
  3664. *
  3665. * Write it:
  3666. * 21-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  3667. \**************************************************************************/
  3668. PCACHED_COLORTRANSFORM
  3669. IcmGetColorTransform(
  3670. HDC hdcRequest,
  3671. PCACHED_COLORSPACE pSource,
  3672. PCACHED_COLORSPACE pDestination,
  3673. PCACHED_COLORSPACE pTarget,
  3674. BOOL bNeedDeviceXform
  3675. )
  3676. {
  3677. PCACHED_COLORTRANSFORM pCXform = NULL;
  3678. PLIST_ENTRY p;
  3679. ICMAPI(("gdi32: IcmGetColorTransform\n"));
  3680. ENTERCRITICALSECTION(&semColorTransformCache);
  3681. p = ListCachedColorTransform.Flink;
  3682. while(p != &ListCachedColorTransform)
  3683. {
  3684. pCXform = CONTAINING_RECORD(p,CACHED_COLORTRANSFORM,ListEntry);
  3685. if (IcmSameColorSpace(pSource,pCXform->SourceColorSpace) &&
  3686. IcmSameColorSpace(pDestination,pCXform->DestinationColorSpace) &&
  3687. IcmSameColorSpace(pTarget,pCXform->TargetColorSpace))
  3688. {
  3689. //
  3690. // If callee needs device color tansform,
  3691. // of course, we should return device color transform.
  3692. //
  3693. if ((bNeedDeviceXform ? 1 : 0) ==
  3694. ((pCXform->flInfo & DEVICE_COLORTRANSFORM) ? 1 : 0))
  3695. {
  3696. //
  3697. // if Cached color transform depends on specific DC, check it.
  3698. //
  3699. if ((pCXform->hdc == NULL) || (pCXform->hdc == hdcRequest))
  3700. {
  3701. ICMMSG(("IcmGetColorTransform():Find in cache !\n"));
  3702. //
  3703. // Match !, use this color transform, increment ref. count
  3704. //
  3705. pCXform->cRef++;
  3706. break;
  3707. }
  3708. }
  3709. }
  3710. p = p->Flink;
  3711. pCXform = NULL;
  3712. }
  3713. LEAVECRITICALSECTION(&semColorTransformCache);
  3714. return (pCXform);
  3715. }
  3716. /******************************Public*Routine******************************\
  3717. * IcmCreateColorTransform
  3718. *
  3719. * Decide whether to call the device driver or mscms.dll to delete a
  3720. * color transform.
  3721. *
  3722. * Arguments:
  3723. *
  3724. * hdc
  3725. * pdcattr
  3726. * pLogColorSpaceW
  3727. *
  3728. * Return Value:
  3729. *
  3730. * handle of new transform
  3731. *
  3732. * History:
  3733. *
  3734. * Write it:
  3735. * 24-Jan-1996 -by- Hideyuki Nagase [hideyukn]
  3736. *
  3737. \**************************************************************************/
  3738. PCACHED_COLORTRANSFORM
  3739. IcmCreateColorTransform(
  3740. HDC hdc,
  3741. PDC_ATTR pdcattr,
  3742. PCACHED_COLORSPACE pInputColorSpace,
  3743. DWORD dwFlags
  3744. )
  3745. {
  3746. PCACHED_COLORTRANSFORM pCXform = NULL;
  3747. PCACHED_COLORSPACE pSourceColorSpace = NULL;
  3748. BOOL bDCSourceColorSpace = (pInputColorSpace == NULL ? TRUE : FALSE);
  3749. BOOL bAnyNewColorSpace = FALSE;
  3750. PGDI_ICMINFO pIcmInfo;
  3751. ICMAPI(("gdi32: IcmCreateColorTransform\n"));
  3752. ASSERTGDI(pdcattr != NULL,"IcmCreateColorTransform: pdcattr == NULL\n");
  3753. //
  3754. // If this is Lazy color correction case, the destination surface
  3755. // will have image in source color space, so the color transform
  3756. // is identical.
  3757. //
  3758. if (IS_ICM_LAZY_CORRECTION(pdcattr->lIcmMode))
  3759. {
  3760. return (IDENT_COLORTRANSFORM);
  3761. }
  3762. //
  3763. // Load external ICM dlls.
  3764. //
  3765. LOAD_ICMDLL(NULL);
  3766. //
  3767. // Initialize ICMINFO
  3768. //
  3769. if ((pIcmInfo = GET_ICMINFO(pdcattr)) == NULL)
  3770. {
  3771. WARNING("gdi32: IcmCreateColorTransform: Can't init icm info\n");
  3772. return(NULL);
  3773. }
  3774. if (bDCSourceColorSpace && (pIcmInfo->pSourceColorSpace == NULL))
  3775. {
  3776. //
  3777. // If we haven't gotton DC source color space, get it there.
  3778. //
  3779. LOGCOLORSPACEW LogColorSpaceW;
  3780. ICMMSG(("IcmCreateColorTransform(): Call getobject to get source color space in DC\n"));
  3781. //
  3782. // Filled with zero.
  3783. //
  3784. RtlZeroMemory(&LogColorSpaceW,sizeof(LOGCOLORSPACEW));
  3785. //
  3786. // Find ColorSpace from cache.
  3787. //
  3788. pSourceColorSpace = IcmGetColorSpaceByHandle(
  3789. (HGDIOBJ)hdc,
  3790. (HANDLE)pdcattr->hColorSpace,
  3791. &LogColorSpaceW,0);
  3792. //
  3793. // If we can not find from cache, but succeeded to obtain
  3794. // valid logcolorspace from handle, create new one.
  3795. //
  3796. if ((pSourceColorSpace == NULL) &&
  3797. (LogColorSpaceW.lcsSignature == LCS_SIGNATURE))
  3798. {
  3799. //
  3800. // Create new cache.
  3801. //
  3802. pSourceColorSpace = IcmCreateColorSpaceByColorSpace(
  3803. (HGDIOBJ)hdc,
  3804. &LogColorSpaceW,
  3805. NULL, 0);
  3806. //
  3807. // we are using new color space
  3808. //
  3809. bAnyNewColorSpace = TRUE;
  3810. }
  3811. //
  3812. // And this is DC's color space, keep it for cache.
  3813. //
  3814. pIcmInfo->pSourceColorSpace = pSourceColorSpace;
  3815. }
  3816. else if (bDCSourceColorSpace)
  3817. {
  3818. ICMMSG(("IcmCreateColorTransform(): Use cached source color space in DC\n"));
  3819. //
  3820. // Get this from client cache !
  3821. //
  3822. pSourceColorSpace = pIcmInfo->pSourceColorSpace;
  3823. }
  3824. else
  3825. {
  3826. ICMMSG(("IcmCreateColorTransform(): Use given source color space\n"));
  3827. //
  3828. // Just use given color space.
  3829. //
  3830. pSourceColorSpace = pInputColorSpace;
  3831. }
  3832. if (pSourceColorSpace)
  3833. {
  3834. HANDLE hColorTransform = NULL;
  3835. PCACHED_COLORSPACE pDestColorSpace = pIcmInfo->pDestColorSpace;
  3836. PCACHED_COLORSPACE pTargetColorSpace = NULL;
  3837. //
  3838. // if we are in proofing mode, consider target profile.
  3839. //
  3840. if (IS_ICM_PROOFING(pdcattr->lIcmMode))
  3841. {
  3842. pTargetColorSpace = pIcmInfo->pTargetColorSpace;
  3843. }
  3844. #if DBG_ICM
  3845. //
  3846. // Dump current color space for the DC.
  3847. //
  3848. if ((pSourceColorSpace->LogColorSpace.lcsFilename[0]) != UNICODE_NULL)
  3849. {
  3850. ICMMSG(("IcmCreateColorTransform(): Source Profile = %ws\n",
  3851. pSourceColorSpace->LogColorSpace.lcsFilename));
  3852. }
  3853. if ((pDestColorSpace) &&
  3854. ((pDestColorSpace->LogColorSpace.lcsFilename[0]) != UNICODE_NULL))
  3855. {
  3856. ICMMSG(("IcmCreateColorTransform(): Destination Profile = %ws\n",
  3857. pDestColorSpace->LogColorSpace.lcsFilename));
  3858. }
  3859. if ((pTargetColorSpace) &&
  3860. ((pTargetColorSpace->LogColorSpace.lcsFilename[0]) != UNICODE_NULL))
  3861. {
  3862. ICMMSG(("IcmCreateColorTransform(): Target Profile = %ws\n",
  3863. pTargetColorSpace->LogColorSpace.lcsFilename));
  3864. }
  3865. ICMMSG(("IcmCreateColorTransform(): Intent = %d\n",
  3866. pSourceColorSpace->ColorIntent));
  3867. #endif // DBG
  3868. //
  3869. // At this moment, we have any source colorspace.
  3870. //
  3871. if (IcmSameColorSpace(pSourceColorSpace,pDestColorSpace))
  3872. {
  3873. if (pTargetColorSpace)
  3874. {
  3875. if (IcmSameColorSpace(pSourceColorSpace,pTargetColorSpace))
  3876. {
  3877. ICMMSG(("IcmCreateColorTransform(): Src == Dest == Trg colorspace\n"));
  3878. //
  3879. // Source ColorSpace == Destination ColorSpace == Target ColorSpace
  3880. // No color transform needed.
  3881. //
  3882. return (IDENT_COLORTRANSFORM);
  3883. }
  3884. }
  3885. else
  3886. {
  3887. ICMMSG(("IcmCreateColorTransform(): Src == Dest colorspace\n"));
  3888. //
  3889. // Source ColorSpace == Destination ColorSpace,
  3890. // and there is no target profile.
  3891. // That means we don't need translate color
  3892. //
  3893. return (IDENT_COLORTRANSFORM);
  3894. }
  3895. }
  3896. //
  3897. // We need to have proper colortransform to adjust color between each colorspace.
  3898. //
  3899. if (dwFlags & ICM_BACKWARD)
  3900. {
  3901. //
  3902. // This is backward transform. (swap source and destination)
  3903. //
  3904. PCACHED_COLORSPACE pSwapColorSpace;
  3905. pSwapColorSpace = pSourceColorSpace;
  3906. pSourceColorSpace = pDestColorSpace;
  3907. pDestColorSpace = pSwapColorSpace;
  3908. }
  3909. //
  3910. // At this moment, at least, we should have Source and Destination color space.
  3911. // And target color space is optional.
  3912. //
  3913. if (pDestColorSpace)
  3914. {
  3915. if (!bAnyNewColorSpace)
  3916. {
  3917. //
  3918. // Find colortransform from cache
  3919. //
  3920. // if this is device ICM, hdc also should matched.
  3921. //
  3922. pCXform = IcmGetColorTransform(
  3923. hdc,
  3924. pSourceColorSpace,
  3925. pDestColorSpace,
  3926. pTargetColorSpace,
  3927. (IS_ICM_DEVICE(pdcattr->lIcmMode)));
  3928. if (pCXform)
  3929. {
  3930. return (pCXform);
  3931. }
  3932. }
  3933. //
  3934. // Allocate CACHED_COLORTRANSFORM
  3935. //
  3936. pCXform = LOCALALLOC(sizeof(CACHED_COLORTRANSFORM));
  3937. if (pCXform)
  3938. {
  3939. ENTERCRITICALSECTION(&semColorSpaceCache);
  3940. //
  3941. // Make sure all color space has been realized
  3942. //
  3943. if (IcmRealizeColorProfile(pSourceColorSpace,TRUE) &&
  3944. IcmRealizeColorProfile(pDestColorSpace,TRUE) &&
  3945. IcmRealizeColorProfile(pTargetColorSpace,TRUE))
  3946. {
  3947. //
  3948. // call ICM dll or device driver to create a color transform
  3949. //
  3950. if (IS_ICM_HOST(pdcattr->lIcmMode))
  3951. {
  3952. DWORD ahIntents[3];
  3953. HPROFILE ahProfiles[3];
  3954. DWORD chProfiles = 0;
  3955. ICMMSG(("Creating Host ICM Transform...\n"));
  3956. //
  3957. // Put source profile in first entry.
  3958. //
  3959. ahIntents[chProfiles] = INTENT_RELATIVE_COLORIMETRIC;
  3960. ahProfiles[chProfiles] = pSourceColorSpace->hProfile;
  3961. chProfiles++;
  3962. ahIntents[chProfiles] = pSourceColorSpace->ColorIntent;
  3963. //
  3964. // If target profile (proofing) is used, insert it
  3965. // between source and destination.
  3966. //
  3967. if (pTargetColorSpace)
  3968. {
  3969. ahProfiles[chProfiles] = pTargetColorSpace->hProfile;
  3970. chProfiles++;
  3971. ahIntents[chProfiles] = INTENT_ABSOLUTE_COLORIMETRIC;
  3972. }
  3973. //
  3974. // Finally, set destination profile.
  3975. //
  3976. ahProfiles[chProfiles] = pDestColorSpace->hProfile;
  3977. chProfiles++;
  3978. //
  3979. // Call MSCMS to create color transform.
  3980. //
  3981. hColorTransform = (*fpCreateMultiProfileTransform)(
  3982. ahProfiles, chProfiles,
  3983. ahIntents, chProfiles,
  3984. NORMAL_MODE | ENABLE_GAMUT_CHECKING,
  3985. INDEX_DONT_CARE);
  3986. }
  3987. else if (IS_ICM_DEVICE(pdcattr->lIcmMode))
  3988. {
  3989. CLIENT_SIDE_FILEVIEW fvwSrcProfile;
  3990. CLIENT_SIDE_FILEVIEW fvwDstProfile;
  3991. CLIENT_SIDE_FILEVIEW fvwTrgProfile;
  3992. ICMMSG(("Creating Device ICM Transform...\n"));
  3993. //
  3994. // Invalidate FILEVIEW.
  3995. //
  3996. RtlZeroMemory(&fvwSrcProfile,sizeof(CLIENT_SIDE_FILEVIEW));
  3997. RtlZeroMemory(&fvwDstProfile,sizeof(CLIENT_SIDE_FILEVIEW));
  3998. RtlZeroMemory(&fvwTrgProfile,sizeof(CLIENT_SIDE_FILEVIEW));
  3999. //
  4000. // Map color profile(s) into memory.
  4001. //
  4002. if (pSourceColorSpace->ColorProfile.dwType == PROFILE_FILENAME)
  4003. {
  4004. if (!bMapFileUNICODEClideSide(
  4005. (PWSTR)(pSourceColorSpace->ColorProfile.pProfileData),
  4006. &fvwSrcProfile,FALSE))
  4007. {
  4008. WARNING("IcmCreateColorTransform(): Fail to map source profile\n");
  4009. goto IcmCreateColorTransform_Cleanup;
  4010. }
  4011. }
  4012. else if (pSourceColorSpace->ColorProfile.dwType == PROFILE_MEMBUFFER)
  4013. {
  4014. ICMMSG(("Source Profile is memory buffer\n"));
  4015. fvwSrcProfile.pvView = pSourceColorSpace->ColorProfile.pProfileData;
  4016. fvwSrcProfile.cjView = pSourceColorSpace->ColorProfile.cbDataSize;
  4017. }
  4018. else
  4019. {
  4020. WARNING("IcmCreateColorTransform():src profile type is not supported\n");
  4021. goto IcmCreateColorTransform_Cleanup;
  4022. }
  4023. if (pDestColorSpace->ColorProfile.dwType == PROFILE_FILENAME)
  4024. {
  4025. if (!bMapFileUNICODEClideSide(
  4026. (PWSTR)(pDestColorSpace->ColorProfile.pProfileData),
  4027. &fvwDstProfile,FALSE))
  4028. {
  4029. WARNING("IcmCreateColorTransform(): Fail to map destination profile\n");
  4030. goto IcmCreateColorTransform_Cleanup;
  4031. }
  4032. }
  4033. else if (pDestColorSpace->ColorProfile.dwType == PROFILE_MEMBUFFER)
  4034. {
  4035. ICMMSG(("Destination Profile is memory buffer\n"));
  4036. fvwDstProfile.pvView = pDestColorSpace->ColorProfile.pProfileData;
  4037. fvwDstProfile.cjView = pDestColorSpace->ColorProfile.cbDataSize;
  4038. }
  4039. else
  4040. {
  4041. WARNING("IcmCreateColorTransform():dst profile type is not supported\n");
  4042. goto IcmCreateColorTransform_Cleanup;
  4043. }
  4044. //
  4045. // Target color space is optional
  4046. //
  4047. if (pTargetColorSpace)
  4048. {
  4049. if (pTargetColorSpace->ColorProfile.dwType == PROFILE_FILENAME)
  4050. {
  4051. if (!bMapFileUNICODEClideSide(
  4052. (PWSTR)(pTargetColorSpace->ColorProfile.pProfileData),
  4053. &fvwTrgProfile,FALSE))
  4054. {
  4055. WARNING("IcmCreateColorTransform(): Fail to map target profile\n");
  4056. goto IcmCreateColorTransform_Cleanup;
  4057. }
  4058. }
  4059. else if (pTargetColorSpace->ColorProfile.dwType == PROFILE_MEMBUFFER)
  4060. {
  4061. ICMMSG(("Target Profile is memory buffer\n"));
  4062. fvwTrgProfile.pvView = pTargetColorSpace->ColorProfile.pProfileData;
  4063. fvwTrgProfile.cjView = pTargetColorSpace->ColorProfile.cbDataSize;
  4064. }
  4065. else
  4066. {
  4067. WARNING("IcmCreateColorTransform():trg profile type is not supported\n");
  4068. goto IcmCreateColorTransform_Cleanup;
  4069. }
  4070. }
  4071. //
  4072. // Call kernel.
  4073. //
  4074. hColorTransform = NtGdiCreateColorTransform(hdc,
  4075. &(pSourceColorSpace->LogColorSpace),
  4076. fvwSrcProfile.pvView, // Source Profile memory mapped file.
  4077. fvwSrcProfile.cjView,
  4078. fvwDstProfile.pvView, // Destination Profile memory mapped file.
  4079. fvwDstProfile.cjView,
  4080. fvwTrgProfile.pvView, // Target Profile memory mapped file.
  4081. fvwTrgProfile.cjView);
  4082. IcmCreateColorTransform_Cleanup:
  4083. //
  4084. // if we mapped file, unmap here.
  4085. //
  4086. if (fvwSrcProfile.hSection)
  4087. {
  4088. vUnmapFileClideSide(&fvwSrcProfile);
  4089. }
  4090. if (fvwDstProfile.hSection)
  4091. {
  4092. vUnmapFileClideSide(&fvwDstProfile);
  4093. }
  4094. if (fvwTrgProfile.hSection)
  4095. {
  4096. vUnmapFileClideSide(&fvwTrgProfile);
  4097. }
  4098. }
  4099. }
  4100. //
  4101. // Once after create tranform, we don't need realized color space,
  4102. // so just unrealize it.
  4103. //
  4104. IcmUnrealizeColorProfile(pSourceColorSpace);
  4105. IcmUnrealizeColorProfile(pDestColorSpace);
  4106. IcmUnrealizeColorProfile(pTargetColorSpace);
  4107. LEAVECRITICALSECTION(&semColorSpaceCache);
  4108. if (hColorTransform)
  4109. {
  4110. BOOL bCacheable = TRUE;
  4111. //
  4112. // Initialize CACHED_COLORTRANSFORM with zero
  4113. //
  4114. RtlZeroMemory(pCXform,sizeof(CACHED_COLORTRANSFORM));
  4115. //
  4116. // Fill up CACHED_COLORTRANSFORM
  4117. //
  4118. pCXform->ColorTransform = hColorTransform;
  4119. pCXform->SourceColorSpace = pSourceColorSpace;
  4120. pCXform->DestinationColorSpace = pDestColorSpace;
  4121. pCXform->TargetColorSpace = pTargetColorSpace;
  4122. if (IS_ICM_DEVICE(pdcattr->lIcmMode))
  4123. {
  4124. //
  4125. // if this is device colortransform, mark it and
  4126. // put DC in CACHED_COLORTRANSFORM strcuture
  4127. //
  4128. pCXform->flInfo |= DEVICE_COLORTRANSFORM;
  4129. //
  4130. // And device color transform is not cacheable.
  4131. //
  4132. bCacheable = FALSE;
  4133. }
  4134. ENTERCRITICALSECTION(&semColorSpaceCache);
  4135. //
  4136. // Increment transform ref. count in each color space.
  4137. //
  4138. if (pSourceColorSpace)
  4139. {
  4140. pSourceColorSpace->cRef++;
  4141. if (bCacheable)
  4142. {
  4143. //
  4144. // Check this color space is cacheable.
  4145. //
  4146. bCacheable &= IcmIsCacheable(pSourceColorSpace);
  4147. }
  4148. }
  4149. if (pDestColorSpace)
  4150. {
  4151. pDestColorSpace->cRef++;
  4152. if (bCacheable)
  4153. {
  4154. //
  4155. // Check this color space is cacheable.
  4156. //
  4157. bCacheable &= IcmIsCacheable(pDestColorSpace);
  4158. }
  4159. }
  4160. if (pTargetColorSpace)
  4161. {
  4162. pTargetColorSpace->cRef++;
  4163. if (bCacheable)
  4164. {
  4165. //
  4166. // Check this color space is cacheable.
  4167. //
  4168. bCacheable &= IcmIsCacheable(pTargetColorSpace);
  4169. }
  4170. }
  4171. LEAVECRITICALSECTION(&semColorSpaceCache);
  4172. //
  4173. // Initialize ref. counter.
  4174. //
  4175. pCXform->cRef = 1;
  4176. //
  4177. // Set cache-able bit, if possible.
  4178. //
  4179. if (bCacheable)
  4180. {
  4181. ICMMSG(("IcmCreateColorTransform(): ColorTransform is cacheable\n"));
  4182. pCXform->flInfo |= CACHEABLE_COLORTRANSFORM;
  4183. }
  4184. else
  4185. {
  4186. ICMMSG(("IcmCreateColorTransform(): ColorTransform is *NOT* cacheable\n"));
  4187. //
  4188. // If this is not cacheable, make sure this get deleted when DC gone.
  4189. //
  4190. pCXform->hdc = hdc;
  4191. }
  4192. //
  4193. // Insert new CACHED_COLORTRANSFORM to list
  4194. //
  4195. ENTERCRITICALSECTION(&semColorTransformCache);
  4196. InsertTailList(&ListCachedColorTransform,&(pCXform->ListEntry));
  4197. cCachedColorTransform++;
  4198. LEAVECRITICALSECTION(&semColorTransformCache);
  4199. }
  4200. else
  4201. {
  4202. ICMWRN(("IcmCreateColorTransform(): Fail to create color transform\n"));
  4203. //
  4204. // Fail to get transform handle
  4205. //
  4206. LOCALFREE(pCXform);
  4207. pCXform = NULL;
  4208. }
  4209. }
  4210. else
  4211. {
  4212. WARNING("IcmCreateColorTransform(): LOCALALLOC() failed\n");
  4213. }
  4214. }
  4215. else
  4216. {
  4217. WARNING("IcmCreateColorTransform(): Dest color space is required\n");
  4218. }
  4219. }
  4220. else
  4221. {
  4222. WARNING("IcmCreateColorTransform(): Fail to get source colorspace\n");
  4223. }
  4224. return(pCXform);
  4225. }
  4226. /******************************Public*Routine******************************\
  4227. * IcmTranslateCOLORREF
  4228. *
  4229. * Arguments:
  4230. *
  4231. * hdc
  4232. * pdcattr
  4233. * ColorIn
  4234. * *ColorOut
  4235. *
  4236. * Return Value:
  4237. *
  4238. * Status
  4239. *
  4240. * History:
  4241. *
  4242. * Write it:
  4243. * 13-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  4244. *
  4245. \**************************************************************************/
  4246. BOOL
  4247. IcmTranslateCOLORREF(
  4248. HDC hdc,
  4249. PDC_ATTR pdcattr,
  4250. COLORREF ColorIn,
  4251. COLORREF *ColorOut,
  4252. DWORD Flags
  4253. )
  4254. {
  4255. COLORREF OldColor = ColorIn;
  4256. COLORREF NewColor;
  4257. BOOL bStatus = TRUE;
  4258. ICMAPI(("gdi32: IcmTranslateCOLORREF\n"));
  4259. ASSERTGDI(ColorOut != NULL,"IcmTranslateCOLORREF(): ColorOut == NULL\n");
  4260. if (bNeedTranslateColor(pdcattr))
  4261. {
  4262. PGDI_ICMINFO pIcmInfo;
  4263. LOAD_ICMDLL(FALSE);
  4264. if ((pIcmInfo = GET_ICMINFO(pdcattr)) == NULL)
  4265. {
  4266. WARNING("gdi32: IcmTranslateCOLORREF: Can't init icm info\n");
  4267. return((int)FALSE);
  4268. }
  4269. else
  4270. {
  4271. ULONG SrcColorFormat;
  4272. ULONG DstColorFormat;
  4273. HANDLE hcmXform = NULL;
  4274. if (Flags & ICM_BACKWARD)
  4275. {
  4276. ICMMSG(("IcmTranslateCOLORREF():Backward Color transform\n"));
  4277. //
  4278. // AnyColorFormat ----> COLORREF (0x00bbggrr)
  4279. //
  4280. // Setup src & dest color type.
  4281. //
  4282. SrcColorFormat = pIcmInfo->pDestColorSpace->ColorFormat;
  4283. DstColorFormat = BM_xBGRQUADS;
  4284. //
  4285. // If there is cached handle, use that.
  4286. //
  4287. if (pIcmInfo->pBackCXform)
  4288. {
  4289. ICMMSG(("IcmTranslateCOLORREF():Use cached transform for Backward Color transform\n"));
  4290. hcmXform = pIcmInfo->pBackCXform->ColorTransform;
  4291. }
  4292. else
  4293. {
  4294. PCACHED_COLORTRANSFORM pCXform;
  4295. ICMMSG(("IcmTranslateCOLORREF():Create cached transform for Backward Color transform\n"));
  4296. //
  4297. // Create backward color transform.
  4298. //
  4299. pCXform = IcmCreateColorTransform(hdc,
  4300. pdcattr,
  4301. NULL,
  4302. ICM_BACKWARD);
  4303. if ((pCXform == NULL) || (pCXform == IDENT_COLORTRANSFORM))
  4304. {
  4305. return (FALSE);
  4306. }
  4307. //
  4308. // Cache created color transform.
  4309. //
  4310. pIcmInfo->pBackCXform = pCXform;
  4311. //
  4312. // We will delete this cached transform, when we don't need this anymore.
  4313. //
  4314. hcmXform = pCXform->ColorTransform;
  4315. }
  4316. }
  4317. else
  4318. {
  4319. //
  4320. // COLORREF (0x00bbggrr) ----> AnyColorFormat
  4321. //
  4322. // Setup src & dest color type.
  4323. //
  4324. SrcColorFormat = BM_xBGRQUADS;
  4325. DstColorFormat = pIcmInfo->pDestColorSpace->ColorFormat;
  4326. //
  4327. // Use foaward color transform.
  4328. //
  4329. hcmXform = GetColorTransformInDC(pdcattr);
  4330. //
  4331. // Source is COLORREF. then, Mask off gdi internal infomation.
  4332. //
  4333. // COLORREF = 0x00bbggrr;
  4334. //
  4335. OldColor &= 0x00ffffff;
  4336. }
  4337. if (hcmXform)
  4338. {
  4339. //
  4340. // We handle COLORREF as 1x1 pixel bitmap data.
  4341. //
  4342. bStatus = (*fpTranslateBitmapBits)(hcmXform,
  4343. (PVOID)&OldColor,
  4344. SrcColorFormat,
  4345. 1,1,
  4346. ALIGN_DWORD(sizeof(COLORREF)),
  4347. (PVOID)&NewColor,
  4348. DstColorFormat,
  4349. //
  4350. 0, // We need pass 0 here, to let Kodak CMM works
  4351. //
  4352. NULL,0);
  4353. }
  4354. else
  4355. {
  4356. //
  4357. // It seems hcmXform is invalid
  4358. //
  4359. ICMWRN(("IcmTranslateCOLORREF():hcmXform is invalid\n"));
  4360. bStatus = FALSE;
  4361. }
  4362. if (bStatus)
  4363. {
  4364. if (Flags & ICM_BACKWARD)
  4365. {
  4366. //
  4367. // OldColor: AnyColorFormat
  4368. // NewColor: COLORREF (0x00bbggrr)
  4369. //
  4370. // [NOTE:]
  4371. // We could not restore flags.
  4372. //
  4373. *ColorOut = NewColor;
  4374. }
  4375. else
  4376. {
  4377. //
  4378. // OldColor: COLORREF (0x00bbggrr)
  4379. // NewColor: AnyColorFormat
  4380. //
  4381. if (!(IS_32BITS_COLOR(pdcattr->lIcmMode)))
  4382. {
  4383. //
  4384. // The distination is not 32Bits Color, Restore assign and preserve flags.
  4385. //
  4386. *ColorOut = (NewColor & 0x00ffffff) | (ColorIn & 0xff000000);
  4387. }
  4388. else
  4389. {
  4390. //
  4391. // The distination is 32bits color.
  4392. //
  4393. // [NOTE:]
  4394. // We will lost flags here.
  4395. //
  4396. *ColorOut = NewColor;
  4397. ICMMSG(("IcmTranslateCOLORREF(): 32 bits color !\n"));
  4398. }
  4399. }
  4400. }
  4401. else
  4402. {
  4403. WARNING("IcmTranslateCOLORREF():Fail TranslateBitmapBits()\n");
  4404. }
  4405. }
  4406. }
  4407. else
  4408. {
  4409. //
  4410. // Just return original color
  4411. //
  4412. *ColorOut = ColorIn;
  4413. bStatus = TRUE;
  4414. }
  4415. return(bStatus);
  4416. }
  4417. /******************************Public*Routine******************************\
  4418. * IcmTranslateTRIVERTEX
  4419. *
  4420. * Translate TRIVERTEX in place. No need for a general routine with
  4421. * separate input and output pointers
  4422. *
  4423. * Arguments:
  4424. *
  4425. * hdc - hdc
  4426. * pdcattr - verified dcattr
  4427. * pVertex - input and output pointer
  4428. *
  4429. * Return Value:
  4430. *
  4431. * Status
  4432. *
  4433. * History:
  4434. *
  4435. * Write it:
  4436. * 13-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  4437. *
  4438. \**************************************************************************/
  4439. BOOL
  4440. IcmTranslateTRIVERTEX(
  4441. HDC hdc,
  4442. PDC_ATTR pdcattr,
  4443. PTRIVERTEX pVertex,
  4444. ULONG nVertex
  4445. )
  4446. {
  4447. BOOL bStatus = TRUE;
  4448. ICMAPI(("gdi32: IcmTranslateTRIVERTEX\n"));
  4449. ASSERTGDI(pVertex != NULL,"IcmTranslateTrivertex(): pVertex == NULL\n");
  4450. if (bNeedTranslateColor(pdcattr))
  4451. {
  4452. PGDI_ICMINFO pIcmInfo;
  4453. LOAD_ICMDLL(FALSE);
  4454. if ((pIcmInfo = GET_ICMINFO(pdcattr)) == NULL)
  4455. {
  4456. WARNING("gdi32: IcmTranslateTRIVERTEX: Can't init icm info\n");
  4457. return((int)FALSE);
  4458. }
  4459. else
  4460. {
  4461. //
  4462. // Use foaward color transform.
  4463. //
  4464. if (GetColorTransformInDC(pdcattr))
  4465. {
  4466. //
  4467. // use 16 bit per channel COLOR_RGB to translate trivertex
  4468. //
  4469. while (nVertex--)
  4470. {
  4471. COLOR Color;
  4472. Color.rgb.red = pVertex->Red;
  4473. Color.rgb.green = pVertex->Green;
  4474. Color.rgb.blue = pVertex->Blue;
  4475. bStatus = (*fpTranslateColors)(
  4476. (HANDLE)GetColorTransformInDC(pdcattr),
  4477. &Color,
  4478. 1,
  4479. COLOR_RGB,
  4480. &Color,
  4481. COLOR_RGB);
  4482. if (bStatus)
  4483. {
  4484. //
  4485. // assign output
  4486. //
  4487. pVertex->Red = Color.rgb.red;
  4488. pVertex->Green = Color.rgb.green;
  4489. pVertex->Blue = Color.rgb.blue;
  4490. }
  4491. else
  4492. {
  4493. WARNING("IcmTranslateTRIVERTEX():Fail TranslateColors()\n");
  4494. break;
  4495. }
  4496. pVertex++;
  4497. }
  4498. }
  4499. else
  4500. {
  4501. //
  4502. // It seems hcmXform is invalid
  4503. //
  4504. ICMWRN(("IcmTranslateTRIVERTEX():hcmXform is invalid\n"));
  4505. bStatus = FALSE;
  4506. }
  4507. }
  4508. }
  4509. else
  4510. {
  4511. bStatus = TRUE;
  4512. }
  4513. return(bStatus);
  4514. }
  4515. /******************************Public*Routine******************************\
  4516. * IcmTranslatePaletteEntry
  4517. *
  4518. * Arguments:
  4519. *
  4520. * hdc
  4521. * pdcattr
  4522. * ColorIn
  4523. * pColorOut
  4524. *
  4525. * Return Value:
  4526. *
  4527. * Status
  4528. *
  4529. * History:
  4530. *
  4531. * Rewrite it:
  4532. * 21-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  4533. * Write it:
  4534. * 5-Aug-1996 -by- Mark Enstrom [marke]
  4535. *
  4536. \**************************************************************************/
  4537. BOOL
  4538. IcmTranslatePaletteEntry(
  4539. HDC hdc,
  4540. PDC_ATTR pdcattr,
  4541. PALETTEENTRY *pColorIn,
  4542. PALETTEENTRY *pColorOut,
  4543. UINT NumberOfEntries
  4544. )
  4545. {
  4546. BOOL bStatus = FALSE;
  4547. ICMAPI(("gdi32: IcmTranslatePaletteEntry\n"));
  4548. if (bNeedTranslateColor(pdcattr))
  4549. {
  4550. PGDI_ICMINFO pIcmInfo = GET_ICMINFO(pdcattr);
  4551. if (pIcmInfo)
  4552. {
  4553. LOAD_ICMDLL(FALSE);
  4554. //
  4555. // We handle PALETTEENTRYs as NumberOfEntries x 1 pixels bitmap data.
  4556. //
  4557. bStatus = (*fpTranslateBitmapBits)((HANDLE)GetColorTransformInDC(pdcattr),
  4558. (PVOID)pColorIn,
  4559. //
  4560. BM_xBGRQUADS, // PALETTEENTRY is 0x00bbggrr format
  4561. //
  4562. NumberOfEntries,1,
  4563. ALIGN_DWORD(NumberOfEntries*sizeof(COLORREF)),
  4564. (PVOID)pColorOut,
  4565. //
  4566. pIcmInfo->pDestColorSpace->ColorFormat, // BM_xBGRQUADS or BM_KYMCQUADS
  4567. //
  4568. //
  4569. 0, // We need pass 0 here, to let Kodak CMM works
  4570. //
  4571. NULL,0);
  4572. if (!bStatus)
  4573. {
  4574. WARNING("IcmTranslatePaletteEntry():Fail TranslateBitmapBits()\n");
  4575. }
  4576. }
  4577. }
  4578. else
  4579. {
  4580. //
  4581. // Just return original color.
  4582. //
  4583. RtlCopyMemory(pColorIn,pColorOut,sizeof(PALETTEENTRY) * NumberOfEntries);
  4584. bStatus = TRUE;
  4585. }
  4586. return(bStatus);
  4587. }
  4588. /******************************Public*Routine******************************\
  4589. * IcmDeleteColorTransform
  4590. *
  4591. * Decide whether to call the device driver or mscms.dll to delete a
  4592. * color transform.
  4593. *
  4594. * Arguments:
  4595. *
  4596. * Return Value:
  4597. *
  4598. * History:
  4599. *
  4600. * Mar.12.1998 -by- Hideyuki Nagase [hideyukn]
  4601. *
  4602. \**************************************************************************/
  4603. BOOL
  4604. IcmDeleteColorTransform(
  4605. PCACHED_COLORTRANSFORM pCXform,
  4606. BOOL bForceDelete
  4607. )
  4608. {
  4609. BOOL bStatus = TRUE;
  4610. ICMAPI(("gdi32: IcmDeleteColorTransform\n"));
  4611. if (pCXform)
  4612. {
  4613. ENTERCRITICALSECTION(&semColorTransformCache);
  4614. //
  4615. // Decrement ref. counter.
  4616. //
  4617. pCXform->cRef--;
  4618. if ((pCXform->cRef == 0) || bForceDelete)
  4619. {
  4620. PCACHED_COLORTRANSFORM pCXformVictim = NULL;
  4621. if ((pCXform->flInfo & CACHEABLE_COLORTRANSFORM) && !bForceDelete)
  4622. {
  4623. if (cCachedColorTransform < MAX_COLORTRANSFORM_CACHE)
  4624. {
  4625. ICMMSG(("IcmDeleteColorTransform(): colortransform can be cached !\n"));
  4626. //
  4627. // The color transform can be cached. so just keep it in list.
  4628. // And don't need to delete anything here.
  4629. //
  4630. pCXformVictim = NULL;
  4631. }
  4632. else
  4633. {
  4634. //
  4635. // Find any cache can delete from list.
  4636. //
  4637. if ((pCXformVictim = IcmGetFirstNonUsedColorTransform()) == NULL)
  4638. {
  4639. ICMMSG(("IcmDeleteColorTransform(): colortransform cache is full, delete myself\n"));
  4640. //
  4641. // Nothing can be deleted from list, so delete myself.
  4642. //
  4643. pCXformVictim = pCXform;
  4644. }
  4645. else
  4646. {
  4647. ICMMSG(("IcmDeleteColorTransform(): colortransform cache is full, delete victim\n"));
  4648. }
  4649. }
  4650. }
  4651. else
  4652. {
  4653. //
  4654. // The colortransform can not be kept, or force delete, so just delete this.
  4655. //
  4656. pCXformVictim = pCXform;
  4657. }
  4658. if (pCXformVictim)
  4659. {
  4660. //
  4661. // Unref color space count.
  4662. //
  4663. if (pCXformVictim->SourceColorSpace)
  4664. {
  4665. IcmReleaseColorSpace(NULL,pCXformVictim->SourceColorSpace,FALSE);
  4666. }
  4667. if (pCXformVictim->DestinationColorSpace)
  4668. {
  4669. IcmReleaseColorSpace(NULL,pCXformVictim->DestinationColorSpace,FALSE);
  4670. }
  4671. if (pCXformVictim->TargetColorSpace)
  4672. {
  4673. IcmReleaseColorSpace(NULL,pCXformVictim->TargetColorSpace,FALSE);
  4674. }
  4675. //
  4676. // Delete color transform
  4677. //
  4678. if (pCXformVictim->flInfo & DEVICE_COLORTRANSFORM)
  4679. {
  4680. //
  4681. // call device driver to delete transform.
  4682. //
  4683. bStatus = NtGdiDeleteColorTransform(pCXformVictim->hdc,pCXformVictim->ColorTransform);
  4684. }
  4685. else
  4686. {
  4687. //
  4688. // call color match dll to delete transform.
  4689. //
  4690. bStatus = (*fpDeleteColorTransform)(pCXformVictim->ColorTransform);
  4691. }
  4692. //
  4693. // Remove from list
  4694. //
  4695. RemoveEntryList(&(pCXformVictim->ListEntry));
  4696. cCachedColorTransform--;
  4697. //
  4698. // free CACHED_COLORTRANSFORM
  4699. //
  4700. LOCALFREE(pCXformVictim);
  4701. }
  4702. }
  4703. LEAVECRITICALSECTION(&semColorTransformCache);
  4704. }
  4705. return(bStatus);
  4706. }
  4707. /******************************Public*Routine******************************\
  4708. * IcmDeleteDCColorTransforms
  4709. *
  4710. * Arguments:
  4711. *
  4712. * Return Value:
  4713. *
  4714. * History:
  4715. *
  4716. * Feb.17.1997 Hideyuki Nagase [hideyukn]
  4717. \**************************************************************************/
  4718. BOOL IcmDeleteDCColorTransforms(
  4719. PGDI_ICMINFO pIcmInfo
  4720. )
  4721. {
  4722. ICMAPI(("gdi32: IcmDeleteDCColorTransforms\n"));
  4723. ASSERTGDI(pIcmInfo != NULL,"IcmDeleteDCColorTransform():pIcmInfo == NULL\n");
  4724. //
  4725. // Delete transform selected in DC.
  4726. //
  4727. if (pIcmInfo->pCXform)
  4728. {
  4729. IcmDeleteColorTransform(pIcmInfo->pCXform,FALSE);
  4730. }
  4731. if (pIcmInfo->pBackCXform)
  4732. {
  4733. IcmDeleteColorTransform(pIcmInfo->pBackCXform,FALSE);
  4734. }
  4735. if (pIcmInfo->pProofCXform)
  4736. {
  4737. IcmDeleteColorTransform(pIcmInfo->pProofCXform,FALSE);
  4738. }
  4739. //
  4740. // Invalidate colortransforms
  4741. //
  4742. pIcmInfo->pCXform = pIcmInfo->pBackCXform = pIcmInfo->pProofCXform = NULL;
  4743. return (TRUE);
  4744. }
  4745. /******************************Public*Routine******************************\
  4746. * IcmDeleteCachedColorTransforms
  4747. *
  4748. * Arguments:
  4749. *
  4750. * Return Value:
  4751. *
  4752. * History:
  4753. *
  4754. * May.06.1997 Hideyuki Nagase [hideyukn]
  4755. \**************************************************************************/
  4756. BOOL
  4757. IcmDeleteCachedColorTransforms(
  4758. HDC hdc
  4759. )
  4760. {
  4761. PCACHED_COLORTRANSFORM pCXform = NULL;
  4762. PLIST_ENTRY p;
  4763. ICMAPI(("gdi32: IcmDeleteCachedColorTransforms\n"));
  4764. ENTERCRITICALSECTION(&semColorTransformCache);
  4765. p = ListCachedColorTransform.Flink;
  4766. while(p != &ListCachedColorTransform)
  4767. {
  4768. //
  4769. // Get cached color transform
  4770. //
  4771. pCXform = CONTAINING_RECORD(p,CACHED_COLORTRANSFORM,ListEntry);
  4772. //
  4773. // Let 'p' points next cell. (this prefer to be done BEFORE un-chain this cell)
  4774. //
  4775. p = p->Flink;
  4776. //
  4777. // Is this color transform is specific to this DC ?
  4778. //
  4779. if (pCXform->hdc == hdc)
  4780. {
  4781. ICMMSG(("IcmDeleteCachedColorTransform():Delete colortransform in cache !\n"));
  4782. //
  4783. // Delete color transform (this call will un-chain this cell)
  4784. //
  4785. IcmDeleteColorTransform(pCXform,TRUE);
  4786. }
  4787. }
  4788. LEAVECRITICALSECTION(&semColorTransformCache);
  4789. return (TRUE);
  4790. }
  4791. /******************************Public*Routine******************************\
  4792. * IcmIsCacheable
  4793. *
  4794. * Arguments:
  4795. *
  4796. * Return Value:
  4797. *
  4798. * History:
  4799. *
  4800. * Mar.12.1998 Hideyuki Nagase [hideyukn]
  4801. \**************************************************************************/
  4802. BOOL
  4803. IcmIsCacheable(
  4804. PCACHED_COLORSPACE pColorSpace
  4805. )
  4806. {
  4807. //
  4808. // If this color space can not be cached, don't cache it.
  4809. //
  4810. if (pColorSpace->flInfo & NOT_CACHEABLE_COLORSPACE)
  4811. {
  4812. return (FALSE);
  4813. }
  4814. //
  4815. // If this is any GDI object specific color space, also can not cache.
  4816. //
  4817. if (pColorSpace->hObj)
  4818. {
  4819. return (FALSE);
  4820. }
  4821. return (TRUE);
  4822. }
  4823. /******************************Public*Routine******************************\
  4824. * IcmReleaseCachedColorSpace
  4825. *
  4826. * Arguments:
  4827. *
  4828. * Return Value:
  4829. *
  4830. * History:
  4831. *
  4832. * May.06.1997 Hideyuki Nagase [hideyukn]
  4833. \**************************************************************************/
  4834. BOOL
  4835. IcmReleaseCachedColorSpace(
  4836. HGDIOBJ hObj
  4837. )
  4838. {
  4839. PCACHED_COLORSPACE pColorSpace = NULL;
  4840. PLIST_ENTRY p;
  4841. ICMAPI(("gdi32: IcmReleaseCachedColorSpace\n"));
  4842. ENTERCRITICALSECTION(&semColorSpaceCache);
  4843. p = ListCachedColorSpace.Flink;
  4844. while(p != &ListCachedColorSpace)
  4845. {
  4846. //
  4847. // Get cached color space
  4848. //
  4849. pColorSpace = CONTAINING_RECORD(p,CACHED_COLORSPACE,ListEntry);
  4850. //
  4851. // Let 'p' points next cell. (this prefer to be done BEFORE un-chain this cell)
  4852. //
  4853. p = p->Flink;
  4854. //
  4855. // Is this color transform is related to this DC ?
  4856. //
  4857. if (pColorSpace->hObj == hObj)
  4858. {
  4859. ICMMSG(("IcmReleaseCachedColorSpace():Delete colorspace in cache !\n"));
  4860. //
  4861. // Delete color space (this call will un-chain this cell)
  4862. //
  4863. IcmReleaseColorSpace(hObj,pColorSpace,TRUE);
  4864. }
  4865. }
  4866. LEAVECRITICALSECTION(&semColorSpaceCache);
  4867. return (TRUE);
  4868. }
  4869. /******************************Public*Routine******************************\
  4870. * IcmReleaseColorSpace
  4871. *
  4872. * Arguments:
  4873. *
  4874. * Return Value:
  4875. *
  4876. * History:
  4877. *
  4878. * Feb.17.1997 -by- Hideyuki Nagase [hideyukn]
  4879. *
  4880. \**************************************************************************/
  4881. VOID IcmReleaseColorSpace(
  4882. HGDIOBJ hObj, /* Must be given if bForceDelete is TRUE */
  4883. PCACHED_COLORSPACE pColorSpace,
  4884. BOOL bForceDelete
  4885. )
  4886. {
  4887. ICMAPI(("gdi32: IcmReleaseColorSpace\n"));
  4888. if (pColorSpace)
  4889. {
  4890. ENTERCRITICALSECTION(&semColorSpaceCache);
  4891. //
  4892. // Decrement ref. counter.
  4893. //
  4894. pColorSpace->cRef--;
  4895. //
  4896. // If this profile associated with other GDI objects (driver, metafile or bitmap)
  4897. // we won't delete until the object is deleted
  4898. //
  4899. if (
  4900. (pColorSpace->flInfo & HGDIOBJ_SPECIFIC_COLORSPACE)
  4901. &&
  4902. (bForceDelete == FALSE)
  4903. )
  4904. {
  4905. ICMWRN(("IcmReleaseColorSpace: Delay Delete for Metafile/Driver/Bitmap profile - %ws\n",\
  4906. (pColorSpace->LogColorSpace.lcsFilename[0] ? \
  4907. pColorSpace->LogColorSpace.lcsFilename : L"no profile")));
  4908. }
  4909. else
  4910. {
  4911. if ((pColorSpace->cRef == 0) // No one uses this profile.
  4912. || // OR
  4913. (bForceDelete && IsColorSpaceOwnedByGDIObject(pColorSpace,hObj))
  4914. // DC or Owner GDI object is going to delete and
  4915. // colorspace is designed for this GDI object.
  4916. )
  4917. {
  4918. ICMMSG(("IcmReleaseColorSpace: Delete - %ws\n", \
  4919. (pColorSpace->LogColorSpace.lcsFilename[0] ? \
  4920. pColorSpace->LogColorSpace.lcsFilename : L"no profile")));
  4921. if (pColorSpace->hProfile)
  4922. {
  4923. IcmUnrealizeColorProfile(pColorSpace);
  4924. }
  4925. if (pColorSpace->flInfo & NEED_TO_FREE_PROFILE)
  4926. {
  4927. ICMMSG(("IcmReleaseColorSpace: Free on memory profile\n"));
  4928. GlobalFree(pColorSpace->ColorProfile.pProfileData);
  4929. }
  4930. if (pColorSpace->flInfo & NEED_TO_DEL_PROFILE)
  4931. {
  4932. ICMMSG(("IcmReleaseColorSpace: Delete TempFile - %ws\n",
  4933. pColorSpace->LogColorSpace.lcsFilename));
  4934. DeleteFileW(pColorSpace->LogColorSpace.lcsFilename);
  4935. }
  4936. //
  4937. // Remove from list
  4938. //
  4939. RemoveEntryList(&(pColorSpace->ListEntry));
  4940. cCachedColorSpace--;
  4941. //
  4942. // Free colorspace.
  4943. //
  4944. LOCALFREE(pColorSpace);
  4945. }
  4946. else
  4947. {
  4948. ICMWRN(("IcmReleaseColorSpace: Still in USE - %ws\n", \
  4949. (pColorSpace->LogColorSpace.lcsFilename[0] ? \
  4950. pColorSpace->LogColorSpace.lcsFilename : L"no profile")));
  4951. }
  4952. }
  4953. LEAVECRITICALSECTION(&semColorSpaceCache);
  4954. }
  4955. }
  4956. /******************************Public*Routine******************************\
  4957. * IcmReleaseDCColorSpace
  4958. *
  4959. * Arguments:
  4960. *
  4961. * Return Value:
  4962. *
  4963. * History:
  4964. *
  4965. * Feb.17.1997 -by- Hideyuki Nagase [hideyukn]
  4966. *
  4967. \**************************************************************************/
  4968. VOID IcmReleaseDCColorSpace(
  4969. PGDI_ICMINFO pIcmInfo,
  4970. BOOL bReleaseDC
  4971. )
  4972. {
  4973. INT i = 0;
  4974. HDC hdc = pIcmInfo->hdc;
  4975. PCACHED_COLORSPACE DeleteColorSpaces[4];
  4976. ICMAPI(("gdi32: IcmReleaseDCColorSpace\n"));
  4977. ASSERTGDI(pIcmInfo != NULL,"IcmReleaseDCColorSpace pIcmInfo == NULL\n");
  4978. //
  4979. // Fill up the table to delete color color spaces.
  4980. //
  4981. DeleteColorSpaces[i++] = pIcmInfo->pSourceColorSpace;
  4982. if (bReleaseDC)
  4983. {
  4984. ICMMSG(("IcmReleaseDCColorSpace: Force Delete\n"));
  4985. //
  4986. // If we are in "force deletion" mode, don't delete twice.
  4987. // since if the color space owned by this HDC, and this DC is going to be
  4988. // deleted, we will delete the color space forcely.
  4989. //
  4990. if (IsColorSpaceOwnedByGDIObject(pIcmInfo->pDestColorSpace,hdc) &&
  4991. IcmSameColorSpace(pIcmInfo->pSourceColorSpace,pIcmInfo->pDestColorSpace))
  4992. {
  4993. ICMMSG(("IcmReleaseDCColorSpace: Force Delete - skip destination (same as source)\n"));
  4994. }
  4995. else
  4996. {
  4997. DeleteColorSpaces[i++] = pIcmInfo->pDestColorSpace;
  4998. }
  4999. if (IsColorSpaceOwnedByGDIObject(pIcmInfo->pTargetColorSpace,hdc) &&
  5000. (IcmSameColorSpace(pIcmInfo->pSourceColorSpace,pIcmInfo->pTargetColorSpace) ||
  5001. IcmSameColorSpace(pIcmInfo->pDestColorSpace,pIcmInfo->pTargetColorSpace)))
  5002. {
  5003. ICMMSG(("IcmReleaseDCColorSpace: Force Delete - skip target (same as source/dest)\n"));
  5004. }
  5005. else
  5006. {
  5007. DeleteColorSpaces[i++] = pIcmInfo->pTargetColorSpace;
  5008. }
  5009. }
  5010. else
  5011. {
  5012. DeleteColorSpaces[i++] = pIcmInfo->pDestColorSpace;
  5013. DeleteColorSpaces[i++] = pIcmInfo->pTargetColorSpace;
  5014. }
  5015. DeleteColorSpaces[i] = NULL;
  5016. for (i = 0; DeleteColorSpaces[i] != NULL; i++)
  5017. {
  5018. IcmReleaseColorSpace((HGDIOBJ)hdc,DeleteColorSpaces[i],bReleaseDC);
  5019. }
  5020. pIcmInfo->pSourceColorSpace = NULL;
  5021. pIcmInfo->pDestColorSpace = NULL;
  5022. pIcmInfo->pTargetColorSpace = NULL;
  5023. }
  5024. /******************************Public*Routine******************************\
  5025. * IcmInitIcmInfo()
  5026. *
  5027. * Arguments:
  5028. *
  5029. * Return Value:
  5030. *
  5031. * History:
  5032. *
  5033. * Jan.31,1997 -by- Hideyuki Nagase [hideyukn]
  5034. *
  5035. \**************************************************************************/
  5036. PGDI_ICMINFO
  5037. IcmInitIcmInfo(
  5038. HDC hdc,
  5039. PDC_ATTR pdcattr
  5040. )
  5041. {
  5042. ICMAPI(("gdi32: IcmInitIcmInfo\n"));
  5043. if (pdcattr == NULL)
  5044. {
  5045. WARNING("IcmInitIcmInfo():pdcattr is NULL\n");
  5046. return (NULL);
  5047. }
  5048. if (pdcattr->pvICM == NULL)
  5049. {
  5050. PGDI_ICMINFO pIcmInfo = NULL;
  5051. PLDC pldc = (PLDC) pdcattr->pvLDC;
  5052. BOOL bDisplay = ((pldc && pldc->hSpooler) ? FALSE : TRUE);
  5053. BOOL bInsertList = bDisplay;
  5054. ENTERCRITICALSECTION(&semListIcmInfo);
  5055. //
  5056. // First try to get ICMINFO from list. if not nothing can be re-used,
  5057. // allocate new one.
  5058. //
  5059. if (bDisplay)
  5060. {
  5061. if ((pIcmInfo = IcmGetUnusedIcmInfo(hdc)) != NULL)
  5062. {
  5063. LIST_ENTRY ListEntry;
  5064. //
  5065. // Save ListEntry.
  5066. //
  5067. ListEntry = pIcmInfo->ListEntry;
  5068. //
  5069. // Init with zero.
  5070. //
  5071. RtlZeroMemory(pIcmInfo,sizeof(GDI_ICMINFO));
  5072. //
  5073. // Restore ListEntry
  5074. //
  5075. pIcmInfo->ListEntry = ListEntry;
  5076. //
  5077. // This ICMInfo already on list, don't need to insert.
  5078. //
  5079. bInsertList = FALSE;
  5080. //
  5081. // Mark this cell in on ListIcmInfo.
  5082. //
  5083. pIcmInfo->flInfo = ICM_ON_ICMINFO_LIST;
  5084. ICMMSG(("IcmInitIcmInfo():Get unused ICMINFO structure = %p\n",pIcmInfo));
  5085. }
  5086. }
  5087. if (pIcmInfo == NULL)
  5088. {
  5089. //
  5090. // ICMINFO is not allocated, yet. then allocate it.
  5091. //
  5092. pIcmInfo = (PGDI_ICMINFO) LOCALALLOC(sizeof(GDI_ICMINFO));
  5093. //
  5094. // Init with zero.
  5095. //
  5096. if (pIcmInfo != NULL) {
  5097. RtlZeroMemory(pIcmInfo,sizeof(GDI_ICMINFO));
  5098. }
  5099. ICMMSG(("IcmInitIcmInfo():Allocate new ICMINFO structure = %p\n",pIcmInfo));
  5100. }
  5101. if (pIcmInfo)
  5102. {
  5103. PDEVMODEW pDevModeW = NULL;
  5104. //
  5105. // Set owner information (hdc and pdcattr).
  5106. //
  5107. pIcmInfo->hdc = hdc;
  5108. pIcmInfo->pvdcattr = (PVOID) pdcattr;
  5109. //
  5110. // initialize LIST_ENTRY for saved icm info.
  5111. //
  5112. InitializeListHead(&(pIcmInfo->SavedIcmInfo));
  5113. //
  5114. // Default is LCS_DEFAULT_INTENT (aka LCS_GM_IMAGES)
  5115. //
  5116. pIcmInfo->dwDefaultIntent = LCS_DEFAULT_INTENT;
  5117. //
  5118. // If this is printer, set default Intent from devmode.
  5119. //
  5120. if (pldc && pldc->hSpooler)
  5121. {
  5122. PVOID pvFree = NULL;
  5123. if (pldc->pDevMode)
  5124. {
  5125. pDevModeW = pldc->pDevMode;
  5126. }
  5127. else
  5128. {
  5129. pDevModeW = pdmwGetDefaultDevMode(pldc->hSpooler,NULL,&pvFree);
  5130. }
  5131. if (pDevModeW && (pDevModeW->dmFields & DM_ICMINTENT))
  5132. {
  5133. DWORD dwIntent = pDevModeW->dmICMIntent;
  5134. ICMMSG(("IcmInitIcmInfo():Intent in devmode = %d\n",dwIntent));
  5135. //
  5136. // Convert intent for devmode to intent for LOGCOLORSPACE.
  5137. //
  5138. switch (dwIntent)
  5139. {
  5140. case DMICM_SATURATE:
  5141. pIcmInfo->dwDefaultIntent = LCS_GM_BUSINESS;
  5142. break;
  5143. case DMICM_COLORIMETRIC:
  5144. pIcmInfo->dwDefaultIntent = LCS_GM_GRAPHICS;
  5145. break;
  5146. case DMICM_ABS_COLORIMETRIC:
  5147. pIcmInfo->dwDefaultIntent = LCS_GM_ABS_COLORIMETRIC;
  5148. break;
  5149. case DMICM_CONTRAST:
  5150. default:
  5151. pIcmInfo->dwDefaultIntent = LCS_DEFAULT_INTENT;
  5152. break;
  5153. }
  5154. }
  5155. ICMMSG(("IcmInitIcmInfo():Default Intent = %d\n",pIcmInfo->dwDefaultIntent));
  5156. //
  5157. // Free devmode buffer.
  5158. //
  5159. if (pvFree)
  5160. {
  5161. LOCALFREE(pvFree);
  5162. }
  5163. }
  5164. //
  5165. // Only ICMINFO for Display ICM put on to the list.
  5166. //
  5167. if (bInsertList)
  5168. {
  5169. //
  5170. // This ICMINFO is newly allocated, so put this on list.
  5171. //
  5172. InsertTailList(&ListIcmInfo,&(pIcmInfo->ListEntry));
  5173. //
  5174. // Mark this cell in on ListIcmInfo.
  5175. //
  5176. pIcmInfo->flInfo |= ICM_ON_ICMINFO_LIST;
  5177. }
  5178. }
  5179. //
  5180. // Store pointer to ICMINFO to DC_ATTR.
  5181. //
  5182. pdcattr->pvICM = (PVOID) pIcmInfo;
  5183. LEAVECRITICALSECTION(&semListIcmInfo);
  5184. }
  5185. return ((PGDI_ICMINFO)(pdcattr->pvICM));
  5186. }
  5187. /******************************Public*Routine******************************\
  5188. * IcmGetUnusedIcmInfo()
  5189. *
  5190. * ATTENTION: semListIcmInfo should be held by caller
  5191. *
  5192. * History:
  5193. * 17-Feb-1999 -by- Hideyuki Nagase [hideyukn]
  5194. \**************************************************************************/
  5195. PGDI_ICMINFO
  5196. IcmGetUnusedIcmInfo(
  5197. HDC hdcNew
  5198. )
  5199. {
  5200. PLIST_ENTRY p;
  5201. PGDI_ICMINFO pInvalidIcmInfo = NULL;
  5202. ICMAPI(("gdi32: IcmGetUnusedIcmInfo\n"));
  5203. p = ListIcmInfo.Flink;
  5204. //
  5205. // First Loop - Find ICMINFO which has same hdc.
  5206. //
  5207. while(p != &ListIcmInfo)
  5208. {
  5209. pInvalidIcmInfo = CONTAINING_RECORD(p,GDI_ICMINFO,ListEntry);
  5210. if (pInvalidIcmInfo->flInfo & ICM_IN_USE)
  5211. {
  5212. //
  5213. // Skip this one, since it's under initializing.
  5214. //
  5215. }
  5216. else
  5217. {
  5218. //
  5219. // If this is same hdc, break.
  5220. //
  5221. if (pInvalidIcmInfo->hdc == hdcNew)
  5222. {
  5223. ICMMSG(("IcmGetUnusedIcmInfo(): ICMINFO at %p is invalid (same hdc)\n",
  5224. pInvalidIcmInfo));
  5225. //
  5226. // break loop.
  5227. //
  5228. break;
  5229. }
  5230. }
  5231. //
  5232. // Move on next.
  5233. //
  5234. p = p->Flink;
  5235. pInvalidIcmInfo = NULL;
  5236. }
  5237. //
  5238. // If not find in first loop, go to second loop.
  5239. //
  5240. if (pInvalidIcmInfo == NULL)
  5241. {
  5242. p = ListIcmInfo.Flink;
  5243. //
  5244. // Second Loop - Find unused ICMINFO.
  5245. //
  5246. while(p != &ListIcmInfo)
  5247. {
  5248. pInvalidIcmInfo = CONTAINING_RECORD(p,GDI_ICMINFO,ListEntry);
  5249. if (pInvalidIcmInfo->flInfo & ICM_IN_USE)
  5250. {
  5251. //
  5252. // Skip this one, since it's under initializing.
  5253. //
  5254. }
  5255. else
  5256. {
  5257. PDC_ATTR pdcattr;
  5258. //
  5259. // Make sure this ICMINFO and hdc is stil effective.
  5260. //
  5261. //
  5262. // Check below by calling PSHARED_GET_VALIDATE.
  5263. //
  5264. // 1) Is this DC handle ?
  5265. // 2) Is this DC handle belonging to this process ?
  5266. // 3) Does this DC has valid user mode DC_ATTR ?
  5267. //
  5268. PSHARED_GET_VALIDATE(pdcattr,pInvalidIcmInfo->hdc,DC_TYPE);
  5269. if (pdcattr == NULL)
  5270. {
  5271. ICMMSG(("IcmGetUnusedIcmInfo(): ICMINFO at %p is invalid (no pdcattr)\n",
  5272. pInvalidIcmInfo));
  5273. //
  5274. // break loop.
  5275. //
  5276. break;
  5277. }
  5278. else
  5279. {
  5280. //
  5281. // Make sure the pointer points each other.
  5282. //
  5283. if ((pdcattr->pvICM != pInvalidIcmInfo ) ||
  5284. (pdcattr != pInvalidIcmInfo->pvdcattr))
  5285. {
  5286. ICMMSG(("IcmGetUnusedIcmInfo(): ICMINFO at %p is invalid (pointer mismatch)\n",
  5287. pInvalidIcmInfo));
  5288. //
  5289. // break loop.
  5290. //
  5291. break;
  5292. }
  5293. }
  5294. }
  5295. //
  5296. // Move on next.
  5297. //
  5298. p = p->Flink;
  5299. pInvalidIcmInfo = NULL;
  5300. }
  5301. }
  5302. if (pInvalidIcmInfo)
  5303. {
  5304. //
  5305. // This ICMINFO is invalid, clean up this ICMINFO.
  5306. //
  5307. IcmCleanupIcmInfo(NULL,pInvalidIcmInfo);
  5308. }
  5309. else
  5310. {
  5311. ICMMSG(("IcmGetUnusedIcmInfo(): Unused ICMINFO is not in list\n"));
  5312. }
  5313. return (pInvalidIcmInfo);
  5314. }
  5315. /******************************Public*Routine******************************\
  5316. * IcmInitDC()
  5317. *
  5318. * Arguments:
  5319. *
  5320. * Return Value:
  5321. *
  5322. * History:
  5323. *
  5324. * Jan.31.1997 -by- Hideyuki Nagase [hideyukn]
  5325. *
  5326. \**************************************************************************/
  5327. BOOL
  5328. IcmInitLocalDC(
  5329. HDC hdc,
  5330. HANDLE hPrinter,
  5331. CONST DEVMODEW *pdm,
  5332. BOOL bReset
  5333. )
  5334. {
  5335. BOOL bRet = TRUE;
  5336. PDC_ATTR pdcattr;
  5337. PLDC pldc;
  5338. ICMAPI(("gdi32: IcmInitLocalDC\n"));
  5339. //
  5340. // all these stuff is for only Printer.
  5341. //
  5342. if (hPrinter == NULL)
  5343. {
  5344. return (TRUE);
  5345. }
  5346. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  5347. if (!pdcattr)
  5348. {
  5349. WARNING("IcmInitDC(): pdcattr is NULL\n");
  5350. return (FALSE);
  5351. }
  5352. if (bReset)
  5353. {
  5354. //
  5355. // Release existing ICMINFO
  5356. //
  5357. if (ghICM || BEXIST_ICMINFO(pdcattr))
  5358. {
  5359. //
  5360. // Delete ICM stuff in this DC.
  5361. //
  5362. IcmDeleteLocalDC(hdc,pdcattr,NULL);
  5363. }
  5364. }
  5365. if (!pdm)
  5366. {
  5367. //
  5368. // DEVMODE are not presented.
  5369. //
  5370. ICMMSG(("IcmInitLocalDC():DEVMODE is not presented\n"));
  5371. return (TRUE);
  5372. }
  5373. //
  5374. // Check pointer to DEVMODE is valid or not. Check validation until
  5375. // DEVMODE.dmSize first, then check whole devmode size specified in dmSize.
  5376. //
  5377. if (IsBadReadPtr((CONST VOID *)pdm, offsetof(DEVMODEW,dmDriverExtra)) ||
  5378. IsBadReadPtr((CONST VOID *)pdm, pdm->dmSize))
  5379. {
  5380. WARNING("IcmInitLocalDC(): Invalid pointer given as PDEVMODEW\n");
  5381. return (FALSE);
  5382. }
  5383. //
  5384. // Check color or mono mode.
  5385. //
  5386. if ((pdm->dmFields & DM_COLOR) && (pdm->dmColor == DMCOLOR_MONOCHROME))
  5387. {
  5388. //
  5389. // This is monochrome mode, don't enable ICM as default.
  5390. // And NEVER enable ICM.
  5391. //
  5392. ICMMSG(("IcmInitLocalDC():DEVMODE says MONOCHROME mode\n"));
  5393. return (TRUE);
  5394. }
  5395. //
  5396. // ATTENTION: AFTER HERE, WE HAVE A DEVMODE WHICH POSSIBLE TO ENABLE ICM LATER OR NOW.
  5397. //
  5398. //
  5399. // Check DM fields
  5400. //
  5401. if (!(pdm->dmFields & DM_ICMMETHOD))
  5402. {
  5403. //
  5404. // DEVMODE does not have ICMMETHOD.
  5405. //
  5406. ICMMSG(("IcmInitLocalDC():DEVMODE does not have ICMMETHOD\n"));
  5407. return (TRUE);
  5408. }
  5409. //
  5410. // NOTE:
  5411. //
  5412. // DEVMODEW structure.
  5413. //
  5414. // ... [omitted]
  5415. // DWORD dmDisplayFrequency;
  5416. // #if(WINVER >= 0x0400)
  5417. // DWORD dmICMMethod; // Windows 95 only / Windows NT 5.0
  5418. // DWORD dmICMIntent; // Windows 95 only / Windows NT 5.0
  5419. // DWORD dmMediaType; // Windows 95 only / Windows NT 5.0
  5420. // ....
  5421. //
  5422. // Then DEVMODE structure should be larger than offset of dmMediaType
  5423. // to access ICM stuff.
  5424. //
  5425. if (pdm->dmSize < offsetof(DEVMODEW,dmMediaType))
  5426. {
  5427. //
  5428. // DEVMODE version might not matched.
  5429. //
  5430. WARNING("IcmInitLocalDC():DEVMODE is small\n");
  5431. return (TRUE);
  5432. }
  5433. //
  5434. // Check requested ICM mode.
  5435. //
  5436. switch (pdm->dmICMMethod)
  5437. {
  5438. case DMICMMETHOD_NONE:
  5439. ICMMSG(("IcmInitDC(): ICM is disabled by default\n"));
  5440. //
  5441. // ICM is not enabled at this time.
  5442. //
  5443. // no more process is needed, just return here...
  5444. //
  5445. return (TRUE);
  5446. case DMICMMETHOD_SYSTEM:
  5447. ICMMSG(("IcmInitDC(): HOST ICM is requested\n"));
  5448. //
  5449. // ICM on Host, is requested.
  5450. //
  5451. SET_HOST_ICM_DEVMODE(pdcattr->lIcmMode);
  5452. break;
  5453. case DMICMMETHOD_DRIVER:
  5454. case DMICMMETHOD_DEVICE:
  5455. ICMMSG(("IcmInitDC(): DEVICE ICM is requested\n"));
  5456. //
  5457. // ICM on device, is requested.
  5458. //
  5459. SET_DEVICE_ICM_DEVMODE(pdcattr->lIcmMode);
  5460. break;
  5461. default:
  5462. //
  5463. // And we treat as Device ICM greater DMICMMETHOD_USER also.
  5464. //
  5465. if (pdm->dmICMMethod >= DMICMMETHOD_USER)
  5466. {
  5467. ICMMSG(("IcmInitDC(): DEVICE ICM (USER) is requested\n"));
  5468. //
  5469. // ICM on device (user defined), is requested.
  5470. //
  5471. SET_DEVICE_ICM_DEVMODE(pdcattr->lIcmMode);
  5472. }
  5473. else
  5474. {
  5475. ICMMSG(("IcmInitDC(): Unknown ICM mode\n"));
  5476. //
  5477. // return with error.
  5478. //
  5479. return (FALSE);
  5480. }
  5481. break;
  5482. }
  5483. //
  5484. // Finally, enabled ICM.
  5485. //
  5486. bRet = SetICMMode(hdc,ICM_ON);
  5487. if (!bRet)
  5488. {
  5489. ICMWRN(("InitLocalDC():FAILED to turn on ICM\n"));
  5490. }
  5491. return (bRet);
  5492. }
  5493. /******************************Public*Routine******************************\
  5494. * IcmUpdateDCColorInfo()
  5495. *
  5496. * Arguments:
  5497. *
  5498. * Return Value:
  5499. *
  5500. * History:
  5501. *
  5502. * May.28.1997 -by- Hideyuki Nagase [hideyukn]
  5503. *
  5504. \**************************************************************************/
  5505. BOOL
  5506. IcmUpdateDCColorInfo(
  5507. HDC hdc,
  5508. PDC_ATTR pdcattr
  5509. )
  5510. {
  5511. BOOL bRet = TRUE;
  5512. PGDI_ICMINFO pIcmInfo;
  5513. ICMAPI(("gdi32: IcmUpdateDCColorInfo\n"));
  5514. pIcmInfo = GET_ICMINFO(pdcattr);
  5515. ASSERTGDI(pIcmInfo != NULL,"IcmUpdateDCColorInfo(): pIcmInfo == NULL\n");
  5516. //
  5517. // Get the ColorSpace for this DC.
  5518. //
  5519. if (!IcmUpdateLocalDCColorSpace(hdc,pdcattr))
  5520. {
  5521. return (FALSE);
  5522. }
  5523. if ((pIcmInfo->pCXform == NULL) || (pdcattr->ulDirty_ & DIRTY_COLORTRANSFORM))
  5524. {
  5525. //
  5526. // if TRUE in above, new color space (or no) has been selected,
  5527. // then updates color transforms.
  5528. //
  5529. PCACHED_COLORTRANSFORM pCXform;
  5530. //
  5531. // At this momernt, we should have destination color space.
  5532. // if this is null, we may fail to update color space in
  5533. // IcmUpdateLocalDCColorSpace()
  5534. //
  5535. if (pIcmInfo->pDestColorSpace)
  5536. {
  5537. //
  5538. // Create the color transform.
  5539. //
  5540. pCXform = IcmCreateColorTransform(hdc,pdcattr,NULL,ICM_FORWARD);
  5541. if (pCXform)
  5542. {
  5543. if (pCXform == IDENT_COLORTRANSFORM)
  5544. {
  5545. ICMMSG(("IcmUpdateDCInfo():Input & Output colorspace is same\n"));
  5546. //
  5547. // Input and Output colorspace is same, could be optimize.
  5548. //
  5549. //
  5550. // Set new color transform to DC.
  5551. //
  5552. IcmSelectColorTransform(hdc,pdcattr,NULL,
  5553. bDeviceCalibrate(pIcmInfo->pDestColorSpace));
  5554. //
  5555. // Delete cached dirty color transform, if we have.
  5556. //
  5557. IcmDeleteDCColorTransforms(pIcmInfo);
  5558. //
  5559. // Set new color transform to ICMINFO.
  5560. //
  5561. pIcmInfo->pCXform = NULL;
  5562. }
  5563. else
  5564. {
  5565. //
  5566. // Select the color transform to DC.
  5567. //
  5568. IcmSelectColorTransform(hdc,pdcattr,pCXform,
  5569. bDeviceCalibrate(pCXform->DestinationColorSpace));
  5570. //
  5571. // Delete cached dirty color transform, if we have.
  5572. //
  5573. IcmDeleteDCColorTransforms(pIcmInfo);
  5574. //
  5575. // Set new color transform to ICMINFO.
  5576. //
  5577. pIcmInfo->pCXform = pCXform;
  5578. //
  5579. // Translate all DC objects to ICM colors. Must
  5580. // force brush/pens to be re-realized when used next
  5581. //
  5582. IcmTranslateColorObjects(hdc,pdcattr,TRUE);
  5583. }
  5584. }
  5585. else
  5586. {
  5587. WARNING("IcmUpdateDCInfo():CreateColorTransform failed\n");
  5588. //
  5589. // Fail to create new transform, keep as is.
  5590. //
  5591. bRet = FALSE;
  5592. }
  5593. }
  5594. else
  5595. {
  5596. WARNING("IcmUpdateDCInfo():No destination color space\n");
  5597. bRet = FALSE;
  5598. }
  5599. }
  5600. else
  5601. {
  5602. ICMMSG(("IcmUpdateDCColorInfo(): Color space does not change or not found\n"));
  5603. }
  5604. return (bRet);
  5605. }
  5606. /******************************Public*Routine******************************\
  5607. * IcmUpdateLocalDCColorSpace
  5608. *
  5609. * Arguments:
  5610. *
  5611. * Return Value:
  5612. *
  5613. * History:
  5614. *
  5615. * 26.Feb.1997 -by- Hideyuki Nagase [hideyukn]
  5616. *
  5617. \**************************************************************************/
  5618. BOOL
  5619. IcmUpdateLocalDCColorSpace(
  5620. HDC hdc,
  5621. PDC_ATTR pdcattr
  5622. )
  5623. {
  5624. BOOL bRet = FALSE;
  5625. BOOL bDirtyXform = FALSE;
  5626. PLDC pldc;
  5627. PGDI_ICMINFO pIcmInfo;
  5628. WCHAR ProfileName[MAX_PATH];
  5629. DWORD dwColorSpaceFlag;
  5630. PCACHED_COLORSPACE pNewColorSpace = NULL;
  5631. ICMAPI(("gdi32: IcmUpdateLocalDCColorSpace\n"));
  5632. ASSERTGDI(pdcattr != NULL,"IcmUpdateLocalDCColorSpace(): pdcattr == NULL\n");
  5633. pldc = pdcattr->pvLDC;
  5634. pIcmInfo = GET_ICMINFO(pdcattr);
  5635. ASSERTGDI(pIcmInfo != NULL,"IcmUpdateLocalDCColorSpace(): pIcmInfo == NULL\n");
  5636. //
  5637. // if the DC already has a destination colorspace, then return TRUE
  5638. //
  5639. if ((pIcmInfo->pDestColorSpace == NULL) || (pdcattr->ulDirty_ & DIRTY_COLORSPACE))
  5640. {
  5641. HCOLORSPACE hDIBColorSpace;
  5642. //
  5643. // Invalidate profilename.
  5644. //
  5645. ProfileName[0] = UNICODE_NULL;
  5646. dwColorSpaceFlag = 0;
  5647. hDIBColorSpace = NULL;
  5648. //
  5649. // if the target DC has DIBSection. it will be DIBsection's color space
  5650. // OR sRGB color space.
  5651. //
  5652. if (bDIBSectionSelected(pdcattr))
  5653. {
  5654. ENTERCRITICALSECTION(&semColorSpaceCache);
  5655. if (pdcattr->dwDIBColorSpace)
  5656. {
  5657. ICMMSG(("IcmUpdateLocalDCColorSpace(): DIB section in DC (V4/V5)\n"));
  5658. //
  5659. // The DIB currently selected, has thier own color space.
  5660. // This case happens when CreateDIBSection called with
  5661. // BITMAPV4/V5 header.
  5662. //
  5663. pNewColorSpace = (PCACHED_COLORSPACE) pdcattr->dwDIBColorSpace;
  5664. //
  5665. // Inc. ref. count.
  5666. //
  5667. pNewColorSpace->cRef++;
  5668. }
  5669. else
  5670. {
  5671. ICMMSG(("IcmUpdateLocalDCColorSpace(): DIB section in DC (no color space)\n"));
  5672. // [This is Win98 compatible behave]
  5673. //
  5674. // If the DIBitmap does not have any specific color space,
  5675. // keep same color space as current DC.
  5676. //
  5677. }
  5678. LEAVECRITICALSECTION(&semColorSpaceCache);
  5679. }
  5680. else if ((pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY) &&
  5681. (PrimaryDisplayProfile[0] != UNICODE_NULL))
  5682. {
  5683. //
  5684. // Use cached color profile.
  5685. //
  5686. lstrcpyW(ProfileName,PrimaryDisplayProfile);
  5687. }
  5688. else if (pIcmInfo->flInfo & ICM_VALID_DEFAULT_PROFILE)
  5689. {
  5690. //
  5691. // Use cached color profile.
  5692. //
  5693. lstrcpyW(ProfileName,pIcmInfo->DefaultDstProfile);
  5694. }
  5695. else
  5696. {
  5697. int iRet;
  5698. //
  5699. // Still couldn't find yet ??. Ask MSCMS to find out profile. (go slow way)
  5700. //
  5701. iRet = IcmEnumColorProfile(hdc,IcmFindProfileCallBack,
  5702. (LPARAM)ProfileName,FALSE,NULL,&dwColorSpaceFlag);
  5703. //
  5704. // if you could not find any profile for this DC, just use sRGB.
  5705. //
  5706. if ((iRet == -1) || (ProfileName[0] == UNICODE_NULL))
  5707. {
  5708. ULONG ulSize = MAX_PATH;
  5709. if (!(*fpGetStandardColorSpaceProfileW)(NULL,LCS_sRGB,ProfileName,&ulSize))
  5710. {
  5711. ICMMSG(("IcmUpdateLocalDCColorSpace():Fail to SCS(sRGB), use hardcode\n"));
  5712. //
  5713. // If error, use hardcoded profile name.
  5714. //
  5715. wcscpy(ProfileName,sRGB_PROFILENAME);
  5716. }
  5717. }
  5718. //
  5719. // Create cache for next usage
  5720. //
  5721. if ((pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY) &&
  5722. (PrimaryDisplayProfile[0] == UNICODE_NULL))
  5723. {
  5724. lstrcpyW(PrimaryDisplayProfile,ProfileName);
  5725. }
  5726. else // otherwise put it into default profile.
  5727. {
  5728. lstrcpyW(pIcmInfo->DefaultDstProfile,ProfileName);
  5729. pIcmInfo->flInfo |= (ICM_VALID_DEFAULT_PROFILE|
  5730. ICM_VALID_CURRENT_PROFILE);
  5731. }
  5732. }
  5733. //
  5734. // If default device profile could be found, associate it into this DC.
  5735. //
  5736. if ((ProfileName[0] != UNICODE_NULL) || (pNewColorSpace != NULL))
  5737. {
  5738. #if DBG
  5739. if (ProfileName[0] != UNICODE_NULL)
  5740. {
  5741. ICMMSG(("IcmUpdateLocalDCColorSpace():Default Device Profile = %ws\n",ProfileName));
  5742. }
  5743. #endif
  5744. //
  5745. // try to find desired color space from cache.
  5746. //
  5747. if (pNewColorSpace == NULL)
  5748. {
  5749. pNewColorSpace = IcmGetColorSpaceByName(
  5750. (HGDIOBJ)hdc,
  5751. ProfileName,
  5752. pIcmInfo->dwDefaultIntent,
  5753. dwColorSpaceFlag);
  5754. if (pNewColorSpace == NULL)
  5755. {
  5756. //
  5757. // create new one.
  5758. //
  5759. pNewColorSpace = IcmCreateColorSpaceByName(
  5760. (HGDIOBJ)hdc,
  5761. ProfileName,
  5762. pIcmInfo->dwDefaultIntent,
  5763. dwColorSpaceFlag);
  5764. }
  5765. }
  5766. if (pNewColorSpace)
  5767. {
  5768. //
  5769. // Is this same destination color space as currently selected in DC ?
  5770. //
  5771. if (IcmSameColorSpace(pNewColorSpace,pIcmInfo->pDestColorSpace))
  5772. {
  5773. ICMMSG(("IcmUpdateLocalDCColorSpace():Same color space is selected already\n"));
  5774. //
  5775. // Color space does NOT changed.
  5776. //
  5777. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  5778. bRet = TRUE;
  5779. }
  5780. else
  5781. {
  5782. //
  5783. // Notify new color format to kernel.
  5784. //
  5785. if (NtGdiSetIcmMode(hdc,ICM_CHECK_COLOR_MODE,pNewColorSpace->ColorFormat))
  5786. {
  5787. //
  5788. // if we have some color space currently selected, delete it.
  5789. //
  5790. if (pIcmInfo->pDestColorSpace)
  5791. {
  5792. IcmReleaseColorSpace(NULL,pIcmInfo->pDestColorSpace,FALSE);
  5793. }
  5794. //
  5795. // DC can accept this color space, Set new colorspace to destination.
  5796. //
  5797. pIcmInfo->pDestColorSpace = pNewColorSpace;
  5798. //
  5799. // Color space is changed. so color transform should be updated.
  5800. //
  5801. bDirtyXform = TRUE;
  5802. bRet = TRUE;
  5803. }
  5804. else
  5805. {
  5806. WARNING("ICM:Detected colorspace was not accepted by target DC\n");
  5807. //
  5808. // This color space does not match to this DC.
  5809. //
  5810. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  5811. }
  5812. }
  5813. }
  5814. else
  5815. {
  5816. WARNING("Failed IcmUpdateLocalDCColorSpace(), Failed to create new color space.\n");
  5817. }
  5818. }
  5819. else
  5820. {
  5821. WARNING("Failed IcmUpdateLocalDCColorSpace(), no device profile is detected.\n");
  5822. }
  5823. }
  5824. else
  5825. {
  5826. ICMMSG(("IcmUpdateLocalDCColoSpace(): Destination Color Space cache is valid\n"));
  5827. bRet = TRUE;
  5828. }
  5829. //
  5830. // [Only for Printer]
  5831. //
  5832. // If we haven't asked default source color profile for this Printer DC,
  5833. // Now is the time to ask it. Only do this when apps does NOT specified
  5834. // thier own color space.
  5835. //
  5836. if (bRet && pldc && pldc->hSpooler)
  5837. {
  5838. if ((pdcattr->hColorSpace == GetStockObject(PRIV_STOCK_COLORSPACE)) &&
  5839. (pIcmInfo->hDefaultSrcColorSpace == NULL))
  5840. {
  5841. PDEVMODEW pDevModeW = NULL;
  5842. PVOID pvFree = NULL;
  5843. BOOL bRetSource = FALSE;
  5844. //
  5845. // Default is no DC specific source color space (= INVALID_COLORSPACE),
  5846. // this also make sure we will not come here again.
  5847. //
  5848. pIcmInfo->hDefaultSrcColorSpace = INVALID_COLORSPACE;
  5849. //
  5850. // Invalidate profilename.
  5851. //
  5852. ProfileName[0] = UNICODE_NULL;
  5853. dwColorSpaceFlag = 0;
  5854. if (pldc->pDevMode)
  5855. {
  5856. ICMMSG(("IcmUpdateLocalDCColorSpace():Cached DEVMODE used\n"));
  5857. pDevModeW = pldc->pDevMode;
  5858. }
  5859. else
  5860. {
  5861. ICMMSG(("IcmUpdateLocalDCColorSpace():Get default DEVMODE\n"));
  5862. pDevModeW = pdmwGetDefaultDevMode(pldc->hSpooler,NULL,&pvFree);
  5863. }
  5864. if (pDevModeW)
  5865. {
  5866. //
  5867. // Get source color proflie from driver.
  5868. //
  5869. if (IcmAskDriverForColorProfile(pldc,QCP_SOURCEPROFILE,
  5870. pDevModeW,ProfileName,&dwColorSpaceFlag) <= 0)
  5871. {
  5872. //
  5873. // No source profile specified.
  5874. //
  5875. ProfileName[0] = UNICODE_NULL;
  5876. }
  5877. }
  5878. //
  5879. // Free devmode buffer.
  5880. //
  5881. if (pvFree)
  5882. {
  5883. LOCALFREE(pvFree);
  5884. }
  5885. //
  5886. // 1) If default source profile could be found, or
  5887. // 2) the default intent in devmode is different from LCS_DEFAULT_INTENT,
  5888. //
  5889. // we need to create new source color space, then associate it into this DC.
  5890. //
  5891. if ((ProfileName[0] != UNICODE_NULL) ||
  5892. (pIcmInfo->dwDefaultIntent != LCS_DEFAULT_INTENT))
  5893. {
  5894. HCOLORSPACE hColorSpace = NULL;
  5895. ICMMSG(("IcmUpdateLocalDCColorSpace():Default devmode Intent = %d\n",
  5896. pIcmInfo->dwDefaultIntent));
  5897. //
  5898. // If no color profile specified, use sRGB.
  5899. //
  5900. if (ProfileName[0] == UNICODE_NULL)
  5901. {
  5902. ULONG ulSize = MAX_PATH;
  5903. if (!(*fpGetStandardColorSpaceProfileW)(NULL,LCS_sRGB,ProfileName,&ulSize))
  5904. {
  5905. ICMMSG(("IcmUpdateLocalDCColorSpace():Fail to SCS(sRGB), use hardcode\n"));
  5906. //
  5907. // If error, use hardcoded profile name.
  5908. //
  5909. wcscpy(ProfileName,sRGB_PROFILENAME);
  5910. }
  5911. }
  5912. ICMMSG(("IcmUpdateLocalDCColorSpace():Default Source Profile = %ws\n",ProfileName));
  5913. //
  5914. // Find from cache first.
  5915. //
  5916. pNewColorSpace = IcmGetColorSpaceByName(
  5917. (HGDIOBJ)hdc,
  5918. ProfileName,
  5919. pIcmInfo->dwDefaultIntent,
  5920. dwColorSpaceFlag);
  5921. if (pNewColorSpace == NULL)
  5922. {
  5923. //
  5924. // create new one.
  5925. //
  5926. pNewColorSpace = IcmCreateColorSpaceByName(
  5927. (HGDIOBJ)hdc,
  5928. ProfileName,
  5929. pIcmInfo->dwDefaultIntent,
  5930. dwColorSpaceFlag);
  5931. }
  5932. if (pNewColorSpace)
  5933. {
  5934. //
  5935. // Create kernel-mode handle.
  5936. //
  5937. hColorSpace = CreateColorSpaceW(&(pNewColorSpace->LogColorSpace));
  5938. if (hColorSpace)
  5939. {
  5940. //
  5941. // Select this into DC.
  5942. //
  5943. if (IcmSetSourceColorSpace(hdc,hColorSpace,pNewColorSpace,0))
  5944. {
  5945. //
  5946. // IcmSetSourceColorSpace increments ref. count of colorspace.
  5947. // but we have done it by Icm[Get|Create]ColorSpaceByName, so
  5948. // decrement ref count of color space here.
  5949. //
  5950. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  5951. //
  5952. // Keep these into ICMINFO.
  5953. //
  5954. pIcmInfo->hDefaultSrcColorSpace = hColorSpace;
  5955. //
  5956. // This color space should be deleted later.
  5957. //
  5958. pIcmInfo->flInfo |= ICM_DELETE_SOURCE_COLORSPACE;
  5959. //
  5960. // Source color space has been changed.
  5961. // (color transform is updated inside IcmSetSourceColorSpace().
  5962. // so not nessesary to set bDirtyXfrom to TRUE)
  5963. //
  5964. bRetSource = TRUE;
  5965. }
  5966. else
  5967. {
  5968. WARNING("Failed IcmUpdateLocalDCColorSpace(), Failed to select new source color space.\n");
  5969. }
  5970. }
  5971. else
  5972. {
  5973. WARNING("Failed IcmUpdateLocalDCColorSpace(), Failed to create new source color space.\n");
  5974. }
  5975. }
  5976. else
  5977. {
  5978. WARNING("Failed IcmUpdateLocalDCColorSpace(), Failed to create new source color space cache.\n");
  5979. }
  5980. if (!bRetSource)
  5981. {
  5982. if (hColorSpace)
  5983. {
  5984. DeleteColorSpace(hColorSpace);
  5985. }
  5986. if (pNewColorSpace)
  5987. {
  5988. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  5989. }
  5990. }
  5991. }
  5992. else
  5993. {
  5994. ICMMSG(("IcmUpdateLocalDCColoSpace(): No default source color Space cache specified\n"));
  5995. }
  5996. }
  5997. }
  5998. //
  5999. // Now color space is valid.
  6000. //
  6001. if (bRet)
  6002. {
  6003. pdcattr->ulDirty_ &= ~DIRTY_COLORSPACE;
  6004. }
  6005. if (bDirtyXform)
  6006. {
  6007. pdcattr->ulDirty_ |= DIRTY_COLORTRANSFORM;
  6008. }
  6009. return (bRet);
  6010. }
  6011. /******************************Public*Routine******************************\
  6012. * IcmCleanupIcmInfo()
  6013. *
  6014. * ATTENTION: semListIcmInfo must be hold by caller
  6015. *
  6016. * History:
  6017. * 16-Feb-1999 -by- Hideyuki Nagase [hideyukn]
  6018. \**************************************************************************/
  6019. BOOL
  6020. IcmCleanupIcmInfo(
  6021. PDC_ATTR pdcattr, // This can be NULL for clean up case.
  6022. PGDI_ICMINFO pIcmInfo // This can *NOT* be NULL at any rate.
  6023. )
  6024. {
  6025. if (ghICM)
  6026. {
  6027. //
  6028. // Delete Saved ICMINFO data (if present)
  6029. //
  6030. IcmRestoreDC(pdcattr,1,pIcmInfo);
  6031. }
  6032. //
  6033. // If there is any default source profile (kernel-side), do something here.
  6034. //
  6035. if ((pIcmInfo->hDefaultSrcColorSpace != NULL) &&
  6036. (pIcmInfo->hDefaultSrcColorSpace != INVALID_COLORSPACE))
  6037. {
  6038. ICMMSG(("IcmCleanupIcmInfo():Delete/Unselect default source color space\n"));
  6039. if (pdcattr)
  6040. {
  6041. //
  6042. // If it is currently selected into this DC, un-select it.
  6043. //
  6044. if (pIcmInfo->hDefaultSrcColorSpace == pdcattr->hColorSpace)
  6045. {
  6046. NtGdiSetColorSpace(pIcmInfo->hdc,GetStockObject(PRIV_STOCK_COLORSPACE));
  6047. }
  6048. }
  6049. //
  6050. // And it should be delete it.
  6051. //
  6052. if (pIcmInfo->flInfo & ICM_DELETE_SOURCE_COLORSPACE)
  6053. {
  6054. DeleteColorSpace(pIcmInfo->hDefaultSrcColorSpace);
  6055. }
  6056. pIcmInfo->hDefaultSrcColorSpace = NULL;
  6057. }
  6058. if (ghICM)
  6059. {
  6060. //
  6061. // Delete Color transforms
  6062. //
  6063. IcmDeleteDCColorTransforms(pIcmInfo);
  6064. //
  6065. // Delete Cached color transform related to this DC.
  6066. // (like device color transform)
  6067. //
  6068. IcmDeleteCachedColorTransforms(pIcmInfo->hdc);
  6069. //
  6070. // Free ICM colorspace datas.
  6071. //
  6072. IcmReleaseDCColorSpace(pIcmInfo,TRUE);
  6073. //
  6074. // Delete Cached color space which related to this DC.
  6075. // (like color space in metafile)
  6076. //
  6077. IcmReleaseCachedColorSpace((HGDIOBJ)(pIcmInfo->hdc));
  6078. }
  6079. pIcmInfo->hdc = NULL;
  6080. pIcmInfo->pvdcattr = NULL;
  6081. pIcmInfo->flInfo = 0;
  6082. return(TRUE);
  6083. }
  6084. /******************************Public*Routine******************************\
  6085. * IcmDeleteLocalDC()
  6086. *
  6087. * Arguments:
  6088. *
  6089. * Return Value:
  6090. *
  6091. * History:
  6092. *
  6093. * Jan.31.1997 -by- Hideyuki Nagase [hideyukn]
  6094. \**************************************************************************/
  6095. BOOL
  6096. IcmDeleteLocalDC(
  6097. HDC hdc,
  6098. PDC_ATTR pdcattr,
  6099. PGDI_ICMINFO pIcmInfo
  6100. )
  6101. {
  6102. ICMAPI(("gdi32: IcmDeleteLocalDC\n"));
  6103. ASSERTGDI(pdcattr != NULL,"IcmDeleteLocalDC():pdcattr == NULL\n");
  6104. //
  6105. // If callee does not provide ICMINFO, get it from pdcattr.
  6106. //
  6107. if (pIcmInfo == NULL)
  6108. {
  6109. pIcmInfo = GET_ICMINFO(pdcattr);
  6110. }
  6111. //
  6112. // Invalidate current color tansform.
  6113. //
  6114. // (but the cache in ICMINFO is still valid, and will be delete
  6115. // inside IcmDeleteDCColorTransforms() called from IcmCleanupIcmInfo().)
  6116. //
  6117. IcmSelectColorTransform(hdc,pdcattr,NULL,TRUE);
  6118. if (IS_ICM_INSIDEDC(pdcattr->lIcmMode))
  6119. {
  6120. //
  6121. // Tell the kernel to disable ICM before delete client side data.
  6122. //
  6123. NtGdiSetIcmMode(hdc,ICM_SET_MODE,REQ_ICM_OFF);
  6124. }
  6125. //
  6126. // Clean up ICMINFO.
  6127. //
  6128. if (pIcmInfo != NULL)
  6129. {
  6130. ENTERCRITICALSECTION(&semListIcmInfo);
  6131. if (pIcmInfo->flInfo & ICM_ON_ICMINFO_LIST)
  6132. {
  6133. //
  6134. // Remove this ICMINFO from list. (since this will be deleted).
  6135. //
  6136. RemoveEntryList(&(pIcmInfo->ListEntry));
  6137. }
  6138. //
  6139. // Clean up ICMINFO.
  6140. //
  6141. IcmCleanupIcmInfo(pdcattr,pIcmInfo);
  6142. //
  6143. // Invalidate ICM info in DC_ATTR.
  6144. //
  6145. pdcattr->pvICM = NULL;
  6146. LEAVECRITICALSECTION(&semListIcmInfo);
  6147. //
  6148. // Free ICM structure.
  6149. //
  6150. LOCALFREE(pIcmInfo);
  6151. }
  6152. return(TRUE);
  6153. }
  6154. /******************************Public*Routine******************************\
  6155. * BOOL IcmSelectColorTransform (HDC, PDC_ATTR, PCACHED_COLORTRANSFORM)
  6156. *
  6157. * History:
  6158. * 23-Sep-1997 -by- Hideyuki Nagase [hideyukn]
  6159. * Wrote it.
  6160. \**************************************************************************/
  6161. BOOL
  6162. IcmSelectColorTransform(
  6163. HDC hdc,
  6164. PDC_ATTR pdcattr,
  6165. PCACHED_COLORTRANSFORM pCXform,
  6166. BOOL bDeviceCalibrate)
  6167. {
  6168. if (pCXform)
  6169. {
  6170. BMFORMAT ColorFormat = pCXform->DestinationColorSpace->ColorFormat;
  6171. // LATER :
  6172. //
  6173. // if (GET_COLORTYPE(pdcattr->lIcmMode) != IcmConvertColorFormat(ColorFormat))
  6174. //
  6175. if (TRUE)
  6176. {
  6177. if (!NtGdiSetIcmMode(hdc,ICM_SET_COLOR_MODE,ColorFormat))
  6178. {
  6179. //
  6180. // The transform color format is not accepted by DC.
  6181. //
  6182. return (FALSE);
  6183. }
  6184. }
  6185. //
  6186. // Select into the color transform to DC_ATTR.
  6187. //
  6188. pdcattr->hcmXform = pCXform->ColorTransform;
  6189. }
  6190. else
  6191. {
  6192. //
  6193. // If curent color type is not RGB, call kernel to reset.
  6194. //
  6195. if (GET_COLORTYPE(pdcattr->lIcmMode) != DC_ICM_RGB_COLOR)
  6196. {
  6197. //
  6198. // Reset current color mode to RGB (default).
  6199. //
  6200. NtGdiSetIcmMode(hdc,ICM_SET_COLOR_MODE,BM_xBGRQUADS);
  6201. }
  6202. //
  6203. // Select null-color transfrom into the DC_ATTR.
  6204. //
  6205. pdcattr->hcmXform = NULL;
  6206. }
  6207. //
  6208. // If device calibration mode need to updated, call kernel to update it.
  6209. //
  6210. if ((bDeviceCalibrate ? 1 : 0) !=
  6211. (IS_ICM_DEVICE_CALIBRATE(pdcattr->lIcmMode) ? 1 : 0))
  6212. {
  6213. NtGdiSetIcmMode(hdc,ICM_SET_CALIBRATE_MODE,bDeviceCalibrate);
  6214. }
  6215. //
  6216. // Remove dirty transform flag.
  6217. //
  6218. pdcattr->ulDirty_ &= ~DIRTY_COLORTRANSFORM;
  6219. return(TRUE);
  6220. }
  6221. /******************************Public*Routine******************************\
  6222. * HBRUSH IcmSelectBrush (HDC hdc, HBRUSH hbrush)
  6223. *
  6224. * History:
  6225. * 04-June-1995 -by- Lingyun Wang [lingyunW]
  6226. * Wrote it.
  6227. \**************************************************************************/
  6228. HBRUSH
  6229. IcmSelectBrush (
  6230. HDC hdc,
  6231. PDC_ATTR pdcattr,
  6232. HBRUSH hbrushNew)
  6233. {
  6234. HBRUSH hbrushOld = pdcattr->hbrush;
  6235. ICMAPI(("gdi32: IcmSelectBrush\n"));
  6236. //
  6237. // Mark brush as dirty, select new brush in dcattr.
  6238. // Color translation may fail, but still select brush
  6239. //
  6240. pdcattr->ulDirty_ |= DC_BRUSH_DIRTY;
  6241. pdcattr->hbrush = hbrushNew;
  6242. if (bNeedTranslateColor(pdcattr))
  6243. {
  6244. IcmTranslateBrushColor(hdc,pdcattr,hbrushNew);
  6245. }
  6246. return (hbrushOld);
  6247. }
  6248. /******************************Public*Routine******************************\
  6249. * HBRUSH IcmTranslateBrushColor(HDC hdc, PDC_ATTR pdcattr, HBRUSH hbrush)
  6250. *
  6251. * History:
  6252. * 10-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  6253. * Wrote it.
  6254. \**************************************************************************/
  6255. BOOL
  6256. IcmTranslateBrushColor(
  6257. HDC hdc,
  6258. PDC_ATTR pdcattr,
  6259. HBRUSH hbrush)
  6260. {
  6261. BOOL bStatus = FALSE;
  6262. COLORREF OldColor;
  6263. COLORREF NewColor;
  6264. PBRUSHATTR pbra;
  6265. //
  6266. // Invalidate BRUSH_TRANSLATED
  6267. //
  6268. pdcattr->ulDirty_ &= ~ICM_BRUSH_TRANSLATED;
  6269. PSHARED_GET_VALIDATE(pbra,hbrush,BRUSH_TYPE);
  6270. if (pbra)
  6271. {
  6272. //
  6273. // translate to new icm mode if not paletteindex
  6274. //
  6275. OldColor = pbra->lbColor;
  6276. if (!(OldColor & 0x01000000))
  6277. {
  6278. bStatus = IcmTranslateCOLORREF(hdc,
  6279. pdcattr,
  6280. OldColor,
  6281. &NewColor,
  6282. ICM_FORWARD);
  6283. if (bStatus)
  6284. {
  6285. pdcattr->IcmBrushColor = NewColor;
  6286. }
  6287. else
  6288. {
  6289. pdcattr->IcmBrushColor = OldColor;
  6290. }
  6291. }
  6292. else
  6293. {
  6294. pdcattr->IcmBrushColor = OldColor;
  6295. }
  6296. //
  6297. // Somehow, IcmBrushColor is initialized.
  6298. //
  6299. pdcattr->ulDirty_ |= ICM_BRUSH_TRANSLATED;
  6300. }
  6301. else
  6302. {
  6303. LOGBRUSH lbrush;
  6304. //
  6305. // stock brush or bitmap/hatch/dib brush
  6306. //
  6307. if(GetObjectW(hbrush,sizeof(LOGBRUSH),&lbrush))
  6308. {
  6309. if ((lbrush.lbStyle == BS_SOLID) || (lbrush.lbStyle == BS_HATCHED))
  6310. {
  6311. //
  6312. // try to translate color
  6313. //
  6314. OldColor = lbrush.lbColor;
  6315. if (!(OldColor & 0x01000000))
  6316. {
  6317. bStatus = IcmTranslateCOLORREF(hdc,
  6318. pdcattr,
  6319. OldColor,
  6320. &NewColor,
  6321. ICM_FORWARD);
  6322. if (bStatus)
  6323. {
  6324. pdcattr->IcmBrushColor = NewColor;
  6325. }
  6326. else
  6327. {
  6328. pdcattr->IcmBrushColor = OldColor;
  6329. }
  6330. }
  6331. else
  6332. {
  6333. pdcattr->IcmBrushColor = OldColor;
  6334. }
  6335. //
  6336. // IcmBrushColor is initialized.
  6337. //
  6338. pdcattr->ulDirty_ |= ICM_BRUSH_TRANSLATED;
  6339. }
  6340. else if (lbrush.lbStyle == BS_DIBPATTERN)
  6341. {
  6342. PBITMAPINFO pbmiDIB;
  6343. //
  6344. // Allocate temorary bitmap info header to get brush bitmap
  6345. //
  6346. pbmiDIB = (PBITMAPINFO)LOCALALLOC(sizeof(BITMAPINFO)+((256-1)*sizeof(RGBQUAD)));
  6347. if (pbmiDIB)
  6348. {
  6349. ULONG iColorUsage;
  6350. BOOL bAlreadyTran;
  6351. BOOL bStatus;
  6352. PVOID pvBits = NULL;
  6353. ULONG cjBits = 0;
  6354. //
  6355. // Get brush bitmap information, colortype, size, etc.
  6356. //
  6357. bStatus = NtGdiIcmBrushInfo(hdc,
  6358. hbrush,
  6359. pbmiDIB,
  6360. pvBits,
  6361. &cjBits,
  6362. &iColorUsage,
  6363. &bAlreadyTran,
  6364. IcmQueryBrush);
  6365. if (bStatus)
  6366. {
  6367. if ((iColorUsage == DIB_RGB_COLORS) &&
  6368. (!bAlreadyTran) && (cjBits))
  6369. {
  6370. pvBits = (PVOID) LOCALALLOC(cjBits);
  6371. if (pvBits)
  6372. {
  6373. //
  6374. // Get brush bitmap bits.
  6375. //
  6376. bStatus = NtGdiIcmBrushInfo(hdc,
  6377. hbrush,
  6378. pbmiDIB,
  6379. pvBits,
  6380. &cjBits,
  6381. NULL,
  6382. NULL,
  6383. IcmQueryBrush);
  6384. if (bStatus)
  6385. {
  6386. //
  6387. // IcmTranslateDIB may create new copy of bitmap bits and/or
  6388. // bitmap info header, if nessesary.
  6389. //
  6390. PVOID pvBitsNew = NULL;
  6391. PBITMAPINFO pbmiDIBNew = NULL;
  6392. bStatus = IcmTranslateDIB(hdc,
  6393. pdcattr,
  6394. cjBits,
  6395. pvBits,
  6396. &pvBitsNew,
  6397. pbmiDIB,
  6398. &pbmiDIBNew,
  6399. NULL,
  6400. (DWORD)-1,
  6401. iColorUsage,
  6402. ICM_FORWARD,
  6403. NULL,NULL);
  6404. if (bStatus)
  6405. {
  6406. if (pvBitsNew != NULL)
  6407. {
  6408. //
  6409. // IcmTranslateDIB creates new bitmap buffer, then
  6410. // free original buffer and set new one.
  6411. //
  6412. LOCALFREE(pvBits);
  6413. pvBits = pvBitsNew;
  6414. }
  6415. if (pbmiDIBNew != NULL)
  6416. {
  6417. //
  6418. // If bitmapInfo header is updated, use new one.
  6419. // And, need to compute bitmap bits size based
  6420. // on new bitmap header.
  6421. //
  6422. LOCALFREE(pbmiDIB);
  6423. pbmiDIB = pbmiDIBNew;
  6424. //
  6425. // Calculate bitmap bits size based on BITMAPINFO and nNumScans
  6426. //
  6427. cjBits = cjBitmapBitsSize(pbmiDIB);
  6428. }
  6429. //
  6430. // Set ICM-translated DIB into brush
  6431. //
  6432. bStatus = NtGdiIcmBrushInfo(hdc,
  6433. hbrush,
  6434. pbmiDIB,
  6435. pvBits,
  6436. &cjBits,
  6437. NULL,
  6438. NULL,
  6439. IcmSetBrush);
  6440. if (bStatus)
  6441. {
  6442. //
  6443. // The color is translated.
  6444. //
  6445. bAlreadyTran = TRUE;
  6446. }
  6447. else
  6448. {
  6449. WARNING("IcmSelectBrush():NtGdiIcmBrushInfo(SET) Failed\n");
  6450. }
  6451. }
  6452. else
  6453. {
  6454. WARNING("IcmSelectBrush():IcmTranslateDIB() Failed\n");
  6455. }
  6456. }
  6457. else
  6458. {
  6459. WARNING("IcmSelectBrush():NtGdiIcmBrushInfo(GET) Failed\n");
  6460. }
  6461. LOCALFREE(pvBits);
  6462. }
  6463. else
  6464. {
  6465. WARNING("IcmSelectBrush(): LOCALALLOC(pvBits) failed\n");
  6466. }
  6467. }
  6468. if (bAlreadyTran)
  6469. {
  6470. //
  6471. // Eventually, IcmBrushColor is initialized.
  6472. //
  6473. pdcattr->ulDirty_ |= ICM_BRUSH_TRANSLATED;
  6474. }
  6475. }
  6476. else
  6477. {
  6478. ICMWRN(("IcmSelectBrush(): Fail to get brush bitmap size or bitmap is DIB_PAL_COLORS\n"));
  6479. }
  6480. LOCALFREE(pbmiDIB);
  6481. }
  6482. else
  6483. {
  6484. WARNING("IcmSelectBrush(): LOCALALLOC(pbmi) failed\n");
  6485. }
  6486. }
  6487. else
  6488. {
  6489. ICMMSG(("IcmSelectBrush(): ICM will not done for this style - %d\n",lbrush.lbStyle));
  6490. }
  6491. }
  6492. else
  6493. {
  6494. WARNING("IcmSelectBrush(): GetObject failed on hbrush\n");
  6495. pdcattr->IcmBrushColor = CLR_INVALID;
  6496. }
  6497. }
  6498. return (bStatus);
  6499. }
  6500. /******************************Public*Routine******************************\
  6501. * IcmSelectPen()
  6502. *
  6503. * History:
  6504. *
  6505. * Wrote it:
  6506. * 31-Jul-1996 -by- Mark Enstrom [marke]
  6507. \**************************************************************************/
  6508. HPEN
  6509. IcmSelectPen(
  6510. HDC hdc,
  6511. PDC_ATTR pdcattr,
  6512. HPEN hpenNew
  6513. )
  6514. {
  6515. HPEN hpenOld = pdcattr->hpen;
  6516. ICMAPI(("gdi32: IcmSelectPen\n"));
  6517. pdcattr->ulDirty_ |= DC_PEN_DIRTY;
  6518. pdcattr->hpen = hpenNew;
  6519. if (bNeedTranslateColor(pdcattr))
  6520. {
  6521. IcmTranslatePenColor(hdc,pdcattr,hpenNew);
  6522. }
  6523. return (hpenOld);
  6524. }
  6525. /******************************Public*Routine******************************\
  6526. * BOOL IcmTranslatePenColor(HDC hdc, PDC_ATTR pdcattr, HBRUSH hbrush)
  6527. *
  6528. * History:
  6529. * 10-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  6530. * Wrote it.
  6531. \**************************************************************************/
  6532. BOOL
  6533. IcmTranslatePenColor(
  6534. HDC hdc,
  6535. PDC_ATTR pdcattr,
  6536. HPEN hpen
  6537. )
  6538. {
  6539. BOOL bStatus = FALSE;
  6540. COLORREF OldColor;
  6541. COLORREF NewColor;
  6542. PBRUSHATTR pbra;
  6543. //
  6544. // Invalidate PEN_TRANSLATED
  6545. //
  6546. pdcattr->ulDirty_ &= ~ICM_PEN_TRANSLATED;
  6547. PSHARED_GET_VALIDATE(pbra,hpen,BRUSH_TYPE);
  6548. if (pbra)
  6549. {
  6550. OldColor = pbra->lbColor;
  6551. //
  6552. // translate to new icm mode if not paletteindex
  6553. //
  6554. if (!(OldColor & 0x01000000))
  6555. {
  6556. bStatus = IcmTranslateCOLORREF(hdc,
  6557. pdcattr,
  6558. OldColor,
  6559. &NewColor,
  6560. ICM_FORWARD);
  6561. if (bStatus)
  6562. {
  6563. pdcattr->IcmPenColor = NewColor;
  6564. }
  6565. else
  6566. {
  6567. pdcattr->IcmPenColor = OldColor;
  6568. }
  6569. }
  6570. else
  6571. {
  6572. pdcattr->IcmPenColor = OldColor;
  6573. }
  6574. //
  6575. // IcmPenColor is initialized.
  6576. //
  6577. pdcattr->ulDirty_ |= ICM_PEN_TRANSLATED;
  6578. }
  6579. else
  6580. {
  6581. LOGPEN logpen;
  6582. //
  6583. // stock brush or bitmap/hatch/dib brush
  6584. //
  6585. if(GetObjectW(hpen,sizeof(LOGPEN),&logpen))
  6586. {
  6587. if (logpen.lopnStyle != PS_NULL)
  6588. {
  6589. //
  6590. // try to translate color
  6591. //
  6592. OldColor = logpen.lopnColor;
  6593. if (!(OldColor & 0x01000000))
  6594. {
  6595. bStatus = IcmTranslateCOLORREF(hdc,
  6596. pdcattr,
  6597. OldColor,
  6598. &NewColor,
  6599. ICM_FORWARD);
  6600. if (bStatus)
  6601. {
  6602. pdcattr->IcmPenColor = NewColor;
  6603. }
  6604. else
  6605. {
  6606. pdcattr->IcmPenColor = OldColor;
  6607. }
  6608. }
  6609. else
  6610. {
  6611. pdcattr->IcmPenColor = OldColor;
  6612. }
  6613. //
  6614. // IcmPenColor is initialized.
  6615. //
  6616. pdcattr->ulDirty_ |= ICM_PEN_TRANSLATED;
  6617. }
  6618. else
  6619. {
  6620. ICMMSG(("IcmSelectPen():Pen style is PS_NULL\n"));
  6621. pdcattr->IcmPenColor = CLR_INVALID;
  6622. }
  6623. }
  6624. else
  6625. {
  6626. WARNING("GetObject failed on hbrush\n");
  6627. pdcattr->IcmPenColor = CLR_INVALID;
  6628. }
  6629. }
  6630. return(bStatus);
  6631. }
  6632. /******************************Public*Routine******************************\
  6633. * IcmSelectExtPen()
  6634. *
  6635. * History:
  6636. *
  6637. * Wrote it:
  6638. * 11-Mar-1997 -by- Hideyuki Nagase [hideyukn]
  6639. \**************************************************************************/
  6640. HPEN
  6641. IcmSelectExtPen(
  6642. HDC hdc,
  6643. PDC_ATTR pdcattr,
  6644. HPEN hpenNew
  6645. )
  6646. {
  6647. HPEN hpenOld;
  6648. ICMAPI(("gdi32: IcmSelectExtPen\n"));
  6649. //
  6650. // Invalidate PEN_TRANSLATED
  6651. //
  6652. pdcattr->ulDirty_ &= ~ICM_PEN_TRANSLATED;
  6653. //
  6654. // Call kernel to select this object.
  6655. //
  6656. hpenOld = NtGdiSelectPen(hdc,hpenNew);
  6657. if (hpenOld && bNeedTranslateColor(pdcattr))
  6658. {
  6659. IcmTranslateExtPenColor(hdc,pdcattr,hpenNew);
  6660. }
  6661. return (hpenOld);
  6662. }
  6663. /******************************Public*Routine******************************\
  6664. * BOOL IcmTranslateExtPenColor(HDC hdc, PDC_ATTR pdcattr, HBRUSH hbrush)
  6665. *
  6666. * History:
  6667. * 10-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  6668. * Wrote it.
  6669. \**************************************************************************/
  6670. BOOL
  6671. IcmTranslateExtPenColor(
  6672. HDC hdc,
  6673. PDC_ATTR pdcattr,
  6674. HPEN hpen
  6675. )
  6676. {
  6677. BOOL bStatus = FALSE;
  6678. COLORREF OldColor;
  6679. COLORREF NewColor;
  6680. EXTLOGPEN logpenLocal;
  6681. EXTLOGPEN *plogpen = &logpenLocal;
  6682. if (!GetObjectW(hpen,sizeof(EXTLOGPEN),plogpen))
  6683. {
  6684. ULONG cbNeeded;
  6685. //
  6686. // It might be PS_USERSTYLE (go slow way...)
  6687. //
  6688. cbNeeded = GetObjectW(hpen,0,NULL);
  6689. if (cbNeeded)
  6690. {
  6691. plogpen = LOCALALLOC(cbNeeded);
  6692. if (plogpen)
  6693. {
  6694. if (!GetObjectW(hpen,cbNeeded,plogpen))
  6695. {
  6696. LOCALFREE(plogpen);
  6697. plogpen = NULL;
  6698. }
  6699. }
  6700. }
  6701. else
  6702. {
  6703. plogpen = NULL;
  6704. }
  6705. }
  6706. if (plogpen)
  6707. {
  6708. if ((plogpen->elpBrushStyle == BS_SOLID) || (plogpen->elpBrushStyle == BS_HATCHED))
  6709. {
  6710. ICMMSG(("IcmSelectExtPen:BS_SOLID or BS_HATCHED\n"));
  6711. //
  6712. // try to translate color
  6713. //
  6714. OldColor = plogpen->elpColor;
  6715. if (!(OldColor & 0x01000000))
  6716. {
  6717. bStatus = IcmTranslateCOLORREF(hdc,
  6718. pdcattr,
  6719. OldColor,
  6720. &NewColor,
  6721. ICM_FORWARD);
  6722. if (bStatus)
  6723. {
  6724. pdcattr->IcmPenColor = NewColor;
  6725. }
  6726. else
  6727. {
  6728. pdcattr->IcmPenColor = OldColor;
  6729. }
  6730. }
  6731. else
  6732. {
  6733. pdcattr->IcmPenColor = OldColor;
  6734. }
  6735. //
  6736. // Somehow, IcmPenColor is initialized.
  6737. //
  6738. pdcattr->ulDirty_ |= ICM_PEN_TRANSLATED;
  6739. }
  6740. else if ((plogpen->elpBrushStyle == BS_DIBPATTERN) || (plogpen->elpBrushStyle == BS_DIBPATTERNPT))
  6741. {
  6742. PBITMAPINFO pbmiDIB;
  6743. ICMMSG(("IcmSelectExtPen:BS_DIBPATTERN or BS_DIBPATTERNPT\n"));
  6744. //
  6745. // Allocate temorary bitmap info header to get brush bitmap
  6746. //
  6747. pbmiDIB = (PBITMAPINFO)LOCALALLOC(sizeof(BITMAPINFO)+((256-1)*sizeof(RGBQUAD)));
  6748. if (pbmiDIB)
  6749. {
  6750. ULONG iColorUsage;
  6751. BOOL bAlreadyTran;
  6752. PVOID pvBits = NULL;
  6753. ULONG cjBits = 0;
  6754. //
  6755. // Get brush bitmap information, colortype, size, etc.
  6756. //
  6757. bStatus = NtGdiIcmBrushInfo(hdc,
  6758. (HBRUSH)hpen,
  6759. pbmiDIB,
  6760. pvBits,
  6761. &cjBits,
  6762. &iColorUsage,
  6763. &bAlreadyTran,
  6764. IcmQueryBrush);
  6765. if (bStatus)
  6766. {
  6767. if ((iColorUsage == DIB_RGB_COLORS) &&
  6768. (!bAlreadyTran) &&
  6769. (cjBits))
  6770. {
  6771. pvBits = (PVOID) LOCALALLOC(cjBits);
  6772. if (pvBits)
  6773. {
  6774. //
  6775. // Get brush bitmap bits.
  6776. //
  6777. bStatus = NtGdiIcmBrushInfo(hdc,
  6778. (HBRUSH)hpen,
  6779. pbmiDIB,
  6780. pvBits,
  6781. &cjBits,
  6782. NULL,
  6783. NULL,
  6784. IcmQueryBrush);
  6785. if (bStatus)
  6786. {
  6787. //
  6788. // must make a copy of the DIB data
  6789. //
  6790. DWORD dwNumScan = ABS(pbmiDIB->bmiHeader.biHeight);
  6791. ULONG nColors = pbmiDIB->bmiHeader.biWidth *
  6792. dwNumScan * (pbmiDIB->bmiHeader.biBitCount/8);
  6793. //
  6794. // IcmTranslateDIB may create new copy of bitmap bits and/or
  6795. // bitmap info header, if nessesary.
  6796. //
  6797. PVOID pvBitsNew = NULL;
  6798. PBITMAPINFO pbmiDIBNew = NULL;
  6799. bStatus = IcmTranslateDIB(hdc,
  6800. pdcattr,
  6801. nColors,
  6802. pvBits,
  6803. &pvBitsNew,
  6804. pbmiDIB,
  6805. &pbmiDIBNew,
  6806. NULL,
  6807. dwNumScan,
  6808. iColorUsage,
  6809. ICM_FORWARD,
  6810. NULL,NULL);
  6811. if (bStatus)
  6812. {
  6813. if (pvBitsNew != NULL)
  6814. {
  6815. //
  6816. // IcmTranslateDIB creates new bitmap buffer, then
  6817. // free original buffer and set new one.
  6818. //
  6819. LOCALFREE(pvBits);
  6820. pvBits = pvBitsNew;
  6821. }
  6822. if (pbmiDIBNew != NULL)
  6823. {
  6824. //
  6825. // If bitmapInfo header is updated, use new one.
  6826. // And, need to compute bitmap bits size based
  6827. // on new bitmap header.
  6828. //
  6829. LOCALFREE(pbmiDIB);
  6830. pbmiDIB = pbmiDIBNew;
  6831. //
  6832. // Calculate bitmap bits size based on BITMAPINFO and nNumScans
  6833. //
  6834. cjBits = cjBitmapBitsSize(pbmiDIB);
  6835. }
  6836. //
  6837. // Set ICM-translated DIB into brush
  6838. //
  6839. bStatus = NtGdiIcmBrushInfo(hdc,
  6840. (HBRUSH)hpen,
  6841. pbmiDIB,
  6842. pvBits,
  6843. &cjBits,
  6844. NULL,
  6845. NULL,
  6846. IcmSetBrush);
  6847. if (bStatus)
  6848. {
  6849. //
  6850. // Translated.
  6851. //
  6852. bAlreadyTran = TRUE;
  6853. }
  6854. else
  6855. {
  6856. WARNING("IcmSelectExtPen():NtGdiIcmBrushInfo(SET) Failed\n");
  6857. }
  6858. }
  6859. else
  6860. {
  6861. WARNING("IcmSelectBrush():IcmTranslateDIB() Failed\n");
  6862. }
  6863. }
  6864. else
  6865. {
  6866. WARNING("IcmSelectExtPen():NtGdiIcmBrushInfo(GET) Failed\n");
  6867. }
  6868. LOCALFREE(pvBits);
  6869. }
  6870. else
  6871. {
  6872. WARNING("IcmSelectExtPen(): LOCALALLOC(pvBits) failed\n");
  6873. }
  6874. }
  6875. if (bAlreadyTran)
  6876. {
  6877. //
  6878. // Eventually, IcmPenColor is initialized.
  6879. //
  6880. pdcattr->ulDirty_ |= ICM_PEN_TRANSLATED;
  6881. }
  6882. }
  6883. else
  6884. {
  6885. ICMWRN(("IcmSelectBrush(): Fail to get brush bitmap size or bitmap is DIB_PAL_COLORS\n"));
  6886. }
  6887. LOCALFREE(pbmiDIB);
  6888. }
  6889. else
  6890. {
  6891. WARNING("IcmSelectExtPen(): LOCALALLOC(pbmi) failed\n");
  6892. }
  6893. }
  6894. else
  6895. {
  6896. #if DBG_ICM
  6897. DbgPrint("IcmSelectExtPen:ICM does not support this style (%d), yet\n",plogpen->elpBrushStyle);
  6898. #endif
  6899. }
  6900. if (plogpen != &logpenLocal)
  6901. {
  6902. LOCALFREE(plogpen);
  6903. }
  6904. }
  6905. else
  6906. {
  6907. WARNING("IcmSelectExtPen():GetObjectW() failed on hextpen\n");
  6908. }
  6909. return(bStatus);
  6910. }
  6911. /******************************Public*Routine******************************\
  6912. * IcmGetProfileColorFormat()
  6913. *
  6914. * History:
  6915. *
  6916. * Write it:
  6917. * 12-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  6918. \**************************************************************************/
  6919. BMFORMAT
  6920. IcmGetProfileColorFormat(
  6921. HPROFILE hProfile
  6922. )
  6923. {
  6924. //
  6925. // defaut is RGB
  6926. //
  6927. ULONG ColorFormat = BM_xBGRQUADS;
  6928. PROFILEHEADER ProfileHeader;
  6929. ICMAPI(("gdi32: IcmGetProfileColorFormat\n"));
  6930. //
  6931. // Get profile header information.
  6932. //
  6933. if (((*fpGetColorProfileHeader)(hProfile,&ProfileHeader)))
  6934. {
  6935. DWORD ColorSpace;
  6936. //
  6937. // Yes, we succeed to get profile header.
  6938. //
  6939. ColorSpace = ProfileHeader.phDataColorSpace;
  6940. //
  6941. // Figure out color format from color space.
  6942. //
  6943. switch (ColorSpace)
  6944. {
  6945. case SPACE_CMYK:
  6946. ICMMSG(("IcmGetProfileColorFormat(): CMYK Color Space\n"));
  6947. //
  6948. // Output format is CMYK color.
  6949. //
  6950. ColorFormat = BM_KYMCQUADS;
  6951. break;
  6952. case SPACE_RGB:
  6953. ICMMSG(("IcmGetProfileColorFormat(): RGB Color Space\n"));
  6954. //
  6955. // Output format is same as COLORREF (0x00bbggrr)
  6956. //
  6957. ColorFormat = BM_xBGRQUADS;
  6958. break;
  6959. default:
  6960. WARNING("IcmGetProfileColorFormat(): Unknown color space\n");
  6961. ColorFormat = 0xFFFFFFFF;
  6962. break;
  6963. }
  6964. }
  6965. return (ColorFormat);
  6966. }
  6967. /******************************Public*Routine******************************\
  6968. * IcmEnumColorProfile()
  6969. *
  6970. * History:
  6971. *
  6972. * Write it:
  6973. * 12-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  6974. \**************************************************************************/
  6975. int
  6976. IcmEnumColorProfile(
  6977. HDC hdc,
  6978. PVOID pvCallBack,
  6979. LPARAM lParam,
  6980. BOOL bAnsiCallBack,
  6981. PDEVMODEW pDevModeW,
  6982. DWORD *pdwColorSpaceFlag
  6983. )
  6984. {
  6985. int iRet = -1; // -1 means fail.
  6986. int iRetFromCMS = -1;
  6987. BYTE StackDeviceData[MAX_PATH*2*sizeof(WCHAR)];
  6988. WCHAR StackProfileData[MAX_PATH];
  6989. WCHAR StackTempBuffer[MAX_PATH];
  6990. CHAR StackTempBufferA[MAX_PATH];
  6991. PVOID pvFree = NULL;
  6992. PWSTR ProfileNames = StackProfileData;
  6993. DWORD cjAllocate = 0;
  6994. LPWSTR pDeviceName = NULL;
  6995. DWORD dwDeviceClass = 0L;
  6996. PLDC pldc = NULL;
  6997. DWORD bDontAskDriver = FALSE;
  6998. DWORD dwSize;
  6999. ICMAPI(("gdi32: IcmEnumColorProfile\n"));
  7000. //
  7001. // Load external ICM dlls
  7002. //
  7003. LOAD_ICMDLL(iRet);
  7004. //
  7005. // Try to identify device name, class and devmode (if hdc is given)
  7006. //
  7007. if (hdc)
  7008. {
  7009. pldc = GET_PLDC(hdc);
  7010. if (pldc && pldc->hSpooler)
  7011. {
  7012. DWORD cbFilled;
  7013. //
  7014. // This is printer.
  7015. //
  7016. dwDeviceClass = CLASS_PRINTER;
  7017. //
  7018. // Get current DEVMODE for printer (if devmode is not given)
  7019. //
  7020. if (!pDevModeW)
  7021. {
  7022. if (pldc->pDevMode)
  7023. {
  7024. ICMMSG(("IcmEnumColorProfile():Cached DEVMODE used\n"));
  7025. pDevModeW = pldc->pDevMode;
  7026. }
  7027. else
  7028. {
  7029. ICMMSG(("IcmEnumColorProfile():Get default DEVMODE\n"));
  7030. //
  7031. // UNDER_CONSTRUCTION: NEED TO USE CURRENT DEVMODE, NOT DEFAULT DEVMODE.
  7032. //
  7033. pDevModeW = pdmwGetDefaultDevMode(pldc->hSpooler,NULL,&pvFree);
  7034. }
  7035. }
  7036. //
  7037. // Get printer device name, Try level 1 information.
  7038. //
  7039. if ((*fpGetPrinterW)(pldc->hSpooler,1,
  7040. (BYTE *) &StackDeviceData,sizeof(StackDeviceData),
  7041. &cbFilled))
  7042. {
  7043. PRINTER_INFO_1W *pPrinterInfo1 = (PRINTER_INFO_1W *) &StackDeviceData;
  7044. //
  7045. // Device name is in there.
  7046. //
  7047. pDeviceName = pPrinterInfo1->pName;
  7048. }
  7049. else
  7050. {
  7051. ICMMSG(("IcmEnumColorProfile():FAILED on GetPrinterW(INFO_1) - %d\n",GetLastError()));
  7052. //
  7053. // Failed on GetPrinter, So get device name from DEVMODE
  7054. // (this will be limited to 32 character, but better than nothing.)
  7055. //
  7056. if (pDevModeW)
  7057. {
  7058. pDeviceName = pDevModeW->dmDeviceName;
  7059. }
  7060. }
  7061. //
  7062. // Get configuration about we need to ask driver for profile or not.
  7063. //
  7064. dwSize = sizeof(DWORD);
  7065. if ((*fpInternalGetDeviceConfig)(pDeviceName, CLASS_PRINTER, MSCMS_PROFILE_ENUM_MODE,
  7066. &bDontAskDriver, &dwSize))
  7067. {
  7068. ICMMSG(("IcmEnumColorProfile():EnumMode = %d\n",bDontAskDriver));
  7069. }
  7070. else
  7071. {
  7072. bDontAskDriver = FALSE; // if error, set back as default.
  7073. }
  7074. }
  7075. else if (GetDeviceCaps(hdc,TECHNOLOGY) == DT_RASDISPLAY)
  7076. {
  7077. //
  7078. // This is display.
  7079. //
  7080. dwDeviceClass = CLASS_MONITOR;
  7081. //
  7082. // Get monitor name for this DC.
  7083. //
  7084. if (NtGdiGetMonitorID(hdc,sizeof(StackDeviceData), (LPWSTR) StackDeviceData))
  7085. {
  7086. pDeviceName = (LPWSTR) StackDeviceData;
  7087. }
  7088. else
  7089. {
  7090. WARNING("NtGdiGetMonitorID failed, use hardcoded data\n");
  7091. //
  7092. // If failed, use "DISPLAY"
  7093. //
  7094. pDeviceName = L"DISPLAY";
  7095. }
  7096. }
  7097. }
  7098. else if (pDevModeW)
  7099. {
  7100. pDeviceName = pDevModeW->dmDeviceName;
  7101. }
  7102. if (pDeviceName)
  7103. {
  7104. ICMMSG(("IcmEnumColorProfile() DeviceName = %ws\n",pDeviceName));
  7105. }
  7106. //
  7107. // If we have devmode, call printer driver UI first to obtain color profile.
  7108. //
  7109. if (pDevModeW && /* devmode should be given */
  7110. pdwColorSpaceFlag && /* no query context */
  7111. pldc && pldc->hSpooler && /* only for printer driver */
  7112. !bDontAskDriver) /* only when we need ask driver */
  7113. {
  7114. //
  7115. // Ask (Printer UI) driver for default device color profile
  7116. //
  7117. iRetFromCMS = IcmAskDriverForColorProfile(pldc,QCP_DEVICEPROFILE,
  7118. pDevModeW,ProfileNames,pdwColorSpaceFlag);
  7119. //
  7120. // if iRet is greater then 0, driver have paticular color profile to use.
  7121. //
  7122. if (iRetFromCMS > 0)
  7123. {
  7124. if (pvCallBack)
  7125. {
  7126. //
  7127. // Build ICM profile file path.
  7128. //
  7129. BuildIcmProfilePath(ProfileNames,StackTempBuffer,MAX_PATH);
  7130. if (bAnsiCallBack)
  7131. {
  7132. bToASCII_N(StackTempBufferA,MAX_PATH,
  7133. StackTempBuffer, wcslen(StackTempBuffer)+1);
  7134. //
  7135. // Callback application.
  7136. //
  7137. iRet = (*(ICMENUMPROCA)pvCallBack)(StackTempBufferA,lParam);
  7138. }
  7139. else
  7140. {
  7141. iRet = (*(ICMENUMPROCW)pvCallBack)(StackTempBuffer,lParam);
  7142. }
  7143. if (iRet > 0)
  7144. {
  7145. //
  7146. // If iRet is positive value, continue to enumeration.
  7147. //
  7148. iRetFromCMS = -1;
  7149. }
  7150. }
  7151. else
  7152. {
  7153. //
  7154. // There is no call back function, just use return value from CMS.
  7155. //
  7156. iRet = iRetFromCMS;
  7157. }
  7158. }
  7159. else
  7160. {
  7161. iRetFromCMS = -1;
  7162. }
  7163. }
  7164. if (iRetFromCMS == -1)
  7165. {
  7166. ENUMTYPEW EnumType;
  7167. //
  7168. // Initialize with zero.
  7169. //
  7170. RtlZeroMemory(&EnumType,sizeof(ENUMTYPEW));
  7171. //
  7172. // Fill up EnumType structure
  7173. //
  7174. EnumType.dwSize = sizeof(ENUMTYPEW);
  7175. EnumType.dwVersion = ENUM_TYPE_VERSION;
  7176. //
  7177. // If device name is given use it, otherwise get it from DEVMODE.
  7178. //
  7179. if (pDeviceName)
  7180. {
  7181. EnumType.dwFields |= ET_DEVICENAME;
  7182. EnumType.pDeviceName = pDeviceName;
  7183. }
  7184. //
  7185. // Set DeviceClass (if hdc is given)
  7186. //
  7187. if (dwDeviceClass)
  7188. {
  7189. EnumType.dwFields |= ET_DEVICECLASS;
  7190. EnumType.dwDeviceClass = dwDeviceClass;
  7191. }
  7192. //
  7193. // Pick up any additional info from devmode (if we have)
  7194. //
  7195. if (pDevModeW)
  7196. {
  7197. //
  7198. // Set MediaType is presented.
  7199. //
  7200. if (pDevModeW->dmFields & DM_MEDIATYPE)
  7201. {
  7202. EnumType.dwFields |= ET_MEDIATYPE;
  7203. EnumType.dwMediaType = pDevModeW->dmMediaType;
  7204. }
  7205. if (pDevModeW->dmFields & DM_DITHERTYPE)
  7206. {
  7207. EnumType.dwFields |= ET_DITHERMODE;
  7208. EnumType.dwDitheringMode = pDevModeW->dmDitherType;
  7209. }
  7210. if ((pDevModeW->dmFields & DM_PRINTQUALITY) &&
  7211. (pDevModeW->dmPrintQuality >= 0))
  7212. {
  7213. EnumType.dwFields |= ET_RESOLUTION;
  7214. EnumType.dwResolution[0] = pDevModeW->dmPrintQuality;
  7215. if (pDevModeW->dmFields & DM_YRESOLUTION)
  7216. {
  7217. EnumType.dwResolution[1] = pDevModeW->dmYResolution;
  7218. }
  7219. else
  7220. {
  7221. EnumType.dwResolution[1] = pDevModeW->dmPrintQuality;
  7222. }
  7223. ICMMSG(("Resolution in devmode (%d,%d)\n",
  7224. EnumType.dwResolution[0],EnumType.dwResolution[1]));
  7225. }
  7226. }
  7227. //
  7228. // Figure out how much memory we need.
  7229. //
  7230. iRetFromCMS = (*fpEnumColorProfilesW)(NULL,&EnumType,NULL,&cjAllocate,NULL);
  7231. //
  7232. // Buffer should be requested ,at least, more then 2 unicode-null.
  7233. //
  7234. if (cjAllocate > (sizeof(UNICODE_NULL) * 2))
  7235. {
  7236. //
  7237. // If the buffer on stack is not enough, allocate it.
  7238. //
  7239. if (cjAllocate > sizeof(StackProfileData))
  7240. {
  7241. //
  7242. // Allocate buffer to recieve data.
  7243. //
  7244. ProfileNames = LOCALALLOC(cjAllocate);
  7245. if (ProfileNames == NULL)
  7246. {
  7247. GdiSetLastError(ERROR_NOT_ENOUGH_MEMORY);
  7248. goto IcmEnumColorProfile_Cleanup;
  7249. }
  7250. }
  7251. //
  7252. // Enumurate profiles
  7253. //
  7254. iRetFromCMS = (*fpEnumColorProfilesW)(NULL,&EnumType,(PBYTE)ProfileNames,&cjAllocate,NULL);
  7255. if (iRetFromCMS == 0)
  7256. {
  7257. //
  7258. // There is no profile enumulated.
  7259. //
  7260. goto IcmEnumColorProfile_Cleanup;
  7261. }
  7262. if (pvCallBack)
  7263. {
  7264. PWSTR pwstr;
  7265. //
  7266. // Callback for each file.
  7267. //
  7268. pwstr = ProfileNames;
  7269. while(*pwstr)
  7270. {
  7271. //
  7272. // Build ICM profile file path.
  7273. //
  7274. BuildIcmProfilePath(pwstr,StackTempBuffer,MAX_PATH);
  7275. if (bAnsiCallBack)
  7276. {
  7277. bToASCII_N(StackTempBufferA,MAX_PATH,
  7278. StackTempBuffer, wcslen(StackTempBuffer)+1);
  7279. //
  7280. // Callback application.
  7281. //
  7282. iRet = (*(ICMENUMPROCA)pvCallBack)(StackTempBufferA,lParam);
  7283. }
  7284. else
  7285. {
  7286. iRet = (*(ICMENUMPROCW)pvCallBack)(StackTempBuffer,lParam);
  7287. }
  7288. if (iRet == 0)
  7289. {
  7290. //
  7291. // Stop enumlation.
  7292. //
  7293. break;
  7294. }
  7295. //
  7296. // Move pointer to next.
  7297. //
  7298. pwstr += (wcslen(pwstr)+1);
  7299. }
  7300. }
  7301. else
  7302. {
  7303. //
  7304. // There is no call back function, just use return value from CMS.
  7305. //
  7306. iRet = iRetFromCMS;
  7307. }
  7308. }
  7309. IcmEnumColorProfile_Cleanup:
  7310. if (ProfileNames && (ProfileNames != StackProfileData))
  7311. {
  7312. LOCALFREE(ProfileNames);
  7313. }
  7314. }
  7315. //
  7316. // Free devmode buffer.
  7317. //
  7318. if (pvFree)
  7319. {
  7320. LOCALFREE(pvFree);
  7321. }
  7322. return (iRet);
  7323. }
  7324. /******************************Public*Routine******************************\
  7325. * IcmQueryProfileCallBack()
  7326. *
  7327. * History:
  7328. *
  7329. * Write it:
  7330. * 19-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  7331. \**************************************************************************/
  7332. int CALLBACK
  7333. IcmQueryProfileCallBack(
  7334. LPWSTR lpFileName,
  7335. LPARAM lAppData
  7336. )
  7337. {
  7338. PROFILECALLBACK_DATA *ProfileCallBack = (PROFILECALLBACK_DATA *)lAppData;
  7339. if (lpFileName)
  7340. {
  7341. PWSZ FileNameOnly = GetFileNameFromPath(lpFileName);
  7342. if (_wcsicmp(ProfileCallBack->pwszFileName,FileNameOnly) == 0)
  7343. {
  7344. //
  7345. // Yes, found it.
  7346. //
  7347. ProfileCallBack->bFound = TRUE;
  7348. //
  7349. // stop enumuration.
  7350. //
  7351. return (0);
  7352. }
  7353. }
  7354. //
  7355. // Continue to enumuration.
  7356. //
  7357. return (1);
  7358. }
  7359. /******************************Public*Routine******************************\
  7360. * IcmFindProfileCallBack()
  7361. *
  7362. * History:
  7363. *
  7364. * Write it:
  7365. * 19-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  7366. \**************************************************************************/
  7367. int CALLBACK
  7368. IcmFindProfileCallBack(
  7369. LPWSTR lpFileName,
  7370. LPARAM lAppData
  7371. )
  7372. {
  7373. //
  7374. // OK, just pick up first enumuration.
  7375. //
  7376. lstrcpyW((PWSZ)lAppData,lpFileName);
  7377. //
  7378. // And then stop enumuration.
  7379. //
  7380. return (0);
  7381. }
  7382. /******************************Public*Routine******************************\
  7383. * GetFileNameFromPath()
  7384. *
  7385. * History:
  7386. *
  7387. * Write it:
  7388. * 19-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  7389. \**************************************************************************/
  7390. PWSTR
  7391. GetFileNameFromPath(
  7392. PWSTR pwszFileName
  7393. )
  7394. {
  7395. PWSTR FileNameOnly = NULL;
  7396. //
  7397. // Check for: C:\PathName\Profile.icm
  7398. //
  7399. FileNameOnly = wcsrchr(pwszFileName,L'\\');
  7400. if (FileNameOnly != NULL)
  7401. {
  7402. FileNameOnly++; // Skip '\\'
  7403. }
  7404. else
  7405. {
  7406. //
  7407. // For: C:Profile.icm
  7408. //
  7409. FileNameOnly = wcschr(pwszFileName,L':');
  7410. if (FileNameOnly != NULL)
  7411. {
  7412. FileNameOnly++; // Skip ':'
  7413. }
  7414. else
  7415. {
  7416. //
  7417. // Otherwise Profile.icm
  7418. //
  7419. FileNameOnly = pwszFileName;
  7420. }
  7421. }
  7422. return (FileNameOnly);
  7423. }
  7424. /******************************Public*Routine******************************\
  7425. * IcmCreateProfileFromLCS()
  7426. *
  7427. * History:
  7428. *
  7429. * Write it:
  7430. * 19-Feb-1997 -by- Hideyuki Nagase [hideyukn]
  7431. \**************************************************************************/
  7432. BOOL
  7433. IcmCreateProfileFromLCS(
  7434. LPLOGCOLORSPACEW lpLogColorSpaceW,
  7435. PVOID *ppvProfileData,
  7436. PULONG pulProfileSize
  7437. )
  7438. {
  7439. BOOL bRet;
  7440. ICMAPI(("gdi32: IcmCreateProfileFromLCS\n"));
  7441. //
  7442. // Call MSCMS.DLL to create Profile from LOGCOLORSPACE
  7443. //
  7444. bRet = (*fpCreateProfileFromLogColorSpaceW)(lpLogColorSpaceW,
  7445. (PBYTE *)ppvProfileData);
  7446. if (bRet && *ppvProfileData)
  7447. {
  7448. *pulProfileSize = (ULONG)GlobalSize(*ppvProfileData);
  7449. }
  7450. return (bRet);
  7451. }
  7452. /******************************Public*Routine******************************\
  7453. * BuildIcmProfilePath()
  7454. *
  7455. * History:
  7456. *
  7457. * Write it:
  7458. * 07-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  7459. \**************************************************************************/
  7460. PWSZ
  7461. BuildIcmProfilePath(
  7462. PWSZ FileName, // IN
  7463. PWSZ FullPathFileName, // OUT
  7464. ULONG BufferSize
  7465. )
  7466. {
  7467. PWSZ FileNameOnly;
  7468. //
  7469. // BufferSize - need to be used for overrap check sometime later...
  7470. //
  7471. FileNameOnly = GetFileNameFromPath(FileName);
  7472. if (FileName == FileNameOnly)
  7473. {
  7474. // It seems we don't have any specified path, just use color directory.
  7475. const UINT c_cBufChars = MAX_PATH;
  7476. // Use a temporary because FileName and FullPathFileName can be the same
  7477. // and wcsncpy doesn't like that.
  7478. WCHAR awchTemp[MAX_PATH];
  7479. int count = c_cBufChars;
  7480. // Copy color directory first, then filename
  7481. // wcsncpy does not append a NULL if the count is smaller than the
  7482. // string. Do it manually so that wcsncat and wcslen work.
  7483. wcsncpy(awchTemp, ColorDirectory, count);
  7484. awchTemp[c_cBufChars-1] = 0;
  7485. // Leave space for the NULL terminator. Note, because we append a
  7486. // NULL terminator above, wcslen cannot return a number bigger than
  7487. // BufferSize-1. Therefore the resulting count cannot be negative.
  7488. count = c_cBufChars-wcslen(awchTemp)-1;
  7489. ASSERT(count>=0);
  7490. wcsncat(awchTemp,L"\\",count);
  7491. // leave space for the NULL
  7492. count = c_cBufChars-wcslen(awchTemp)-1;
  7493. ASSERT(count>=0);
  7494. wcsncat(awchTemp, FileNameOnly, count);
  7495. // copy to the final destination and force NULL termination.
  7496. wcsncpy(FullPathFileName, awchTemp, BufferSize);
  7497. FullPathFileName[BufferSize-1] = 0;
  7498. }
  7499. else
  7500. {
  7501. //
  7502. // Input path contains path, just use that.
  7503. //
  7504. if (FileName != FullPathFileName)
  7505. {
  7506. //
  7507. // Source and destination buffer is different, need to copy.
  7508. //
  7509. wcsncpy(FullPathFileName,FileName,BufferSize);
  7510. FullPathFileName[BufferSize-1] = 0;
  7511. }
  7512. }
  7513. return (FileNameOnly);
  7514. }
  7515. /******************************Public*Routine******************************\
  7516. * IcmSameColorSpace()
  7517. *
  7518. * History:
  7519. *
  7520. * Write it:
  7521. * 21-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  7522. \**************************************************************************/
  7523. BOOL
  7524. IcmSameColorSpace(
  7525. PCACHED_COLORSPACE pColorSpaceA,
  7526. PCACHED_COLORSPACE pColorSpaceB
  7527. )
  7528. {
  7529. ICMAPI(("gdi32: IcmSameColorSpace\n"));
  7530. if (pColorSpaceA == pColorSpaceB)
  7531. {
  7532. ICMMSG(("IcmSameColorSpace - Yes\n"));
  7533. return (TRUE);
  7534. }
  7535. else
  7536. {
  7537. ICMMSG(("IcmSameColorSpace - No\n"));
  7538. return (FALSE);
  7539. }
  7540. }
  7541. /******************************Public*Routine******************************\
  7542. * IcmGetColorSpaceByColorSpace()
  7543. *
  7544. * History:
  7545. *
  7546. * Write it:
  7547. * 21-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  7548. \**************************************************************************/
  7549. PCACHED_COLORSPACE
  7550. IcmGetColorSpaceByColorSpace(
  7551. HGDIOBJ hObjRequest,
  7552. LPLOGCOLORSPACEW lpLogColorSpace,
  7553. PPROFILE pColorProfile,
  7554. DWORD dwColorSpaceFlags
  7555. )
  7556. {
  7557. PCACHED_COLORSPACE pCandidateColorSpace = NULL;
  7558. PWSZ pProfileName;
  7559. BOOL bNeedMatchHdc = FALSE;
  7560. PLIST_ENTRY p;
  7561. ICMAPI(("gdi32: IcmGetColorSpaceByColorSpace\n"));
  7562. //
  7563. // If this is "on memory" profile which size is larger than
  7564. // maximum size of cachable profile withOUT filename,
  7565. // don't search cache, since we never be able to find from cache.
  7566. //
  7567. if (pColorProfile &&
  7568. (pColorProfile->dwType == PROFILE_MEMBUFFER) &&
  7569. (pColorProfile->cbDataSize > MAX_SIZE_OF_COLORPROFILE_TO_CACHE) &&
  7570. (lpLogColorSpace->lcsFilename[0] == UNICODE_NULL))
  7571. {
  7572. return (NULL);
  7573. }
  7574. //
  7575. // If this is metafile color space, must match hdc.
  7576. //
  7577. if (GET_COLORSPACE_TYPE(dwColorSpaceFlags) == GET_COLORSPACE_TYPE(METAFILE_COLORSPACE))
  7578. {
  7579. bNeedMatchHdc = TRUE;
  7580. }
  7581. pProfileName = lpLogColorSpace->lcsFilename;
  7582. //
  7583. // Search from cache.
  7584. //
  7585. ENTERCRITICALSECTION(&semColorSpaceCache);
  7586. p = ListCachedColorSpace.Flink;
  7587. while(p != &ListCachedColorSpace)
  7588. {
  7589. pCandidateColorSpace = CONTAINING_RECORD(p,CACHED_COLORSPACE,ListEntry);
  7590. //
  7591. // If this colorspace depends on specific gdi object, check it.
  7592. //
  7593. if (/* hdc is match */
  7594. (pCandidateColorSpace->hObj == hObjRequest) ||
  7595. /* candidate is not specific to hdc, and does not need to match hdc */
  7596. ((bNeedMatchHdc == FALSE) && (pCandidateColorSpace->hObj == NULL)))
  7597. {
  7598. LOGCOLORSPACEW *pCandidateLogColorSpace;
  7599. PWSZ pCandidateProfileName;
  7600. //
  7601. // Get pointer to profile
  7602. //
  7603. pCandidateLogColorSpace = &(pCandidateColorSpace->LogColorSpace);
  7604. pCandidateProfileName = pCandidateColorSpace->LogColorSpace.lcsFilename;
  7605. //
  7606. // Check lcsIntent.
  7607. //
  7608. if (pCandidateLogColorSpace->lcsIntent == lpLogColorSpace->lcsIntent)
  7609. {
  7610. //
  7611. // Check profile name if given
  7612. //
  7613. if (*pProfileName && *pCandidateProfileName)
  7614. {
  7615. if (_wcsicmp(pProfileName,pCandidateProfileName) == 0)
  7616. {
  7617. ICMMSG(("IcmGetColorSpaceByColorSpace():Find in cache (by profile name)\n"));
  7618. //
  7619. // Find it ! then Increment ref. counter
  7620. //
  7621. pCandidateColorSpace->cRef++;
  7622. break;
  7623. }
  7624. }
  7625. else if ((*pProfileName == UNICODE_NULL) && (*pCandidateProfileName == UNICODE_NULL))
  7626. {
  7627. if (pColorProfile == NULL)
  7628. {
  7629. //
  7630. // Both of color space does not have color profile, check inside LOGCOLORSPACE.
  7631. //
  7632. if ((pCandidateLogColorSpace->lcsCSType == lpLogColorSpace->lcsCSType) &&
  7633. (pCandidateLogColorSpace->lcsGammaRed == lpLogColorSpace->lcsGammaRed) &&
  7634. (pCandidateLogColorSpace->lcsGammaGreen == lpLogColorSpace->lcsGammaGreen) &&
  7635. (pCandidateLogColorSpace->lcsGammaBlue == lpLogColorSpace->lcsGammaBlue) &&
  7636. (RtlCompareMemory(&(pCandidateLogColorSpace->lcsEndpoints),
  7637. &(lpLogColorSpace->lcsEndpoints),sizeof(CIEXYZTRIPLE))
  7638. == sizeof(CIEXYZTRIPLE)))
  7639. {
  7640. ICMMSG(("IcmGetColorSpaceByColorSpace():Find in cache (by metrics)\n"));
  7641. //
  7642. // Find it ! then Increment ref. counter
  7643. //
  7644. pCandidateColorSpace->cRef++;
  7645. break;
  7646. }
  7647. }
  7648. else if ((pColorProfile->dwType == PROFILE_MEMBUFFER) &&
  7649. (pCandidateColorSpace->ColorProfile.dwType == PROFILE_MEMBUFFER))
  7650. {
  7651. if (pCandidateColorSpace->ColorProfile.cbDataSize == pColorProfile->cbDataSize)
  7652. {
  7653. if (RtlCompareMemory(pCandidateColorSpace->ColorProfile.pProfileData,
  7654. pColorProfile->pProfileData,
  7655. pColorProfile->cbDataSize)
  7656. == pColorProfile->cbDataSize)
  7657. {
  7658. ICMMSG(("IcmGetColorSpaceByColorSpace():Find in cache (by on memory profile)\n"));
  7659. //
  7660. // Find it ! then Increment ref. counter
  7661. //
  7662. pCandidateColorSpace->cRef++;
  7663. break;
  7664. }
  7665. }
  7666. }
  7667. }
  7668. }
  7669. }
  7670. p = p->Flink;
  7671. pCandidateColorSpace = NULL;
  7672. }
  7673. LEAVECRITICALSECTION(&semColorSpaceCache);
  7674. return (pCandidateColorSpace);
  7675. }
  7676. /******************************Public*Routine******************************\
  7677. * IcmGetColorSpaceByHandle()
  7678. *
  7679. * History:
  7680. *
  7681. * Write it:
  7682. * 21-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  7683. \**************************************************************************/
  7684. PCACHED_COLORSPACE
  7685. IcmGetColorSpaceByHandle(
  7686. HGDIOBJ hObj,
  7687. HCOLORSPACE hColorSpace,
  7688. LPLOGCOLORSPACEW lpLogColorSpace,
  7689. DWORD dwFlags
  7690. )
  7691. {
  7692. ULONG cRet;
  7693. ICMAPI(("gdi32: IcmGetColorSpaceByHandle\n"));
  7694. //
  7695. // Get LOGCOLORSPACE from handle
  7696. //
  7697. cRet = NtGdiExtGetObjectW(hColorSpace,sizeof(LOGCOLORSPACEW),lpLogColorSpace);
  7698. if (cRet >= sizeof(LOGCOLORSPACEW))
  7699. {
  7700. if (lpLogColorSpace->lcsFilename[0] != UNICODE_NULL)
  7701. {
  7702. //
  7703. // Normalize filename
  7704. //
  7705. BuildIcmProfilePath(lpLogColorSpace->lcsFilename,lpLogColorSpace->lcsFilename,MAX_PATH);
  7706. }
  7707. else
  7708. {
  7709. if (lpLogColorSpace->lcsCSType != LCS_CALIBRATED_RGB)
  7710. {
  7711. ULONG ulSize = MAX_PATH;
  7712. //
  7713. // if CSType is not LCS_CALIBRATED_RGB, we should go to MSCMS.DLL
  7714. // to get color profile for corresponding LCSType, then any given
  7715. // profile name from application is IGNORED.
  7716. //
  7717. if ((*fpGetStandardColorSpaceProfileW)(
  7718. NULL,
  7719. lpLogColorSpace->lcsCSType,
  7720. lpLogColorSpace->lcsFilename,
  7721. &ulSize))
  7722. {
  7723. ICMMSG(("IcmGetColorSpaceByHandle():CSType %x = %ws\n",
  7724. lpLogColorSpace->lcsCSType,
  7725. lpLogColorSpace->lcsFilename));
  7726. }
  7727. else
  7728. {
  7729. ICMWRN(("IcmGetColorSpaceByHandle():Error CSType = %x\n",
  7730. lpLogColorSpace->lcsCSType));
  7731. return (NULL);
  7732. }
  7733. }
  7734. }
  7735. //
  7736. // Find it !
  7737. //
  7738. return (IcmGetColorSpaceByColorSpace(hObj,lpLogColorSpace,NULL,dwFlags));
  7739. }
  7740. else
  7741. {
  7742. ICMWRN(("IcmGetColorSpaceByHandle():Failed on GetObject\n"));
  7743. return (NULL);
  7744. }
  7745. }
  7746. /******************************Public*Routine******************************\
  7747. * IcmGetColorSpaceByName()
  7748. *
  7749. * History:
  7750. *
  7751. * Write it:
  7752. * 21-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  7753. \**************************************************************************/
  7754. PCACHED_COLORSPACE
  7755. IcmGetColorSpaceByName(
  7756. HGDIOBJ hObj,
  7757. PWSZ ColorProfileName,
  7758. DWORD dwIntent,
  7759. DWORD dwFlags
  7760. )
  7761. {
  7762. ICMAPI(("gdi32: IcmGetColorSpaceByName (%ws)\n",(ColorProfileName ? ColorProfileName : L"null")));
  7763. if (ColorProfileName)
  7764. {
  7765. LOGCOLORSPACEW LogColorSpace;
  7766. RtlZeroMemory(&LogColorSpace,sizeof(LOGCOLORSPACEW));
  7767. //
  7768. // Put intent in LOGCOLORSPACE
  7769. //
  7770. LogColorSpace.lcsIntent = (LCSGAMUTMATCH) dwIntent;
  7771. //
  7772. // Normalize path name
  7773. //
  7774. BuildIcmProfilePath(ColorProfileName,LogColorSpace.lcsFilename,MAX_PATH);
  7775. //
  7776. // Find it !
  7777. //
  7778. return (IcmGetColorSpaceByColorSpace(hObj,&LogColorSpace,NULL,dwFlags));
  7779. }
  7780. else
  7781. {
  7782. return (NULL);
  7783. }
  7784. }
  7785. /******************************Public*Routine******************************\
  7786. * IcmCreateColorSpaceByName()
  7787. *
  7788. * History:
  7789. *
  7790. * Write it:
  7791. * 21-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  7792. \**************************************************************************/
  7793. PCACHED_COLORSPACE
  7794. IcmCreateColorSpaceByName(
  7795. HGDIOBJ hObj,
  7796. PWSZ ColorProfileName,
  7797. DWORD dwIntent,
  7798. DWORD dwFlags
  7799. )
  7800. {
  7801. LOGCOLORSPACEW LogColorSpace;
  7802. ICMAPI(("gdi32: IcmCreateColorSpaceByName\n"));
  7803. RtlZeroMemory(&LogColorSpace,sizeof(LOGCOLORSPACEW));
  7804. //
  7805. // Fill up LOGCOLORSPACE fields.
  7806. //
  7807. LogColorSpace.lcsSignature = LCS_SIGNATURE;
  7808. LogColorSpace.lcsVersion = 0x400;
  7809. LogColorSpace.lcsSize = sizeof(LOGCOLORSPACEW);
  7810. LogColorSpace.lcsCSType = LCS_CALIBRATED_RGB;
  7811. LogColorSpace.lcsIntent = (LCSGAMUTMATCH) dwIntent;
  7812. //
  7813. // Put profile file name in lcsFilename[]
  7814. //
  7815. lstrcpyW(LogColorSpace.lcsFilename,ColorProfileName);
  7816. //
  7817. // Create colorspace with LOGCOLORSPACE
  7818. //
  7819. return (IcmCreateColorSpaceByColorSpace(hObj,&LogColorSpace,NULL,dwFlags));
  7820. }
  7821. /******************************Public*Routine******************************\
  7822. * IcmCreateColorSpaceByColorSpace()
  7823. *
  7824. * History:
  7825. *
  7826. * Write it:
  7827. * 21-Apr-1997 -by- Hideyuki Nagase [hideyukn]
  7828. \**************************************************************************/
  7829. PCACHED_COLORSPACE
  7830. IcmCreateColorSpaceByColorSpace(
  7831. HGDIOBJ hObj,
  7832. LPLOGCOLORSPACEW lpLogColorSpace,
  7833. PPROFILE pProfileData,
  7834. DWORD dwFlags
  7835. )
  7836. {
  7837. PCACHED_COLORSPACE pColorSpace = NULL;
  7838. ICMAPI(("gdi32: IcmCreateColorSpaceByColorSpace\n"));
  7839. if (lpLogColorSpace)
  7840. {
  7841. //
  7842. // If ICMDLL is not loaded, yet, Just Load ICMDLL regardless current ICM mode,
  7843. // since we need it for handle this color profile. And apps can enable ICM
  7844. // later at that time, the opened color profile mighted be used.
  7845. //
  7846. if ((ghICM == NULL) && (!IcmInitialize()))
  7847. {
  7848. ICMWRN(("IcmCreateColorSpace():Fail to load ICM dlls\n"));
  7849. return (NULL);
  7850. }
  7851. //
  7852. // Allocate CACHED_COLORSPACE
  7853. //
  7854. pColorSpace = LOCALALLOC(sizeof(CACHED_COLORSPACE));
  7855. if (pColorSpace)
  7856. {
  7857. //
  7858. // Zero init CACHED_COLORSPACE
  7859. //
  7860. RtlZeroMemory(pColorSpace,sizeof(CACHED_COLORSPACE));
  7861. //
  7862. // Copy LOGCOLORSPACE into CACHED_COLORSPACE
  7863. //
  7864. RtlCopyMemory(&(pColorSpace->LogColorSpace),lpLogColorSpace,sizeof(LOGCOLORSPACEW));
  7865. //
  7866. // Default colorspace is RGB (BGR = 0x00bbggrr same as COLORREF format)
  7867. //
  7868. pColorSpace->ColorFormat = BM_xBGRQUADS;
  7869. //
  7870. // Map intent value for MSCMS from LOGCOLORSPACE.
  7871. //
  7872. switch (lpLogColorSpace->lcsIntent)
  7873. {
  7874. case LCS_GM_BUSINESS:
  7875. pColorSpace->ColorIntent = INTENT_SATURATION;
  7876. break;
  7877. case LCS_GM_GRAPHICS:
  7878. pColorSpace->ColorIntent = INTENT_RELATIVE_COLORIMETRIC;
  7879. break;
  7880. case LCS_GM_IMAGES:
  7881. pColorSpace->ColorIntent = INTENT_PERCEPTUAL;
  7882. break;
  7883. case LCS_GM_ABS_COLORIMETRIC:
  7884. pColorSpace->ColorIntent = INTENT_ABSOLUTE_COLORIMETRIC;
  7885. break;
  7886. default:
  7887. ICMWRN(("IcmCreateColorSpace():Invalid intent value\n"));
  7888. LOCALFREE(pColorSpace);
  7889. return (NULL);
  7890. }
  7891. //
  7892. // Keep flags
  7893. //
  7894. pColorSpace->flInfo = dwFlags;
  7895. //
  7896. // if the color space is specific to some GDI object, keep its handle.
  7897. //
  7898. // for DIBSECTION_COLORSPACE, CreateDIBSection calls us this hdc in hObj,
  7899. // then later overwrite hObj with thier bitmap handle. this prevent from
  7900. // this color space is shared with others.
  7901. //
  7902. if (dwFlags & HGDIOBJ_SPECIFIC_COLORSPACE)
  7903. {
  7904. pColorSpace->hObj = hObj;
  7905. }
  7906. //
  7907. // If this is not LCS_CALIBRATED_RGB, get color profile name.
  7908. //
  7909. if (lpLogColorSpace->lcsCSType != LCS_CALIBRATED_RGB)
  7910. {
  7911. ULONG ulSize = MAX_PATH;
  7912. //
  7913. // if CSType is not LCS_CALIBRATED_RGB, we should go to MSCMS.DLL
  7914. // to get color profile for corresponding LCSType, then any given
  7915. // profile name from application is IGNORED.
  7916. //
  7917. if ((*fpGetStandardColorSpaceProfileW)(
  7918. NULL, lpLogColorSpace->lcsCSType,
  7919. pColorSpace->LogColorSpace.lcsFilename, &ulSize))
  7920. {
  7921. ICMMSG(("IcmCreateColorSpace():CSType %x = %ws\n",
  7922. lpLogColorSpace->lcsCSType,
  7923. pColorSpace->LogColorSpace.lcsFilename));
  7924. }
  7925. else
  7926. {
  7927. ICMWRN(("IcmCreateColorSpace():Error CSType = %x\n",
  7928. lpLogColorSpace->lcsCSType));
  7929. LOCALFREE(pColorSpace);
  7930. return (NULL);
  7931. }
  7932. }
  7933. //
  7934. // Use PROFILE if profile is given
  7935. //
  7936. if ((pProfileData != NULL) &&
  7937. (pProfileData->dwType == PROFILE_MEMBUFFER) &&
  7938. (pProfileData->pProfileData != NULL) &&
  7939. (pProfileData->cbDataSize != 0))
  7940. {
  7941. ICMMSG(("IcmCreateColorSpace():Create ColorSpace cache by memory profile\n"));
  7942. ASSERTGDI(dwFlags & ON_MEMORY_PROFILE,
  7943. "IcmCreateColorSpace():dwFlags does not have ON_MEMORY_PROFILE");
  7944. if (!(dwFlags & NOT_CACHEABLE_COLORSPACE))
  7945. {
  7946. //
  7947. // Try to make a copy, if profile size is small enough,
  7948. // so that we can cache this profile.
  7949. //
  7950. if (pProfileData->cbDataSize <= MAX_SIZE_OF_COLORPROFILE_TO_CACHE)
  7951. {
  7952. pColorSpace->ColorProfile.pProfileData = GlobalAlloc(GMEM_FIXED,pProfileData->cbDataSize);
  7953. if (pColorSpace->ColorProfile.pProfileData)
  7954. {
  7955. ICMMSG(("IcmCreateColorSpace():Profile data can be cacheable\n"));
  7956. pColorSpace->ColorProfile.dwType = PROFILE_MEMBUFFER;
  7957. pColorSpace->ColorProfile.cbDataSize = pProfileData->cbDataSize;
  7958. RtlCopyMemory(pColorSpace->ColorProfile.pProfileData,
  7959. pProfileData->pProfileData,
  7960. pProfileData->cbDataSize);
  7961. //
  7962. // Make sure it is cachable...
  7963. //
  7964. ASSERTGDI((pColorSpace->flInfo & NOT_CACHEABLE_COLORSPACE) == 0,
  7965. "IcmCreateColorSpace():flInfo has NOT_CACHEABLE_COLORSPACE");
  7966. //
  7967. // Profile memory need to be freed at deletion.
  7968. //
  7969. pColorSpace->flInfo |= NEED_TO_FREE_PROFILE;
  7970. }
  7971. }
  7972. }
  7973. //
  7974. // If not able to cache, it the profile data in application.
  7975. //
  7976. if (pColorSpace->ColorProfile.pProfileData == NULL)
  7977. {
  7978. //
  7979. // Use PROFILE data if it's given in parameter.
  7980. //
  7981. pColorSpace->ColorProfile = *pProfileData;
  7982. //
  7983. // We don't make a copy of profile data, so profile data possible to be
  7984. // free by application, so this color space can not be cached
  7985. //
  7986. pColorSpace->flInfo |= NOT_CACHEABLE_COLORSPACE;
  7987. }
  7988. }
  7989. else if (lpLogColorSpace->lcsFilename[0] != UNICODE_NULL)
  7990. {
  7991. PWSZ pszFileNameOnly;
  7992. ICMMSG(("IcmCreateColorSpace():Create ColorSpace cache by file - %ws\n",
  7993. lpLogColorSpace->lcsFilename));
  7994. //
  7995. // Normalize filename
  7996. //
  7997. pszFileNameOnly = BuildIcmProfilePath(pColorSpace->LogColorSpace.lcsFilename,
  7998. pColorSpace->LogColorSpace.lcsFilename,MAX_PATH);
  7999. //
  8000. // If this is sRGB (= sRGB Color Space Profile.icm) color profile, ...
  8001. //
  8002. if (_wcsicmp(pszFileNameOnly,sRGB_PROFILENAME) == 0)
  8003. {
  8004. //
  8005. // Mark device_calibrate_colorspace flag.
  8006. //
  8007. pColorSpace->flInfo |= DEVICE_CALIBRATE_COLORSPACE;
  8008. }
  8009. //
  8010. // Fill up PROFILE structure and open it.
  8011. //
  8012. pColorSpace->ColorProfile.dwType = PROFILE_FILENAME;
  8013. pColorSpace->ColorProfile.pProfileData = pColorSpace->LogColorSpace.lcsFilename;
  8014. pColorSpace->ColorProfile.cbDataSize = MAX_PATH * sizeof(WCHAR);
  8015. }
  8016. else // if we only have parameter in LOGCOLORSPACE but not lcsFileName.
  8017. {
  8018. BOOL bRet;
  8019. //
  8020. // Convert LOGCOLORSPACE to ICC Profile.
  8021. //
  8022. ICMMSG(("IcmCreateColorSpace():Create ColorSpace cache by LOGCOLRSPACE\n"));
  8023. //
  8024. // Fill up PROFILE structure.
  8025. //
  8026. pColorSpace->ColorProfile.dwType = PROFILE_MEMBUFFER;
  8027. pColorSpace->ColorProfile.pProfileData = NULL;
  8028. //
  8029. // Call convert function. (LOGCOLORSPACE -> ICC PROFILE)
  8030. //
  8031. bRet = IcmCreateProfileFromLCS(
  8032. &(pColorSpace->LogColorSpace), // source logColorSpace
  8033. &(pColorSpace->ColorProfile.pProfileData), // receive pointer to profile image
  8034. &(pColorSpace->ColorProfile.cbDataSize)); // receive size of profile image
  8035. if ((bRet == FALSE) ||
  8036. (pColorSpace->ColorProfile.pProfileData == NULL) ||
  8037. (pColorSpace->ColorProfile.cbDataSize == 0))
  8038. {
  8039. ICMWRN(("IcmCreateColorSpaceByColorSpace():IcmCreateProfileFromLCS() failed\n"));
  8040. LOCALFREE(pColorSpace);
  8041. return (NULL);
  8042. }
  8043. //
  8044. // Mark pProfileData must be freed at deletion.
  8045. //
  8046. pColorSpace->flInfo |= NEED_TO_FREE_PROFILE;
  8047. }
  8048. //
  8049. // At this point, we don't have color format yet,
  8050. // so call IcmRealizeColorProfile with no color format checking.
  8051. //
  8052. if (IcmRealizeColorProfile(pColorSpace,FALSE))
  8053. {
  8054. //
  8055. // Get profile color format
  8056. //
  8057. pColorSpace->ColorFormat = IcmGetProfileColorFormat(pColorSpace->hProfile);
  8058. //
  8059. // Until create color transform, we don't need realized color space.
  8060. //
  8061. IcmUnrealizeColorProfile(pColorSpace);
  8062. }
  8063. else
  8064. {
  8065. ICMWRN(("IcmCreateColorSpace():Fail to realize color profile\n"));
  8066. if (pColorSpace->flInfo & NEED_TO_FREE_PROFILE)
  8067. {
  8068. GlobalFree(pColorSpace->ColorProfile.pProfileData);
  8069. }
  8070. LOCALFREE(pColorSpace);
  8071. return (NULL);
  8072. }
  8073. //
  8074. // Initialize ref. counter
  8075. //
  8076. pColorSpace->cRef = 1;
  8077. //
  8078. // Put the created color space into the list
  8079. //
  8080. ENTERCRITICALSECTION(&semColorSpaceCache);
  8081. InsertTailList(&ListCachedColorSpace,&(pColorSpace->ListEntry));
  8082. cCachedColorSpace++;
  8083. LEAVECRITICALSECTION(&semColorSpaceCache);
  8084. }
  8085. else
  8086. {
  8087. WARNING("gdi32:IcmCreateColorSpace():LOCALALLOC failed\n");
  8088. }
  8089. }
  8090. return (pColorSpace);
  8091. }
  8092. /******************************Public*Routine******************************\
  8093. * ColorProfile on demand loading/unloading support functions
  8094. *
  8095. * History:
  8096. *
  8097. * Write it:
  8098. * 29-Nov-1998 -by- Hideyuki Nagase [hideyukn]
  8099. \**************************************************************************/
  8100. BOOL
  8101. IcmRealizeColorProfile(
  8102. PCACHED_COLORSPACE pColorSpace,
  8103. BOOL bCheckColorFormat
  8104. )
  8105. {
  8106. ICMAPI(("gdi32: IcmRealizeColorProfile\n"));
  8107. if (pColorSpace)
  8108. {
  8109. if ((pColorSpace->hProfile == NULL) &&
  8110. (pColorSpace->ColorProfile.pProfileData != NULL))
  8111. {
  8112. HPROFILE hProfile = (*fpOpenColorProfileW)(
  8113. &(pColorSpace->ColorProfile),
  8114. PROFILE_READ,
  8115. FILE_SHARE_READ | FILE_SHARE_WRITE,
  8116. OPEN_EXISTING);
  8117. if (hProfile)
  8118. {
  8119. //
  8120. // Make sure color format of color profile has not been changed.
  8121. //
  8122. if ((bCheckColorFormat == FALSE) ||
  8123. (pColorSpace->ColorFormat == IcmGetProfileColorFormat(hProfile)))
  8124. {
  8125. pColorSpace->hProfile = hProfile;
  8126. }
  8127. else
  8128. {
  8129. (*fpCloseColorProfile)(hProfile);
  8130. }
  8131. }
  8132. }
  8133. return ((BOOL)!!pColorSpace->hProfile);
  8134. }
  8135. else
  8136. {
  8137. return (TRUE);
  8138. }
  8139. }
  8140. VOID
  8141. IcmUnrealizeColorProfile(
  8142. PCACHED_COLORSPACE pColorSpace
  8143. )
  8144. {
  8145. ICMAPI(("gdi32: IcmUnrealizeColorProfile\n"));
  8146. if (pColorSpace && pColorSpace->hProfile)
  8147. {
  8148. (*fpCloseColorProfile)(pColorSpace->hProfile);
  8149. pColorSpace->hProfile = NULL;
  8150. }
  8151. }
  8152. /******************************Public*Routine******************************\
  8153. * Metafiling support functions
  8154. *
  8155. * History:
  8156. *
  8157. * Write it:
  8158. * 23-May-1997 -by- Hideyuki Nagase [hideyukn]
  8159. \**************************************************************************/
  8160. VOID
  8161. IcmInsertMetafileList(
  8162. PLIST_ENTRY pListHead,
  8163. PWSZ pName
  8164. )
  8165. {
  8166. PMETAFILE_COLORPROFILE pData;
  8167. pData = LOCALALLOC(sizeof(METAFILE_COLORPROFILE));
  8168. if (pData)
  8169. {
  8170. wcscpy(pData->ColorProfile,pName);
  8171. InsertTailList(pListHead,&(pData->ListEntry));
  8172. }
  8173. }
  8174. BOOL
  8175. IcmCheckMetafileList(
  8176. PLIST_ENTRY pListHead,
  8177. PWSZ pName
  8178. )
  8179. {
  8180. PLIST_ENTRY p;
  8181. PMETAFILE_COLORPROFILE pData;
  8182. p = pListHead->Flink;
  8183. while (p != pListHead)
  8184. {
  8185. pData = (PVOID) CONTAINING_RECORD(p,METAFILE_COLORPROFILE,ListEntry);
  8186. if (_wcsicmp(pData->ColorProfile,pName) == 0)
  8187. {
  8188. return TRUE;
  8189. }
  8190. p = p->Flink;
  8191. }
  8192. return FALSE;
  8193. }
  8194. VOID
  8195. IcmFreeMetafileList(
  8196. PLIST_ENTRY pListHead
  8197. )
  8198. {
  8199. PLIST_ENTRY p;
  8200. PVOID pData;
  8201. p = pListHead->Flink;
  8202. while(p != pListHead)
  8203. {
  8204. pData = (PVOID) CONTAINING_RECORD(p,METAFILE_COLORPROFILE,ListEntry);
  8205. //
  8206. // Need to get pointer to next before free memory.
  8207. //
  8208. p = p->Flink;
  8209. //
  8210. // then free memory.
  8211. //
  8212. LOCALFREE(pData);
  8213. }
  8214. InitializeListHead(pListHead);
  8215. }
  8216. /******************************Public*Routine******************************\
  8217. * IcmStretchBlt()
  8218. *
  8219. * History:
  8220. *
  8221. * Write it:
  8222. * 29-May-1997 -by- Hideyuki Nagase [hideyukn]
  8223. \**************************************************************************/
  8224. BOOL
  8225. IcmStretchBlt(HDC hdc, int x, int y, int cx, int cy,
  8226. HDC hdcSrc, int x1, int y1, int cx1, int cy1, DWORD rop,
  8227. PDC_ATTR pdcattr, PDC_ATTR pdcattrSrc)
  8228. {
  8229. int iRet = 0;
  8230. PGDI_ICMINFO pIcmInfo;
  8231. HBITMAP hbm;
  8232. PVOID pvBits;
  8233. PBITMAPINFO pbmi;
  8234. ULONG cjBits;
  8235. HCOLORSPACE hSourceColorSpace = NULL,
  8236. hOldColorSpace = NULL;
  8237. PCACHED_COLORSPACE pSourceColorSpace = NULL;
  8238. POINT ptDevice[2];
  8239. UINT nNumScan, nNumWidth;
  8240. UINT nStartScan, nStartWidth;
  8241. BOOL bNoScaling;
  8242. BYTE dibData[(sizeof(DIBSECTION)+256*sizeof(RGBQUAD))];
  8243. ICMAPI(("gdi32: IcmStretchBlt\n"));
  8244. //
  8245. // Convert Logical coord to Physical coord on source.
  8246. //
  8247. ptDevice[0].x = x1;
  8248. ptDevice[0].y = y1;
  8249. ptDevice[1].x = x1 + cx1;
  8250. ptDevice[1].y = y1 + cy1;
  8251. if (LPtoDP(hdcSrc,ptDevice,2) == FALSE)
  8252. {
  8253. //
  8254. // can't handle, let callee handle this.
  8255. //
  8256. return (FALSE);
  8257. }
  8258. //
  8259. // Compute new origin.
  8260. //
  8261. nStartWidth = ptDevice[0].x;
  8262. nStartScan = ptDevice[0].y;
  8263. nNumWidth = ptDevice[1].x - ptDevice[0].x;
  8264. nNumScan = ptDevice[1].y - ptDevice[0].y;
  8265. //
  8266. // Check source bounds.
  8267. //
  8268. if (((INT)nStartWidth < 0) || ((INT)nStartScan < 0) || ((INT)nNumWidth < 0) || ((INT)nNumScan < 0))
  8269. {
  8270. ICMWRN(("IcmStretchBlt: (x1,y1) is out of surface\n"));
  8271. //
  8272. // We can't handle this, let callee handle this.
  8273. //
  8274. return (FALSE);
  8275. }
  8276. //
  8277. // Is there any scaling ?
  8278. //
  8279. bNoScaling = ((cx == (int)nNumWidth) && (cy == (int)nNumScan));
  8280. //
  8281. // Get bitmap handle.
  8282. //
  8283. hbm = (HBITMAP) GetDCObject(hdcSrc, LO_BITMAP_TYPE);
  8284. if (bDIBSectionSelected(pdcattrSrc))
  8285. {
  8286. //
  8287. // Get DIBSECTION currently selected in source DC.
  8288. //
  8289. if (GetObject(hbm, sizeof(DIBSECTION), &dibData) != (int)sizeof(DIBSECTION))
  8290. {
  8291. WARNING("IcmStretchBlt: GetObject(DIBSECTION) failed\n");
  8292. return(FALSE);
  8293. }
  8294. //
  8295. // Load color table and overwrite DIBSECTION structure from right after BITMAPINFOHEADER
  8296. //
  8297. if (((DIBSECTION *)&dibData)->dsBm.bmBitsPixel <= 8)
  8298. {
  8299. GetDIBColorTable(hdcSrc, 0, 256, (RGBQUAD *)&((DIBSECTION *)&dibData)->dsBitfields[0]);
  8300. }
  8301. pbmi = (PBITMAPINFO)&(((DIBSECTION *)&dibData)->dsBmih);
  8302. // if ((nStartScan + nNumScan) > (((DIBSECTION *)&dibData)->dsBm.bmHeight))
  8303. // {
  8304. // nNumScan = (((DIBSECTION *)&dibData)->dsBm.bmHeight - nStartScan);
  8305. // }
  8306. //
  8307. // Setup color source/destination colorspaces
  8308. //
  8309. if (IS_ICM_INSIDEDC(pdcattrSrc->lIcmMode))
  8310. {
  8311. //
  8312. // if ICM is turned on source DC. we will use source DC's
  8313. // destination color space as destination DC's source
  8314. // color space.
  8315. //
  8316. pIcmInfo = GET_ICMINFO(pdcattrSrc);
  8317. if (pIcmInfo && pIcmInfo->pDestColorSpace)
  8318. {
  8319. hSourceColorSpace = CreateColorSpaceW(&(pIcmInfo->pDestColorSpace->LogColorSpace));
  8320. pSourceColorSpace = pIcmInfo->pDestColorSpace;
  8321. }
  8322. }
  8323. if (hSourceColorSpace == NULL)
  8324. {
  8325. //
  8326. // if no colorspace, use sRGB.
  8327. //
  8328. hSourceColorSpace = GetStockObject(PRIV_STOCK_COLORSPACE);
  8329. pSourceColorSpace = NULL;
  8330. }
  8331. }
  8332. else if (IS_ICM_LAZY_CORRECTION(pdcattrSrc->lIcmMode))
  8333. {
  8334. //
  8335. // Get BITMAP currently selected in source DC.
  8336. //
  8337. if (GetObject(hbm, sizeof(BITMAP), &dibData) != (int)sizeof(BITMAP))
  8338. {
  8339. WARNING("IcmStretchBlt: GetObject(BITMAP) failed\n");
  8340. return(FALSE);
  8341. }
  8342. //
  8343. // Create bitmap info header
  8344. //
  8345. pbmi = (PBITMAPINFO) ((PBYTE)dibData+sizeof(BITMAP));
  8346. pbmi->bmiHeader.biSize = sizeof(BITMAPINFO);
  8347. pbmi->bmiHeader.biHeight = ((BITMAP *)&dibData)->bmHeight;
  8348. pbmi->bmiHeader.biWidth = ((BITMAP *)&dibData)->bmWidth;
  8349. pbmi->bmiHeader.biPlanes = 1;
  8350. pbmi->bmiHeader.biBitCount = 24; // 24bpp
  8351. pbmi->bmiHeader.biCompression = BI_RGB;
  8352. pbmi->bmiHeader.biSizeImage = 0;
  8353. pbmi->bmiHeader.biXPelsPerMeter = 0;
  8354. pbmi->bmiHeader.biYPelsPerMeter = 0;
  8355. pbmi->bmiHeader.biClrUsed = 0;
  8356. pbmi->bmiHeader.biClrImportant = 0;
  8357. // if ((nStartScan + nNumScan) > pbmi->bmiHeader.biHeight)
  8358. // {
  8359. // nNumScan = pbmi->bmiHeader.biHeight - nStartScan;
  8360. // }
  8361. ASSERTGDI(IS_ICM_INSIDEDC(pdcattrSrc->lIcmMode),
  8362. "IcmStretchBlt():Lazy color correction, but ICM is not enabled\n");
  8363. pIcmInfo = GET_ICMINFO(pdcattrSrc);
  8364. if (pIcmInfo && pIcmInfo->pSourceColorSpace)
  8365. {
  8366. hSourceColorSpace = CreateColorSpaceW(&(pIcmInfo->pSourceColorSpace->LogColorSpace));
  8367. pSourceColorSpace = pIcmInfo->pSourceColorSpace;
  8368. }
  8369. else
  8370. {
  8371. //
  8372. // Otherwise, just use Stcok color space (= sRGB)
  8373. //
  8374. hSourceColorSpace = GetStockObject(PRIV_STOCK_COLORSPACE);
  8375. pSourceColorSpace = NULL;
  8376. }
  8377. }
  8378. else
  8379. {
  8380. //
  8381. // Can't handle here, let callee handle it.
  8382. //
  8383. return (FALSE);
  8384. }
  8385. //
  8386. // Get bitmap size
  8387. //
  8388. cjBits = cjBitmapScanSize(pbmi,nNumScan);
  8389. pvBits = LOCALALLOC(cjBits);
  8390. if (pvBits)
  8391. {
  8392. //
  8393. // Fix up the start scan (bottom-left).
  8394. //
  8395. nStartScan = (pbmi->bmiHeader.biHeight - nStartScan - nNumScan);
  8396. //
  8397. // Call NtGdiGetDIBitsInternal directly, because
  8398. // we don't want to backward color correction to
  8399. // source color space in hdcSrc.
  8400. //
  8401. if (NtGdiGetDIBitsInternal(
  8402. hdcSrc,hbm,
  8403. nStartScan,nNumScan,
  8404. pvBits,pbmi,
  8405. DIB_RGB_COLORS,
  8406. cjBits,0) == 0)
  8407. {
  8408. WARNING("IcmStretchBlt(): Failed on GetDIBits()\n");
  8409. LOCALFREE(pvBits);
  8410. pvBits = NULL;
  8411. }
  8412. //
  8413. // Fix up the bitmap height, since pvBits only has nNumScan image.
  8414. //
  8415. pbmi->bmiHeader.biHeight = nNumScan;
  8416. }
  8417. if (pvBits)
  8418. {
  8419. if (hSourceColorSpace)
  8420. {
  8421. hOldColorSpace = IcmSetSourceColorSpace(hdc,hSourceColorSpace,pSourceColorSpace,0);
  8422. }
  8423. //
  8424. // Draw the bitmap.
  8425. //
  8426. // Target - x,y (upper left).
  8427. // Source - nStartWidth,0 (upper left).
  8428. //
  8429. if (bNoScaling && (rop == SRCCOPY))
  8430. {
  8431. iRet = SetDIBitsToDevice(hdc,x,y,cx,cy,nStartWidth,0,0,nNumScan,
  8432. pvBits,pbmi,DIB_RGB_COLORS);
  8433. }
  8434. else
  8435. {
  8436. iRet = StretchDIBits(hdc,x,y,cx,cy,nStartWidth,0,nNumWidth,nNumScan,
  8437. pvBits,pbmi,DIB_RGB_COLORS,rop);
  8438. }
  8439. //
  8440. // Back to original color space, if created
  8441. //
  8442. if (hOldColorSpace)
  8443. {
  8444. IcmSetSourceColorSpace(hdc,hOldColorSpace,NULL,0);
  8445. }
  8446. LOCALFREE(pvBits);
  8447. }
  8448. if (hSourceColorSpace)
  8449. {
  8450. DeleteColorSpace(hSourceColorSpace);
  8451. }
  8452. return (BOOL) !!iRet;
  8453. }
  8454. /******************************Public*Routine******************************\
  8455. * IcmGetColorSpaceforBitmap()
  8456. *
  8457. * History:
  8458. *
  8459. * Write it:
  8460. * 29-May-1997 -by- Hideyuki Nagase [hideyukn]
  8461. \**************************************************************************/
  8462. PCACHED_COLORSPACE
  8463. IcmGetColorSpaceforBitmap(HBITMAP hbm)
  8464. {
  8465. ICMAPI(("gdi32: IcmGetColorSpaceforBitmap\n"));
  8466. FIXUP_HANDLE(hbm);
  8467. return ((PCACHED_COLORSPACE)NtGdiGetColorSpaceforBitmap(hbm));
  8468. }
  8469. /******************************Public*Routine******************************\
  8470. * IcmEnableForCompatibleDC()
  8471. *
  8472. * History:
  8473. *
  8474. * Write it:
  8475. * 13-Jun-1997 -by- Hideyuki Nagase [hideyukn]
  8476. \**************************************************************************/
  8477. BOOL
  8478. IcmEnableForCompatibleDC(
  8479. HDC hdcCompatible,
  8480. HDC hdcDevice,
  8481. PDC_ATTR pdcaDevice
  8482. )
  8483. {
  8484. PDC_ATTR pdcaCompatible;
  8485. ICMAPI(("gdi32: IcmEnableForCompatibleDC\n"));
  8486. PSHARED_GET_VALIDATE(pdcaCompatible,hdcCompatible,DC_TYPE);
  8487. if (pdcaCompatible)
  8488. {
  8489. PGDI_ICMINFO pIcmInfoCompatible;
  8490. PGDI_ICMINFO pIcmInfoDevice;
  8491. // Initialize ICMINFO
  8492. //
  8493. // for device DC, ICMINFO should be presented.
  8494. //
  8495. if ((pIcmInfoDevice = GET_ICMINFO(pdcaDevice)) == NULL)
  8496. {
  8497. WARNING("gdi32: IcmEnableForCompatibleDC: Can't init icm info\n");
  8498. return (FALSE);
  8499. }
  8500. //
  8501. // for compatible DC, it was just created, ICMINFO is not exist, then create here.
  8502. //
  8503. if ((pIcmInfoCompatible = INIT_ICMINFO(hdcCompatible,pdcaCompatible)) == NULL)
  8504. {
  8505. WARNING("gdi32: IcmEnableForCompatibleDC: Can't init icm info\n");
  8506. return (FALSE);
  8507. }
  8508. //
  8509. // Set Source color space as same as original DC
  8510. //
  8511. // Kernel side...
  8512. //
  8513. if (pdcaDevice->hColorSpace)
  8514. {
  8515. if (pdcaDevice->hColorSpace != GetStockObject(PRIV_STOCK_COLORSPACE))
  8516. {
  8517. //
  8518. // Call directly kernel to set the color space to DC. (don't need client stuff)
  8519. //
  8520. NtGdiSetColorSpace(hdcCompatible,(HCOLORSPACE)pdcaDevice->hColorSpace);
  8521. }
  8522. //
  8523. // Keep it in ICMINFO, so that we can un-select it later.
  8524. //
  8525. pIcmInfoCompatible->hDefaultSrcColorSpace = pdcaDevice->hColorSpace;
  8526. }
  8527. // And client side...
  8528. //
  8529. ENTERCRITICALSECTION(&semColorSpaceCache);
  8530. if (pIcmInfoDevice->pSourceColorSpace)
  8531. {
  8532. pIcmInfoCompatible->pSourceColorSpace = pIcmInfoDevice->pSourceColorSpace;
  8533. pIcmInfoCompatible->pSourceColorSpace->cRef++;
  8534. }
  8535. //
  8536. // Set destination color space as same as original DC
  8537. //
  8538. if (pIcmInfoDevice->pDestColorSpace)
  8539. {
  8540. pIcmInfoCompatible->pDestColorSpace = pIcmInfoDevice->pDestColorSpace;
  8541. pIcmInfoCompatible->pDestColorSpace->cRef++;
  8542. }
  8543. LEAVECRITICALSECTION(&semColorSpaceCache);
  8544. //
  8545. // copy default profile name (if they has)
  8546. //
  8547. if (pIcmInfoDevice->DefaultDstProfile[0] != UNICODE_NULL)
  8548. {
  8549. wcscpy(pIcmInfoCompatible->DefaultDstProfile,pIcmInfoDevice->DefaultDstProfile);
  8550. pIcmInfoCompatible->flInfo |= (ICM_VALID_DEFAULT_PROFILE|
  8551. ICM_VALID_CURRENT_PROFILE);
  8552. }
  8553. //
  8554. // Make sure we have valid color space.
  8555. //
  8556. pdcaCompatible->ulDirty_ &= ~DIRTY_COLORSPACE;
  8557. //
  8558. // And we don't have valid color transform.
  8559. //
  8560. pdcaCompatible->ulDirty_ |= DIRTY_COLORTRANSFORM;
  8561. if (IS_ICM_INSIDEDC(pdcaDevice->lIcmMode))
  8562. {
  8563. //
  8564. // For compatible DC, use host ICM anytime...
  8565. //
  8566. ULONG ReqIcmMode = REQ_ICM_HOST;
  8567. //
  8568. // Turn ICM on for this compatible DC.
  8569. //
  8570. if (!NtGdiSetIcmMode(hdcCompatible,ICM_SET_MODE,ReqIcmMode))
  8571. {
  8572. //
  8573. // something wrong... we are fail to enable ICM.
  8574. //
  8575. return (FALSE);
  8576. }
  8577. //
  8578. // Update color transform.
  8579. //
  8580. if (!IcmUpdateDCColorInfo(hdcCompatible,pdcaCompatible))
  8581. {
  8582. //
  8583. // Fail to create new transform
  8584. //
  8585. NtGdiSetIcmMode(hdcCompatible,ICM_SET_MODE,REQ_ICM_OFF);
  8586. return (FALSE);
  8587. }
  8588. }
  8589. }
  8590. return (TRUE);
  8591. }
  8592. /******************************Public*Routine******************************\
  8593. * IcmAskDriverForColorProfile
  8594. *
  8595. * History:
  8596. * 08-Oct-1997 -by- Hideyuki Nagase [hideyukn]
  8597. \**************************************************************************/
  8598. int
  8599. IcmAskDriverForColorProfile(
  8600. PLDC pldc,
  8601. ULONG ulQueryMode,
  8602. PDEVMODEW pDevMode,
  8603. PWSTR pProfileName,
  8604. DWORD *pdwColorSpaceFlag
  8605. )
  8606. {
  8607. INT iRet;
  8608. BYTE TempProfileData[MAX_PATH];
  8609. PVOID pvProfileData = (PVOID) TempProfileData;
  8610. ULONG cjProfileSize = sizeof(TempProfileData);
  8611. FLONG flProfileFlag = 0;
  8612. ICMAPI(("gdi32: IcmAskDriverForColorProfile\n"));
  8613. //
  8614. // Call driver to get device profile data.
  8615. //
  8616. iRet = QueryColorProfileEx(pldc,
  8617. pDevMode,
  8618. ulQueryMode,
  8619. pvProfileData,
  8620. &cjProfileSize,
  8621. &flProfileFlag);
  8622. if (iRet == -1)
  8623. {
  8624. ICMMSG(("gdi32: IcmAskDriverForColorProfile():Driver does not hook color profile\n"));
  8625. //
  8626. // Driver does not support profile hook.
  8627. //
  8628. return iRet;
  8629. }
  8630. else if ((iRet == 0) &&
  8631. (cjProfileSize > sizeof(TempProfileData)) &&
  8632. (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
  8633. {
  8634. ICMMSG(("gdi32: IcmAskDriverForColorProfile():Allocate larger memory\n"));
  8635. //
  8636. // Buffer is not enough, so allocate it.
  8637. //
  8638. pvProfileData = LOCALALLOC(cjProfileSize);
  8639. if (pvProfileData)
  8640. {
  8641. iRet = QueryColorProfileEx(pldc,
  8642. pDevMode,
  8643. ulQueryMode,
  8644. pvProfileData,
  8645. &cjProfileSize,
  8646. &flProfileFlag);
  8647. }
  8648. }
  8649. if ((iRet > 0) && (pvProfileData != NULL) && (cjProfileSize != 0))
  8650. {
  8651. if (flProfileFlag == QCP_PROFILEDISK)
  8652. {
  8653. ICMMSG(("gdi32: IcmAskDriverForColorProfile():Profiles - %ws\n",pvProfileData));
  8654. //
  8655. // pvProfileData contains filename in Unicode.
  8656. //
  8657. wcsncpy(pProfileName,(PWSTR)pvProfileData,MAX_PATH);
  8658. }
  8659. else if (flProfileFlag == QCP_PROFILEMEMORY)
  8660. {
  8661. //
  8662. // pvProfileData contains color profile itself.
  8663. //
  8664. //
  8665. // No desired name.
  8666. //
  8667. *pProfileName = UNICODE_NULL;
  8668. //
  8669. // Create temporary color profile.
  8670. //
  8671. if (IcmCreateTemporaryColorProfile(pProfileName,pvProfileData,cjProfileSize))
  8672. {
  8673. ICMMSG(("gdi32: IcmAskDriverForColorProfile():Profiles - %ws\n",pProfileName));
  8674. //
  8675. // Mark this as temporary file, so that when this is not used
  8676. // the file will be deleted.
  8677. //
  8678. *pdwColorSpaceFlag = (DRIVER_COLORSPACE | NEED_TO_DEL_PROFILE);
  8679. }
  8680. else
  8681. {
  8682. ICMMSG(("gdi32: IcmAskDriverForColorProfile():Failed to create temp file\n"));
  8683. //
  8684. // failed to create temporary color profile.
  8685. //
  8686. iRet = 0;
  8687. }
  8688. }
  8689. else
  8690. {
  8691. //
  8692. // Unknown data type.
  8693. //
  8694. iRet = 0;
  8695. }
  8696. }
  8697. else
  8698. {
  8699. iRet = 0;
  8700. }
  8701. if (pvProfileData && (pvProfileData != TempProfileData))
  8702. {
  8703. LOCALFREE(pvProfileData);
  8704. }
  8705. return (iRet);
  8706. }
  8707. /******************************Public*Routine******************************\
  8708. * GdiConvertBitmapV5
  8709. *
  8710. * pbBitmapData - pointer to BITMAPV4/V5 data
  8711. * iSizeOfBitmapData - size of buffer
  8712. * uConvertFormat - either of CF_DIB or CF_BITMAP
  8713. *
  8714. * History:
  8715. * 12-Dec-1997 -by- Hideyuki Nagase [hideyukn]
  8716. \**************************************************************************/
  8717. HANDLE GdiConvertBitmapV5(
  8718. LPBYTE pbBitmapData,
  8719. int iSizeOfBitmapData,
  8720. HPALETTE hPalette,
  8721. UINT uConvertFormat
  8722. )
  8723. {
  8724. HANDLE hRet = NULL;
  8725. UNREFERENCED_PARAMETER(hPalette);
  8726. ICMAPI(("gdi32: GdiConvertBitmapV5\n"));
  8727. if (pbBitmapData && iSizeOfBitmapData)
  8728. {
  8729. BITMAPINFO *pbmi = (BITMAPINFO *)pbBitmapData;
  8730. BITMAPINFOHEADER *pbmih = &(pbmi->bmiHeader);
  8731. PVOID pvBits = NULL;
  8732. ULONG ulColorTableSize = (ULONG)-1;
  8733. BOOL bTransColorTable = FALSE;
  8734. BOOL bMoveColorMasks = FALSE;
  8735. //
  8736. // Load external ICM dlls.
  8737. //
  8738. LOAD_ICMDLL(NULL);
  8739. //
  8740. // Find the bitmap bits pointer.
  8741. //
  8742. try
  8743. {
  8744. //
  8745. // Calculate color table size.
  8746. //
  8747. if (pbmih->biCompression == BI_BITFIELDS)
  8748. {
  8749. //
  8750. // Bitfields are a part of BITMAPV4/V5 header.
  8751. //
  8752. ulColorTableSize = 0;
  8753. bMoveColorMasks = TRUE;
  8754. }
  8755. else if (pbmih->biCompression == BI_RGB)
  8756. {
  8757. if (pbmih->biClrUsed)
  8758. {
  8759. ulColorTableSize = (pbmih->biClrUsed * sizeof(RGBQUAD));
  8760. if (pbmih->biBitCount <= 8)
  8761. {
  8762. bTransColorTable = TRUE;
  8763. }
  8764. }
  8765. else if (pbmih->biBitCount <= 8)
  8766. {
  8767. ulColorTableSize = ((1 << pbmih->biBitCount) * sizeof(RGBQUAD));
  8768. bTransColorTable = TRUE;
  8769. }
  8770. else
  8771. {
  8772. ulColorTableSize = 0;
  8773. }
  8774. }
  8775. else if (pbmih->biCompression == BI_RLE4)
  8776. {
  8777. ulColorTableSize = 16 * sizeof(RGBQUAD);
  8778. bTransColorTable = TRUE;
  8779. }
  8780. else if (pbmih->biCompression == BI_RLE8)
  8781. {
  8782. ulColorTableSize = 256 * sizeof(RGBQUAD);
  8783. bTransColorTable = TRUE;
  8784. }
  8785. else
  8786. {
  8787. //
  8788. // BI_JPEG, BI_PNG, and others can not convert
  8789. //
  8790. ICMWRN(("GdiConvertBitmapV5: "
  8791. "given data is BI_JPEG, BI_PNG, or unkown\n"));
  8792. }
  8793. if (ulColorTableSize != (ULONG)-1)
  8794. {
  8795. //
  8796. // Make sure given data is either BITMAPV4 or V5 header.
  8797. //
  8798. if (pbmih->biSize == sizeof(BITMAPV5HEADER))
  8799. {
  8800. pvBits = (BYTE *)pbmi
  8801. + sizeof(BITMAPV5HEADER)
  8802. + ulColorTableSize
  8803. + ((LPBITMAPV5HEADER)pbmi)->bV5ProfileSize;
  8804. }
  8805. else if (pbmih->biSize != sizeof(BITMAPV4HEADER))
  8806. {
  8807. pvBits = (BYTE *)pbmi
  8808. + sizeof(BITMAPV4HEADER)
  8809. + ulColorTableSize;
  8810. }
  8811. else
  8812. {
  8813. ICMWRN(("GdiConvertBitmapV5: given data is not bitmapV4/V5\n"));
  8814. }
  8815. }
  8816. }
  8817. except(EXCEPTION_EXECUTE_HANDLER)
  8818. {
  8819. pvBits = NULL;
  8820. }
  8821. if (pvBits)
  8822. {
  8823. if (uConvertFormat == CF_DIB)
  8824. {
  8825. ULONG cjBitmapBits;
  8826. ICMMSG(("GdiConvertBitmapV5(): CF_DIBV5 -----> CF_DIB\n"));
  8827. //
  8828. // Calculate size of bitmap bits
  8829. //
  8830. try
  8831. {
  8832. cjBitmapBits = cjBitmapBitsSize(pbmi);
  8833. }
  8834. except(EXCEPTION_EXECUTE_HANDLER)
  8835. {
  8836. cjBitmapBits = 0;
  8837. }
  8838. if (cjBitmapBits)
  8839. {
  8840. //
  8841. // Allocate buffer for color translation
  8842. //
  8843. hRet = GlobalAlloc(GHND,sizeof(BITMAPINFOHEADER)
  8844. + (bMoveColorMasks ? (3 * sizeof(DWORD)) : \
  8845. (ulColorTableSize))
  8846. + cjBitmapBits);
  8847. if (hRet)
  8848. {
  8849. PBYTE pjSrc = (PBYTE)pbmi;
  8850. PBYTE pjDest = GlobalLock(hRet);
  8851. BOOL bTransformError = FALSE;
  8852. if (pjDest)
  8853. {
  8854. PROFILE sRGBColorProfileData;
  8855. LOGCOLORSPACEW LogColorSpaceW;
  8856. PROFILE ColorProfile;
  8857. DWORD dwFlags = 0;
  8858. HANDLE hColorTransform = NULL;
  8859. HANDLE hsRGBColorProfile = NULL;
  8860. HANDLE hBitmapColorProfile = NULL;
  8861. PCACHED_COLORSPACE pColorSpace = NULL;
  8862. try
  8863. {
  8864. //
  8865. // Extract color space from BITMAPV4/V5 header.
  8866. //
  8867. bTransformError = !(IcmGetBitmapColorSpace(
  8868. pbmi,
  8869. &LogColorSpaceW,
  8870. &ColorProfile,
  8871. &dwFlags));
  8872. }
  8873. except(EXCEPTION_EXECUTE_HANDLER)
  8874. {
  8875. bTransformError = TRUE;
  8876. }
  8877. if (!bTransformError)
  8878. {
  8879. //
  8880. // Create color space and color transform
  8881. //
  8882. if ((LogColorSpaceW.lcsCSType == LCS_sRGB) ||
  8883. (LogColorSpaceW.lcsCSType == LCS_WINDOWS_COLOR_SPACE))
  8884. {
  8885. ICMMSG(("GdiConvertBitmapV5(): Original bitmap is sRGB\n"));
  8886. //
  8887. // No color translarion required.
  8888. //
  8889. hColorTransform = NULL;
  8890. }
  8891. else
  8892. {
  8893. //
  8894. // Get source color space (if bitmap has color space)
  8895. //
  8896. //
  8897. // First, find ColorSpace from cache.
  8898. //
  8899. pColorSpace = IcmGetColorSpaceByColorSpace(
  8900. (HGDIOBJ)NULL,
  8901. &LogColorSpaceW,
  8902. &ColorProfile,
  8903. dwFlags);
  8904. if (pColorSpace == NULL)
  8905. {
  8906. pColorSpace = IcmCreateColorSpaceByColorSpace(
  8907. (HGDIOBJ)NULL,
  8908. &LogColorSpaceW,
  8909. &ColorProfile,
  8910. dwFlags);
  8911. }
  8912. if (pColorSpace && IcmRealizeColorProfile(pColorSpace,TRUE))
  8913. {
  8914. hBitmapColorProfile = pColorSpace->hProfile;
  8915. }
  8916. //
  8917. // Open sRGB color space profile as destination color space.
  8918. //
  8919. sRGBColorProfileData.dwType = PROFILE_FILENAME;
  8920. sRGBColorProfileData.pProfileData = (PVOID)sRGB_PROFILENAME;
  8921. sRGBColorProfileData.cbDataSize = MAX_PATH * sizeof(WCHAR);
  8922. hsRGBColorProfile = (*fpOpenColorProfileW)(
  8923. &sRGBColorProfileData,
  8924. PROFILE_READ,
  8925. FILE_SHARE_READ | FILE_SHARE_WRITE,
  8926. OPEN_EXISTING);
  8927. if (hBitmapColorProfile && hsRGBColorProfile)
  8928. {
  8929. DWORD ahIntents[2];
  8930. HPROFILE ahProfiles[2];
  8931. ahIntents[0] = INTENT_RELATIVE_COLORIMETRIC;
  8932. ahIntents[1] = pColorSpace->ColorIntent;
  8933. ahProfiles[0] = hBitmapColorProfile;
  8934. ahProfiles[1] = hsRGBColorProfile;
  8935. hColorTransform = (*fpCreateMultiProfileTransform)(
  8936. ahProfiles, 2,
  8937. ahIntents, 2,
  8938. NORMAL_MODE | ENABLE_GAMUT_CHECKING,
  8939. INDEX_DONT_CARE);
  8940. }
  8941. if (!hColorTransform)
  8942. {
  8943. bTransformError = TRUE;
  8944. }
  8945. }
  8946. if (!bTransformError)
  8947. {
  8948. //
  8949. // Copy the bitmap to target with proper color space conversion.
  8950. //
  8951. try
  8952. {
  8953. BITMAPV5HEADER *pbm5h = (BITMAPV5HEADER *)pbmi;
  8954. //
  8955. // Copy bitmap header to target.
  8956. //
  8957. RtlCopyMemory(pjDest,pjSrc,sizeof(BITMAPINFOHEADER));
  8958. //
  8959. // Adjust bmHeader.biSize
  8960. //
  8961. ((BITMAPINFOHEADER *)pjDest)->biSize = sizeof(BITMAPINFOHEADER);
  8962. //
  8963. // Move src and dest pointers
  8964. //
  8965. pjSrc += pbmih->biSize;
  8966. pjDest += sizeof(BITMAPINFOHEADER);
  8967. //
  8968. // Copy bit mask or color table.
  8969. //
  8970. if (bMoveColorMasks)
  8971. {
  8972. //
  8973. // Move color masks. cast it to pointer to BITMAPV5HEADER
  8974. // since same offset on BITMAPV4HEADER too.
  8975. //
  8976. *(DWORD *)pjDest = pbm5h->bV5RedMask;
  8977. pjDest += sizeof(DWORD);
  8978. *(DWORD *)pjDest = pbm5h->bV5GreenMask;
  8979. pjDest += sizeof(DWORD);
  8980. *(DWORD *)pjDest = pbm5h->bV5BlueMask;
  8981. pjDest += sizeof(DWORD);
  8982. }
  8983. else
  8984. {
  8985. if (ulColorTableSize)
  8986. {
  8987. if (bTransColorTable && hColorTransform)
  8988. {
  8989. bTransformError = !(*fpTranslateBitmapBits)(
  8990. hColorTransform,
  8991. pjSrc, BM_xRGBQUADS,
  8992. ulColorTableSize/sizeof(RGBQUAD), 1,
  8993. 0,
  8994. pjDest, BM_xRGBQUADS,
  8995. 0,NULL,0);
  8996. }
  8997. else
  8998. {
  8999. RtlCopyMemory(pjDest,pjSrc,ulColorTableSize);
  9000. }
  9001. pjSrc += ulColorTableSize;
  9002. pjDest += ulColorTableSize;
  9003. }
  9004. }
  9005. if (bTransColorTable || (hColorTransform == NULL))
  9006. {
  9007. //
  9008. // All the color information is in the color table. and
  9009. // it has been translated, so just copy bitmap bits.
  9010. //
  9011. RtlCopyMemory(pjDest,pvBits,cjBitmapBits);
  9012. }
  9013. else
  9014. {
  9015. //
  9016. // Translate bitmap bits.
  9017. //
  9018. BMFORMAT bmColorType;
  9019. //
  9020. // Get BMFORMAT based on bitmap format.
  9021. //
  9022. if (pbmih->biBitCount == 16)
  9023. {
  9024. if (pbmih->biCompression == BI_RGB)
  9025. {
  9026. bmColorType = BM_x555RGB;
  9027. }
  9028. else if (pbmih->biCompression == BI_BITFIELDS)
  9029. {
  9030. if ((pbm5h->bV5RedMask == 0x007c00) &&
  9031. (pbm5h->bV5GreenMask == 0x0003e0) &&
  9032. (pbm5h->bV5BlueMask == 0x00001f))
  9033. {
  9034. bmColorType = BM_x555RGB;
  9035. }
  9036. else if ((pbm5h->bV5RedMask == 0x00f800) &&
  9037. (pbm5h->bV5GreenMask == 0x0007e0) &&
  9038. (pbm5h->bV5BlueMask == 0x00001f))
  9039. {
  9040. bmColorType = BM_565RGB;
  9041. }
  9042. else
  9043. {
  9044. ICMWRN(("GdiConvertBitmapV5: Bad Bitfields Mask for 16 bpp\n"));
  9045. bTransformError = TRUE;
  9046. }
  9047. }
  9048. else
  9049. {
  9050. ICMWRN(("GdiConvertBitmapV5: Bad biCompression for 16 bpp\n"));
  9051. bTransformError = TRUE;
  9052. }
  9053. }
  9054. else if (pbmih->biBitCount == 24)
  9055. {
  9056. bmColorType = BM_RGBTRIPLETS;
  9057. }
  9058. else if (pbmih->biBitCount == 32)
  9059. {
  9060. if (pbmih->biCompression == BI_RGB)
  9061. {
  9062. bmColorType = BM_xRGBQUADS;
  9063. }
  9064. else if (pbmih->biCompression == BI_BITFIELDS)
  9065. {
  9066. if ((pbm5h->bV5RedMask == 0x0000ff) && /* Red */
  9067. (pbm5h->bV5GreenMask == 0x00ff00) && /* Green */
  9068. (pbm5h->bV5BlueMask == 0xff0000)) /* Blue */
  9069. {
  9070. bmColorType = BM_xBGRQUADS;
  9071. }
  9072. else if ((pbm5h->bV5RedMask == 0xff0000) && /* Red */
  9073. (pbm5h->bV5GreenMask == 0x00ff00) && /* Green */
  9074. (pbm5h->bV5BlueMask == 0x0000ff)) /* Blue */
  9075. {
  9076. bmColorType = BM_xRGBQUADS;
  9077. }
  9078. else
  9079. {
  9080. ICMWRN(("GdiConvertBitmapV5: Bad Bitfields Mask for 32 bpp\n"));
  9081. bTransformError = TRUE;
  9082. }
  9083. }
  9084. else
  9085. {
  9086. ICMWRN(("GdiConvertBitmapV5: Bad biCompression for 32 bpp\n"));
  9087. bTransformError = TRUE;
  9088. }
  9089. }
  9090. else
  9091. {
  9092. ICMWRN(("GdiConvertBitmapV5: Bad biBitCount\n"));
  9093. bTransformError = TRUE;
  9094. }
  9095. if (!bTransformError)
  9096. {
  9097. bTransformError = !(*fpTranslateBitmapBits)(
  9098. hColorTransform,
  9099. pvBits, bmColorType,
  9100. pbmih->biWidth,
  9101. ABS(pbmih->biHeight),
  9102. 0,
  9103. pjDest, bmColorType,
  9104. 0,NULL,0);
  9105. }
  9106. }
  9107. }
  9108. except(EXCEPTION_EXECUTE_HANDLER)
  9109. {
  9110. bTransformError = TRUE;
  9111. }
  9112. }
  9113. //
  9114. // Clean up used color transform and color profile handles
  9115. //
  9116. if (hColorTransform)
  9117. {
  9118. (*fpDeleteColorTransform)(hColorTransform);
  9119. }
  9120. if (hsRGBColorProfile)
  9121. {
  9122. (*fpCloseColorProfile)(hsRGBColorProfile);
  9123. }
  9124. if (pColorSpace)
  9125. {
  9126. IcmReleaseColorSpace(NULL,pColorSpace,FALSE);
  9127. }
  9128. }
  9129. }
  9130. GlobalUnlock(hRet);
  9131. if (bTransformError)
  9132. {
  9133. GlobalFree(hRet);
  9134. hRet = NULL;
  9135. }
  9136. }
  9137. else
  9138. {
  9139. ICMWRN(("GdiConvertBitmapV5: Fail on GlobalAlloc()\n"));
  9140. }
  9141. }
  9142. else
  9143. {
  9144. ICMWRN(("GdiConvertBitmapV5: cjBitmapBits is 0\n"));
  9145. }
  9146. return (hRet);
  9147. }
  9148. else if (uConvertFormat == CF_BITMAP)
  9149. {
  9150. HDC hDC = GetDC(NULL);
  9151. HBITMAP hBitmap = NULL;
  9152. if (hDC)
  9153. {
  9154. ICMMSG(("GdiConvertBitmapV5(): CF_DIBV5 -----> CF_BITMAP\n"));
  9155. //
  9156. // Set destination color space as sRGB, and enable ICM.
  9157. //
  9158. if (IcmSetDestinationColorSpace(hDC,sRGB_PROFILENAME,NULL,0) &&
  9159. SetICMMode(hDC,ICM_ON))
  9160. {
  9161. try
  9162. {
  9163. //
  9164. // Create bitmap handle with given bitmap V5 data.
  9165. //
  9166. hBitmap = CreateDIBitmap(hDC,
  9167. pbmih,
  9168. CBM_INIT,
  9169. pvBits,
  9170. pbmi,
  9171. DIB_RGB_COLORS);
  9172. }
  9173. except(EXCEPTION_EXECUTE_HANDLER)
  9174. {
  9175. hBitmap = NULL;
  9176. }
  9177. if (!hBitmap)
  9178. {
  9179. ICMWRN(("GdiConvertBitmapV5: Fail on CreateDIBitmap()\n"));
  9180. }
  9181. }
  9182. //
  9183. // Clean up DC
  9184. //
  9185. SetICMMode(hDC,ICM_OFF);
  9186. ReleaseDC(NULL,hDC);
  9187. }
  9188. return ((HANDLE)hBitmap);
  9189. }
  9190. else
  9191. {
  9192. ICMWRN(("GdiConvertBitmapV5(): CF_DIBV5 -----> Unknown\n"));
  9193. }
  9194. }
  9195. }
  9196. return (hRet);
  9197. }
  9198. /******************************Public*Routine******************************\
  9199. * IcmSetTargetColorSpace()
  9200. *
  9201. * History:
  9202. * 8-Jun-1998 -by- Hideyuki Nagase [hideyukn]
  9203. \**************************************************************************/
  9204. BOOL
  9205. IcmSetTargetColorSpace(
  9206. HDC hdc,
  9207. PCACHED_COLORSPACE pTargetColorSpace,
  9208. DWORD uiAction
  9209. )
  9210. {
  9211. BOOL bRet = FALSE;
  9212. PDC_ATTR pdcattr;
  9213. PGDI_ICMINFO pIcmInfo;
  9214. ICMAPI(("gdi32: IcmSetTargetColorSpace\n"));
  9215. FIXUP_HANDLE(hdc);
  9216. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  9217. if (pdcattr == NULL)
  9218. {
  9219. return (FALSE);
  9220. }
  9221. if ((pIcmInfo = GET_ICMINFO(pdcattr)) == NULL)
  9222. {
  9223. return (FALSE);
  9224. }
  9225. switch (uiAction)
  9226. {
  9227. case CS_ENABLE:
  9228. {
  9229. //
  9230. // Check validation of given Target color space.
  9231. //
  9232. if (pTargetColorSpace != NULL)
  9233. {
  9234. PCACHED_COLORTRANSFORM pCXform;
  9235. BOOL bDeleteOldCXform = FALSE;
  9236. //
  9237. // Mark we are in proofing mode.
  9238. //
  9239. SET_ICM_PROOFING(pdcattr->lIcmMode);
  9240. if ((pIcmInfo->pProofCXform != NULL) &&
  9241. IcmSameColorSpace(pTargetColorSpace,pIcmInfo->pTargetColorSpace))
  9242. {
  9243. ICMMSG(("IcmSetTargetColorSpace():Use Cached Proof Transform\n"));
  9244. ENTERCRITICALSECTION(&semColorTransformCache);
  9245. //
  9246. // the cached proofing transform is still valid.
  9247. //
  9248. pCXform = pIcmInfo->pProofCXform;
  9249. if (pCXform)
  9250. {
  9251. //
  9252. // Increment ref count of it.
  9253. //
  9254. pCXform->cRef++;
  9255. }
  9256. LEAVECRITICALSECTION(&semColorTransformCache);
  9257. }
  9258. else
  9259. {
  9260. ICMMSG(("IcmSetTargetColorSpace():Create New Proof Transform\n"));
  9261. //
  9262. // We don't have cached color space or it is no longer valid.
  9263. //
  9264. //
  9265. // Check we still have cached color space and it's still valid ?
  9266. //
  9267. if (pIcmInfo->pTargetColorSpace &&
  9268. IcmSameColorSpace(pTargetColorSpace,pIcmInfo->pTargetColorSpace))
  9269. {
  9270. //
  9271. // Cached target color space are still valid, keep as is.
  9272. //
  9273. }
  9274. else
  9275. {
  9276. //
  9277. // Release old target color space.
  9278. //
  9279. IcmReleaseColorSpace(NULL,pIcmInfo->pTargetColorSpace,FALSE);
  9280. //
  9281. // Increment ref count of it.
  9282. //
  9283. IcmReferenceColorSpace(pTargetColorSpace);
  9284. //
  9285. // set target destination profile into current DC as target profile
  9286. //
  9287. pIcmInfo->pTargetColorSpace = pTargetColorSpace;
  9288. }
  9289. //
  9290. // create new transform
  9291. //
  9292. pCXform = IcmCreateColorTransform(hdc,pdcattr,NULL,ICM_FORWARD);
  9293. //
  9294. // Marks as need to delete old color transform if we have.
  9295. //
  9296. bDeleteOldCXform = pIcmInfo->pProofCXform ? TRUE : FALSE;
  9297. }
  9298. if ((pCXform == IDENT_COLORTRANSFORM) || (pCXform == NULL))
  9299. {
  9300. //
  9301. // Invalidate color transform
  9302. //
  9303. IcmSelectColorTransform(hdc,pdcattr,NULL,
  9304. bDeviceCalibrate(pIcmInfo->pDestColorSpace));
  9305. //
  9306. // Delete old color transform.
  9307. //
  9308. if (bDeleteOldCXform)
  9309. {
  9310. //
  9311. // Delete cached proofing color transform
  9312. //
  9313. IcmDeleteColorTransform(pIcmInfo->pProofCXform,FALSE);
  9314. }
  9315. //
  9316. // Set null color transform to ICMINFO
  9317. //
  9318. pIcmInfo->pProofCXform = NULL;
  9319. if (pCXform == IDENT_COLORTRANSFORM)
  9320. {
  9321. ICMMSG(("IcmSetTargetColorSpace():Input & Output colorspace is same\n"));
  9322. //
  9323. // Input & Destination & Target color space is same, there is
  9324. // no color translation needed.
  9325. //
  9326. bRet = TRUE;
  9327. }
  9328. else
  9329. {
  9330. ICMWRN(("IcmSetTargetColorSpace():Fail to create color transform\n"));
  9331. }
  9332. //
  9333. // Translate back to DC color object to original
  9334. //
  9335. IcmTranslateColorObjects(hdc,pdcattr,FALSE);
  9336. }
  9337. else
  9338. {
  9339. //
  9340. // Select the color transform to DC.
  9341. //
  9342. IcmSelectColorTransform(hdc,pdcattr,pCXform,
  9343. bDeviceCalibrate(pCXform->DestinationColorSpace));
  9344. //
  9345. // Delete old color transform.
  9346. //
  9347. if (bDeleteOldCXform)
  9348. {
  9349. //
  9350. // Delete cached proofing color transform
  9351. //
  9352. IcmDeleteColorTransform(pIcmInfo->pProofCXform,FALSE);
  9353. }
  9354. //
  9355. // Set new color transform to ICMINFO.
  9356. //
  9357. pIcmInfo->pProofCXform = pCXform;
  9358. //
  9359. // Initialize color attributes in this DC.
  9360. //
  9361. IcmTranslateColorObjects(hdc,pdcattr,TRUE);
  9362. bRet = TRUE;
  9363. }
  9364. }
  9365. else
  9366. {
  9367. GdiSetLastError(ERROR_INVALID_PARAMETER);
  9368. WARNING("IcmSetTargetColorSpace: target color space is NULL\n");
  9369. //
  9370. // Anyway, just re-initialize without target profile.
  9371. //
  9372. IcmTranslateColorObjects(hdc,pdcattr,TRUE);
  9373. }
  9374. if (!bRet)
  9375. {
  9376. //
  9377. // if failed, mask off as we are not in proofing mode
  9378. //
  9379. CLEAR_ICM_PROOFING(pdcattr->lIcmMode);
  9380. if (pIcmInfo->pTargetColorSpace)
  9381. {
  9382. //
  9383. // Release target color space.
  9384. //
  9385. IcmReleaseColorSpace(NULL,pIcmInfo->pTargetColorSpace,FALSE);
  9386. //
  9387. // Disable target profile.
  9388. //
  9389. pIcmInfo->pTargetColorSpace = NULL;
  9390. }
  9391. }
  9392. break;
  9393. }
  9394. case CS_DISABLE:
  9395. case CS_DELETE_TRANSFORM:
  9396. {
  9397. //
  9398. // We are going to be out of proofing mode.
  9399. //
  9400. CLEAR_ICM_PROOFING(pdcattr->lIcmMode);
  9401. if (pdcattr->ulDirty_ & DIRTY_COLORTRANSFORM)
  9402. {
  9403. if (uiAction == CS_DELETE_TRANSFORM)
  9404. {
  9405. if (pIcmInfo->pTargetColorSpace)
  9406. {
  9407. //
  9408. // Release target color space.
  9409. //
  9410. IcmReleaseColorSpace(NULL,pIcmInfo->pTargetColorSpace,FALSE);
  9411. //
  9412. // Disable target profile.
  9413. //
  9414. pIcmInfo->pTargetColorSpace = NULL;
  9415. }
  9416. }
  9417. //
  9418. // While DC is in proofing mode, the source or
  9419. // destination color space has been changed by
  9420. // SetColorSpace() or SetICMProfile(). So,
  9421. // we will reset all color transform in this
  9422. // DC.
  9423. //
  9424. if (IcmUpdateDCColorInfo(hdc,pdcattr))
  9425. {
  9426. bRet = TRUE;
  9427. }
  9428. else
  9429. {
  9430. GdiSetLastError(ERROR_DELETING_ICM_XFORM);
  9431. }
  9432. }
  9433. else
  9434. {
  9435. //
  9436. // We are leaving proofing mode, Select back the normal colortransform into DC.
  9437. //
  9438. IcmSelectColorTransform(hdc,pdcattr,pIcmInfo->pCXform,
  9439. bDeviceCalibrate(pIcmInfo->pDestColorSpace));
  9440. //
  9441. // The color transform cache will effective...
  9442. //
  9443. if (uiAction == CS_DELETE_TRANSFORM)
  9444. {
  9445. if (pIcmInfo->pTargetColorSpace)
  9446. {
  9447. //
  9448. // Release target color space.
  9449. //
  9450. IcmReleaseColorSpace(NULL,pIcmInfo->pTargetColorSpace,FALSE);
  9451. //
  9452. // Disable target profile.
  9453. //
  9454. pIcmInfo->pTargetColorSpace = NULL;
  9455. }
  9456. //
  9457. // Delete ONLY proofing color transform (if it is)
  9458. //
  9459. if (pIcmInfo->pProofCXform)
  9460. {
  9461. if (!IcmDeleteColorTransform(pIcmInfo->pProofCXform,FALSE))
  9462. {
  9463. GdiSetLastError(ERROR_DELETING_ICM_XFORM);
  9464. return (FALSE);
  9465. }
  9466. //
  9467. // There is no proofing transform in this ICMINFO.
  9468. //
  9469. pIcmInfo->pProofCXform = NULL;
  9470. }
  9471. }
  9472. bRet = TRUE;
  9473. }
  9474. if (bRet)
  9475. {
  9476. //
  9477. // Initialize color attributes in this DC.
  9478. //
  9479. IcmTranslateColorObjects(hdc,pdcattr,TRUE);
  9480. }
  9481. break;
  9482. }
  9483. default:
  9484. {
  9485. WARNING("IcmSetTargetColorSpace: uiAction is invalid\n");
  9486. GdiSetLastError(ERROR_INVALID_PARAMETER);
  9487. }
  9488. }
  9489. return (bRet);
  9490. }
  9491. /******************************Public*Routine******************************\
  9492. * IcmSetDestinationColorSpace()
  9493. *
  9494. * History:
  9495. * 17-Jul-1998 -by- Hideyuki Nagase [hideyukn]
  9496. \**************************************************************************/
  9497. BOOL
  9498. IcmSetDestinationColorSpace(
  9499. HDC hdc,
  9500. LPWSTR pwszFileName,
  9501. PCACHED_COLORSPACE pColorSpace,
  9502. DWORD dwFlags
  9503. )
  9504. {
  9505. BOOL bRet = FALSE;
  9506. PDC_ATTR pdcattr;
  9507. ULONG FileNameSize;
  9508. if (pColorSpace)
  9509. {
  9510. ICMAPI(("gdi32: IcmSetDestinationColorSpace by ColorSpace (%ws):dwFlags - %d\n",
  9511. pColorSpace->LogColorSpace.lcsFilename,dwFlags));
  9512. }
  9513. else if (pwszFileName)
  9514. {
  9515. ICMAPI(("gdi32: IcmSetDestinationColorSpace by profile name (%ws):dwFlags - %x\n",
  9516. pwszFileName,dwFlags));
  9517. //
  9518. // Check filename
  9519. //
  9520. if (pwszFileName)
  9521. {
  9522. FileNameSize = lstrlenW(pwszFileName);
  9523. }
  9524. if ((FileNameSize == 0) || (FileNameSize > MAX_PATH))
  9525. {
  9526. ICMWRN(("IcmSetDestinatonColorSpace - no or too long profile name\n"));
  9527. return FALSE;
  9528. }
  9529. }
  9530. else
  9531. {
  9532. ICMAPI(("gdi32: IcmSetDestinationColorSpace - invalid parameter\n"));
  9533. return FALSE;
  9534. }
  9535. FIXUP_HANDLE(hdc);
  9536. //
  9537. // We are going to try to select this color space into thisDC,
  9538. // default is false.
  9539. //
  9540. bRet = FALSE;
  9541. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  9542. //
  9543. // Profile filename or pColorSpace should be presented.
  9544. //
  9545. if (pdcattr)
  9546. {
  9547. PGDI_ICMINFO pIcmInfo;
  9548. //
  9549. // Initialize ICMINFO
  9550. //
  9551. if ((pIcmInfo = INIT_ICMINFO(hdc,pdcattr)) == NULL)
  9552. {
  9553. WARNING("gdi32: IcmSetDestinationColorSpace: Can't init icm info\n");
  9554. return(FALSE);
  9555. }
  9556. if (IsColorDeviceContext(hdc))
  9557. {
  9558. PCACHED_COLORSPACE pNewColorSpace = NULL;
  9559. //
  9560. // Load external ICM dlls.
  9561. //
  9562. LOAD_ICMDLL(FALSE);
  9563. if (pColorSpace == NULL)
  9564. {
  9565. //
  9566. // Find colorspace from cache
  9567. //
  9568. pNewColorSpace = IcmGetColorSpaceByName(
  9569. (HGDIOBJ)hdc,
  9570. pwszFileName,
  9571. pIcmInfo->dwDefaultIntent,
  9572. dwFlags);
  9573. if (pNewColorSpace == NULL)
  9574. {
  9575. ICMMSG(("IcmSetDestinationColorSpace():This is new color space, create it\n"));
  9576. //
  9577. // Can not find, Create new one
  9578. //
  9579. pNewColorSpace = IcmCreateColorSpaceByName(
  9580. (HGDIOBJ)hdc,
  9581. pwszFileName,
  9582. pIcmInfo->dwDefaultIntent,
  9583. dwFlags);
  9584. }
  9585. }
  9586. else
  9587. {
  9588. //
  9589. // Increment ref count of given color space
  9590. //
  9591. IcmReferenceColorSpace(pColorSpace);
  9592. //
  9593. // Use pColorSpace from parameter.
  9594. //
  9595. pNewColorSpace = pColorSpace;
  9596. }
  9597. //
  9598. // We are going to select this colorspace onto DC. and free previous profile.
  9599. //
  9600. if (pNewColorSpace)
  9601. {
  9602. PCACHED_COLORSPACE pOldColorSpace = pIcmInfo->pDestColorSpace;
  9603. //
  9604. // Is this same destination color space currently selected in DC ?
  9605. //
  9606. if (IcmSameColorSpace(pNewColorSpace,pIcmInfo->pDestColorSpace))
  9607. {
  9608. //
  9609. // Yes, early-out. We don't need new color space.
  9610. //
  9611. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  9612. return (TRUE);
  9613. }
  9614. //
  9615. // Before change destination color space, we need to flush batched gdi functions.
  9616. //
  9617. CHECK_AND_FLUSH(hdc,pdcattr);
  9618. //
  9619. // Check new color format is accepted by this DC or not.
  9620. //
  9621. if (!NtGdiSetIcmMode(hdc,ICM_CHECK_COLOR_MODE,pNewColorSpace->ColorFormat))
  9622. {
  9623. ICMWRN(("IcmSetDestinationColorSpace(): DC does not accept this color format\n"));
  9624. GdiSetLastError(ERROR_INVALID_PROFILE);
  9625. }
  9626. else
  9627. {
  9628. //
  9629. // Set new color space into DC.
  9630. //
  9631. pIcmInfo->pDestColorSpace = pNewColorSpace;
  9632. //
  9633. // Remove dirty transform flag.
  9634. //
  9635. pdcattr->ulDirty_ &= ~DIRTY_COLORSPACE;
  9636. if (IS_ICM_INSIDEDC(pdcattr->lIcmMode) && !IS_ICM_PROOFING(pdcattr->lIcmMode))
  9637. {
  9638. PCACHED_COLORTRANSFORM pCXform;
  9639. //
  9640. // create new color transform base on new colorspace
  9641. //
  9642. pCXform = IcmCreateColorTransform(hdc,pdcattr,NULL,ICM_FORWARD);
  9643. if (pCXform == IDENT_COLORTRANSFORM)
  9644. {
  9645. //
  9646. // Select null color transform to DC.
  9647. //
  9648. IcmSelectColorTransform(hdc,pdcattr,NULL,
  9649. bDeviceCalibrate(pIcmInfo->pDestColorSpace));
  9650. //
  9651. // delete old color transform in DC.
  9652. //
  9653. IcmDeleteDCColorTransforms(pIcmInfo);
  9654. //
  9655. // Select null color transform to ICMINFO.
  9656. //
  9657. pIcmInfo->pCXform = NULL;
  9658. //
  9659. // back it to original color (non-ICMed color).
  9660. //
  9661. IcmTranslateColorObjects(hdc,pdcattr,FALSE);
  9662. //
  9663. // And, everything O.K.
  9664. //
  9665. bRet = TRUE;
  9666. }
  9667. else if (pCXform)
  9668. {
  9669. //
  9670. // Select the colortransform into DC.
  9671. //
  9672. if (IcmSelectColorTransform(
  9673. hdc,pdcattr,pCXform,
  9674. bDeviceCalibrate(pCXform->DestinationColorSpace)))
  9675. {
  9676. //
  9677. // delete old color transform in DC.
  9678. //
  9679. IcmDeleteDCColorTransforms(pIcmInfo);
  9680. //
  9681. // Select it to ICMINFO.
  9682. //
  9683. pIcmInfo->pCXform = pCXform;
  9684. //
  9685. // Adjust to new color transform.
  9686. //
  9687. IcmTranslateColorObjects(hdc,pdcattr,TRUE);
  9688. //
  9689. // And, everything O.K.
  9690. //
  9691. bRet = TRUE;
  9692. }
  9693. else
  9694. {
  9695. //
  9696. // Failed to select it to the DC in client side.
  9697. // so delete it and invalidate pCXform.
  9698. //
  9699. IcmDeleteColorTransform(pCXform,FALSE);
  9700. pCXform = NULL;
  9701. }
  9702. }
  9703. if (pCXform == NULL)
  9704. {
  9705. //
  9706. // Failed to create/select color stransform,
  9707. // so put back previous color space.
  9708. //
  9709. pIcmInfo->pDestColorSpace = pOldColorSpace;
  9710. }
  9711. }
  9712. else
  9713. {
  9714. //
  9715. // if ICM is not turned on currently, we just mark
  9716. // cached color transform is no longer valid.
  9717. //
  9718. pdcattr->ulDirty_ |= DIRTY_COLORTRANSFORM;
  9719. // For ColorMatchToTarget()
  9720. //
  9721. // While color matching to the target is enabled by setting
  9722. // uiAction to CS_ENABLE, application changes to the color
  9723. // space or gamut matching method are ignored.
  9724. // Those changes then take effect when color matching to
  9725. // the target is disabled.
  9726. //
  9727. if (IS_ICM_PROOFING(pdcattr->lIcmMode))
  9728. {
  9729. ICMMSG(("IcmSetDestinationColorSpace():In Proofing mode, lazy setting...\n"));
  9730. }
  9731. bRet = TRUE;
  9732. }
  9733. }
  9734. if (bRet)
  9735. {
  9736. //
  9737. // We are succeeded to select new color space, then
  9738. // close and free references to old color space.
  9739. //
  9740. IcmReleaseColorSpace(NULL,pOldColorSpace,FALSE);
  9741. }
  9742. else
  9743. {
  9744. //
  9745. // We will not use this color space as destination color space,
  9746. // because 1) DC does not accept this color space, 2) Fail to
  9747. // create color transform based on this color space.
  9748. //
  9749. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  9750. }
  9751. }
  9752. else
  9753. {
  9754. GdiSetLastError(ERROR_PROFILE_NOT_FOUND);
  9755. }
  9756. }
  9757. else
  9758. {
  9759. ICMMSG(("IcmSetDestinationColorSpace(): for Mono-device\n"));
  9760. //
  9761. // Just copy Apps specifyed profile to internal buffer, which will
  9762. // be return to app by GetICMProfile(), but it is NEVER used for
  9763. // non-color device other than that case, since there is no ICM
  9764. // happen.
  9765. //
  9766. wcsncpy(pIcmInfo->DefaultDstProfile,pwszFileName,MAX_PATH);
  9767. //
  9768. // This is not default profile, but current profile.
  9769. //
  9770. pIcmInfo->flInfo &= ~ICM_VALID_DEFAULT_PROFILE;
  9771. pIcmInfo->flInfo |= ICM_VALID_CURRENT_PROFILE;
  9772. }
  9773. }
  9774. else
  9775. {
  9776. GdiSetLastError(ERROR_INVALID_PARAMETER);
  9777. }
  9778. return(bRet);
  9779. }
  9780. /******************************Public*Routine******************************\
  9781. * IcmSetSourceColorSpace()
  9782. *
  9783. * History:
  9784. * 17-Jul-1998 -by- Hideyuki Nagase [hideyukn]
  9785. \**************************************************************************/
  9786. HCOLORSPACE
  9787. IcmSetSourceColorSpace(
  9788. HDC hdc,
  9789. HCOLORSPACE hColorSpace,
  9790. PCACHED_COLORSPACE pColorSpace,
  9791. DWORD dwFlags)
  9792. {
  9793. HANDLE hRet = NULL;
  9794. PDC_ATTR pdcattr;
  9795. ICMAPI(("gdi32: IcmSetSourceColorSpace\n"));
  9796. FIXUP_HANDLE(hdc);
  9797. FIXUP_HANDLE(hColorSpace);
  9798. //
  9799. // validate and access hdc
  9800. //
  9801. PSHARED_GET_VALIDATE(pdcattr,hdc,DC_TYPE);
  9802. if (pdcattr)
  9803. {
  9804. PGDI_ICMINFO pIcmInfo;
  9805. //
  9806. // Initialize ICMINFO
  9807. //
  9808. if ((pIcmInfo = INIT_ICMINFO(hdc,pdcattr)) == NULL)
  9809. {
  9810. WARNING("gdi32: IcmSetSourceColorSpace: Can't init icm info\n");
  9811. return(NULL);
  9812. }
  9813. if (pdcattr->hColorSpace != hColorSpace)
  9814. {
  9815. //
  9816. // Before change source color space, we need to flush batched gdi functions.
  9817. //
  9818. CHECK_AND_FLUSH(hdc,pdcattr);
  9819. //
  9820. // Return Old (currently selected) color space handle.
  9821. //
  9822. hRet = pdcattr->hColorSpace;
  9823. //
  9824. // set new color space, call kernel to keep reference count tracking
  9825. // of colospace object
  9826. //
  9827. if (NtGdiSetColorSpace(hdc,hColorSpace))
  9828. {
  9829. if (IsColorDeviceContext(hdc))
  9830. {
  9831. PCACHED_COLORSPACE pNewColorSpace;
  9832. LOGCOLORSPACEW LogColorSpaceW;
  9833. RtlZeroMemory(&LogColorSpaceW,sizeof(LOGCOLORSPACEW));
  9834. //
  9835. // Load external ICM dlls.
  9836. //
  9837. LOAD_ICMDLL(NULL);
  9838. if (pColorSpace == NULL)
  9839. {
  9840. //
  9841. // Check if there is client-cached colorspace for this or not.
  9842. //
  9843. pNewColorSpace = IcmGetColorSpaceByHandle(
  9844. (HGDIOBJ)hdc,
  9845. hColorSpace,
  9846. &LogColorSpaceW,dwFlags);
  9847. //
  9848. // If we can not find from cache, but succeeded to obtain
  9849. // valid logcolorspace from handle, create new one.
  9850. //
  9851. if ((pNewColorSpace == NULL) &&
  9852. (LogColorSpaceW.lcsSignature == LCS_SIGNATURE))
  9853. {
  9854. //
  9855. // Create new one.
  9856. //
  9857. pNewColorSpace = IcmCreateColorSpaceByColorSpace(
  9858. (HGDIOBJ)hdc,
  9859. &LogColorSpaceW,
  9860. NULL,
  9861. dwFlags);
  9862. }
  9863. }
  9864. else
  9865. {
  9866. //
  9867. // Increment ref count of given color space
  9868. //
  9869. IcmReferenceColorSpace(pColorSpace);
  9870. //
  9871. // Use pColorSpace from parameter.
  9872. //
  9873. pNewColorSpace = pColorSpace;
  9874. }
  9875. //
  9876. // Update current source color space to new one.
  9877. //
  9878. if (pNewColorSpace)
  9879. {
  9880. PCACHED_COLORSPACE pOldColorSpace = pIcmInfo->pSourceColorSpace;
  9881. //
  9882. // Check the colorspace is same one as currently selected ?
  9883. //
  9884. if (IcmSameColorSpace(pNewColorSpace,pIcmInfo->pSourceColorSpace))
  9885. {
  9886. //
  9887. // This is the "actually" same color space, but differrent handle,
  9888. // don't need to update
  9889. //
  9890. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  9891. return (hRet);
  9892. }
  9893. //
  9894. // Source color space should be RGB color space.
  9895. //
  9896. if (pNewColorSpace->ColorFormat != BM_xBGRQUADS)
  9897. {
  9898. ICMWRN(("IcmSetSourceColorSpace():Source color space is not RGB\n"));
  9899. //
  9900. // Set back previous color space. (can't fail these calls)
  9901. //
  9902. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  9903. NtGdiSetColorSpace(hdc,hRet);
  9904. GdiSetLastError(ERROR_INVALID_COLORSPACE);
  9905. return (NULL);
  9906. }
  9907. //
  9908. // And set new color space.
  9909. //
  9910. pIcmInfo->pSourceColorSpace = pNewColorSpace;
  9911. //
  9912. // if ICM is enabled, needs update color transform, right now.
  9913. //
  9914. if (IS_ICM_INSIDEDC(pdcattr->lIcmMode) && !IS_ICM_PROOFING(pdcattr->lIcmMode))
  9915. {
  9916. PCACHED_COLORTRANSFORM pCXform;
  9917. //
  9918. // create new color transform
  9919. //
  9920. pCXform = IcmCreateColorTransform(hdc,pdcattr,NULL,ICM_FORWARD);
  9921. if (pCXform == IDENT_COLORTRANSFORM)
  9922. {
  9923. ICMMSG(("IcmSetSourceColorSpace():Input & Output colorspace is same\n"));
  9924. //
  9925. // select NULL transform into DC.
  9926. //
  9927. IcmSelectColorTransform(hdc,pdcattr,NULL,
  9928. bDeviceCalibrate(pIcmInfo->pDestColorSpace));
  9929. //
  9930. // delete old colorspace/transform from ICMINFO.
  9931. //
  9932. IcmDeleteDCColorTransforms(pIcmInfo);
  9933. //
  9934. // select NULL tranform to ICMINFO.
  9935. //
  9936. pIcmInfo->pCXform = NULL;
  9937. //
  9938. // Set DC objects color to non-ICMed color.
  9939. //
  9940. IcmTranslateColorObjects(hdc,pdcattr,FALSE);
  9941. }
  9942. else if (pCXform)
  9943. {
  9944. //
  9945. // Select the color transform to DC.
  9946. //
  9947. if (IcmSelectColorTransform(
  9948. hdc,pdcattr,pCXform,
  9949. bDeviceCalibrate(pCXform->DestinationColorSpace)))
  9950. {
  9951. //
  9952. // delete old colorspace/transform from ICMINFO.
  9953. //
  9954. IcmDeleteDCColorTransforms(pIcmInfo);
  9955. //
  9956. // select new color transform to ICMINFO.
  9957. //
  9958. pIcmInfo->pCXform = pCXform;
  9959. //
  9960. // Succeed to select into DC, Validate DC color objects
  9961. //
  9962. IcmTranslateColorObjects(hdc,pdcattr,TRUE);
  9963. }
  9964. else
  9965. {
  9966. //
  9967. // Failed to select it to the DC in client side.
  9968. // so delete it and invalidate pCXform.
  9969. //
  9970. IcmDeleteColorTransform(pCXform,FALSE);
  9971. pCXform = NULL;
  9972. }
  9973. }
  9974. if (pCXform == NULL)
  9975. {
  9976. ICMMSG(("IcmSetSourceColorSpace():Fail to create/select color transform\n"));
  9977. //
  9978. // Set back previous color space. (can't fail these calls)
  9979. //
  9980. pIcmInfo->pSourceColorSpace = pOldColorSpace;
  9981. NtGdiSetColorSpace(hdc,hRet);
  9982. hRet = NULL;
  9983. }
  9984. }
  9985. else
  9986. {
  9987. //
  9988. // Otherwise, we just mark color transform might be dirty.
  9989. // Because new color space was selected.
  9990. //
  9991. pdcattr->ulDirty_ |= DIRTY_COLORTRANSFORM;
  9992. // For ColorMatchToTarget()
  9993. //
  9994. // While color matching to the target is enabled by setting
  9995. // uiAction to CS_ENABLE, application changes to the color
  9996. // space or gamut matching method are ignored.
  9997. // Those changes then take effect when color matching to
  9998. // the target is disabled.
  9999. //
  10000. if (IS_ICM_PROOFING(pdcattr->lIcmMode))
  10001. {
  10002. ICMMSG(("IcmSetSourceColorSpace():In Proofing mode, lazy setting...\n"));
  10003. }
  10004. }
  10005. if (hRet)
  10006. {
  10007. //
  10008. // Succeed to select new color space, then delete old one.
  10009. //
  10010. IcmReleaseColorSpace(NULL,pOldColorSpace,FALSE);
  10011. }
  10012. else
  10013. {
  10014. IcmReleaseColorSpace(NULL,pNewColorSpace,FALSE);
  10015. }
  10016. }
  10017. }
  10018. else
  10019. {
  10020. ICMMSG(("IcmSetSourceColorSpace(): for Mono-device\n"));
  10021. //
  10022. // For monochrome device case, just return kernel color space
  10023. // handle, then just don't create client-side representitive,
  10024. // since there is no ICM for monochrome device.
  10025. //
  10026. }
  10027. }
  10028. else
  10029. {
  10030. WARNING("Error: hdc and hColorSpace check out but NtGdi call failed\n");
  10031. hRet = NULL;
  10032. }
  10033. }
  10034. else
  10035. {
  10036. //
  10037. // Same color space was selected, just return current.
  10038. //
  10039. hRet = hColorSpace;
  10040. }
  10041. }
  10042. if (hRet == NULL)
  10043. {
  10044. GdiSetLastError(ERROR_INVALID_COLORSPACE);
  10045. }
  10046. return (hRet);
  10047. }
  10048. /******************************Public*Routine******************************\
  10049. * IcmSaveDC()
  10050. *
  10051. * History:
  10052. * 7-Dec-1998 -by- Hideyuki Nagase [hideyukn]
  10053. \**************************************************************************/
  10054. BOOL
  10055. IcmSaveDC(
  10056. HDC hdc,
  10057. PDC_ATTR pdcattr,
  10058. PGDI_ICMINFO pIcmInfo)
  10059. {
  10060. BOOL bRet = TRUE;
  10061. ICMAPI(("gdi32: IcmSaveDC\n"));
  10062. if (pdcattr && pIcmInfo)
  10063. {
  10064. //
  10065. // Get currect saved level.
  10066. //
  10067. DWORD dwCurrentSavedDepth;
  10068. if (NtGdiGetDCDword(hdc,DDW_SAVEDEPTH,&dwCurrentSavedDepth))
  10069. {
  10070. PSAVED_ICMINFO pSavedIcmInfo = LOCALALLOC(sizeof(SAVED_ICMINFO));
  10071. if (pSavedIcmInfo)
  10072. {
  10073. PCACHED_COLORSPACE pSourceColorSpace = pIcmInfo->pSourceColorSpace;
  10074. PCACHED_COLORSPACE pDestColorSpace = pIcmInfo->pDestColorSpace;
  10075. PCACHED_COLORSPACE pTargetColorSpace = pIcmInfo->pTargetColorSpace;
  10076. PCACHED_COLORTRANSFORM pCXform = pIcmInfo->pCXform;
  10077. PCACHED_COLORTRANSFORM pBackCXform = pIcmInfo->pBackCXform;
  10078. PCACHED_COLORTRANSFORM pProofCXform = pIcmInfo->pProofCXform;
  10079. //
  10080. // Increment reference count of color spaces in DC.
  10081. //
  10082. IcmReferenceColorSpace(pSourceColorSpace);
  10083. IcmReferenceColorSpace(pDestColorSpace);
  10084. IcmReferenceColorSpace(pTargetColorSpace);
  10085. //
  10086. // Increment reference count of color transform in DC.
  10087. //
  10088. IcmReferenceColorTransform(pCXform);
  10089. IcmReferenceColorTransform(pBackCXform);
  10090. IcmReferenceColorTransform(pProofCXform);
  10091. //
  10092. // Save color spaces.
  10093. //
  10094. pSavedIcmInfo->pSourceColorSpace = pSourceColorSpace;
  10095. pSavedIcmInfo->pDestColorSpace = pDestColorSpace;
  10096. pSavedIcmInfo->pTargetColorSpace = pTargetColorSpace;
  10097. //
  10098. // Save color transforms.
  10099. //
  10100. pSavedIcmInfo->pCXform = pCXform;
  10101. pSavedIcmInfo->pBackCXform = pBackCXform;
  10102. pSavedIcmInfo->pProofCXform = pProofCXform;
  10103. //
  10104. // Put current saved level in DC.
  10105. //
  10106. pSavedIcmInfo->dwSavedDepth = dwCurrentSavedDepth;
  10107. //
  10108. // Insert saved data to list.
  10109. //
  10110. InsertHeadList(&(pIcmInfo->SavedIcmInfo),&(pSavedIcmInfo->ListEntry));
  10111. ICMMSG(("gdi32: IcmSaveDC() - Saved Depth = %d\n",dwCurrentSavedDepth));
  10112. }
  10113. else
  10114. {
  10115. WARNING("IcmSaveDC():Failed on LOCALALLOC()\n");
  10116. bRet = FALSE;
  10117. }
  10118. }
  10119. else
  10120. {
  10121. WARNING("IcmSaveDC():Failed on NtGdiGetDCDword(DDW_SAVEDEPTH)\n");
  10122. bRet = FALSE;
  10123. }
  10124. }
  10125. return (bRet);
  10126. }
  10127. /******************************Public*Routine******************************\
  10128. * IcmRestoreDC()
  10129. *
  10130. * History:
  10131. * 7-Dec-1998 -by- Hideyuki Nagase [hideyukn]
  10132. \**************************************************************************/
  10133. VOID
  10134. IcmRestoreDC(
  10135. PDC_ATTR pdcattr,
  10136. int iLevel,
  10137. PGDI_ICMINFO pIcmInfo)
  10138. {
  10139. ICMAPI(("gdi32: IcmRestoreDC - iLevel = %d\n",iLevel));
  10140. if (pIcmInfo)
  10141. {
  10142. //
  10143. // Still have same ICMINFO.
  10144. //
  10145. PLIST_ENTRY p = pIcmInfo->SavedIcmInfo.Flink;
  10146. BOOL bContinue = TRUE;
  10147. while (bContinue &&
  10148. (iLevel != 0) &&
  10149. (p != &(pIcmInfo->SavedIcmInfo)))
  10150. {
  10151. PSAVED_ICMINFO pSavedIcmInfo = CONTAINING_RECORD(p,SAVED_ICMINFO,ListEntry);
  10152. if (iLevel > 0)
  10153. {
  10154. //
  10155. // iLevel is absolute saved depth to restore
  10156. //
  10157. if (iLevel == (int) pSavedIcmInfo->dwSavedDepth)
  10158. {
  10159. bContinue = FALSE;
  10160. }
  10161. }
  10162. else
  10163. {
  10164. //
  10165. // iLevel is relative saved depth to restore
  10166. //
  10167. if (++iLevel == 0)
  10168. {
  10169. bContinue = FALSE;
  10170. }
  10171. }
  10172. if (bContinue == FALSE)
  10173. {
  10174. PCACHED_COLORSPACE pSourceColorSpace = pIcmInfo->pSourceColorSpace;
  10175. PCACHED_COLORSPACE pDestColorSpace = pIcmInfo->pDestColorSpace;
  10176. PCACHED_COLORSPACE pTargetColorSpace = pIcmInfo->pTargetColorSpace;
  10177. PCACHED_COLORTRANSFORM pCXform = pIcmInfo->pCXform;
  10178. PCACHED_COLORTRANSFORM pBackCXform = pIcmInfo->pBackCXform;
  10179. PCACHED_COLORTRANSFORM pProofCXform = pIcmInfo->pProofCXform;
  10180. //
  10181. // Restore this saved data to DC.
  10182. //
  10183. pIcmInfo->pSourceColorSpace = pSavedIcmInfo->pSourceColorSpace;
  10184. pIcmInfo->pDestColorSpace = pSavedIcmInfo->pDestColorSpace;
  10185. pIcmInfo->pTargetColorSpace = pSavedIcmInfo->pTargetColorSpace;
  10186. pIcmInfo->pCXform = pSavedIcmInfo->pCXform;
  10187. pIcmInfo->pBackCXform = pSavedIcmInfo->pBackCXform;
  10188. pIcmInfo->pProofCXform = pSavedIcmInfo->pProofCXform;
  10189. //
  10190. // Release color space which *WAS* selected in DC.
  10191. //
  10192. IcmReleaseColorSpace(NULL,pSourceColorSpace,FALSE);
  10193. IcmReleaseColorSpace(NULL,pDestColorSpace,FALSE);
  10194. IcmReleaseColorSpace(NULL,pTargetColorSpace,FALSE);
  10195. //
  10196. // Delete color transform which *WAS* selected in DC.
  10197. //
  10198. IcmDeleteColorTransform(pCXform,FALSE);
  10199. IcmDeleteColorTransform(pBackCXform,FALSE);
  10200. IcmDeleteColorTransform(pProofCXform,FALSE);
  10201. if (pdcattr)
  10202. {
  10203. //
  10204. // Validate flags.
  10205. //
  10206. pdcattr->ulDirty_ &= ~(DIRTY_COLORSPACE | DIRTY_COLORTRANSFORM);
  10207. }
  10208. }
  10209. else
  10210. {
  10211. //
  10212. // Decrement ref count of color space.
  10213. //
  10214. IcmReleaseColorSpace(NULL,pSavedIcmInfo->pSourceColorSpace,FALSE);
  10215. IcmReleaseColorSpace(NULL,pSavedIcmInfo->pDestColorSpace,FALSE);
  10216. IcmReleaseColorSpace(NULL,pSavedIcmInfo->pTargetColorSpace,FALSE);
  10217. //
  10218. // Decrement ref count of color transform.
  10219. //
  10220. IcmDeleteColorTransform(pSavedIcmInfo->pCXform,FALSE);
  10221. IcmDeleteColorTransform(pSavedIcmInfo->pBackCXform,FALSE);
  10222. IcmDeleteColorTransform(pSavedIcmInfo->pProofCXform,FALSE);
  10223. }
  10224. //
  10225. // Get pointer to next.
  10226. //
  10227. p = p->Flink;
  10228. //
  10229. // Remove from list.
  10230. //
  10231. RemoveEntryList(&(pSavedIcmInfo->ListEntry));
  10232. //
  10233. // Free SAVED_ICMINFO.
  10234. //
  10235. LOCALFREE(pSavedIcmInfo);
  10236. }
  10237. }
  10238. }