|
|
/*******************************Module*Header*******************************\
* Module Name: * * icmobj.cxx * * Abstract * * This module contains object support for COLORTRANSFORM objects and ICM * Objects * * Author: * * Feb.23.1997 -by- Hideyuki Nagase [hideyukn] * * Copyright (c) 1997-1999 Microsoft Corporation \**************************************************************************/
#include "precomp.hxx"
/******************************Public*Routine******************************\
* COLORTRANSFORMOBJ::hCreate() * * History: * * Write it: * 23-Feb-1997 -by- Hideyuki Nagase [hideyukn] \**************************************************************************/
HANDLE COLORTRANSFORMOBJ::hCreate( XDCOBJ& dco, LOGCOLORSPACEW *pLogColorSpaceW, PVOID pvSource, ULONG cjSource, PVOID pvDestination, ULONG cjDestination, PVOID pvTarget, ULONG cjTarget ) { HANDLE hObject = NULL;
PCOLORTRANSFORM pNewCXform = NULL;
ICMAPI(("COLORTRANSFORM::hCreate()\n"));
HDEV hdev = dco.hdev();
//
// This object should not have any existing realization.
//
ASSERTGDI(_pColorTransform == NULL,"COLORTRANSFORMOBJ::hCreate() object is exist\n");
PDEVOBJ po(hdev);
if (po.bValid()) { //
// Allocate ColorTransform object.
//
pNewCXform = (PCOLORTRANSFORM) ALLOCOBJ(sizeof(COLORTRANSFORM),ICMCXF_TYPE, FALSE);
if (pNewCXform) { //
// Register COLORTRANSFORM handle.
//
hObject = (HCOLORSPACE)HmgInsertObject( pNewCXform, HMGR_ALLOC_ALT_LOCK, ICMCXF_TYPE);
if (hObject) { HANDLE hDeviceColorTransform = NULL;
//
// Set new object to this COLORTRANSFORMNOBJ
//
_pColorTransform = pNewCXform;
//
// Lock device
//
DEVLOCKOBJ devLock(po);
//
// Create driver's transform.
//
if (PPFNVALID(po,IcmCreateColorTransform)) { //
// Call device driver to obtain handle of device driver.
//
hDeviceColorTransform = (*PPFNDRV(po, IcmCreateColorTransform)) ( po.dhpdev(), pLogColorSpaceW, pvSource, cjSource, pvDestination, cjDestination, pvTarget, cjTarget, 0 /* dwReserved */); } else { WARNING("CreateColorTransform called on device that does not support call\n"); SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER); }
if (hDeviceColorTransform) { ICMMSG(("CreateColorTransform(): Succeed to get handle from driver\n"));
//
// Set the handle to COLORTRANSFORM object.
//
vSetDeviceColorTransform(hDeviceColorTransform);
//
// Insert this pColorTransform to this DC.
//
dco.bAddColorTransform(hObject); } else { ICMMSG(("CreateColorTransform(): Fail to get handle from driver\n"));
//
// Mark this object does not have driver's realization.
//
vSetDeviceColorTransform(NULL);
//
// We are fail to get driver's handle, delete this.
//
bDelete(dco);
//
// Invalidate hObject and pColorTransform.
// (these are deleted in above bDelete())
//
hObject = NULL; pNewCXform = NULL; } } } else { SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY); }
if ((hObject == NULL) && (pNewCXform != NULL)) { FREEOBJ(pNewCXform,ICMCXF_TYPE); } }
return (hObject); }
/******************************Public*Routine******************************\
* COLORTRANSFORMOBJ::bDelete() * * History: * * Write it: * 23-Feb-1997 -by- Hideyuki Nagase [hideyukn] \**************************************************************************/
BOOL COLORTRANSFORMOBJ::bDelete(XDCOBJ& dco,BOOL bProcessCleanup) { BOOL bRet = FALSE;
PCOLORTRANSFORM pDeleteXCForm;
ICMAPI(("COLORTRANSFORM::bDelete()\n"));
if (bValid()) { BOOL bCanBeRemoved;
//
// Get colortransform object handle.
//
HANDLE hObject = _pColorTransform->hColorTransform();
//
// Unlock it. (this was locked in constructor).
//
DEC_SHARE_REF_CNT(_pColorTransform);
//
// Remote from object table.
//
bCanBeRemoved = (BOOL)(ULONG_PTR)HmgRemoveObject((HOBJ)(hObject),0,0,TRUE,ICMCXF_TYPE);
if (bCanBeRemoved) { HANDLE hDeviceColorTransform;
//
// Yes, we can remove object from object table, try to delete driver's realization.
//
ICMMSG(("DeleteColorTransform(): Succeed to remove object from table\n"));
//
// Get device driver's handle.
//
hDeviceColorTransform = hGetDeviceColorTransform();
if (hDeviceColorTransform) { //
// Initialize PDEV object with owner.
//
PDEVOBJ po(dco.hdev());
if (po.bValid()) { if (po.bUMPD() && bProcessCleanup) { ICMMSG(("DeleteColorTransform():Will not callout to user mode since UMPD.\n"));
//
// Overwrite driver transform as NULL.
//
vSetDeviceColorTransform(NULL); } else { DEVLOCKOBJ devLock(po);
//
// Delete driver's realization.
//
if (PPFNVALID(po,IcmDeleteColorTransform)) { //
// Call device driver to free driver's handle
//
if ((*PPFNDRV(po, IcmDeleteColorTransform))( po.dhpdev(), hDeviceColorTransform)) { ICMMSG(("DeleteColorTransform():Succeed to IcmDeleteColorTransform()\n"));
//
// This object does not have driver realization anymore.
//
vSetDeviceColorTransform(NULL); } else { WARNING("DeleteColorTransform():Fail to IcmDeleteColorTransform()\n"); } } else { WARNING("DeleteColorTransform called on device that does not support call\n"); SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER); } } } } else { ICMMSG(("DeleteColorTransform(): There is no driver handle\n")); }
//
// We could delete object allocation if there is no driver's realization.
//
if (hGetDeviceColorTransform() == NULL) { //
// Remove this pColorTransform from DC.
//
dco.bRemoveColorTransform(hObject);
//
// Free it.
//
FREEOBJ(_pColorTransform,ICMCXF_TYPE);
//
// Invalidate pointer.
//
_pColorTransform = NULL;
//
// Yes, everything fine!
//
bRet = TRUE; } } else { ICMMSG(("DeleteColorTransform(): Fail to remove object from table\n")); }
//
// If we could not remove this object from object table, or could not
// delete object (including driver's realization)
//
if ((!bCanBeRemoved) || (!bRet)) { //
// can not delete now. somebody will using...
//
WARNING("COLORTRANSFORMOBJ::vDelete(): Fail to Delete object, lazy deletion may happen\n");
//
// Back reference counter (deconstuctor will decrement this).
//
INC_SHARE_REF_CNT(_pColorTransform);
//
// Anyway, we will delete later at cleanup.
//
bRet = TRUE; } }
return (bRet); }
/******************************Public*Routine******************************\
* XDCOBJ::bAddColorTransform() * * History: * * Write it: * 27-Feb-1997 -by- Hideyuki Nagase [hideyukn] \**************************************************************************/
BOOL XDCOBJ::bAddColorTransform(HANDLE hCXform) { CXFLIST *pCXFListThis;
//
// Allocate new cell of CXFLIST
//
pCXFListThis = (CXFLIST *) PALLOCMEM(sizeof(CXFLIST),'ddaG');
if (pCXFListThis) { //
// Fill up CXFLIST structure
//
pCXFListThis->hCXform = hCXform; pCXFListThis->pNext = pdc->pCXFList;
//
// Insert this into top of list.
//
pdc->pCXFList = pCXFListThis;
return (TRUE); } else { ICMMSG(("XDCOBJ::bAddColorTransform() Failed\n")); return (FALSE); } }
/******************************Public*Routine******************************\
* XDCOBJ::bRemoveColorTransform() * * History: * * Write it: * 27-Feb-1997 -by- Hideyuki Nagase [hideyukn] \**************************************************************************/
BOOL XDCOBJ::bRemoveColorTransform(HANDLE hCXform) { if (pdc->pCXFList) { PCXFLIST pPrev, pThis;
pPrev = pThis = pdc->pCXFList;
while (pThis) { if (pThis->hCXform == hCXform) { //
// This is the cell, we need to remove.
//
if (pPrev == pThis) { //
// We are going to remove first cell. then need to
// update root.
//
pdc->pCXFList = pThis->pNext; } else { //
// Remove this from list.
//
pPrev->pNext = pThis->pNext; }
//
// Invalidate root.
//
VFREEMEM(pThis);
return (TRUE); }
//
// Move to next cell
//
pPrev = pThis; pThis = pThis->pNext; } } else { ICMMSG(("bRemoveColorTransform():There is no colortransform()\n")); }
return (FALSE); }
/******************************Public*Routine******************************\
* XDCOBJ::vCleanupColorTransform() * * History: * * Write it: * 27-Feb-1997 -by- Hideyuki Nagase [hideyukn] \**************************************************************************/
VOID XDCOBJ::vCleanupColorTransform(BOOL bProcessCleanup) { if (pdc->pCXFList) { PCXFLIST pLast, pThis;
pThis = pdc->pCXFList;
while (pThis) { COLORTRANSFORMOBJ CXformObj(pThis->hCXform);
pLast = pThis;
if (CXformObj.bValid()) { //
// Delete this color transform
//
if (CXformObj.bDelete(*this,bProcessCleanup)) { ICMMSG(("vCleanupColorTransform():Delete colortransform in this DC\n")); } else { ICMMSG(("vCleanupColorTransform():Fail to delete colortransform in this DC\n")); } }
//
// we don't need to walk through the list, because above COLORTRANSFORMOBJ.bDelete()
// will re-chain this list, then we just pick up the cell on the top of list everytime.
//
pThis = pdc->pCXFList;
//
// But if still new pThis is eqaul to pLast, this means we might fail to
// delete object or un-chain list, then just un-chain this forcely.
//
if (pThis == pLast) { //
// Skip pThis.
//
pThis = pThis->pNext;
//
// Update root too,
//
pdc->pCXFList = pThis; } } } else { // ICMMSG(("vCleanupColorTransform():There is no color transform in this DC\n"));
} }
/******************************Public*Routine******************************\
* XEPALOBJ::CorrectColors() * * History: * * Write it: * 29-Apr-1997 -by- Hideyuki Nagase [hideyukn] \**************************************************************************/
VOID XEPALOBJ::CorrectColors(PPALETTEENTRY ppalentry, ULONG cEntries) { ICMMSG(("XEPALOBJ::CorrectColors\n"));
PDEVOBJ po(hdevOwner());
if (po.bValid()) { if (po.bHasGammaRampTable()) { ICMMSG(("XEPALOBJ::CorrectColors(): Do Gamma Correction\n")); ICMMSG(("XEPALOBJ::CorrectColors(): GammaRamp Owner HDEV = %x\n",po.hdev()));
PGAMMARAMP_ARRAY pGammaRampArray = (PGAMMARAMP_ARRAY)(po.pvGammaRampTable());
for (ULONG i = 0; i < cEntries; i++) { //
// Adjust colors based on GammaRamp table.
//
ppalentry->peRed = (pGammaRampArray->Red[ppalentry->peRed]) >> 8; ppalentry->peGreen = (pGammaRampArray->Green[ppalentry->peGreen]) >> 8; ppalentry->peBlue = (pGammaRampArray->Blue[ppalentry->peBlue]) >> 8;
//
// next palette entry
//
ppalentry++; } } else { ICMMSG(("XEPALOBJ::CorrectColors(): PDEV does not have Gamma Table\n")); } } else { ICMMSG(("XEPALOBJ::CorrectColors(): PDEV is invalid\n")); } }
/******************************Public*Routine******************************\
* UpdateGammaRampOnDevice() * * History: * * Write it: * 29-Apr-1997 -by- Hideyuki Nagase [hideyukn] \**************************************************************************/
BOOL UpdateGammaRampOnDevice(HDEV hdev,BOOL bForceUpdate) { BOOL bRet = FALSE;
ICMMSG(("UpdateGammaRampOnDevice()\n"));
PDEVOBJ po(hdev);
if (po.bValid()) { ICMMSG(("UpdateGammaRampOnDevice():Set GammaRamp to HDEV = %x\n",po.hdev()));
if ((po.iDitherFormat() == BMF_8BPP) || (po.iDitherFormat() == BMF_16BPP) || (po.iDitherFormat() == BMF_24BPP) || (po.iDitherFormat() == BMF_32BPP)) { //
// Driver might provide the entry point.
//
if ((PPFNVALID(po, IcmSetDeviceGammaRamp)) && (po.flGraphicsCaps2() & GCAPS2_CHANGEGAMMARAMP)) { //
// PDEV should have GammaRampTable
//
if (po.bHasGammaRampTable()) { ICMMSG(("UpdateGammaRampOnDevice():Call SetDeviceGammaRamp()\n"));
//
// Call device driver to set new GammaRamp.
//
bRet = (*PPFNDRV(po, IcmSetDeviceGammaRamp))(po.dhpdev(), IGRF_RGB_256WORDS, po.pvGammaRampTable()); } } else { //
// if the drive does not support, we will simulate it only for 8bpp case.
//
if ((po.iDitherFormat() == BMF_8BPP) && (po.bIsPalManaged())) { ICMMSG(("UpdateGammaRampOnDevice(): Call SetPalette()\n"));
//
// Check:
// 1) Are we going to reset pallete forcely ? (ex. back to default GammaRamp)
// 2) Or, Adjust Palette based on GammaRamp in PDEV.
//
if (bForceUpdate || po.bHasGammaRampTable()) { //
// Get palette on device surface.
//
XEPALOBJ palSurf(po.ppalSurf());
ASSERTGDI(palSurf.bIsIndexed(),"UpdateGammaRampOnDevice(): Palette is not indexed\n");
//
// Mark this palette need to Gamma correction
// (if this is not default GammaRamp, default GammaRamp case
// PDEV does not have table.)
//
palSurf.bNeedGammaCorrection(po.bHasGammaRampTable());
//
// And put owner of PDEV which has GammaRamp table.
// (if they already has some value in there, we will
// overwrite it, but actually it should be same or
// uninitialized.)
//
palSurf.hdevOwner(po.hdev());
ICMMSG(("UpdateGammaRampOnDevice():Set GammaRamp to HDEV = %x\n",po.hdev()));
//
// Update palettes based on new GammaRamp.
//
// (Color will be adjusted in PALOBJ_cGetColors())
//
GreAcquireSemaphoreEx(po.hsemDevLock(), SEMORDER_DEVLOCK, NULL); GreEnterMonitoredSection(po.ppdev, WD_DEVLOCK); { SEMOBJ so(po.hsemPointer());
if (!po.bDisabled()) { ASSERTGDI(PPFNVALID(po,SetPalette),"ERROR palette is not managed");
bRet = (*PPFNDRV(po, SetPalette))(po.dhpdev(), (PALOBJ *) &palSurf, 0, 0, palSurf.cEntries()); } } GreExitMonitoredSection(po.ppdev, WD_DEVLOCK); GreReleaseSemaphoreEx(po.hsemDevLock()); } } else { ICMMSG(("UpdateGammaRampOnDevice():Driver doesn't have DrvSetDeviceGammaRamp()\n")); } } } else { //
// Can not set GammaRamp for 1/4 bpp surface
//
ICMMSG(("UpdateGammaRampOnDevice():GammaRamp does not support on 1/4 bpp\n")); }
if (!bRet) { ICMMSG(("UpdateGammaRampOnDevice(): device driver returns error\n")); } } else { ICMMSG(("UpdateGammaRampOnDevice(): HDEV is invalid\n")); }
return (bRet); }
/******************************Public*Routine******************************\
* GetColorManagementCaps() * * History: * * Write it: * 24-Feb-1998 -by- Hideyuki Nagase [hideyukn] \**************************************************************************/
ULONG GetColorManagementCaps(PDEVOBJ& po) { ULONG fl = CM_NONE;
PDEVINFO pDevInfo = po.pdevinfoNotDynamic();
//
// Check CM_GAMMA_RAMP - it will be enabled when
//
// 0) Only for display device.
// 1) DitherFormat is 8bpp. (GDI simulate regardless driver capabilities)
// 2) Driver can do it.
//
if (po.bDisplayPDEV()) { if ((pDevInfo->iDitherFormat == BMF_8BPP) || (po.flGraphicsCaps2NotDynamic() & GCAPS2_CHANGEGAMMARAMP)) { fl |= CM_GAMMA_RAMP; } }
//
// Check CM_CMYK_COLOR when driver can understand.
//
if (po.flGraphicsCapsNotDynamic() & GCAPS_CMYKCOLOR) { fl |= CM_CMYK_COLOR; }
//
// Check CM_DEVICE_ICM when driver can do.
//
if (po.flGraphicsCapsNotDynamic() & GCAPS_ICM) { fl |= CM_DEVICE_ICM; }
return fl; }
|