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.
2443 lines
69 KiB
2443 lines
69 KiB
/****************************Module*Header*******************************\
|
|
* Module Name: ylateobj.cxx
|
|
*
|
|
* This contains the xlate object constructors, destructors and methods
|
|
* An xlateobj is used to translate indexes from one palette to another.
|
|
*
|
|
* When blting between raster surfaces we create a translate object
|
|
* between to speed up the BitBlt. When the destination surface is
|
|
* palette managed we have to do a bit more work.
|
|
*
|
|
* Created: 18-Nov-1990 14:23:55
|
|
* Author: Patrick Haluptzok patrickh
|
|
*
|
|
* Copyright (c) 1990-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
extern "C" VOID vInitXLATE();
|
|
|
|
#pragma alloc_text(INIT, vInitXLATE)
|
|
|
|
// These two variables are for the translate components cacheing of
|
|
// translate objects. There access is restricted to being done only
|
|
// after the palette semaphore has been grabbed.
|
|
|
|
XLATETABLE xlateTable[XLATE_CACHE_SIZE];
|
|
ULONG ulTableIndex = 0;
|
|
|
|
TRANSLATE20 defaultTranslate =
|
|
{
|
|
0,
|
|
{0,1,2,3,4,5,6,7,8,9,246,247,248,249,250,251,252,253,254,255}
|
|
};
|
|
|
|
// This is the identity xlate object
|
|
|
|
XLATE256 xloIdent;
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vInitXLATE
|
|
*
|
|
* initialize the xlateobj component
|
|
*
|
|
* History:
|
|
* 10-Jan-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
extern "C" VOID vInitXLATE()
|
|
{
|
|
RtlZeroMemory(xlateTable, (UINT) XLATE_CACHE_SIZE * sizeof(XLATETABLE));
|
|
|
|
xloIdent.iUniq = XLATE_IDENTITY_UNIQ;
|
|
xloIdent.flXlate = XO_TRIVIAL;
|
|
xloIdent.iSrcType = 0;
|
|
xloIdent.iDstType = 0;
|
|
xloIdent.cEntries = 256;
|
|
xloIdent.pulXlate = xloIdent.ai;
|
|
xloIdent.iBackSrc = 0;
|
|
xloIdent.iForeDst = 0;
|
|
xloIdent.iBackDst = 0;
|
|
|
|
//
|
|
// This may seem hackish but XLATE_CACHE_JOURANL ensures that
|
|
// it doesn't cause anything to get unlocked or freed in
|
|
// the destructor.
|
|
//
|
|
|
|
xloIdent.lCacheIndex = XLATE_CACHE_JOURNAL;
|
|
xloIdent.ppalSrc = (PPALETTE) NULL;
|
|
xloIdent.ppalDst = (PPALETTE) NULL;
|
|
xloIdent.ppalDstDC = (PPALETTE) NULL;
|
|
|
|
xloIdent.hcmXform = NULL;
|
|
xloIdent.lIcmMode = DC_ICM_OFF;
|
|
|
|
UINT uiTemp;
|
|
|
|
for (uiTemp = 0; uiTemp < 256; uiTemp++)
|
|
{
|
|
xloIdent.ai[uiTemp] = uiTemp;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EXLATEOBJ::vDelete
|
|
*
|
|
* Deletes the object.
|
|
*
|
|
* History:
|
|
* Sun 17-Oct-1993 -by- Patrick Haluptzok [patrickh]
|
|
* Kill hmgr references.
|
|
*
|
|
* 26-Nov-1990 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID EXLATEOBJ::vDelete()
|
|
{
|
|
if (pxlate != (PXLATE) NULL)
|
|
{
|
|
if (pxlate->lCacheIndex == XLATE_CACHE_JOURNAL)
|
|
{
|
|
if (ppalSrc())
|
|
{
|
|
bDeletePalette((HPAL) ppalSrc()->hGet());
|
|
}
|
|
}
|
|
|
|
VFREEMEM(pxlate);
|
|
pxlate = (PXLATE) NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* XLATEMEMOBJ destructor
|
|
*
|
|
* destructor for xlate memory objects
|
|
*
|
|
* History:
|
|
* Mon 19-Nov-1990 -by- Patrick Haluptzok [patrickh]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
XLATEMEMOBJ::~XLATEMEMOBJ()
|
|
{
|
|
if (pxlate != (PXLATE) NULL)
|
|
{
|
|
VFREEMEM(pxlate);
|
|
pxlate = (PXLATE) NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* XLATE::vMapNewXlate
|
|
*
|
|
* Maps a pxlate from being relative to one palette to being relative to
|
|
* another palette.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* ptrans - Translate to map
|
|
*
|
|
* History:
|
|
* 10-Jan-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
FASTCALL
|
|
XLATE::vMapNewXlate(
|
|
PTRANSLATE ptrans
|
|
)
|
|
{
|
|
ULONG ulTemp;
|
|
ULONG ulCount = cEntries;
|
|
|
|
if (ptrans == NULL)
|
|
{
|
|
//
|
|
// This is the default palette case
|
|
//
|
|
|
|
while (ulCount--)
|
|
{
|
|
ulTemp = ai[ulCount];
|
|
|
|
if (ulTemp >= 10)
|
|
{
|
|
ai[ulCount] = ulTemp + 236;
|
|
}
|
|
|
|
//
|
|
// else
|
|
//
|
|
//
|
|
// do nothing, the first 10 are a 1 to 1 mapping.
|
|
//
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ULONG *pultemp = ai;
|
|
|
|
while (ulCount--)
|
|
{
|
|
*pultemp = (ULONG) ptrans->ajVector[*pultemp];
|
|
pultemp++;
|
|
|
|
//
|
|
// ai[ulCount] = (ULONG) ptrans->ajVector[ai[ulCount]];
|
|
//
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EXLATEOBJ::bMakeXlate
|
|
*
|
|
* This is called by SetDIBitsToDevice for the DIB_PAL_COLORS case.
|
|
* This takes the indices in bmiColors and translates them through
|
|
* a logical palette.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pusIndices -
|
|
* palDC -
|
|
* pSurfDst -
|
|
* cEntriesInit -
|
|
* cEntriesMax -
|
|
*
|
|
* History:
|
|
* 17-Apr-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
EXLATEOBJ::bMakeXlate(
|
|
PUSHORT pusIndices,
|
|
XEPALOBJ palDC,
|
|
SURFACE *pSurfDst,
|
|
ULONG cEntriesInit,
|
|
ULONG cEntriesMax
|
|
)
|
|
{
|
|
ASSERTGDI(pSurfDst != NULL, "ERROR GDI bMakeXlate1");
|
|
ASSERTGDI(palDC.bValid(), "ERROR bMakeXlate 134");
|
|
|
|
XEPALOBJ palDst(pSurfDst->ppal());
|
|
|
|
ULONG ulTemp;
|
|
ULONG ulIndex;
|
|
|
|
//
|
|
// count of colors in DC
|
|
//
|
|
|
|
ULONG cColorsDC;
|
|
PXLATE pXlateTemp;
|
|
|
|
ASSERTGDI(palDC.cEntries() != 0, "ERROR 0 entry dc palette isn't allowed");
|
|
|
|
//
|
|
// Allocate room for the Xlate.
|
|
//
|
|
|
|
pxlate = pXlateTemp = (PXLATE) PALLOCNOZ(sizeof(XLATE) +
|
|
(sizeof(ULONG) * cEntriesMax),
|
|
'tlxG');
|
|
|
|
if (pXlateTemp == (PXLATE)NULL)
|
|
{
|
|
WARNING("GDISRV bMakeXlate failed memory allocation\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
pXlateTemp->iUniq = ulGetNewUniqueness(ulXlatePalUnique);
|
|
pXlateTemp->flXlate = XO_TABLE;
|
|
pXlateTemp->iSrcType = pXlateTemp->iDstType = 0;
|
|
pXlateTemp->cEntries = cEntriesMax;
|
|
pXlateTemp->pulXlate = pXlateTemp->ai;
|
|
pXlateTemp->iBackSrc = 0;
|
|
pXlateTemp->iForeDst = 0;
|
|
pXlateTemp->iBackDst = 0;
|
|
pXlateTemp->lCacheIndex = XLATE_CACHE_INVALID;
|
|
pXlateTemp->ppalSrc = (PPALETTE) NULL;
|
|
pXlateTemp->ppalDst = palDst.ppalGet();
|
|
pXlateTemp->ppalDstDC = palDC.ppalGet();
|
|
|
|
RtlZeroMemory(((ULONG *)pXlateTemp->ai) + cEntriesInit,
|
|
(UINT) (cEntriesMax - cEntriesInit) * sizeof(ULONG));
|
|
|
|
PAL_ULONG palentry;
|
|
PTRANSLATE ptrans;
|
|
cColorsDC = palDC.cEntries();
|
|
|
|
//
|
|
// Grab the palette semaphore so you can touch the pxlates.
|
|
//
|
|
|
|
SEMOBJ semo(ghsemPalette);
|
|
|
|
//
|
|
// Ok fill in the pxlate correctly.
|
|
//
|
|
|
|
if ((!palDst.bValid()) || (palDst.bIsPalManaged()))
|
|
{
|
|
//
|
|
// Do the palette managed cases
|
|
//
|
|
|
|
if (palDC.bIsPalDefault())
|
|
{
|
|
for(ulTemp = 0; ulTemp < cEntriesInit; ulTemp++)
|
|
{
|
|
//
|
|
// Get the index into the logical palette
|
|
//
|
|
|
|
ulIndex = (ULONG) pusIndices[ulTemp];
|
|
|
|
//
|
|
// Make sure it isn't too large
|
|
//
|
|
|
|
if (ulIndex >= 20)
|
|
{
|
|
ulIndex = ulIndex % 20;
|
|
}
|
|
|
|
if (ulIndex < 10)
|
|
{
|
|
pXlateTemp->ai[ulTemp] = ulIndex;
|
|
}
|
|
else
|
|
{
|
|
pXlateTemp->ai[ulTemp] = ulIndex + 236;
|
|
}
|
|
}
|
|
}
|
|
else if (palDst.bValid() && (palDC.ptransCurrent() != NULL))
|
|
{
|
|
//
|
|
// Map through the current translate.
|
|
//
|
|
|
|
ptrans = palDC.ptransCurrent();
|
|
|
|
for(ulTemp = 0; ulTemp < cEntriesInit; ulTemp++)
|
|
{
|
|
//
|
|
// Get the index into the logical palette
|
|
//
|
|
|
|
ulIndex = (ULONG) pusIndices[ulTemp];
|
|
|
|
if (ulIndex >= cColorsDC)
|
|
{
|
|
ulIndex = ulIndex % cColorsDC;
|
|
}
|
|
|
|
pXlateTemp->ai[ulTemp] = (ULONG) ptrans->ajVector[ulIndex];
|
|
|
|
ASSERTGDI(pXlateTemp->ai[ulTemp] < 256, "ERROR GDI bMakeXlate6");
|
|
}
|
|
}
|
|
else if ((!palDst.bValid()) && (palDC.ptransFore() != NULL))
|
|
{
|
|
//
|
|
// It's a bitmap, Map through the foreground translate.
|
|
//
|
|
|
|
ptrans = palDC.ptransFore();
|
|
|
|
for(ulTemp = 0; ulTemp < cEntriesInit; ulTemp++)
|
|
{
|
|
//
|
|
// Get the index into the logical palette
|
|
//
|
|
|
|
ulIndex = (ULONG) pusIndices[ulTemp];
|
|
|
|
if (ulIndex >= cColorsDC)
|
|
{
|
|
ulIndex = ulIndex % cColorsDC;
|
|
}
|
|
|
|
pXlateTemp->ai[ulTemp] = (ULONG) ptrans->ajVector[ulIndex];
|
|
|
|
ASSERTGDI(pXlateTemp->ai[ulTemp] < 256, "ERROR GDI bMakeXlate6");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// It's palette hasn't been realized. Grab the palette value and
|
|
// then map into default palette if not PC_EXPLICIT entry.
|
|
//
|
|
|
|
for (ulTemp = 0; ulTemp < cEntriesInit; ulTemp++)
|
|
{
|
|
//
|
|
// Get the index into the logical palette
|
|
//
|
|
|
|
ulIndex = (ULONG) pusIndices[ulTemp];
|
|
|
|
if (ulIndex >= cColorsDC)
|
|
{
|
|
ulIndex = ulIndex % cColorsDC;
|
|
}
|
|
|
|
palentry.ul = palDC.ulEntryGet(ulIndex);
|
|
|
|
if (palentry.pal.peFlags == PC_EXPLICIT)
|
|
{
|
|
//
|
|
// Get the correct index in the surface palette.
|
|
//
|
|
|
|
ulIndex = palentry.ul & 0x0000FFFF;
|
|
|
|
if (ulIndex >= 256)
|
|
{
|
|
ulIndex = ulIndex % 256;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Match against the default palette entries.
|
|
//
|
|
|
|
ulIndex = ((XEPALOBJ) ppalDefault).ulGetNearestFromPalentry(palentry.pal);
|
|
|
|
if (ulIndex >= 10)
|
|
{
|
|
ulIndex = ulIndex + 236;
|
|
}
|
|
}
|
|
|
|
pXlateTemp->ai[ulTemp] = ulIndex;
|
|
ASSERTGDI(pXlateTemp->ai[ulTemp] < 256, "ERROR GDI bMakeXlate6");
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Find the RGB in the palDC (reaching down to palDst for
|
|
// PC_EXPLICIT entries). Then find closest match in surface palette.
|
|
//
|
|
|
|
ASSERTGDI(palDst.bValid(), "ERROR palDst is not valid");
|
|
|
|
for (ulTemp = 0; ulTemp < cEntriesInit; ulTemp++)
|
|
{
|
|
//
|
|
// Get the index into the logical palette
|
|
//
|
|
|
|
palentry.ul = (ULONG) pusIndices[ulTemp];
|
|
|
|
if (palentry.ul >= cColorsDC)
|
|
{
|
|
palentry.ul = palentry.ul % cColorsDC;
|
|
}
|
|
|
|
palentry.pal = palDC.palentryGet(palentry.ul);
|
|
|
|
if (palentry.pal.peFlags == PC_EXPLICIT)
|
|
{
|
|
//
|
|
// Get the correct index in the surface palette.
|
|
//
|
|
|
|
if (palDst.cEntries())
|
|
{
|
|
palentry.ul = palentry.ul & 0x0000FFFF;
|
|
|
|
if (palentry.ul >= palDst.cEntries())
|
|
{
|
|
palentry.ul = palentry.ul % palDst.cEntries();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Well what else can we do ?
|
|
//
|
|
|
|
palentry.ul = 0;
|
|
}
|
|
|
|
pXlateTemp->ai[ulTemp] = palentry.ul;
|
|
}
|
|
else
|
|
{
|
|
pXlateTemp->ai[ulTemp] = palDst.ulGetNearestFromPalentry(palentry.pal);
|
|
}
|
|
}
|
|
}
|
|
|
|
pxlate->vCheckForTrivial();
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// This describes the overall logic of surface to surface xlates.
|
|
// There are basically n types of xlates to worry about:
|
|
//
|
|
// 1. XO_TRIVIAL - no translation occurs, identity.
|
|
//
|
|
// 2. XO_TABLE - look up in a table for the correct table translation.
|
|
//
|
|
// a. XO_TO_MONO - look in to table for the correct tranlation,
|
|
// but when getting it out of the cache make sure iBackSrc is the
|
|
// same. iBackSrc goes to 1, everything else to 0.
|
|
// b. XLATE_FROM_MONO - look into table for the correct translation
|
|
// but when getting it out of the cache make sure iBackDst and
|
|
// iForeDst are both still valid. 1 goes to iBackDst, 0 to iForeDst.
|
|
// c. just plain jane indexed to indexed or rgb translation.
|
|
//
|
|
// 3. XLATE_RGB_SRC - Have to call XLATEOBJ_iXlate to get it translated.
|
|
//
|
|
// a. XO_TO_MONO - we have saved the iBackColor in ai[0]
|
|
// b. just plain jane RGB to indexed. Grab the RGB, find the closest
|
|
// match in Dst palette. Lot's of work.
|
|
//
|
|
// 4. XLATE_RGB_BOTH - Bit mashing time. Call XLATEOBJ_iXlate
|
|
//
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EXLATEOBJ::bInitXlateObj
|
|
*
|
|
* Cache aware initializer for Xlates.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hcmXform - hColorTransform, may be NULL
|
|
* pdc - pointer to DC object
|
|
* palSrc - src surface palette
|
|
* palDst - dst surface palette
|
|
* palSrcDC - src DC palette
|
|
* palDstDC - dst DC palette
|
|
* iForeDst - For Mono->Color this is what a 0 goes to
|
|
* iBackDst - For Mono->Color this is what a 1 goes to
|
|
* iBackSrc - For Color->Mono this is the color that goes to
|
|
* 1, all other colors go to 0.
|
|
* flCear - Used for multi-monitor systems
|
|
*
|
|
* History:
|
|
* Sun 23-Jun-1991 -by- Patrick Haluptzok [patrickh]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
EXLATEOBJ::bInitXlateObj(
|
|
HANDLE hcmXform,
|
|
LONG lIcmMode,
|
|
XEPALOBJ palSrc,
|
|
XEPALOBJ palDst,
|
|
XEPALOBJ palSrcDC,
|
|
XEPALOBJ palDstDC,
|
|
ULONG iForeDst,
|
|
ULONG iBackDst,
|
|
ULONG iBackSrc,
|
|
ULONG flCreate
|
|
)
|
|
{
|
|
//
|
|
// Check if blting from compatible bitmap to screen. This is a common
|
|
// occurrence on 8bpp devices we want to accelerate.
|
|
//
|
|
|
|
if (!palSrc.bValid())
|
|
{
|
|
if (
|
|
!palDst.bValid() ||
|
|
(
|
|
palDst.bIsPalManaged() &&
|
|
(
|
|
(palDstDC.ptransCurrent() == NULL) ||
|
|
(palDstDC.ptransCurrent() == palDstDC.ptransFore())
|
|
)
|
|
)
|
|
)
|
|
{
|
|
vMakeIdentity();
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check if blting from screen to compatible bitmap.
|
|
//
|
|
|
|
if (!palDst.bValid())
|
|
{
|
|
if (palSrc.bIsPalManaged())
|
|
{
|
|
//
|
|
// Blting from screen to memory bitmap. Check for identity.
|
|
//
|
|
|
|
if ((palDstDC.ptransCurrent() == NULL) ||
|
|
(palDstDC.ptransCurrent() == palDstDC.ptransFore()))
|
|
{
|
|
vMakeIdentity();
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
ASSERTGDI(palDstDC.bValid(), "7GDIERROR vInitXlateObj");
|
|
ASSERTGDI(palDst.bValid() || palSrc.bValid(), "8GDIERROR vInitXlateObj");
|
|
|
|
//
|
|
// Check for the easy identity out. This check does the right thing for
|
|
// ppal==ppal and equal times of two different ppals.
|
|
//
|
|
|
|
if ((palSrc.bValid()) && (palDst.bValid()))
|
|
{
|
|
if (palSrc.ulTime() == palDst.ulTime())
|
|
{
|
|
ASSERTGDI(palSrc.cEntries() == palDst.cEntries(), "Xlateobj matching times, different # of entries");
|
|
vMakeIdentity();
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
BOOL bCacheXlate = TRUE;
|
|
|
|
if (IS_ICM_ON(lIcmMode) && (hcmXform != NULL))
|
|
{
|
|
//
|
|
// If we enable ICM and have a valid color tranform,
|
|
// don't search from cache and don't insert new Xlate to cache.
|
|
//
|
|
|
|
bCacheXlate = FALSE;
|
|
}
|
|
else if ((palSrc.bValid()) && (palDst.bValid()))
|
|
{
|
|
if (bSearchCache(palSrc, palDst, palSrcDC, palDstDC,
|
|
iForeDst, iBackDst, iBackSrc, flCreate))
|
|
{
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
pxlate = CreateXlateObject(hcmXform,
|
|
lIcmMode,
|
|
palSrc,
|
|
palDst,
|
|
palSrcDC,
|
|
palDstDC,
|
|
iForeDst,
|
|
iBackDst,
|
|
iBackSrc,
|
|
flCreate);
|
|
|
|
if (pxlate != (PXLATE) NULL)
|
|
{
|
|
if (bCacheXlate &&
|
|
palSrc.bValid() &&
|
|
palDst.bValid() &&
|
|
(!(pxlate->flPrivate & XLATE_RGB_SRC)))
|
|
{
|
|
vAddToCache(palSrc, palDst, palSrcDC, palDstDC);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
else
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* CreateXlateObject
|
|
*
|
|
* Allocates an xlate sets it up.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* palSrc - src surface palette
|
|
* palDestSurf - dst surface palette
|
|
* palSrcDC - src DC palette
|
|
* palDestDC - dst DC palette
|
|
* iForeDst - For Mono->Color this is what a 0 goes to
|
|
* iBackDst - For Mono->Color this is what a 1 goes to
|
|
* iBackSrc - For Color->Mono this is the color that goes to
|
|
* 1, all other colors go to 0.
|
|
*
|
|
* History:
|
|
* 02-May-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PXLATE
|
|
CreateXlateObject(
|
|
HANDLE hcmXform,
|
|
LONG lIcmMode,
|
|
XEPALOBJ palSrc,
|
|
XEPALOBJ palDestSurf,
|
|
XEPALOBJ palSrcDC,
|
|
XEPALOBJ palDestDC,
|
|
ULONG iForeDst,
|
|
ULONG iBackDst,
|
|
ULONG iBackSrc,
|
|
ULONG flCreateFlag
|
|
)
|
|
{
|
|
ASSERTGDI(palDestDC.bValid(), "CreateXlateObject recieved bad ppalDstDC, bug in GDI");
|
|
ASSERTGDI(palSrc.bValid() || palDestSurf.bValid(), "CreateXlaetObject recieved bad ppalSrc, bug in GDI");
|
|
ASSERTGDI(palSrc.ppalGet() != palDestSurf.ppalGet(), "Didn't recognize ident quickly");
|
|
|
|
//
|
|
// cEntry == 0 means the source palette is an RGB/Bitfields type.
|
|
// An invalid palette means it's a compatible bitmap on a palette managed device.
|
|
//
|
|
|
|
ULONG ulTemp;
|
|
ULONG cEntry = palSrc.bValid() ? palSrc.cEntries() : 256;
|
|
|
|
//
|
|
// Allocate room for the structure.
|
|
//
|
|
|
|
PXLATE pxlate = pCreateXlate(cEntry);
|
|
|
|
if (pxlate == NULL)
|
|
{
|
|
WARNING("CreateXlateObject failed pCreateXlate\n");
|
|
return(pxlate);
|
|
}
|
|
|
|
//
|
|
// Grab the palette semaphore so you can access the ptrans in palDestDC.
|
|
//
|
|
|
|
SEMOBJ semo(ghsemPalette); // ??? This may not need to be grabbed
|
|
// ??? since we have the DC's locked that
|
|
// ??? this palette DC is in. Investigate.
|
|
|
|
//
|
|
// Initialize ICM stuffs.
|
|
//
|
|
|
|
pxlate->vCheckForICM(hcmXform,lIcmMode);
|
|
|
|
BOOL bCMYKColor = ((pxlate->flXlate & XO_FROM_CMYK) ? TRUE : FALSE);
|
|
|
|
//
|
|
// See if we should be matching to the Dest DC palette instead of the
|
|
// surface. This occurs when the surface is palette managed and the
|
|
// user hasn't selected an RGB palette into his destination DC.
|
|
// Note we check for a valid pxlate in the Destination DC palette.
|
|
// In multi-task OS the user can do things to get the translate in a
|
|
// invalid or NULL state easily. We match against the reserved palette
|
|
// in this case.
|
|
//
|
|
|
|
BOOL bPalManaged = (!palDestSurf.bValid()) || (palDestSurf.bIsPalManaged());
|
|
|
|
if (bPalManaged)
|
|
{
|
|
//
|
|
// We are blting to a compatible bitmap or the screen on a palette managed
|
|
// device. Check that we have a foreground realization already done,
|
|
// otherwise just use the default palette for the DC palette.
|
|
//
|
|
|
|
ASSERTGDI(((palDestDC.ptransFore() == NULL) && (palDestDC.ptransCurrent() == NULL)) ||
|
|
((palDestDC.ptransFore() != NULL) && (palDestDC.ptransCurrent() != NULL)),
|
|
"ERROR translates are either both valid or both invalid");
|
|
|
|
if (palDestDC.ptransFore() == NULL)
|
|
{
|
|
//
|
|
// Match against the default palette, valid translate is not available.
|
|
//
|
|
|
|
palDestDC.ppalSet(ppalDefault);
|
|
}
|
|
|
|
if (!(flCreateFlag & XLATE_USE_SURFACE_PAL))
|
|
{
|
|
pxlate->flPrivate |= XLATE_PAL_MANAGED;
|
|
|
|
//
|
|
// Set a flag that says whether we are background or foreground.
|
|
//
|
|
|
|
if (palDestSurf.bValid())
|
|
{
|
|
pxlate->flPrivate |= XLATE_USE_CURRENT;
|
|
}
|
|
}
|
|
}
|
|
|
|
pxlate->ppalSrc = palSrc.ppalGet();
|
|
pxlate->ppalDst = palDestSurf.ppalGet();
|
|
pxlate->ppalDstDC = palDestDC.ppalGet();
|
|
|
|
PTRANSLATE ptransFore = palDestDC.ptransFore();
|
|
PTRANSLATE ptransCurrent = palDestDC.ptransCurrent();
|
|
|
|
//
|
|
// Ok, lets build the translate vector.
|
|
//
|
|
|
|
if (
|
|
(!palSrc.bValid()) ||
|
|
(
|
|
(palSrc.bIsPalManaged()) &&
|
|
((ptransFore == ptransCurrent) || (flCreateFlag & XLATE_USE_FOREGROUND))
|
|
)
|
|
)
|
|
{
|
|
//
|
|
// The source is a compatible bitmap on a palette managed device or the screen
|
|
// with Dst DC palette having been realized in the foreground.
|
|
//
|
|
// We start out assuming an identity blt.
|
|
//
|
|
|
|
if (ptransFore == NULL)
|
|
{
|
|
//
|
|
// Match against the default palette since a
|
|
// valid translate is not available.
|
|
//
|
|
|
|
palDestDC.ppalSet(ppalDefault);
|
|
pxlate->ppalDstDC = ppalDefault;
|
|
ptransFore = ptransCurrent = (TRANSLATE *) &defaultTranslate;
|
|
}
|
|
|
|
ASSERTGDI(cEntry == 256, "ERROR xlate too small");
|
|
|
|
for (ulTemp = 0; ulTemp < 256; ulTemp++)
|
|
{
|
|
pxlate->ai[ulTemp] = ulTemp;
|
|
}
|
|
|
|
if (!palDestSurf.bValid())
|
|
{
|
|
//
|
|
// Compatible bitmap to compatible bitmap on palette managed
|
|
// device. Both are relevant to the foreground realize of the
|
|
// DestDC palette so the xlate is identity.
|
|
//
|
|
|
|
pxlate->flXlate |= XO_TRIVIAL;
|
|
}
|
|
else if ((palDestSurf.bIsPalDibsection()) && (bEqualRGB_In_Palette(palDestSurf, palDestDC)))
|
|
{
|
|
//
|
|
// If you blt from a compatible bitmap to a DIBSECTION it will be identity
|
|
// if the RGB's of both the DC palette and the DIBSECTION's palette are the same.
|
|
// We do this special check so that if they contain duplicates we still get an
|
|
// identity xlate.
|
|
//
|
|
|
|
pxlate->flXlate |= XO_TRIVIAL; // Size wise this will combine with first check
|
|
|
|
}
|
|
else if ((palDestSurf.bIsPalDibsection()) && (palSrc.bValid()) && (bEqualRGB_In_Palette(palDestSurf, palSrc)))
|
|
{
|
|
pxlate->flXlate |= XO_TRIVIAL; // Size wise this will combine with first check
|
|
}
|
|
else if (palDestSurf.bIsPalManaged())
|
|
{
|
|
//
|
|
// Compatible bitmap to the screen on a palette managed device.
|
|
// The compatible bitmaps colors are defined as the foreground
|
|
// realization of the destination DC's palette. If the Dst
|
|
// DC's palette is realized in the foreground it's identity.
|
|
// Otherwise we translate from the current to the foreground
|
|
// indices.
|
|
//
|
|
|
|
if (ptransCurrent == ptransFore)
|
|
{
|
|
//
|
|
// It's in the foreground or not realized yet so it's
|
|
// identity. Not realized case also hits on default logical palette.
|
|
//
|
|
|
|
pxlate->flXlate |= XO_TRIVIAL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// It's foreground to current translation.
|
|
//
|
|
|
|
ASSERTGDI(ptransFore != ptransCurrent, "Should have been identity, never get here");
|
|
ASSERTGDI(ptransFore != NULL, "ERROR this should not have got here Fore");
|
|
ASSERTGDI(ptransCurrent != NULL, "ERROR this should not have got here Current");
|
|
|
|
for (ulTemp = 0; ulTemp < palDestDC.cEntries(); ulTemp++)
|
|
{
|
|
pxlate->ai[ptransFore->ajVector[ulTemp]] = (ULONG) ptransCurrent->ajVector[ulTemp];
|
|
}
|
|
|
|
//
|
|
// Now map the default colors that are really there independant of logical palette.
|
|
//
|
|
|
|
if (palDestSurf.bIsNoStatic())
|
|
{
|
|
//
|
|
// Only black and white are here.
|
|
//
|
|
|
|
pxlate->ai[0] = 0;
|
|
pxlate->ai[255] = 255;
|
|
}
|
|
else if (!palDestSurf.bIsNoStatic256())
|
|
{
|
|
//
|
|
// All the 20 holy colors are here.
|
|
// Fix them up.
|
|
//
|
|
|
|
for (ulTemp = 0; ulTemp < 10; ulTemp++)
|
|
{
|
|
pxlate->ai[ulTemp] = ulTemp;
|
|
pxlate->ai[ulTemp + 246] = ulTemp + 246;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (palDestSurf.bIsMonochrome())
|
|
{
|
|
RtlZeroMemory(pxlate->ai, 256 * sizeof(ULONG));
|
|
|
|
ulTemp = ulGetNearestIndexFromColorref(palSrc, palSrcDC, iBackSrc);
|
|
|
|
ASSERTGDI(ulTemp < 256, "ERROR palSrc invalid - ulGetNearest is > 256");
|
|
|
|
pxlate->vSetIndex(ulTemp, 1);
|
|
pxlate->flXlate |= XO_TO_MONO;
|
|
pxlate->iBackSrc = iBackSrc;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Blting from palette-managed bitmap to non-palette managed surface.
|
|
//
|
|
// Do all the non-default colors that are realized.
|
|
//
|
|
|
|
if (palDestSurf.cEntries() != 256)
|
|
{
|
|
//
|
|
// If the dest is 256 entries we will just leave
|
|
// the identity xlate as the initial state.
|
|
// Otherwise we 0 it out so we don't have a translation
|
|
// index left that's potentially bigger than the
|
|
// destination palette.
|
|
//
|
|
|
|
RtlZeroMemory(pxlate->ai, 256 * sizeof(ULONG));
|
|
}
|
|
|
|
//
|
|
// We need to fill in where the default colors map.
|
|
//
|
|
|
|
for (ulTemp = 0; ulTemp < 10; ulTemp++)
|
|
{
|
|
pxlate->ai[ulTemp] =
|
|
palDestSurf.ulGetNearestFromPalentry(logDefaultPal.palPalEntry[ulTemp]);
|
|
pxlate->ai[ulTemp + 246] =
|
|
palDestSurf.ulGetNearestFromPalentry(logDefaultPal.palPalEntry[ulTemp+10]);
|
|
}
|
|
|
|
if (flCreateFlag & XLATE_USE_SURFACE_PAL)
|
|
{
|
|
//
|
|
// Map directly to destination surface palette from source surface palette.
|
|
//
|
|
|
|
for (ulTemp = 0; ulTemp < palSrc.cEntries(); ulTemp++)
|
|
{
|
|
pxlate->ai[ulTemp] = palDestSurf.ulGetNearestFromPalentry(palSrc.palentryGet(ulTemp));
|
|
}
|
|
|
|
pxlate->flPrivate |= XLATE_USE_SURFACE_PAL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Go through DC palette and then map to destination surface palette.
|
|
//
|
|
|
|
if (ptransFore != NULL)
|
|
{
|
|
for (ulTemp = 0; ulTemp < palDestDC.cEntries(); ulTemp++)
|
|
{
|
|
pxlate->ai[ptransFore->ajVector[ulTemp]] =
|
|
palDestSurf.ulGetNearestFromPalentry(palDestDC.palentryGet(ulTemp));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (palSrc.bIsPalDibsection() &&
|
|
((palDestSurf.bValid() &&
|
|
palDestSurf.bIsPalDibsection() &&
|
|
bEqualRGB_In_Palette(palSrc, palDestSurf)
|
|
) ||
|
|
(((!palDestSurf.bValid()) ||
|
|
(palDestSurf.bIsPalManaged() && (ptransFore == ptransCurrent))
|
|
) &&
|
|
bEqualRGB_In_Palette(palSrc, palDestDC)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
//
|
|
// Blting from a Dibsection &&
|
|
// ((To another Dibsection with ident palette) ||
|
|
// (((To a compatible palette managed bitmap) ||
|
|
// (To a palette managed screen with the DstDc's logical palette realized in the foreground)) &&
|
|
// (the dst logical palette == Dibsection's palette)
|
|
// ))
|
|
//
|
|
// This is identity. We do this special check so even if there are duplicate
|
|
// colors in the palette we still get identity.
|
|
//
|
|
|
|
for (ulTemp = 0; ulTemp < 256; ulTemp++)
|
|
{
|
|
pxlate->ai[ulTemp] = ulTemp;
|
|
}
|
|
|
|
pxlate->flXlate |= XO_TRIVIAL;
|
|
}
|
|
else if ((palSrc.bIsPalManaged()) && (!palDestSurf.bValid()))
|
|
{
|
|
//
|
|
// We are blting from the screen to a compatible bitmap on a palette
|
|
// managed device where the screen is realized in the background.
|
|
//
|
|
|
|
//
|
|
// Make it identity by default.
|
|
//
|
|
|
|
for (ulTemp = 0; ulTemp < 256; ulTemp++)
|
|
{
|
|
pxlate->ai[ulTemp] = ulTemp;
|
|
}
|
|
|
|
//
|
|
// We are blting background to foreground.
|
|
// i.e. we are blting current realize to foreground realize.
|
|
//
|
|
|
|
ASSERTGDI(pxlate->cEntries == 256, "ERROR xlate too small");
|
|
ASSERTGDI(ptransFore != ptransCurrent, "Should have been identity, never get here");
|
|
ASSERTGDI(ptransFore != NULL, "ERROR this should not have got here Fore");
|
|
ASSERTGDI(ptransCurrent != NULL, "ERROR this should not have got here Current");
|
|
|
|
for (ulTemp = 0; ulTemp < palDestDC.cEntries(); ulTemp++)
|
|
{
|
|
pxlate->ai[ptransCurrent->ajVector[ulTemp]] = (ULONG) ptransFore->ajVector[ulTemp];
|
|
}
|
|
|
|
//
|
|
// Now map the default colors that are really there independant of logical palette realization.
|
|
//
|
|
|
|
if (palSrc.bIsNoStatic())
|
|
{
|
|
//
|
|
// Only black and white are here.
|
|
//
|
|
|
|
pxlate->ai[0] = 0;
|
|
pxlate->ai[255] = 255;
|
|
}
|
|
else if (!palSrc.bIsNoStatic256())
|
|
{
|
|
//
|
|
// All the 20 holy colors are here.
|
|
// Fix them up.
|
|
//
|
|
|
|
for (ulTemp = 0; ulTemp < 10; ulTemp++)
|
|
{
|
|
pxlate->ai[ulTemp] = ulTemp;
|
|
pxlate->ai[ulTemp + 246] = ulTemp + 246;
|
|
}
|
|
}
|
|
}
|
|
else if (palSrc.bIsMonochrome())
|
|
{
|
|
if (palDestSurf.bIsMonochrome())
|
|
{
|
|
//
|
|
// It's identity blt.
|
|
//
|
|
|
|
pxlate->vSetIndex(0, 0);
|
|
pxlate->vSetIndex(1, 1);
|
|
}
|
|
else
|
|
{
|
|
if (bCMYKColor)
|
|
{
|
|
pxlate->vSetIndex(0, iForeDst);
|
|
pxlate->vSetIndex(1, iBackDst);
|
|
}
|
|
else
|
|
{
|
|
pxlate->vSetIndex(0, ulGetNearestIndexFromColorref(palDestSurf,
|
|
palDestDC,
|
|
iForeDst));
|
|
pxlate->vSetIndex(1, ulGetNearestIndexFromColorref(palDestSurf,
|
|
palDestDC,
|
|
iBackDst));
|
|
}
|
|
|
|
//
|
|
// XLATE_FROM_MONO is set so we know to look at colors in
|
|
// cache code for getting a hit.
|
|
//
|
|
|
|
pxlate->flPrivate |= XLATE_FROM_MONO;
|
|
pxlate->iForeDst = iForeDst;
|
|
pxlate->iBackDst = iBackDst;
|
|
}
|
|
}
|
|
else if (cEntry == 0)
|
|
{
|
|
ASSERTGDI(palSrc.cEntries() == 0, "ERROR how could this happen");
|
|
|
|
//
|
|
// Src is a RGB/Bitfields palette.
|
|
//
|
|
|
|
if (palDestSurf.bIsMonochrome())
|
|
{
|
|
//
|
|
// Put the color the Background of the source matches in pulXlate[0]
|
|
//
|
|
|
|
pxlate->ai[0] = ulGetNearestIndexFromColorref(palSrc, palSrcDC, iBackSrc);
|
|
pxlate->flXlate |= XO_TO_MONO;
|
|
pxlate->iBackSrc = iBackSrc;
|
|
|
|
//
|
|
// The S3 and other snazzy drivers look at this and get the color out
|
|
// of slot 0 when XO_TO_MONO is set to get way better performance in
|
|
// WinBench.
|
|
//
|
|
|
|
pxlate->pulXlate = pxlate->ai;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Src is a regular indexed palette, it wouldn't have duplicating entries
|
|
// in it so we don't need to check for the Dibsection case. This is like
|
|
// a palette for a 16 color VGA or a printer or a SetDIBitsToDevice.
|
|
//
|
|
|
|
if (palDestSurf.bValid() && palDestSurf.bIsMonochrome())
|
|
{
|
|
RtlZeroMemory(pxlate->ai,(UINT) cEntry * sizeof(*pxlate->ai));
|
|
cEntry = ulGetNearestIndexFromColorref(palSrc, palSrcDC, iBackSrc);
|
|
ASSERTGDI(cEntry < pxlate->cEntries, "ERROR this is not in range");
|
|
pxlate->vSetIndex(cEntry, 1);
|
|
pxlate->flXlate |= XO_TO_MONO;
|
|
pxlate->iBackSrc = iBackSrc;
|
|
}
|
|
else
|
|
{
|
|
if (bCMYKColor)
|
|
{
|
|
//
|
|
// Copy source CMYK color table to index table.
|
|
//
|
|
|
|
while(cEntry--)
|
|
{
|
|
pxlate->ai[cEntry] = palSrc.ulEntryGet(cEntry);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If the destination is palette managed, map to logical palette
|
|
// and then translate to physical indices accordingly. Otherwise
|
|
// map to the physical palette directly.
|
|
//
|
|
|
|
PPALETTE ppalTemp;
|
|
|
|
if (bPalManaged && !(flCreateFlag & XLATE_USE_SURFACE_PAL))
|
|
{
|
|
ppalTemp = palDestDC.ppalGet();
|
|
}
|
|
else
|
|
{
|
|
ppalTemp = palDestSurf.ppalGet();
|
|
|
|
if (flCreateFlag & XLATE_USE_SURFACE_PAL)
|
|
{
|
|
pxlate->flPrivate |= XLATE_USE_SURFACE_PAL;
|
|
}
|
|
}
|
|
|
|
XEPALOBJ palTemp(ppalTemp);
|
|
|
|
while(cEntry--)
|
|
{
|
|
|
|
pxlate->ai[cEntry] =
|
|
palTemp.ulGetNearestFromPalentry(
|
|
palSrc.palentryGet(cEntry));
|
|
}
|
|
|
|
if (bPalManaged && !(flCreateFlag & XLATE_USE_SURFACE_PAL))
|
|
{
|
|
//
|
|
// Map from DC palette to surface palette.
|
|
//
|
|
|
|
pxlate->vMapNewXlate((palDestSurf.bValid()) ? ptransCurrent
|
|
: ptransFore);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pxlate->vCheckForTrivial();
|
|
return(pxlate);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* pCreateXlate
|
|
*
|
|
* This allocates an xlate object with ulNumEntries.
|
|
*
|
|
* Returns: The pointer to the xlate object, NULL for failure.
|
|
*
|
|
* History:
|
|
* 17-May-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PXLATE pCreateXlate(ULONG ulNumEntries)
|
|
{
|
|
//
|
|
// Allocate room for the XLATE.
|
|
//
|
|
|
|
PXLATE pxlate = (PXLATE) PALLOCNOZ((sizeof(XLATE) + sizeof(ULONG) * ulNumEntries),
|
|
'tlxG');
|
|
|
|
if (pxlate != NULL)
|
|
{
|
|
pxlate->iUniq = ulGetNewUniqueness(ulXlatePalUnique);
|
|
if (ulNumEntries > 0)
|
|
{
|
|
pxlate->flXlate = XO_TABLE;
|
|
pxlate->pulXlate = pxlate->ai;
|
|
pxlate->flPrivate = 0;
|
|
}
|
|
else
|
|
{
|
|
pxlate->flXlate = 0;
|
|
pxlate->pulXlate = NULL;
|
|
pxlate->flPrivate = XLATE_RGB_SRC;
|
|
}
|
|
|
|
pxlate->iSrcType = pxlate->iDstType = 0;
|
|
pxlate->cEntries = ulNumEntries;
|
|
pxlate->lCacheIndex = XLATE_CACHE_INVALID;
|
|
pxlate->ppalSrc = (PPALETTE) NULL;
|
|
pxlate->ppalDst = (PPALETTE) NULL;
|
|
pxlate->ppalDstDC = (PPALETTE) NULL;
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
WARNING("pCreateXlate failed memory allocation\n");
|
|
}
|
|
#endif
|
|
|
|
return(pxlate);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vCheckForTrivial
|
|
*
|
|
* We need to check for trivial translation, it speeds up the inner-loop
|
|
* for blting a great deal.
|
|
*
|
|
* History:
|
|
*
|
|
* 11-Oct-1995 -by- Tom Zakrajsek [tomzak]
|
|
* Fixed it to not mark xlates as trivial unless the Src and Dst were
|
|
* the same color depth.
|
|
*
|
|
* 17-Oct-1993 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID XLATE::vCheckForTrivial()
|
|
{
|
|
//
|
|
// Check if we already recognized trivial during creation
|
|
//
|
|
|
|
if (flXlate & XO_TRIVIAL)
|
|
return;
|
|
|
|
//
|
|
// Source Color is CMYK, XO_TRIVIAL will not be on.
|
|
//
|
|
|
|
if (flXlate & XO_FROM_CMYK)
|
|
return;
|
|
|
|
//
|
|
// See if it's really just a trivial xlate.
|
|
//
|
|
|
|
if (cEntries)
|
|
{
|
|
//
|
|
// Just make sure that each index translates to itself, and
|
|
// that the color depths are the same for the source and
|
|
// destination.
|
|
//
|
|
|
|
ULONG ulTemp;
|
|
|
|
if ((ppalSrc != NULL) &&
|
|
(ppalDst != NULL) &&
|
|
(ppalSrc->cEntries != ppalDst->cEntries))
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (ulTemp = 0; ulTemp < cEntries; ulTemp++)
|
|
{
|
|
if (pulXlate[ulTemp] != ulTemp)
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If the Src and Dst have the same masks it's identity.
|
|
//
|
|
|
|
XEPALOBJ palSrc(ppalSrc);
|
|
XEPALOBJ palDst(ppalDst);
|
|
|
|
if ((palSrc.bValid()) &&
|
|
(palDst.bValid()) &&
|
|
(!palDst.bIsIndexed()))
|
|
{
|
|
ASSERTGDI(!palSrc.bIsIndexed(), "ERROR Src not indexed?");
|
|
|
|
FLONG flRedSrc, flGreSrc, flBluSrc;
|
|
FLONG flRedDst, flGreDst, flBluDst;
|
|
|
|
if (palSrc.bIsBitfields())
|
|
{
|
|
flRedSrc = palSrc.flRed();
|
|
flGreSrc = palSrc.flGre();
|
|
flBluSrc = palSrc.flBlu();
|
|
}
|
|
else
|
|
{
|
|
flGreSrc = 0x0000FF00;
|
|
|
|
if (palSrc.bIsRGB())
|
|
{
|
|
flRedSrc = 0x000000FF;
|
|
flBluSrc = 0x00FF0000;
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(palSrc.bIsBGR(), "What is it then?");
|
|
flRedSrc = 0x00FF0000;
|
|
flBluSrc = 0x000000FF;
|
|
}
|
|
}
|
|
|
|
if (palDst.bIsBitfields())
|
|
{
|
|
flRedDst = palDst.flRed();
|
|
flGreDst = palDst.flGre();
|
|
flBluDst = palDst.flBlu();
|
|
}
|
|
else
|
|
{
|
|
flGreDst = 0x0000FF00;
|
|
|
|
if (palDst.bIsRGB())
|
|
{
|
|
flRedDst = 0x000000FF;
|
|
flBluDst = 0x00FF0000;
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(palDst.bIsBGR(), "What is it then?");
|
|
flRedDst = 0x00FF0000;
|
|
flBluDst = 0x000000FF;
|
|
}
|
|
}
|
|
|
|
if ((flRedSrc != flRedDst) ||
|
|
(flGreSrc != flGreDst) ||
|
|
(flBluSrc != flBluDst))
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
|
|
//
|
|
// We found it is really just trivial.
|
|
//
|
|
|
|
flXlate |= XO_TRIVIAL;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EXLATEOBJ::vAddToCache
|
|
*
|
|
* Adds an xlate object to the cache.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* palSrc -
|
|
* palDst -
|
|
* palSrcDC -
|
|
* palDstDC -
|
|
*
|
|
* History:
|
|
* 13-Jun-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID
|
|
EXLATEOBJ::vAddToCache(
|
|
XEPALOBJ palSrc,
|
|
XEPALOBJ palDst,
|
|
XEPALOBJ palSrcDC,
|
|
XEPALOBJ palDstDC
|
|
)
|
|
{
|
|
ULONG cEntries;
|
|
SEMOBJ semo(ghsemPalette);
|
|
|
|
for (cEntries = 0; cEntries < XLATE_CACHE_SIZE; cEntries++)
|
|
{
|
|
ASSERTGDI(ulTableIndex < XLATE_CACHE_SIZE, "table index out of range");
|
|
|
|
if (xlateTable[ulTableIndex].pxlate != (PXLATE) 0)
|
|
{
|
|
if (xlateTable[ulTableIndex].ulReference != 0)
|
|
{
|
|
ulTableIndex = (ulTableIndex + 1) & XLATE_MODULA;
|
|
continue;
|
|
}
|
|
|
|
VFREEMEM(xlateTable[ulTableIndex].pxlate);
|
|
}
|
|
|
|
//
|
|
// Now add ours into the cache.
|
|
//
|
|
|
|
xlateTable[ulTableIndex].ulReference = 1;
|
|
xlateTable[ulTableIndex].pxlate = (PXLATE)pxlate;
|
|
xlateTable[ulTableIndex].ulPalSrc = palSrc.ulTime();
|
|
xlateTable[ulTableIndex].ulPalDst = palDst.ulTime();
|
|
xlateTable[ulTableIndex].ulPalSrcDC = palSrcDC.ulTime();
|
|
xlateTable[ulTableIndex].ulPalDstDC = palDstDC.ulTime();
|
|
|
|
//
|
|
// Mark it so the destructor doesn't free it
|
|
//
|
|
|
|
pxlate->lCacheIndex = (LONG) ulTableIndex;
|
|
|
|
//
|
|
// Put in palSrc the index where to be found most quickly
|
|
//
|
|
|
|
palSrc.iXlateIndex(ulTableIndex);
|
|
|
|
//
|
|
// Move the cache ahead so we don't get deleted right away
|
|
//
|
|
|
|
ulTableIndex = (ulTableIndex + 1) & XLATE_MODULA;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EXLATEOBJ::bSearchCache
|
|
*
|
|
* Searches cache for a previously created xlate.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* palSrc - src surface palette
|
|
* palDst - dst surface palette
|
|
* palSrcDC - src DC palette
|
|
* palDstDC - dst DC palette
|
|
* iForeDst - For Mono->Color this is what a 0 goes to
|
|
* iBackDst - For Mono->Color this is what a 1 goes to
|
|
* iBackSrc - For Color->Mono this is the color that goes to
|
|
* 1, all other colors go to 0.
|
|
*
|
|
* History:
|
|
* 13-Jun-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
EXLATEOBJ::bSearchCache(
|
|
XEPALOBJ palSrc,
|
|
XEPALOBJ palDst,
|
|
XEPALOBJ palSrcDC,
|
|
XEPALOBJ palDstDC,
|
|
ULONG iForeDst,
|
|
ULONG iBackDst,
|
|
ULONG iBackSrc,
|
|
ULONG flCreate
|
|
)
|
|
{
|
|
//
|
|
// Start ulIndex at the last place in the cache that an pxlate match was
|
|
// found for palSrc.
|
|
//
|
|
|
|
ULONG ulIndex = palSrc.iXlateIndex();
|
|
ULONG ulLoop;
|
|
SEMOBJ semo(ghsemPalette);
|
|
|
|
for (ulLoop = 0; ulLoop < XLATE_CACHE_SIZE; ulLoop++)
|
|
{
|
|
//
|
|
// If the destination is palette managed we need to make sure we are going
|
|
// through the correct Destination DC and that it is up to date.
|
|
//
|
|
|
|
if ((xlateTable[ulIndex].ulPalSrc == palSrc.ulTime()) &&
|
|
(xlateTable[ulIndex].ulPalDst == palDst.ulTime()) &&
|
|
(xlateTable[ulIndex].ulPalDstDC == palDstDC.ulTime()))
|
|
{
|
|
//
|
|
// Lock down all the cache objects.
|
|
//
|
|
|
|
pxlate = xlateTable[ulIndex].pxlate;
|
|
ASSERTGDI(bValid(), "GDIERROR:invalid pxlate xlate cache entry\n");
|
|
ASSERTGDI(pxlate->lCacheIndex == (LONG) ulIndex, "GDIERROR:bad xlate.lCacheIndex\n");
|
|
ASSERTGDI(!(pxlate->flPrivate & XLATE_RGB_SRC), "GDIERROR:a RGB_SRC in the cache ???\n");
|
|
ASSERTGDI(palSrc.cEntries() == pxlate->cEntries, "ERROR bSearchCache cEntries not matching palSrc");
|
|
|
|
//
|
|
// Now check if it's a to/from monochrome and if it is,
|
|
// are the fore/back colors still valid.
|
|
//
|
|
|
|
if (
|
|
(
|
|
((XLATE_USE_SURFACE_PAL|XLATE_USE_FOREGROUND) & pxlate->flPrivate) == flCreate
|
|
)
|
|
&&
|
|
(
|
|
(
|
|
!((XO_TO_MONO & pxlate->flXlate) || (XLATE_FROM_MONO & pxlate->flPrivate))
|
|
)
|
|
||
|
|
(
|
|
(XO_TO_MONO & pxlate->flXlate) &&
|
|
(iBackSrc == pxlate->iBackSrc) &&
|
|
(xlateTable[ulIndex].ulPalSrcDC == palSrcDC.ulTime())
|
|
)
|
|
||
|
|
(
|
|
(XLATE_FROM_MONO & pxlate->flPrivate) &&
|
|
(iForeDst == pxlate->iForeDst) &&
|
|
(iBackDst == pxlate->iBackDst)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
|
|
//
|
|
// HOT DOG, valid cache entry. It isn't deletable now
|
|
// because we have it locked down. Cache the index in palSrc.
|
|
//
|
|
|
|
InterlockedIncrement((LPLONG) &(xlateTable[ulIndex].ulReference));
|
|
palSrc.iXlateIndex(ulIndex);
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
ulIndex = (ulIndex + 1) & XLATE_MODULA;
|
|
}
|
|
|
|
pxlate = (PXLATE) NULL;
|
|
return(FALSE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* XLATEOBJ_iXlate
|
|
*
|
|
* This translates an index of a src palette to the closest index in the
|
|
* dst palette.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pxlo -
|
|
* cIndex -
|
|
*
|
|
* History:
|
|
* Mon 16-Mar-1992 -by- Patrick Haluptzok [patrickh]
|
|
* Fixed something.
|
|
*
|
|
* Wed 24-Jul-1991 -by- Patrick Haluptzok [patrickh]
|
|
* put in support for RGB-->monochrome.
|
|
*
|
|
* 22-Jul-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
extern "C"
|
|
ULONG
|
|
XLATEOBJ_iXlate(
|
|
XLATEOBJ *pxlo,
|
|
ULONG cIndex
|
|
)
|
|
{
|
|
if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
|
|
{
|
|
return(cIndex);
|
|
}
|
|
|
|
if (pxlo->flXlate & XO_TABLE)
|
|
{
|
|
if (cIndex > pxlo->cEntries)
|
|
{
|
|
cIndex = cIndex % pxlo->cEntries;
|
|
}
|
|
|
|
return(((XLATE *) pxlo)->ai[cIndex]);
|
|
}
|
|
|
|
//
|
|
// We are beyond source palette being PAL_INDEXED.
|
|
//
|
|
|
|
if (pxlo->flXlate & XO_TO_MONO)
|
|
{
|
|
if (cIndex == ((XLATE *) pxlo)->ai[0])
|
|
{
|
|
return(1);
|
|
}
|
|
else
|
|
{
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
ASSERTGDI(((XLATE *) pxlo)->ppalSrc != (PPALETTE) NULL, "ERROR ppalSrc is NULL");
|
|
|
|
//
|
|
// For 8bpp destinations, go through MarkE's optimized tablelookup code. This is
|
|
// not so much for performance reasons (XLATEOBJ_iXlate is already hopelessly slow),
|
|
// but to make sure GDI always performs this translation in the same way (with some drivers,
|
|
// StretchBlt to a device surface ends up in EngCopyBits which uses MarkE's table, but
|
|
// on the same machines StretchBlt to a memory surface goes through ulTranslate)
|
|
//
|
|
|
|
PPALETTE ppal = (((XLATE *) pxlo)->flPrivate & XLATE_PAL_MANAGED ?
|
|
((XLATE *) pxlo)->ppalDstDC : ((XLATE *) pxlo)->ppalDst);
|
|
|
|
ASSERTGDI(ppal != (PPALETTE) NULL, "ERROR ppal is NULL");
|
|
ASSERTGDI(((XLATE *) pxlo)->ppalDstDC != (PPALETTE) NULL, "ERROR ppalDstDC is NULL");
|
|
|
|
if ((ppal->flPal & PAL_INDEXED) &&
|
|
(((XLATE *) pxlo)->ppalDstDC->cEntries == 256))
|
|
{
|
|
PBYTE pxlate555 = ((XEPALOBJ) ppal).pGetRGBXlate();
|
|
if (pxlate555 == NULL)
|
|
{
|
|
WARNING1("Error in XLATEOBJ_iXlate: can't generate pxlate555");
|
|
return 0;
|
|
}
|
|
cIndex = XLATEOBJ_ulIndexToPalSurf(pxlo, pxlate555, cIndex);
|
|
}
|
|
else
|
|
{
|
|
PAL_ULONG palul;
|
|
|
|
palul.ul = ((XEPALOBJ) ((XLATE *) pxlo)->ppalSrc).ulIndexToRGB(cIndex);
|
|
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_PAL_MANAGED)
|
|
{
|
|
ASSERTGDI(((XLATE *) pxlo)->ppalDstDC != (PPALETTE) NULL, "ERROR ppalDstDC is NULL");
|
|
|
|
cIndex = ((XEPALOBJ) (((XLATE *) pxlo)->ppalDstDC)).ulGetNearestFromPalentry(palul.pal, SE_DONT_SEARCH_EXACT_FIRST);
|
|
|
|
|
|
if (((XLATE *) pxlo)->ppalDstDC == ppalDefault)
|
|
{
|
|
if (cIndex >= 10)
|
|
{
|
|
cIndex += 236;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(((XLATE *) pxlo)->ppalDstDC->flPal & PAL_DC, "ERROR in ulTranslate XLATEOBJ is hosed \n");
|
|
ASSERTGDI(cIndex < ((XLATE *) pxlo)->ppalDstDC->cEntries, "ERROR in ultranslate3");
|
|
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_USE_CURRENT)
|
|
{
|
|
cIndex = (ULONG) ((XLATE *) pxlo)->ppalDstDC->ptransCurrent->ajVector[cIndex];
|
|
}
|
|
else
|
|
{
|
|
cIndex = (ULONG) ((XLATE *) pxlo)->ppalDstDC->ptransFore->ajVector[cIndex];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(((XLATE *) pxlo)->ppalDst != (PPALETTE) NULL, "ERROR ppalDst is NULL");
|
|
|
|
cIndex = ((XEPALOBJ) (((XLATE *) pxlo)->ppalDst)).ulGetNearestFromPalentry(palul.pal, ((XEPALOBJ) (((XLATE *) pxlo)->ppalDst)).cEntries() ? SE_DONT_SEARCH_EXACT_FIRST : SE_DO_SEARCH_EXACT_FIRST);
|
|
}
|
|
}
|
|
|
|
return(cIndex);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* XLATEOBJ_pGetXlate555
|
|
*
|
|
* Retrieve 555 rgb xlate vector from appropriate palette
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pxlo
|
|
*
|
|
* Return Value:
|
|
*
|
|
* rgb555 xlate vector or NULL
|
|
*
|
|
* History:
|
|
*
|
|
* 2/27/1997 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
PBYTE
|
|
XLATEOBJ_pGetXlate555(
|
|
XLATEOBJ *pxlo
|
|
)
|
|
{
|
|
PBYTE pxlate555 = NULL;
|
|
|
|
//
|
|
// return hi color to palette 555 translate table if the xlateobj
|
|
// is appropriate
|
|
//
|
|
|
|
if (
|
|
(pxlo == NULL) ||
|
|
(pxlo->flXlate & XO_TRIVIAL) ||
|
|
(pxlo->flXlate & XO_TABLE) ||
|
|
(pxlo->flXlate & XO_TO_MONO)
|
|
)
|
|
{
|
|
return(NULL);
|
|
}
|
|
|
|
//
|
|
// determine palette type to map.
|
|
//
|
|
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_PAL_MANAGED)
|
|
{
|
|
ASSERTGDI(((XLATE *) pxlo)->ppalDstDC != (PPALETTE) NULL, "ERROR ppalDstDC is NULL");
|
|
|
|
pxlate555 = ((XEPALOBJ) (((XLATE *) pxlo)->ppalDstDC)).pGetRGBXlate();
|
|
}
|
|
else
|
|
{
|
|
if (((XEPALOBJ) (((XLATE *) pxlo)->ppalDst)).bValid())
|
|
{
|
|
pxlate555 = ((XEPALOBJ) (((XLATE *) pxlo)->ppalDst)).pGetRGBXlate();
|
|
}
|
|
}
|
|
|
|
return(pxlate555);
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* XLATEOBJ_ulIndexToPalSurf
|
|
* - take generic pixel input, convert it to RGB, then use the rgb555
|
|
* to palette index table to look up a palette index
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pxlo - xlate object
|
|
* pxlate555 - member of dest palette object, 555RGB to palette
|
|
* ulRGB - index input
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Destination 8 bit pixel
|
|
*
|
|
* History:
|
|
*
|
|
* 2/20/1997 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BYTE
|
|
XLATEOBJ_ulIndexToPalSurf(
|
|
XLATEOBJ *pxlo,
|
|
PBYTE pxlate555,
|
|
ULONG ulRGB
|
|
)
|
|
{
|
|
ALPHAPIX apix;
|
|
BYTE palIndex = 0;
|
|
|
|
ASSERTGDI(pxlate555 != NULL,"XLATEOBJ_ulIndexToPalSurf: NULL pxlate555\n");
|
|
|
|
apix.ul = ulRGB;
|
|
|
|
apix.ul = ((XEPALOBJ) ((XLATE *) pxlo)->ppalSrc).ulIndexToRGB(ulRGB);
|
|
|
|
palIndex = pxlate555[((apix.pix.b & 0xf8) << 7) |
|
|
((apix.pix.g & 0xf8) << 2) |
|
|
((apix.pix.r & 0xf8) >> 3)];
|
|
|
|
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_PAL_MANAGED)
|
|
{
|
|
if (((XLATE *) pxlo)->ppalDstDC == ppalDefault)
|
|
{
|
|
if (palIndex >= 10)
|
|
{
|
|
palIndex += 236;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_USE_CURRENT)
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransCurrent->ajVector[palIndex];
|
|
}
|
|
else
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransFore->ajVector[palIndex];
|
|
}
|
|
}
|
|
}
|
|
|
|
return(palIndex);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* XLATEOBJ_RGB32ToPalSurf
|
|
* - take 32 RGB pixel input, then use the rgb555
|
|
* to palette index table to look up a palette index
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pxlo - xlate object
|
|
* pxlate555 - member of dest palette object, 555RGB to palette
|
|
* ulRGB - 32 bit RGB input pixel
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Destination 8 bit pixel
|
|
*
|
|
* History:
|
|
*
|
|
* 2/20/1997 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BYTE
|
|
XLATEOBJ_RGB32ToPalSurf(
|
|
XLATEOBJ *pxlo,
|
|
PBYTE pxlate555,
|
|
ULONG ulRGB
|
|
)
|
|
{
|
|
ALPHAPIX apix;
|
|
BYTE palIndex = 0;
|
|
|
|
ASSERTGDI(pxlate555 != NULL,"XLATEOBJ_RGB32ToPalSurf: NULL pxlate555\n");
|
|
|
|
apix.ul = ulRGB;
|
|
|
|
palIndex = pxlate555[((apix.pix.b & 0xf8) << 7) |
|
|
((apix.pix.g & 0xf8) << 2) |
|
|
((apix.pix.r & 0xf8) >> 3)];
|
|
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_PAL_MANAGED)
|
|
{
|
|
if (((XLATE *) pxlo)->ppalDstDC == ppalDefault)
|
|
{
|
|
if (palIndex >= 10)
|
|
{
|
|
palIndex += 236;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_USE_CURRENT)
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransCurrent->ajVector[palIndex];
|
|
}
|
|
else
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransFore->ajVector[palIndex];
|
|
}
|
|
}
|
|
}
|
|
|
|
return(palIndex);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* XLATEOBJ_RGB32ToPalSurf
|
|
* - take 32 BGR pixel input, then use the rgb555
|
|
* to palette index table to look up a palette index
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pxlo - xlate object
|
|
* pxlate555 - member of dest palette object, 555RGB to palette
|
|
* ulRGB - 32 bit BGR input pixel
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Destination 8 bit pixel
|
|
*
|
|
* History:
|
|
*
|
|
* 2/20/1997 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BYTE
|
|
XLATEOBJ_BGR32ToPalSurf(
|
|
XLATEOBJ *pxlo,
|
|
PBYTE pxlate555,
|
|
ULONG ulRGB
|
|
)
|
|
{
|
|
BYTE palIndex;
|
|
ALPHAPIX apix;
|
|
|
|
ASSERTGDI(pxlate555 != NULL,"XLATEOBJ_BGR32ToPalSurf: NULL pxlate555\n");
|
|
|
|
apix.ul = ulRGB;
|
|
|
|
palIndex = pxlate555[((apix.pix.r & 0xf8) << 7) |
|
|
((apix.pix.g & 0xf8) << 2) |
|
|
((apix.pix.b & 0xf8) >> 3)];
|
|
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_PAL_MANAGED)
|
|
{
|
|
if (((XLATE *) pxlo)->ppalDstDC == ppalDefault)
|
|
{
|
|
if (palIndex >= 10)
|
|
{
|
|
palIndex += 236;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_USE_CURRENT)
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransCurrent->ajVector[palIndex];
|
|
}
|
|
else
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransFore->ajVector[palIndex];
|
|
}
|
|
}
|
|
}
|
|
return(palIndex);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* XLATEOBJ_RGB16_565ToPalSurf
|
|
* - take 16 bit 565 pixel input, then use the rgb555
|
|
* to palette index table to look up a palette index
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pxlo - xlate object
|
|
* pxlate555 - member of dest palette object, 555RGB to palette
|
|
* ulRGB - 16 bit 565 input pixel
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Destination 8 bit pixel
|
|
*
|
|
* History:
|
|
*
|
|
* 2/20/1997 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BYTE
|
|
XLATEOBJ_RGB16_565ToPalSurf(
|
|
XLATEOBJ *pxlo,
|
|
PBYTE pxlate555,
|
|
ULONG ulRGB
|
|
)
|
|
{
|
|
BYTE palIndex = 0;
|
|
|
|
ASSERTGDI(pxlate555 != NULL,"XLATEOBJ_BGR16_565ToPalSurf: NULL pxlate555\n");
|
|
|
|
palIndex = pxlate555[((ulRGB & 0xf800) >> 1) |
|
|
((ulRGB & 0x07c0) >> 1) |
|
|
((ulRGB & 0x001f))];
|
|
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_PAL_MANAGED)
|
|
{
|
|
if (((XLATE *) pxlo)->ppalDstDC == ppalDefault)
|
|
{
|
|
if (palIndex >= 10)
|
|
{
|
|
palIndex += 236;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_USE_CURRENT)
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransCurrent->ajVector[palIndex];
|
|
}
|
|
else
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransFore->ajVector[palIndex];
|
|
}
|
|
}
|
|
}
|
|
return(palIndex);
|
|
}
|
|
|
|
/**************************************************************************\
|
|
* XLATEOBJ_RGB16_555ToPalSurf
|
|
* - take 16 bit 555 pixel input, then use the rgb555
|
|
* to palette index table to look up a palette index
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pxlo - xlate object
|
|
* pxlate555 - member of dest palette object, 555RGB to palette
|
|
* ulRGB - 16 bit 555 input pixel
|
|
*
|
|
*
|
|
* Return Value:
|
|
*
|
|
* Destination 8 bit pixel
|
|
*
|
|
* History:
|
|
*
|
|
* 2/20/1997 Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BYTE
|
|
XLATEOBJ_RGB16_555ToPalSurf(
|
|
XLATEOBJ *pxlo,
|
|
PBYTE pxlate555,
|
|
ULONG ulRGB
|
|
)
|
|
{
|
|
BYTE palIndex = 0;
|
|
|
|
ASSERTGDI(pxlate555 != NULL,"XLATEOBJ_BGR16_555ToPalSurf: NULL pxlate555\n");
|
|
|
|
palIndex = pxlate555[ulRGB & 0x7fff];
|
|
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_PAL_MANAGED)
|
|
{
|
|
if (((XLATE *) pxlo)->ppalDstDC == ppalDefault)
|
|
{
|
|
if (palIndex >= 10)
|
|
{
|
|
palIndex += 236;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (((XLATE *) pxlo)->flPrivate & XLATE_USE_CURRENT)
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransCurrent->ajVector[palIndex];
|
|
}
|
|
else
|
|
{
|
|
palIndex = ((XLATE *) pxlo)->ppalDstDC->ptransFore->ajVector[palIndex];
|
|
}
|
|
}
|
|
}
|
|
return(palIndex);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* XLATEMEMOBJ
|
|
*
|
|
* This is a special constructor for the UpdateColors case. It deletes the
|
|
* old xlate when it is done.
|
|
*
|
|
* History:
|
|
* 12-Dec-1991 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
XLATEMEMOBJ::XLATEMEMOBJ(
|
|
XEPALOBJ palSurf,
|
|
XEPALOBJ palDC
|
|
)
|
|
{
|
|
//
|
|
// Assert some fundamental truths.
|
|
//
|
|
|
|
ASSERTGDI(palDC.bValid(), "invalid palDC in xlatememobj123\n");
|
|
ASSERTGDI(palSurf.bIsPalManaged(), "invalid surface palette in UpdateColors xlate");
|
|
ASSERTGDI(palSurf.bValid(), "invalid palSurf in xlatememobj123\n");
|
|
ASSERTGDI(!(palDC.bIsRGB()), "RGB palDC in DC->surf xlate constructor123\n");
|
|
ASSERTGDI(!(palSurf.bIsRGB()), "RGB palSurf in DC->surf xlate constructor123\n");
|
|
ASSERTGDI(palDC.bIsPalDC(), "not a palDC for palDC in xlatememobj123\n");
|
|
ASSERTGDI(palDC.ptransCurrent() != NULL, "ERROR ptrans Null UpdateColors");
|
|
ASSERTGDI(palDC.ptransOld() != NULL, "ERROR ptransOld Null UpdateColors");
|
|
|
|
ULONG ulTemp;
|
|
PULONG pulTemp;
|
|
|
|
pxlate = pCreateXlate(palSurf.cEntries());
|
|
|
|
if (pxlate)
|
|
{
|
|
pxlate->ppalSrc = palSurf.ppalGet();
|
|
pxlate->ppalDst = palSurf.ppalGet();
|
|
pxlate->ppalDstDC = palDC.ppalGet();
|
|
pulTemp = pxlate->ai;
|
|
|
|
//
|
|
// Set up identity vector for all entries
|
|
//
|
|
|
|
for (ulTemp = 0; ulTemp < pxlate->cEntries; ulTemp++)
|
|
{
|
|
pulTemp[ulTemp] = ulTemp;
|
|
}
|
|
|
|
//
|
|
// Change the ones that are affected by the palette realizations.
|
|
//
|
|
|
|
PTRANSLATE ptransOld = palDC.ptransOld();
|
|
PTRANSLATE ptransCurrent = palDC.ptransCurrent();
|
|
|
|
for (ulTemp = 0; ulTemp < palDC.cEntries(); ulTemp++)
|
|
{
|
|
pulTemp[ptransOld->ajVector[ulTemp]] = (ULONG) ptransCurrent->ajVector[ulTemp];
|
|
}
|
|
|
|
pxlate->vCheckForTrivial();
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EXLATEOBJ::bCreateXlateFromTable
|
|
*
|
|
* This is used to initialize an xlate when the table is already computed.
|
|
* We need this to support journaling.
|
|
*
|
|
* History:
|
|
* 17-Mar-1992 -by- Patrick Haluptzok patrickh
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
EXLATEOBJ::bCreateXlateFromTable(
|
|
ULONG cEntry,
|
|
PULONG pulVector,
|
|
XEPALOBJ palDst
|
|
)
|
|
{
|
|
//
|
|
// Assert good input data.
|
|
//
|
|
|
|
ASSERTGDI(palDst.bValid(), "ERROR bInitXlate bad palDst");
|
|
ASSERTGDI(pulVector != (PULONG) NULL, "ERROR bInitXlate bad pulVector");
|
|
ASSERTGDI(cEntry != 0, "ERROR bInitXlate cEntry is 0");
|
|
|
|
//
|
|
// Allocate room for the Xlate.
|
|
//
|
|
|
|
pxlate = pCreateXlate(cEntry);
|
|
|
|
if (pxlate == NULL)
|
|
{
|
|
WARNING("ERROR bInitXlate failed call to pCreateXlate\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
pxlate->ppalDst = palDst.ppalGet();
|
|
pxlate->iDstType = (USHORT) palDst.iPalMode();
|
|
|
|
//
|
|
// Ok, fill in the xlate vector.
|
|
//
|
|
|
|
RtlCopyMemory(pxlate->ai, pulVector, (UINT) (cEntry * sizeof(ULONG)));
|
|
|
|
//
|
|
// Init accelerators, out of here.
|
|
//
|
|
|
|
pxlate->vCheckForTrivial();
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* XLATE::vCheckForICM()
|
|
*
|
|
* History:
|
|
* 26-Feb-1997 -by- Hideyuki Nagase [hideyukn]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID XLATE::vCheckForICM(HANDLE _hcmXform,ULONG _lIcmMode)
|
|
{
|
|
//
|
|
// First, initialize ICM mode as default (off)
|
|
//
|
|
lIcmMode = DC_ICM_OFF;
|
|
hcmXform = NULL;
|
|
|
|
//
|
|
// Check is there any ICM is enabled ?
|
|
//
|
|
if (IS_ICM_ON(_lIcmMode))
|
|
{
|
|
if (IS_ICM_INSIDEDC(_lIcmMode))
|
|
{
|
|
//
|
|
// Inside DC ICM is enabled with valid color transform.
|
|
//
|
|
|
|
//
|
|
// Copy mode and color transform handle to XLATE.
|
|
//
|
|
lIcmMode = _lIcmMode;
|
|
hcmXform = _hcmXform;
|
|
|
|
if (IS_ICM_DEVICE(lIcmMode))
|
|
{
|
|
COLORTRANSFORMOBJ CXFormObj(_hcmXform);
|
|
|
|
//
|
|
// Check transform handle is valid or not.
|
|
//
|
|
if (CXFormObj.bValid())
|
|
{
|
|
ICMMSG(("vCheckForICM():XO_DEVICE_ICM\n"));
|
|
|
|
//
|
|
// Device driver will do color matching.
|
|
//
|
|
flXlate |= XO_DEVICE_ICM;
|
|
}
|
|
}
|
|
else if (IS_ICM_HOST(lIcmMode))
|
|
{
|
|
ICMMSG(("vCheckForICM():XO_HOST_ICM\n"));
|
|
|
|
//
|
|
// Inform the images is corrected by host CMM
|
|
//
|
|
flXlate |= XO_HOST_ICM;
|
|
|
|
if (IS_CMYK_COLOR(lIcmMode) && (hcmXform != NULL))
|
|
{
|
|
ICMMSG(("vCheckForICM():XO_FROM_CMYK\n"));
|
|
|
|
//
|
|
// The destination surface is 32bits CMYK color,
|
|
// This is only happen when ICM is done by host.
|
|
//
|
|
flXlate |= XO_FROM_CMYK;
|
|
}
|
|
}
|
|
}
|
|
else if (IS_ICM_OUTSIDEDC(_lIcmMode))
|
|
{
|
|
//
|
|
// Outside DC is enabled, color correction is done by application.
|
|
//
|
|
|
|
//
|
|
// Copy mode and color transform handle to XLATE.
|
|
//
|
|
lIcmMode = _lIcmMode;
|
|
hcmXform = 0;
|
|
|
|
//
|
|
// Inform the images is corrected by Host (application) ICM
|
|
//
|
|
flXlate |= XO_HOST_ICM;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vXlateBitfieldsToBitfields
|
|
*
|
|
* Translates a color between to arbitrary bitfield (or RGB or BGR) formats.
|
|
\**************************************************************************/
|
|
|
|
ULONG FASTCALL iXlateBitfieldsToBitfields(XLATEOBJ* pxlo, ULONG ul)
|
|
{
|
|
ul = ((XEPALOBJ) ((XLATE *) pxlo)->ppalSrc).ulIndexToRGB(ul);
|
|
ul = ((XEPALOBJ) ((XLATE *) pxlo)->ppalDst).ulGetNearestFromPalentry(
|
|
*((PALETTEENTRY*) &ul));
|
|
|
|
return(ul);
|
|
}
|
|
|
|
ULONG FASTCALL iXlate565ToBGR(XLATEOBJ *pxlo, ULONG ul)
|
|
{
|
|
return(((ul << 8) & 0xf80000)
|
|
| ((ul << 3) & 0x070000)
|
|
| ((ul << 5) & 0x00fc00)
|
|
| ((ul >> 1) & 0x000300)
|
|
| ((ul << 3) & 0x0000f8)
|
|
| ((ul >> 2) & 0x000007));
|
|
}
|
|
|
|
ULONG FASTCALL iXlate555ToBGR(XLATEOBJ *pxlo, ULONG ul)
|
|
{
|
|
return(((ul << 9) & 0xf80000)
|
|
| ((ul << 4) & 0x070000)
|
|
| ((ul << 6) & 0x00f800)
|
|
| ((ul << 1) & 0x000700)
|
|
| ((ul << 3) & 0x0000f8)
|
|
| ((ul >> 2) & 0x000007));
|
|
}
|
|
|
|
ULONG FASTCALL iXlateBGRTo565(XLATEOBJ *pxlo, ULONG ul)
|
|
{
|
|
return(((ul >> 8) & 0xf800)
|
|
| ((ul >> 5) & 0x07e0)
|
|
| ((ul >> 3) & 0x001f));
|
|
}
|
|
|
|
ULONG FASTCALL iXlateBGRTo555(XLATEOBJ *pxlo, ULONG ul)
|
|
{
|
|
return(((ul >> 9) & 0x7c00)
|
|
| ((ul >> 6) & 0x03e0)
|
|
| ((ul >> 3) & 0x001f));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* pfnXlateBetweenBitfields
|
|
*
|
|
* Returns a pointer to an optimized routine for converting between
|
|
* two bitfields (or RGB or BGR) colors.
|
|
\**************************************************************************/
|
|
|
|
PFN_pfnXlate XLATE::pfnXlateBetweenBitfields()
|
|
{
|
|
PFN_pfnXlate pfnXlate;
|
|
XEPALOBJ palSrc(ppalSrc);
|
|
XEPALOBJ palDst(ppalDst);
|
|
|
|
ASSERTGDI(palSrc.bIsBitfields() || palSrc.bIsRGB() || palSrc.bIsBGR(),
|
|
"ERROR: Expected bitfields source");
|
|
ASSERTGDI(palDst.bIsBitfields() || palDst.bIsRGB() || palDst.bIsBGR(),
|
|
"ERROR: Expected bitfields destination");
|
|
|
|
pfnXlate = iXlateBitfieldsToBitfields;
|
|
|
|
if (palDst.bIsBGR())
|
|
{
|
|
if (palSrc.bIs565())
|
|
{
|
|
pfnXlate = iXlate565ToBGR;
|
|
}
|
|
else if (palSrc.bIs555())
|
|
{
|
|
pfnXlate = iXlate555ToBGR;
|
|
}
|
|
}
|
|
else if (palSrc.bIsBGR())
|
|
{
|
|
if (palDst.bIs565())
|
|
{
|
|
pfnXlate = iXlateBGRTo565;
|
|
}
|
|
else if (palDst.bIs555())
|
|
{
|
|
pfnXlate = iXlateBGRTo555;
|
|
}
|
|
}
|
|
|
|
return(pfnXlate);
|
|
}
|