mirror of https://github.com/lianthony/NT4.0
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.
1386 lines
34 KiB
1386 lines
34 KiB
/******************************Module*Header*******************************\
|
|
* Module Name:
|
|
*
|
|
* icmgdi.cxx
|
|
*
|
|
* Abstract
|
|
*
|
|
* This module implements Integrated Color matching GDI support
|
|
*
|
|
* Author:
|
|
*
|
|
* Mark Enstrom (marke) 9-27-93
|
|
*
|
|
* Copyright (c) 1993 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
|
|
#include "precomp.hxx"
|
|
|
|
//
|
|
// global ICM table for storing Color Transforms,
|
|
// These can probably be combined and protected by
|
|
// the same semaphore
|
|
//
|
|
|
|
HCOLORSPACE hStockColorSpace = (HCOLORSPACE)NULL;
|
|
PCOLORSPACE gpStockColorSpace = (PCOLORSPACE)NULL;
|
|
HANDLE ghDefaultICM = (HANDLE)NULL;
|
|
PICMDLL pGlobalIcmDllTable = (PICMDLL)NULL;
|
|
PCOLORXFORM pGlobalColorXformList = (PCOLORXFORM)NULL;
|
|
PWSTR gpIcmDllName = L"ICM32.DLL";
|
|
|
|
#if DBG
|
|
|
|
ULONG IcmDebugLevel = 2;
|
|
|
|
#endif
|
|
|
|
extern DCLEVEL dclevelDefault;
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* ICMLoadRegistryColorMatchers
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Load the named color matcher dll, or it that is NULL
|
|
* then look in registry for DLL identified by profile
|
|
*
|
|
* Arguments:
|
|
*
|
|
* PWSTR pImageColorMatcher
|
|
* PWSTR pProfile
|
|
*
|
|
* Return Value:
|
|
*
|
|
* BOOL Status
|
|
*
|
|
\**************************************************************************/
|
|
PICMDLL
|
|
ICMLoadRegistryColorMatcher(
|
|
PWSTR pImageColorMatcher,
|
|
PWSTR pProfile
|
|
)
|
|
{
|
|
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
//
|
|
// determine a DLL name
|
|
//
|
|
|
|
if (pImageColorMatcher == (PWSTR)NULL) {
|
|
|
|
//
|
|
// map in pProfile, get cmh_CMMType field.
|
|
// this is a 16 bit field where 'KCMS' is the
|
|
// default KODAK color mather icm32.dll. If the value is
|
|
// anyting, look in registry for the ident field. The DLL
|
|
// name is associated with this value
|
|
//
|
|
|
|
//
|
|
// !!! just make it icm32.dll for now
|
|
//
|
|
|
|
pImageColorMatcher = gpIcmDllName;
|
|
|
|
}
|
|
|
|
ICMDLLMEM IcmDllMem;
|
|
|
|
IcmDllMem.bCreateIcmDll(pImageColorMatcher);
|
|
|
|
return(IcmDllMem.pIcmDll);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* InitDeviceIndColor
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* This routine is called once at initialization time. The Stock Logical
|
|
* Color Space is created and saved. Then reg registry is queried for the
|
|
* List of COLOR MATCHER DLLs to load. These DLLs are loaded and saved in
|
|
* the global ICM_COLOR_MATCHER list. This list is not modified after
|
|
* creation.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* None
|
|
*
|
|
* Return Value:
|
|
*
|
|
* BOOL Status
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
InitDeviceIndColor()
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
DbgPrint("\n\nInit Device Independent Color\n\n");
|
|
}
|
|
#endif
|
|
|
|
BOOL Status = FALSE;
|
|
|
|
pGlobalColorXformList = (PCOLORXFORM)NULL;
|
|
pGlobalIcmDllTable = (PICMDLL)NULL;
|
|
|
|
//
|
|
// Init ICM semaphore (!!!can probably use palette semaphopre!!!)
|
|
//
|
|
|
|
gpsemIcmMgmt = hsemCreate();
|
|
|
|
if (gpsemIcmMgmt == NULL) {
|
|
DbgPrint("Error, creation of ICM management semaphore fails\n");
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// define stock color space
|
|
//
|
|
|
|
LOGCOLORSPACEW StockColorSpace = {
|
|
0,
|
|
0x400,
|
|
sizeof(LOGCOLORSPACE),
|
|
1,
|
|
1,
|
|
{
|
|
{0x000006978,0x000005BA4,0x000002E58},
|
|
{0x000003688,0x00000B74C,0x000001270},
|
|
{0x0000004DC,0x000001E78,0x00000F3F8}
|
|
},
|
|
0x1CCCD,
|
|
0x1CCCD,
|
|
0x1CCCD,
|
|
0};
|
|
|
|
|
|
//
|
|
// Create STOCK color space
|
|
//
|
|
|
|
hStockColorSpace = GreCreateColorSpace(&StockColorSpace);
|
|
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
DbgPrint("Stock Color space = %lx\n",hStockColorSpace);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// check failure
|
|
//
|
|
|
|
if (hStockColorSpace == NULL) {
|
|
return(Status);
|
|
}
|
|
|
|
//
|
|
// set the "ILCS_STOCK" flag in the color space just created and add it as
|
|
// the first entry in the global list of color spaces
|
|
//
|
|
|
|
COLORSPACEREF ColorSpaceRef(hStockColorSpace);
|
|
|
|
if (ColorSpaceRef.bValid())
|
|
{
|
|
ColorSpaceRef.pColorSpace->flags(ILCS_STOCK);
|
|
|
|
//
|
|
// set the default color space into the default DC
|
|
//
|
|
|
|
ColorSpaceRef.vSetPID(OBJECT_OWNER_PUBLIC);
|
|
|
|
gpStockColorSpace = ColorSpaceRef.pColorSpace;
|
|
|
|
dclevelDefault.hColorSpace = hStockColorSpace;
|
|
dclevelDefault.pColorSpace = gpStockColorSpace;
|
|
|
|
//
|
|
// Init global list of color transforms
|
|
//
|
|
|
|
COLORXFORMMEM GlobalXform;
|
|
|
|
if (!GlobalXform.bCreateColorXform(NULL,NULL,NULL,NULL,NULL))
|
|
{
|
|
|
|
WARNING("ICM: Memory allocation for COLOR_TRANSFORM sentinell failed");
|
|
Status = FALSE;
|
|
|
|
} else {
|
|
|
|
GlobalXform.vKeepIt();
|
|
GlobalXform.pColorXform->vAddToList();
|
|
|
|
//
|
|
// !!! <should defer this load until needed> load the default color matcher
|
|
//
|
|
|
|
PICMDLL pIcmDll = ICMLoadRegistryColorMatcher(gpIcmDllName,(PWSTR)NULL);
|
|
|
|
if (pIcmDll == (PICMDLL)NULL)
|
|
{
|
|
DbgPrint("!!! Load of default color matcher fails !!!\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* CreateColorTransform
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Create a color transform from the ICM selected to the output
|
|
* devcice indicated by pDCTarget.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* ICMIdent - ICM identifier from DC
|
|
* hdc - DC of device
|
|
* hdcTarget - DC of target only for ColorMatchToTarget
|
|
*
|
|
* Return Value:
|
|
*
|
|
* BOOL Status
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
CreateColorTransform(
|
|
HANDLE ICMIdent,
|
|
HDC hdc,
|
|
HDC hdcTarget
|
|
)
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
BOOL bStatus = FALSE;
|
|
|
|
//
|
|
// check params
|
|
//
|
|
|
|
ASSERTGDI(pGlobalColorXformList != NULL,"ICM: Global color transform list is NULL");
|
|
|
|
if (pGlobalIcmDllTable == (PICMDLL)NULL)
|
|
{
|
|
DbgPrint("CreateColorTransform fails because no ICM Color matcher could be loaded\n");
|
|
return(bStatus);
|
|
}
|
|
|
|
//
|
|
// Get DC, make sure it is valid
|
|
//
|
|
|
|
DCOBJ dco(hdc);
|
|
|
|
if (dco.bValid())
|
|
{
|
|
|
|
PICMDLL pIcmDllObj = pGlobalIcmDllTable;
|
|
PCOLORXFORM pColorXform = pGlobalColorXformList;
|
|
PICMDLL pCurrentICMDll;
|
|
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
DbgPrint("Creaete Color Transform, pColorSapce = %lx\n",dco.pdc->GetPColorSpace());
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// get the file name of the profile for the output device
|
|
//
|
|
|
|
PVOID pvDeviceProfile = pvGetDeviceProfile(dco);
|
|
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
if (pvDeviceProfile == NULL)
|
|
{
|
|
DbgPrint("pvGetDeviceProfile returns NULL\n");
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("pvGetDeviceProfile returns %lx\n",(ULONG)pvDeviceProfile);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Make sure the ICL DLL specified by the DC profile is loaded. This DLL may be
|
|
// needed even in the case where a device driver is in use that implements it's
|
|
// own ICM routines
|
|
//
|
|
|
|
pCurrentICMDll = ICMLoadRegistryColorMatcher((PWSTR)NULL,(PWSTR)pvDeviceProfile);
|
|
|
|
//
|
|
// If the device driver passed in an ICM Ident, this indicates that the device
|
|
// driver has some ICM support. Locate it's DLL entry points in the ICMDLL
|
|
// table and replace pCurrentICMDLl with this.
|
|
//
|
|
|
|
if (ICMIdent != NULL) {
|
|
|
|
//
|
|
// Search ICMDLL table for this ident
|
|
//
|
|
|
|
pCurrentICMDll = pIcmDllObj->pGetICMCallTable((ULONG)ICMIdent);
|
|
}
|
|
|
|
if (pCurrentICMDll != (PICMDLL)NULL)
|
|
{
|
|
|
|
//
|
|
// Search the list of current color transforms for one that matches
|
|
// the device and color space
|
|
//
|
|
|
|
PDEV *pPDev = dco.pdc->ppdev();
|
|
PWSTR pTrgtLDev = (PWSTR)NULL;
|
|
PCOLORSPACE pColorSpTemp = (PCOLORSPACE)dco.pdc->GetPColorSpace();
|
|
ULONG Owner = 0;
|
|
|
|
if (pColorSpTemp == NULL) {
|
|
|
|
//
|
|
// no color space is selected, use stock color space
|
|
//
|
|
|
|
pColorSpTemp = gpStockColorSpace;
|
|
}
|
|
|
|
//
|
|
// The target hdc is only supplied for the color match to target case.
|
|
//
|
|
|
|
DCOBJ dcoTrg(hdcTarget);
|
|
|
|
if (dcoTrg.bValid())
|
|
{
|
|
pTrgtLDev = (PWSTR)dcoTrg.pdc->GetDeviceProfile();
|
|
}
|
|
|
|
//
|
|
// search the color transform list for matching ldev and color space
|
|
//
|
|
|
|
pColorXform = pColorXform->pFindMatchingColorXform(pColorSpTemp,pPDev,pTrgtLDev,Owner);
|
|
|
|
|
|
if (pColorXform == (PCOLORXFORM)NULL)
|
|
{
|
|
//
|
|
// must create new color transform
|
|
//
|
|
|
|
COLORXFORMMEM NewColorXform;
|
|
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
DbgPrint("Create New Color Transform\n");
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Need to allocate and fill in a new ColorTransform
|
|
//
|
|
|
|
|
|
if (NewColorXform.bCreateColorXform(pColorSpTemp,pPDev,pTrgtLDev,Owner,pCurrentICMDll))
|
|
{
|
|
|
|
//
|
|
// call CMCreateTransform
|
|
//
|
|
|
|
PFN_CM_CREATE_TRANSFORM pfnCreate;
|
|
|
|
pfnCreate = (PFN_CM_CREATE_TRANSFORM)NewColorXform.pColorXform->pIcmDll->CMCreateTransform;
|
|
|
|
NewColorXform.pColorXform->hxform(
|
|
pfnCreate(
|
|
NewColorXform.pColorXform->pIlcs
|
|
,pvDeviceProfile,
|
|
NULL
|
|
)
|
|
);
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
DbgPrint(" New Transform handle = 0x%lx\n",NewColorXform.pColorXform->hXform);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Is the transform valid
|
|
//
|
|
|
|
if ((ULONG)NewColorXform.pColorXform->hxform() <= COLORXFORM_ERROR_MAX)
|
|
{
|
|
|
|
//
|
|
// the handle returned in not valid, this call fails
|
|
//
|
|
|
|
WARNING("ICM: ICM DLL did net create valid color transform");
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// Add color transform to the end of the list of color transforms
|
|
//
|
|
|
|
NewColorXform.vKeepIt();
|
|
NewColorXform.pColorXform->vAddToList();
|
|
|
|
NewColorXform.vSetPID(W32GetCurrentPID());
|
|
|
|
pColorXform = NewColorXform.pColorXform;
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
DbgPrint("Allocation of new color transform fails\n");
|
|
}
|
|
|
|
}
|
|
|
|
if ((pColorXform != (PCOLORXFORM)NULL))
|
|
{
|
|
|
|
//
|
|
// set the color transform in the dc
|
|
//
|
|
|
|
dco.pdc->SetColorTransform(pColorXform);
|
|
dco.pdc->hcmXform(pColorXform->hXform);
|
|
|
|
bStatus = TRUE;
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return(bStatus);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* DeleteColorTransform
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Delete color transform specified by object handle
|
|
*
|
|
* Arguments:
|
|
* hColorXform handle of objext
|
|
*
|
|
* Return Value:
|
|
*
|
|
* BOOL Status
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
bDeleteColorTransform(
|
|
HANDLE hObj
|
|
)
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
//
|
|
// select color transform
|
|
//
|
|
|
|
COLORXFORMREF cxForm((HCOLORXFORM)hObj);
|
|
|
|
if (cxForm.bValid())
|
|
{
|
|
|
|
//
|
|
// remove from list for xforms
|
|
//
|
|
|
|
cxForm.pColorXform->vRemoveFromList();
|
|
|
|
ASSERTGDI(HmgQueryLock((HOBJ) hObj) == 0, "bDeleteColorXform cLock != 0");
|
|
|
|
if (HmgRemoveObject((HOBJ) hObj, 0, 2, FALSE, ICMCXF_TYPE))
|
|
{
|
|
|
|
FREEOBJ(cxForm.pColorXform, ICMCXF_TYPE);
|
|
|
|
cxForm.pColorXform = (PCOLORXFORM)NULL;
|
|
|
|
bRet = TRUE;
|
|
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("HmgRemoveObject fails\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DbgPrint("failed to init color xform from handle %lx\n",hObj);
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
BOOL bDeleteColorSpace(HCOLORSPACE)
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* vCleanupICM
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* remove all color transforms owned by process pid
|
|
*
|
|
* Arguments:
|
|
*
|
|
* Process quitting
|
|
*
|
|
* Return Value:
|
|
*
|
|
*
|
|
\**************************************************************************/
|
|
VOID
|
|
vCleanupICM(
|
|
W32PID pid
|
|
)
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
|
|
//
|
|
// remove color transforms and color spaces owned by this pid
|
|
//
|
|
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
DbgPrint("vCleanupICM, pid = 0x%lx\n",pid);
|
|
}
|
|
#endif
|
|
|
|
HOBJ hobj = HmgNextOwned((HOBJ) 0, pid);
|
|
|
|
for (;(hobj != (HOBJ) NULL);hobj = HmgNextOwned(hobj, pid))
|
|
{
|
|
|
|
if (HmgObjtype(hobj) == ICMLCS_TYPE)
|
|
{
|
|
|
|
HmgSetLock(hobj, 0);
|
|
GreDeleteColorSpace((HCOLORSPACE)hobj);
|
|
|
|
}
|
|
|
|
else if (HmgObjtype(hobj) == ICMCXF_TYPE)
|
|
|
|
{
|
|
|
|
HmgSetLock(hobj, 0);
|
|
bDeleteColorTransform((HCOLORXFORM)hobj);
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Locate a pointer to the name of a profile to use.
|
|
* First it looks in the dc to see if we've done this before on this dc.
|
|
* Then it looks in the ldev to see if we've done this before on this ldev.
|
|
* If not done before, then search registry.ini for a profile for this
|
|
* dc. Then update the field in the dc.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* xdco - locked dc object
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Pointer to device profile or NULL
|
|
*
|
|
\**************************************************************************/
|
|
PVOID
|
|
pvGetDeviceProfile(
|
|
XDCOBJ xdco
|
|
)
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
ULONG ulIntent;
|
|
WCHAR NonFriendly[32];
|
|
WCHAR ProfileNameBuffer[MAX_PATH];
|
|
PWSTR pDeviceProfile = (PWSTR)NULL;
|
|
|
|
return(NULL);
|
|
|
|
//
|
|
// Look in DC for profile pointer
|
|
//
|
|
|
|
pDeviceProfile = (PWSTR)xdco.pdc->GetDeviceProfile();
|
|
|
|
if (pDeviceProfile == (PVOID)NULL)
|
|
{
|
|
|
|
PCOLORSPACE pColorSpace = (PCOLORSPACE)xdco.pdc->GetPColorSpace();
|
|
ULONG Intent;
|
|
BOOL bStatus;
|
|
|
|
//
|
|
// if DC ColorSpace is NULL, use stock ColorSpace
|
|
//
|
|
|
|
if (pColorSpace == (PCOLORSPACE)NULL)
|
|
{
|
|
pColorSpace = gpStockColorSpace;
|
|
}
|
|
|
|
Intent = pColorSpace->csIntent;
|
|
|
|
PDEVOBJ pdo(xdco.hdev());
|
|
|
|
//
|
|
// is the device a display
|
|
//
|
|
|
|
if (pdo.pldev()->ldevType == LDEV_DEVICE_DISPLAY)
|
|
{
|
|
bStatus = icm_FindMonitorProfile(&ProfileNameBuffer[0],Intent);
|
|
|
|
//
|
|
// fails
|
|
//
|
|
|
|
if (!bStatus)
|
|
{
|
|
goto pvGetDeviceProfileExit;
|
|
}
|
|
|
|
//
|
|
// ok, returns a good profile string, now what??
|
|
//
|
|
|
|
//
|
|
// allcate real memory for the profile and keep it
|
|
//
|
|
|
|
pDeviceProfile = (PWSTR)PALLOCMEM(sizeof(WCHAR) * wcslen(ProfileNameBuffer), 'mciG');
|
|
|
|
if (pDeviceProfile == (PWSTR)NULL)
|
|
{
|
|
goto pvGetDeviceProfileExit;
|
|
}
|
|
|
|
wcscat(pDeviceProfile,ProfileNameBuffer);
|
|
|
|
|
|
xdco.pdc->SetDeviceProfile(pDeviceProfile);
|
|
|
|
}
|
|
else
|
|
{
|
|
if (pdo.pldev()->ldevType == LDEV_DEVICE_PRINTER)
|
|
{
|
|
//
|
|
//BUGBUG PRINTER_INFO
|
|
// //
|
|
// // get the spooler handle
|
|
// //
|
|
//
|
|
// PDEVOBJ pDevObj(xdco.pdc->ppdev());
|
|
// HANDLE hSpooler = pDevObj.hSpooler();
|
|
//
|
|
// if (hSpooler != (HANDLE)NULL)
|
|
// {
|
|
//
|
|
// //
|
|
// // get printer name info, first find out how big this memory is
|
|
// //
|
|
//
|
|
// DWORD cb;
|
|
// PPRINTER_INFO_2W pDrivNew = (PPRINTER_INFO_2W)NULL;
|
|
//
|
|
// if (GetPrinterW(hSpooler,2,NULL,0,&cb))
|
|
// {
|
|
//
|
|
// pDrivNew = (PPRINTER_INFO_2W)PALLOCNOZ(cb, 'mciG');
|
|
//
|
|
// if (pDrivNew != (PPRINTER_INFO_2W)NULL)
|
|
// {
|
|
//
|
|
// //
|
|
// // now actually get printer info
|
|
// //
|
|
//
|
|
// if (GetPrinterW(hSpooler,2,(LPBYTE)pDrivNew,cb,&cb))
|
|
// {
|
|
//
|
|
// //
|
|
// // search for printer profile
|
|
// //
|
|
//
|
|
// bStatus = icm_FindPrinterProfile(
|
|
// &ProfileNameBuffer[0],
|
|
// pDrivNew->pDevMode,
|
|
// pDrivNew->pPrinterName,
|
|
// Intent
|
|
// );
|
|
//
|
|
// if (bStatus)
|
|
// {
|
|
//
|
|
// //
|
|
// // !!! pDeviceProfile never gets freed !!!
|
|
// //
|
|
//
|
|
// pDeviceProfile = (PWSTR) PALLOCNOZ(sizeof(WCHAR) * lstrlenW(ProfileNameBuffer), 'mciG');
|
|
//
|
|
// if (pDeviceProfile == (PWSTR)NULL)
|
|
// {
|
|
// goto pvGetDeviceProfileExit;
|
|
// }
|
|
//
|
|
// if (IcmDebugLevel >= 2)
|
|
// {
|
|
// DbgPrint("pvGetDeviceProfile returns %s\n",ProfileNameBuffer);
|
|
// }
|
|
//
|
|
// lstrcatW(pDeviceProfile,ProfileNameBuffer);
|
|
//
|
|
// xdco.pdc->SetDeviceProfile(pDeviceProfile);
|
|
// }
|
|
// }
|
|
//
|
|
// //
|
|
// // free allocated memory
|
|
// //
|
|
//
|
|
// VFREEMEM(pDrivNew);
|
|
// }
|
|
// }
|
|
//
|
|
// }
|
|
//
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// error
|
|
//
|
|
|
|
DbgPrint("pvGetDeviceProfile call on a non-Display and non-printer LDEV\n");
|
|
goto pvGetDeviceProfileExit;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
return(pDeviceProfile);
|
|
|
|
pvGetDeviceProfileExit:
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* For a driver that supports ICM. This call registers the driver's ICM
|
|
* entry points in the global ICM DLL table so that DCs can call it.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hDeviceModule - module handle of driver dll
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
HookInDeviceICM(
|
|
HANDLE hDeviceModule
|
|
)
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
BOOL bStatus = FALSE;
|
|
ICMDLLMEM IcmDllMemObj;
|
|
|
|
|
|
bStatus = IcmDllMemObj.bCreateIcmDll((PUSHORT) hDeviceModule);
|
|
|
|
return(bStatus);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Removes the DLL from the ICM DLL list and frees memory
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hDeviceModule - module handle of driver dll
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
UnhookDeviceICM(
|
|
HANDLE hDeviceModule
|
|
)
|
|
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
BOOL bStatus = TRUE;
|
|
return(bStatus);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* ICMTranslateDIB
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* ICM Translate DIB in place using Dest DC Color Transform
|
|
*
|
|
* Arguments:
|
|
*
|
|
* xdco - Destination DC object
|
|
* pInfoHeader - DIB Format information
|
|
* pDIB - DIB Pixels
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
PBYTE
|
|
IcmTranslateDIB(
|
|
XDCOBJ xdco,
|
|
LONG iUsage,
|
|
ULONG uiBitCount,
|
|
ULONG uiCompression,
|
|
PULONG pulColors,
|
|
ULONG uiWidth,
|
|
LONG cNumScans,
|
|
PVOID pDIB
|
|
)
|
|
{
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
DbgPrint("IcmTranslateDIB\n");
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// default return initial bit pointer
|
|
//
|
|
|
|
PBYTE pbRet = (PBYTE)pDIB;
|
|
ULONG CmsFormat;
|
|
BOOL bIllegalFormat = FALSE;
|
|
|
|
//
|
|
// if ICM is enabled,
|
|
// the driver doesn't do its own ICM,
|
|
// its not a palette device,
|
|
// and the DIB is high color ( > 8 bpp)
|
|
//
|
|
|
|
PDEVOBJ pdo(xdco.pdc->hdev());
|
|
|
|
if (
|
|
(xdco.pdc->GetICMMode() & DC_DIC_ON) && //(driver level != CMS_LEVEL2 or CMS_LEVEL3) &&
|
|
(!pdo.bIsPalManaged()) &&
|
|
(uiBitCount > 8)
|
|
)
|
|
{
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
|
|
//
|
|
// can't do custom formats or RLE
|
|
//
|
|
|
|
if (
|
|
(uiCompression < BI_BITFIELDS) &&
|
|
(uiCompression != BI_RLE8) &&
|
|
(uiCompression != BI_RLE4)
|
|
)
|
|
{
|
|
|
|
//
|
|
// determine format
|
|
//
|
|
|
|
|
|
switch (uiBitCount) {
|
|
case 16:
|
|
{
|
|
//
|
|
// assume 555
|
|
//
|
|
|
|
CmsFormat = CMS_x555WORD;
|
|
|
|
if (uiCompression != BI_RGB) {
|
|
|
|
//
|
|
// if compression is a 16bpp bitfield, find out which format it is,
|
|
// 565 is the only other 16bpp format supported
|
|
//
|
|
// 0000 0000 0000 0000 1111 1000 0000 0000 R
|
|
// 0000 0000 0000 0000 0000 0111 1110 0000 G
|
|
// 0000 0000 0000 0000 0000 0000 0001 1111 B
|
|
//
|
|
|
|
if (
|
|
(pulColors[0] = 0x0000F800) &&
|
|
(pulColors[1] = 0x000007E0) &&
|
|
(pulColors[2] = 0x0000001F)
|
|
)
|
|
{
|
|
CmsFormat = CMS_x565WORD;
|
|
|
|
} else {
|
|
|
|
//
|
|
// format not supported
|
|
//
|
|
|
|
bIllegalFormat = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case 24:
|
|
{
|
|
//
|
|
// assume 24 bit RGB
|
|
//
|
|
|
|
CmsFormat = CMS_RGBTRIPL;
|
|
|
|
if (uiCompression != BI_RGB) {
|
|
|
|
if (
|
|
(pulColors[0] = 0x000000FF) &&
|
|
(pulColors[1] = 0x0000FF00) &&
|
|
(pulColors[2] = 0x00FF0000)
|
|
)
|
|
{
|
|
CmsFormat = CMS_BGRTRIPL;
|
|
|
|
} else {
|
|
|
|
//
|
|
// format not supported
|
|
//
|
|
|
|
bIllegalFormat = TRUE;
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case 32:
|
|
{
|
|
//
|
|
// assume RGB
|
|
//
|
|
|
|
CmsFormat = CMS_XRGBQUAD;
|
|
|
|
if (uiCompression != BI_RGB) {
|
|
|
|
if (
|
|
(pulColors[0] = 0x000000FF) &&
|
|
(pulColors[1] = 0x0000FF00) &&
|
|
(pulColors[2] = 0x00FF0000)
|
|
)
|
|
{
|
|
CmsFormat = CMS_XBGRQUADS;
|
|
|
|
} else {
|
|
|
|
//
|
|
// format not supported
|
|
//
|
|
|
|
bIllegalFormat = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
break;
|
|
|
|
//
|
|
// illegal uiBitCount
|
|
//
|
|
|
|
default:
|
|
bIllegalFormat = TRUE;
|
|
break;
|
|
}
|
|
|
|
if (!bIllegalFormat)
|
|
{
|
|
|
|
//
|
|
// allocate a buffer for return values
|
|
//
|
|
|
|
ULONG ulBufSize = uiWidth * cNumScans * (uiBitCount / 8);
|
|
|
|
PBYTE pbBuffer = (PBYTE)PALLOCNOZ(ulBufSize, 'mciG');
|
|
|
|
if (pbBuffer == (PBYTE)NULL)
|
|
{
|
|
|
|
WARNING("Allocation of temporary buffer failed IcmTranslateDIB\n");
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
//
|
|
// call ICM translate DLL
|
|
//
|
|
|
|
PFN_CM_TRAN_RGBS pfnXlate;
|
|
PCOLORXFORM pTrans;
|
|
|
|
pTrans = (PCOLORXFORM)xdco.pdc->GetColorTransform();
|
|
|
|
if (pTrans != (PCOLORXFORM)NULL)
|
|
{
|
|
|
|
pfnXlate = (PFN_CM_TRAN_RGBS)pTrans->pIcmDll->CMTranslateRGBs;
|
|
|
|
if (pfnXlate != (PFN_CM_TRAN_RGBS)NULL)
|
|
{
|
|
#if DBG
|
|
if (IcmDebugLevel >= 2)
|
|
{
|
|
DbgPrint("IcmTranslateDIB: call ICM DLL\n");
|
|
}
|
|
#endif
|
|
|
|
if (pfnXlate(pTrans->hXform,
|
|
pDIB,
|
|
CmsFormat,
|
|
uiWidth,
|
|
cNumScans,
|
|
0,
|
|
(LPVOID)pbBuffer,
|
|
CmsFormat,
|
|
CMS_FORWARD))
|
|
{
|
|
|
|
//
|
|
// OK, assign buffer
|
|
//
|
|
|
|
pbRet = pbBuffer;
|
|
|
|
}
|
|
else
|
|
{
|
|
WARNING("Call to CMTranslateRGBs failed\n");
|
|
VFREEMEM(pbBuffer);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WARNING("Could not locate ICM DLL routine CMTranslateRGBs\n");
|
|
VFREEMEM(pbBuffer);
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WARNING("Color transform for DC is NULL but ICM is enabled\n");
|
|
VFREEMEM(pbBuffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(pbRet);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* ICMTranslatePALENTRY
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Translate an RGB value based on the ColorTransform selected in hDC
|
|
* and ulTranslateFlag.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* xdco - Destination DC OBJECT
|
|
* pColor - Color to translate
|
|
* ulTranslateFlag - Forward or Backward
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Status
|
|
*
|
|
\**************************************************************************/
|
|
BOOL
|
|
IcmTranslatePALENTRY(
|
|
XDCOBJ xdco,
|
|
PAL_ULONG* pColor,
|
|
ULONG ulTranslateFlag
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
//
|
|
// Get the DC object from hDC and validatem then check if
|
|
// ICM is enabled for this DC
|
|
//
|
|
|
|
if (xdco.bValid())
|
|
{
|
|
if (xdco.pdc->GetICMMode() & DC_DIC_ON) {
|
|
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
|
|
ULONG Index;
|
|
COLORQUAD RgbSrc,RgbTran;
|
|
PFN_CM_TRAN_RGB pfnXlate;
|
|
PCOLORXFORM pTrans = (PCOLORXFORM)xdco.pdc->GetColorTransform();
|
|
|
|
//
|
|
// ICM is enabled, convert the color in place
|
|
//
|
|
|
|
if (pTrans != (PCOLORXFORM)NULL) {
|
|
|
|
pfnXlate = (PFN_CM_TRAN_RGB)pTrans->pIcmDll->CMTranslateRGB;
|
|
|
|
if (pfnXlate != (PFN_CM_TRAN_RGB)NULL) {
|
|
|
|
//
|
|
// translate
|
|
//
|
|
|
|
RgbSrc.RGB.rgbRed = pColor->pal.peRed;
|
|
RgbSrc.RGB.rgbGreen = pColor->pal.peGreen;
|
|
RgbSrc.RGB.rgbBlue = pColor->pal.peBlue;
|
|
RgbSrc.RGB.rgbReserved = 0;
|
|
|
|
if (pfnXlate(pTrans->hXform,RgbSrc.COLOR,&RgbTran.COLOR,ulTranslateFlag))
|
|
{
|
|
pColor->pal.peRed = RgbTran.RGB.rgbRed;
|
|
pColor->pal.peGreen = RgbTran.RGB.rgbGreen;
|
|
pColor->pal.peBlue = RgbTran.RGB.rgbBlue;
|
|
}
|
|
bReturn = TRUE;
|
|
|
|
} else {
|
|
|
|
WARNING("HDC has ICM enabled but a NULL CMTranslateRGB");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
WARNING("HDC has ICM enabled but a NULL Color Transform");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// just return true, nothing to do
|
|
//
|
|
|
|
bReturn = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
return(bReturn);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name
|
|
*
|
|
* ICMSetPhysicalColor
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* Given a physical color, determine if ICM is enabled. If ICM
|
|
* is enabled then determine whether to translate the color now
|
|
* or leave it as is:
|
|
*
|
|
* Translate when: ICM Enabled,
|
|
* Dest not palette device
|
|
* Dest Driver does not do ICM
|
|
*
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pdc - Destination DC OBJECT
|
|
* pColorIn - RGB to translate
|
|
*
|
|
* Return Value:
|
|
*
|
|
* RGB Result, pColorIn if error or no translate
|
|
*
|
|
\**************************************************************************/
|
|
COLORREF
|
|
IcmSetPhysicalColor(
|
|
PCOLORXFORM pColorXform,
|
|
LPCOLORREF pColorIn
|
|
)
|
|
{
|
|
|
|
//
|
|
// validate params
|
|
//
|
|
|
|
ASSERTGDI(pColorIn != (LPCOLORREF)NULL,"ERROR: ICM Passed NULL Color pColorIn");
|
|
|
|
COLORREF ColorRet = *pColorIn;
|
|
|
|
if (pColorXform != (PCOLORXFORM)NULL)
|
|
{
|
|
|
|
ASSERTGDI(FALSE,"Shouldn't be calling ICM functions");
|
|
|
|
//
|
|
// is the destination a palette device?
|
|
//
|
|
// what if color specifies PALETTEINDEX ?
|
|
// RGB ?
|
|
// PALETTERGB ?
|
|
//
|
|
|
|
//
|
|
// Color must be translated
|
|
//
|
|
|
|
PFN_CM_TRAN_RGB pfnXlate;
|
|
|
|
//
|
|
// Check values, then translate
|
|
//
|
|
|
|
if (pColorXform->pIcmDll != (PICMDLL)NULL)
|
|
{
|
|
|
|
pfnXlate = (PFN_CM_TRAN_RGB)(pColorXform->pIcmDll->CMTranslateRGB);
|
|
|
|
if (pfnXlate != (PFN_CM_TRAN_RGB)NULL)
|
|
{
|
|
|
|
//
|
|
// translate
|
|
//
|
|
|
|
COLORREF ColorTemp;
|
|
|
|
if (pfnXlate(pColorXform->hXform,*pColorIn,&ColorTemp,CMS_FORWARD))
|
|
{
|
|
ColorRet = ColorTemp;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
WARNING("IcmSetPhysicalColor: NULL CMTranslateRGB");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARNING("IcmSetPhysicalColor: PCOLORSPACE has NULL PICMDLL");
|
|
DbgPrint("IcmSetPhysicalColor: pColorXform = %lx\n",pColorXform);
|
|
DbgPrint("IcmSetPhysicalColor: pColorIn = %lx\n",pColorIn);
|
|
}
|
|
}
|
|
|
|
return(ColorRet);
|
|
}
|
|
|