Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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);
}