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