|
|
/******************************Module*Header*******************************\
* Module Name: palgdi.cxx * * This module provides the API level interface functions for dealing with * palettes. * * Created: 07-Nov-1990 22:21:11 * Author: Patrick Haluptzok patrickh * * Copyright (c) 1990-1999 Microsoft Corporation \**************************************************************************/
#include "precomp.hxx"
// hForePalette is a global variable that tells which palette is currently
// realized in the foreground.
HPALETTE hForePalette = 0; PW32PROCESS hForePID = 0;
#if DBG
ULONG DbgPal = 0; #define PAL_DEBUG(l,x) {if (l <= DbgPal) {DbgPrint("%p ", hpalDC); DbgPrint(x);}}
#else
#define PAL_DEBUG(l,x)
#endif
/******************************Public*Routine******************************\
* GreGetDIBColorTable * * Get the color table of the DIB section currently selected into the dc * identified by the given hdc. If the surface is not a DIB section, * this function will fail. * * History: * 07-Sep-1993 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
#if ((BMF_1BPP != 1) || (BMF_4BPP != 2) || (BMF_8BPP != 3))
#error GetDIBColorTable BAD FORMAT
#endif
UINT APIENTRY GreGetDIBColorTable( HDC hdc, UINT iStart, UINT cEntries, RGBQUAD *pRGB ) {
UINT iRet = 0; DCOBJ dco(hdc);
if (pRGB != (RGBQUAD *)NULL) { if (dco.bValid()) { //
// Protect against dynamic mode changes while we go grunging
// around in the surface.
//
DEVLOCKOBJ dlo; dlo.vLockNoDrawing(dco);
//
// Fail if the selected in surface is not a DIB or the depth is more than
// 8BPP.
//
SURFACE *pSurf = dco.pSurfaceEff(); ULONG iFormat = pSurf->iFormat(); if ((pSurf->bDIBSection() || (pSurf->pPal != NULL)) && (iFormat <= BMF_8BPP) && (iFormat >= BMF_1BPP)) { //
// Lock the surface palette and figure out the max index allowed on the
// palette. Win95 does not return un-used entries.
//
XEPALOBJ pal(pSurf->ppal()); ASSERTGDI(pal.bValid(), "GetDIBColorTable: invalid pal\n");
UINT iMax = (UINT) pal.cEntries();
if (iStart >= iMax) { return(0); }
UINT iLast = iStart + cEntries;
if (iLast > iMax) { iLast = iMax; }
pal.vFill_rgbquads(pRGB, iStart, iRet = iLast - iStart); } else { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); } } else { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); } } else { SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER); }
return(iRet); }
/******************************Public*Routine******************************\
* GreSetDIBColorTable * * Set the color table of the DIB section currently selected into the dc * identified by the given hdc. If the surface is not a DIB section, * this function will fail. * * History: * 07-Sep-1993 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
UINT APIENTRY GreSetDIBColorTable( HDC hdc, UINT iStart, UINT cEntries, RGBQUAD *pRGB ) {
UINT iRet = 0; DCOBJ dco(hdc);
if (dco.bValid()) { //
// Protect against dynamic mode changes while we go grunging
// around in the surface.
//
DEVLOCKOBJ dlo; dlo.vLockNoDrawing(dco);
//
// Fail if the selected in surface is not a DIB or the depth is more than
// 8BPP.
//
SURFACE *pSurf = dco.pSurfaceEff(); ULONG iFormat = pSurf->iFormat(); if (pSurf->bDIBSection() && (iFormat <= BMF_8BPP) && (iFormat >= BMF_1BPP)) { //
// Mark the brushes dirty.
//
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
//
// Lock the surface palette and figure out the max
// index allowed on the palette.
//
XEPALOBJ pal(pSurf->ppal()); ASSERTGDI(pal.bValid(), "GetDIBColorTable: invalid pal\n");
UINT iMax = (UINT) pal.cEntries(); if (iStart < iMax) { UINT iLast = iStart + cEntries; if (iLast > iMax) iLast = iMax;
pal.vCopy_rgbquad(pRGB, iStart, iRet = iLast - iStart); } } else { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); } } else { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); }
return(iRet); }
/******************************Public*Routine******************************\
* GreCreatePalette - creates a palette from the logpal information given * * API function. * * returns HPALETTE for succes, (HPALETTE) 0 for failure * * History: * 07-Nov-1990 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
HPALETTE APIENTRY GreCreatePalette( LPLOGPALETTE pLogPal ) {
return(GreCreatePaletteInternal(pLogPal,pLogPal->palNumEntries)); }
HPALETTE APIENTRY GreCreatePaletteInternal( LPLOGPALETTE pLogPal, UINT cEntries ) { if ((pLogPal->palVersion != 0x300) || (cEntries == 0)) { WARNING("GreCreatePalette failed, 0 entries or wrong version\n"); return((HPALETTE) 0); }
//
// The constructor checks for invalid flags and fails if they are found.
//
PALMEMOBJ pal;
if (!pal.bCreatePalette(PAL_INDEXED, cEntries, (PULONG) pLogPal->palPalEntry, 0, 0, 0, (PAL_DC | PAL_FREE))) { return((HPALETTE) 0); }
ASSERTGDI(pal.cEntries() != 0, "ERROR can't be 0, bGetEntriesFrom depends on that");
pal.vKeepIt(); GreSetPaletteOwner((HPALETTE)pal.hpal(), OBJECT_OWNER_CURRENT); return((HPALETTE) pal.hpal()); }
/******************************Public*Routine******************************\
* NtGdiCreatePaletteInternal() * * History: * 01-Nov-1994 -by- Eric Kutter [erick] * Wrote it. \**************************************************************************/
HPALETTE APIENTRY NtGdiCreatePaletteInternal( LPLOGPALETTE pLogPal, UINT cEntries ) { HPALETTE hpalRet = (HPALETTE)1;
//
// verify cEntries
//
if (cEntries <= 65536) { int cj = cEntries * sizeof(PALETTEENTRY) + offsetof(LOGPALETTE,palPalEntry); WORD Version; PULONG pPaletteEntry;
__try { // it is safe to do a byte here. If we can access dword's on byte boundries
// this will work. If not we will hit an exception under a try except. Winhelp
// passes in an unaligned palette but only on x86.
ProbeForRead(pLogPal,cj, sizeof(BYTE)); Version = pLogPal->palVersion; pPaletteEntry = (PULONG) pLogPal->palPalEntry; } __except(EXCEPTION_EXECUTE_HANDLER) { // SetLastError(GetExceptionCode());
hpalRet = (HPALETTE)0; }
if (hpalRet) { if ((Version != 0x300) || (cEntries == 0)) { WARNING("GreCreatePalette failed, 0 entries or wrong version\n"); hpalRet = (HPALETTE)0; }
if (hpalRet) {
//
// The constructor checks for invalid flags and fails if they are found.
//
PALMEMOBJ pal; BOOL bStatus;
//
// bCreatePalette must use a try-except when accessing pPaletteEntry
//
bStatus = pal.bCreatePalette(PAL_INDEXED, cEntries, pPaletteEntry, 0, 0, 0, (PAL_DC | PAL_FREE));
if (bStatus) { ASSERTGDI(pal.cEntries() != 0, "ERROR can't be 0, bGetEntriesFrom depends on that");
bStatus = GreSetPaletteOwner((HPALETTE)pal.hpal(), OBJECT_OWNER_CURRENT);
if (bStatus) { pal.vKeepIt(); hpalRet = pal.hpal(); } else { hpalRet = (HPALETTE)0; } } else { hpalRet = (HPALETTE)0; } } } } else { hpalRet = 0; WARNING("GreCreatePalette failed,cEntries too large\n"); }
return(hpalRet); }
/******************************Public*Routine******************************\
* GreCreateCompatibleHalftonePalette * * Creates the win95 compatible halftone palette * * Arguments: * * * * Return Value: * * * * History: * * 11/27/1996 Mark Enstrom [marke] * \**************************************************************************/
HPALETTE APIENTRY GreCreateCompatibleHalftonePalette( HDC hdc ) { HPALETTE hpalRet; PALMEMOBJ pal; BOOL bStatus;
//
// bCreatePalette must use a try-except when accessing pPaletteEntry
//
bStatus = pal.bCreatePalette(PAL_INDEXED, 256, (PULONG)&aPalHalftone[0].ul, 0, 0, 0, (PAL_DC | PAL_FREE | PAL_HT));
if (bStatus) { ASSERTGDI(pal.cEntries() != 0, "ERROR can't be 0, bGetEntriesFrom depends on that");
pal.flPal(PAL_HT);
bStatus = GreSetPaletteOwner((HPALETTE)pal.hpal(), OBJECT_OWNER_CURRENT);
if (bStatus) { pal.vKeepIt(); hpalRet = pal.hpal(); } else { hpalRet = (HPALETTE)0; } } else { hpalRet = (HPALETTE)0; } return(hpalRet); }
/******************************Public*Routine******************************\
* GreCreateHalftonePalette(hdc) * * Create a halftone palette for the given DC. * * History: * 31-Aug-1992 -by- Wendy Wu [wendywu] * Wrote it. \**************************************************************************/
HPALETTE APIENTRY GreCreateHalftonePalette( HDC hdc ) { //
// Validate and lock down the DC. NOTE: Even though the surface is accessed
// in this function, it is only for information purposes. No reading or
// writing of the surface occurs.
//
DCOBJ dco(hdc);
if (!dco.bValid()) { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); return((HPALETTE) 0); }
//
// Get the PDEV from the DC.
//
PDEVOBJ po(dco.hdev());
//
// Acquire the devlock to protect against dynamic mode changes while
// we enable halftoning for the PDEV and we construct the halftone
// palette from this information.
//
DEVLOCKOBJ dlo(po);
//
// Create the halftone block if it has not existed yet.
//
if ((po.pDevHTInfo() == NULL) && !po.bEnableHalftone((PCOLORADJUSTMENT)NULL)) return((HPALETTE) 0);
DEVICEHALFTONEINFO *pDevHTInfo = (DEVICEHALFTONEINFO *)po.pDevHTInfo();
//
// Use the entries in the halftone palette in the halftone block to create
// the palette.
//
EPALOBJ palHT((HPALETTE)pDevHTInfo->DeviceOwnData); ASSERTGDI(palHT.bValid(), "GreCreateHalftonePalette: invalid HT pal\n");
PALMEMOBJ pal; if (palHT.cEntries()) { if (!pal.bCreatePalette(PAL_INDEXED, palHT.cEntries(), (PULONG)palHT.apalColorGet(), 0, 0, 0, (PAL_DC | PAL_FREE | PAL_HT))) { return((HPALETTE) 0); } } else { //
// 16BPP halftone uses 555 for RGB. We can't create a zero
// entry palette at the API level, so lets create a default palette.
//
if (!pal.bCreatePalette(PAL_INDEXED, (ULONG)logDefaultPal.palNumEntries, (PULONG)logDefaultPal.palPalEntry, 0, 0, 0, PAL_DC | PAL_FREE | PAL_HT)) { return(FALSE); } }
pal.vKeepIt(); GreSetPaletteOwner((HPALETTE)pal.hpal(), OBJECT_OWNER_CURRENT); return((HPALETTE) pal.hpal()); }
/******************************Public*Routine******************************\
* GreGetNearestPaletteIndex - returns the nearest palette index to crColor * in the hpalette. Can only fail if hpal passed in is busy or bad. * * API function. * * returns value >= 0 for success, -1 for failure. * * History: * 09-Nov-1990 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
UINT APIENTRY NtGdiGetNearestPaletteIndex( HPALETTE hpal, COLORREF crColor ) { EPALOBJ pal((HPALETTE) hpal);
if (pal.bValid()) { //
// If the palette has 0 entries return the color passed in.
//
if (pal.cEntries()) { if (crColor & 0x01000000) { crColor &= 0x0000FFFF;
if (crColor >= pal.cEntries()) crColor = 0; } else { crColor &= 0x00FFFFFF; crColor = pal.ulGetNearestFromPalentry(*((PPALETTEENTRY) &crColor)); } } } else { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); crColor = CLR_INVALID; }
return((UINT) crColor); }
/******************************Public*Routine******************************\
* GreAnimatePalette * * API function * * Returns: The number of logical palette entries animated, 0 for error. * * History: * 17-Nov-1990 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
BOOL APIENTRY GreAnimatePalette(HPALETTE hpal, UINT ulStartIndex, UINT ulNumEntries, CONST PALETTEENTRY *lpPaletteColors) { BOOL bReturn = FALSE;
EPALOBJ pal((HPALETTE) hpal);
if (pal.bValid()) { bReturn = (BOOL) pal.ulAnimatePalette(ulStartIndex, ulNumEntries, lpPaletteColors); }
return(bReturn); }
/******************************Public*Routine******************************\
* GreGetPaletteEntries * * API function * * returns: 0 for failure, else number of entries retrieved. * * History: * 18-Nov-1990 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
UINT APIENTRY GreGetPaletteEntries(HPALETTE hpal, UINT ulStartIndex, UINT ulNumEntries, LPPALETTEENTRY pRGB) { //
// Note on this call we can just let the default palette go through
// since it isn't getting modified, and the constructor is smart
// enough not to really lock it down.
//
EPALOBJ pal((HPALETTE) hpal);
if (!pal.bValid()) { SAVE_ERROR_CODE(ERROR_INVALID_HANDLE); return(0); }
return(pal.ulGetEntries(ulStartIndex, ulNumEntries, pRGB, FALSE)); }
/******************************Public*Routine******************************\
* GreSetPaletteEntries * * API function * * returns: 0 for failure, else number of entries retrieved. * * History: * 18-Nov-1990 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
UINT GreSetPaletteEntries( HPALETTE hpal, UINT ulStartIndex, UINT ulNumEntries, CONST PALETTEENTRY *pRGB ) { //
// Note on this call we don't worry about STOCKOBJ_PAL because ulSetEntries
// won't let the default palette get modified.
//
UINT uiReturn = 0;
EPALOBJ pal((HPALETTE) hpal);
if (pal.bValid()) { //
// You must grab the palette semaphore to touch the linked list of DC's.
//
SEMOBJ semo(ghsemPalette);
uiReturn = (UINT) pal.ulSetEntries(ulStartIndex, ulNumEntries, pRGB);
//
// Run down all the DC's for this palette.
// Set the flags to dirty the brushes, since we changed the palette!
//
{ MLOCKFAST mlo;
HDC hdcNext = pal.hdcHead(); while ( hdcNext != (HDC)0 ) { MDCOBJA dco(hdcNext);
//
// WINBUG #55203 2-1-2000 bhouse Remove temporary fix to avoid AV when setting DIRTY_BRUSHES
// This is just a temp fix (since '95 hehehe) to keep
// this from doing an AV. Lingyun, making the
// brush flags all be in kernel memory will
// fix this.
//
// this should just be
// dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
//
if (GreGetObjectOwner((HOBJ)hdcNext,DC_TYPE) == W32GetCurrentPID()) { dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES); } else { dco.pdc->flbrushAdd(DIRTY_FILL); }
hdcNext = dco.pdc->hdcNext(); } } }
return(uiReturn); }
/******************************Public*Routine******************************\
* GreGetNearestColor * * This function returns the color that will be displayed on the device * if a solid brush was created with the given colorref. * * History: * Mon 29-Nov-1993 -by- Patrick Haluptzok [patrickh] * Don't round the color on non-indexed devices * * 15-Jan-1991 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
COLORREF APIENTRY GreGetNearestColor(HDC hdc, COLORREF crColor) { ULONG ulRet;
DCOBJ dco(hdc);
if (dco.bValid()) {
//
// Protect against dynamic mode changes while we go grunging
// around in the surface.
//
DEVLOCKOBJ dlo; dlo.vLockNoDrawing(dco);
XEPALOBJ palDC(dco.ppal());
XEPALOBJ palSurf;
SURFACE *pSurf = dco.pSurfaceEff();
if ((dco.dctp() == DCTYPE_INFO) || (dco.dctp() == DCTYPE_DIRECT)) { PDEVOBJ po(dco.hdev()); ASSERTGDI(po.bValid(), "ERROR GreGetNearestColor invalid PDEV\n");
palSurf.ppalSet(po.ppalSurf()); ASSERTGDI(palSurf.bValid(), "ERROR GreGetNearestColor invalid palDefault"); } else { ASSERTGDI(dco.dctp() == DCTYPE_MEMORY, "Not a memory DC type"); palSurf.ppalSet(pSurf->ppal()); }
//
// if ICM translate the color to CMYK, just return the passed CMYK color.
//
if (dco.pdc->bIsCMYKColor()) { ulRet = crColor; } else { if (((crColor & 0x01000000) == 0) && (palSurf.bValid() && !(palSurf.bIsIndexed()))) { //
// Well if it isn't index it's RGB,BGR, or Bitfields.
// In any case to support Win3.1 we need to return exactly
// what was passed in otherwise they think we are a monochrome
// device. Bitfields could result is some messy rounding so
// it's more exact to just return the RGB passed in.
//
ulRet = crColor & 0x00FFFFFF; // mask off the highest byte
} else { ulRet = ulIndexToRGB(palSurf, palDC, ulGetNearestIndexFromColorref(palSurf, palDC, crColor)); } } } else { ulRet = CLR_INVALID; }
return(ulRet); }
/******************************Public*Routine******************************\
* GreGetSystemPaletteEntries * * API Function - copies out the range of palette entries from the DC's * surface's palette. * * returns: number of entries retrieved from the surface palette, 0 for FAIL * * History: * 15-Jan-1991 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
UINT APIENTRY GreGetSystemPaletteEntries(HDC hdc, UINT ulStartIndex, UINT ulNumEntries, PPALETTEENTRY pRGB) { UINT uiReturn = 0;
DCOBJ dco(hdc);
if (dco.bValid()) { PDEVOBJ po(dco.hdev());
//
// Acquire the devlock while grunging in the surface palette to
// protect against dynamic mode changes.
//
DEVLOCKOBJ dlo(po);
if (po.bIsPalManaged()) { XEPALOBJ palSurf(po.ppalSurf()); uiReturn = (UINT) palSurf.ulGetEntries(ulStartIndex, ulNumEntries, pRGB, TRUE); } }
return(uiReturn); }
/******************************Public*Routine******************************\
* GreGetSystemPaletteUse * * API function * * returns: SYSPAL_STATIC or SYSPAL_NOSTATIC, 0 for an error * * History: * 15-Jan-1991 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
UINT APIENTRY GreGetSystemPaletteUse(HDC hdc) { ULONG ulReturn = SYSPAL_ERROR;
DCOBJ dco(hdc);
if (dco.bValid()) { PDEVOBJ po(dco.hdev());
//
// Acquire the devlock while grunging in the surface palette to
// protect against dynamic mode changes.
//
DEVLOCKOBJ dlo(po);
if (po.bIsPalManaged()) { XEPALOBJ palSurf(po.ppalSurf());
if (palSurf.bIsNoStatic()) { ulReturn = SYSPAL_NOSTATIC; } else if (palSurf.bIsNoStatic256()) { ulReturn = SYSPAL_NOSTATIC256; } else { ulReturn = SYSPAL_STATIC; } } }
return(ulReturn); }
/******************************Public*Routine******************************\
* GreSetSystemPaletteUse * * API function - Sets the number of reserved entries if palette managed * * returns - the old flag for the palette, 0 for error * * History: * 15-Jan-1991 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
UINT APIENTRY GreSetSystemPaletteUse(HDC hdc, UINT ulUsage) { //
// Validate the parameters, Win3.1 sets the flag to static if it's invalid.
//
if ((ulUsage != SYSPAL_STATIC) && (ulUsage != SYSPAL_NOSTATIC) && (ulUsage != SYSPAL_NOSTATIC256)) ulUsage = SYSPAL_STATIC;
//
// Initialize return value.
//
ULONG ulReturn = SYSPAL_ERROR; BOOL bPalChanged = FALSE; ULONG i;
DCOBJ dco(hdc);
if (dco.bValid()) { //
// Lock the screen semaphore so that we don't get flipped into
// full screen after checking the bit. This also protects us
// from dynamic mode changes that change the 'bIsPalManaged'
// status.
//
PDEVOBJ po(dco.hdev());
DEVLOCKOBJ dlo(po);
XEPALOBJ palSurf(po.ppalSurf()); XEPALOBJ palDC(dco.ppal());
if (po.bIsPalManaged()) { //
// The palette managed case.
//
{ //
// Protect access to the goodies in the system palette
// with the SEMOBJ. We don't want a realize happening
// while we fiddle flags.
//
SEMOBJ semo(ghsemPalette);
if (palSurf.bIsNoStatic()) { ulReturn = SYSPAL_NOSTATIC; } else if (palSurf.bIsNoStatic256()) { ulReturn = SYSPAL_NOSTATIC256; } else { ulReturn = SYSPAL_STATIC; }
if (ulUsage == SYSPAL_STATIC) { //
// reset the colors from their original copy in the devinfo palette.
// The copy already has the flags properly set.
//
if (palSurf.bIsNoStatic() || palSurf.bIsNoStatic256()) { //
// Change the palette that GDI manages, copy over up to
// 20 static colors from ppalDefault
//
XEPALOBJ palOriginal(ppalDefault); ASSERTGDI(palOriginal.bValid(), "ERROR ulMakeStatic0");
ULONG ulNumReserved = palSurf.ulNumReserved() >> 1;
if (ulNumReserved > 10) { ulNumReserved = 10; }
//
// set the beginning entries
//
for (i = 0; i < ulNumReserved; i++) { PALETTEENTRY palEntry = palOriginal.palentryGet(i);
palEntry.peFlags = PC_USED | PC_FOREGROUND; palSurf.palentrySet(i,palEntry); }
//
// set the ending entries
//
ULONG ulCurrentPal = palSurf.cEntries(); ULONG ulCurrentDef = 20;
for (i = 0; i < ulNumReserved; i++) { PALETTEENTRY palEntry;
ulCurrentPal--; ulCurrentDef--;
palEntry = palOriginal.palentryGet(ulCurrentDef); palEntry.peFlags = PC_USED | PC_FOREGROUND; palSurf.palentrySet(ulCurrentPal,palEntry); }
//
// Mark the brushes dirty for this DC.
//
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
palSurf.flPalSet(palSurf.flPal() & ~PAL_NOSTATIC & ~PAL_NOSTATIC256); palSurf.vUpdateTime(); bPalChanged = TRUE; } } else if (ulUsage == SYSPAL_NOSTATIC) { //
// unmark all the static colors, with the exception of black and
// white that stay with us.
//
for (i = 1; i < (palSurf.cEntries()-1); i++) { palSurf.apalColorGet()[i].pal.peFlags = 0; }
palSurf.vSetNoStatic(); } else //SYSPAL_NOSTATIC256
{ //
// unmark all the static colors
//
for (i = 0; i < (palSurf.cEntries()); i++) { palSurf.apalColorGet()[i].pal.peFlags = 0; }
palSurf.vSetNoStatic256();
}
}
if (bPalChanged) { SEMOBJ so(po.hsemPointer());
if (!po.bDisabled()) { po.pfnSetPalette()( po.dhpdevParent(), (PALOBJ *) &palSurf, 0, 0, palSurf.cEntries()); } } } }
return(ulReturn); }
/******************************Public*Routine******************************\
* NtGdiResizePalette() * * API function * * returns: TRUE for success, FALSE for failure * * History: * Tue 10-Sep-1991 -by- Patrick Haluptzok [patrickh] * rewrite to be multi-threaded safe * * 19-Jan-1991 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
#define PAL_MAX_SIZE 1024
BOOL APIENTRY NtGdiResizePalette( HPALETTE hpal, UINT cEntry ) { //
// Check for quick out before constructors
//
if ((cEntry > PAL_MAX_SIZE) || (cEntry == 0)) { WARNING("GreResizePalette failed - invalid size\n"); return(FALSE); }
BOOL bReturn = FALSE;
//
// Validate the parameter.
//
EPALOBJ palOld(hpal);
if ((palOld.bValid()) && (!palOld.bIsPalDefault()) && (palOld.bIsPalDC())) { //
// Create a new palette. Don't mark it to keep because after
// bSwap it will be palOld and we want it to be deleted.
//
PALMEMOBJ pal;
if (pal.bCreatePalette(PAL_INDEXED, cEntry, (PULONG) NULL, 0, 0, 0, PAL_DC | PAL_FREE)) {
//
// Grab the palette semaphore which stops any palettes from being selected
// in or out. It protects the linked DC list, can't copy DC head until
// we hold it.
//
SEMOBJ semo(ghsemPalette);
//
// Copy the data from old palette.
//
pal.vCopyEntriesFrom(palOld); pal.flPalSet(palOld.flPal()); pal.hdcHead(palOld.hdcHead()); pal.hdev(palOld.hdev()); pal.cRefhpal(palOld.cRefhpal()); pal.vComputeCallTables();
HDC hdcNext, hdcTemp;
MLOCKFAST mlo;
//
// Run down the list and exclusive lock all the handles.
//
{ hdcNext = pal.hdcHead();
while (hdcNext != (HDC) 0) { MDCOBJ dcoLock(hdcNext);
if (!dcoLock.bLocked()) { WARNING1("ResizePalette failed because a DC the hpal is in is busy\n"); break; }
hdcNext = dcoLock.pdc->hdcNext(); dcoLock.vDontUnlockDC(); } }
if (hdcNext == (HDC) 0) { //
// We have the palette semaphore and all the DC's exclusively locked. Noone else
// can be accessing the translates because you must hold one of those things to
// access them. So we can delete the translates.
//
palOld.vMakeNoXlate(); palOld.vUpdateTime();
//
// Note that bSwap calls locked SpapHandle vesrion so the Hmgr Resource
// is required (luckily it was grabbed earlier).
//
//
// try to swap palettes, bSwap can only succedd if
// this routine owns the only locks on the objecs
//
bReturn = pal.bSwap((PPALETTE *) &palOld,1,1);
if (bReturn) { ASSERTGDI(bReturn, "ERROR no way");
//
// Run down all the DC's for this palette and update the pointer.
// Set the flags to dirty the brushes since we changed the palette.
//
{ hdcNext = pal.hdcHead();
while (hdcNext != (HDC)0) { MDCOBJA dcoAltLock(hdcNext); dcoAltLock.pdc->ppal(palOld.ppalGet()); dcoAltLock.ulDirty(dcoAltLock.ulDirty() | DIRTY_BRUSHES); hdcNext = dcoAltLock.pdc->hdcNext(); } } } else { WARNING1("ResizePalette failed - ref count != 1\n"); }
} else { WARNING1("ResizePalette failed lock of DC in chain\n"); }
//
// Unlock all the DC we have locked and return FALSE
//
{ hdcTemp = pal.hdcHead();
while (hdcTemp != hdcNext) { MDCOBJ dcoUnlock(hdcTemp); ASSERTGDI(dcoUnlock.bLocked(), "ERROR couldn't re-lock to unlock"); DEC_EXCLUSIVE_REF_CNT(dcoUnlock.pdc); hdcTemp = dcoUnlock.pdc->hdcNext(); } } } else { WARNING("GreResizePalette failed palette creation\n"); } } else { WARNING("GreResizePalette failed invalid hpal\n"); }
return(bReturn); }
/******************************Public*Routine******************************\
* GreUpdateColors * * API function - Updates the colors in the Visible Region for a Window on * a palette mangaged device. * * This is an example of how UpdateColors is used: * * case WM_PALETTECHANGED: * * // if NTPAL was not responsible for palette change and if
* // palette realization causes a palette change, do a redraw.
* * if ((HWND)wParam != hWnd) * { * if (bLegitDraw) * { * hDC = GetDC(hWnd); * hOldPal = SelectPalette(hDC, hpalCurrent, 0); * * i = RealizePalette(hDC); * * if (i) * { * if (bUpdateColors) * { * UpdateColors(hDC); * UpdateCount++; * } * else * InvalidateRect(hWnd, (LPRECT) (NULL), 1); * } * * SelectPalette(hDC, hOldPal, 0); * ReleaseDC(hWnd, hDC); * } * } * break; * * The hpal can only be selected into 1 type of device DC at a time. * Xlates from the DC palette to the surface palette are only done on DC's * that are for the PDEV surface. Since an hpal can only be selected into * one of these and creation and deletion of the pxlate needs to be semaphored * we use the PDEV semaphore to protect it's access. * * An xlate vector mapping the DC palette to the surface palette is created * during a RealizePalette if the surface is a palette managed device. This * is put in pxlate in the hpal. The old pxlate is moved into pxlateOld * and the xlate in pxlateOld is deleted. UpdateColors works by looking at * the difference between the current xlate mapping and the old xlate mapping * and updating the pixels in the VisRgn to get a closest mapping. * * This API can only be called once for a palette. The old xlate is deleted * during UpdateColors so that the next time it is called it will fail. This * is because it only makes sense to update the pixels once. Doing it more * than once would give ugly unpredictable results. * * History: * 12-Dec-1991 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
BOOL APIENTRY NtGdiUpdateColors(HDC hdc) { BOOL bReturn = FALSE;
DCOBJ dco(hdc);
if (!dco.bValidSurf()) { return(FALSE); }
PDEVOBJ pdo(dco.hdev());
//
// Grab DEVLOCK for output and to lock the surface
//
DEVLOCKOBJ dlo(dco);
if (pdo.bIsPalManaged()) { SURFACE *pSurf = dco.pSurface();
//
// This only works on palette managed surfaces.
//
if (pSurf == pdo.pSurface()) { XEPALOBJ palSurf(pSurf->ppal()); XEPALOBJ palDC(dco.ppal());
//
// Accumulate bounds. We can do this before knowing if the operation is
// successful because bounds can be loose.
//
if (dco.fjAccum()) dco.vAccumulate(dco.erclWindow());
if (dlo.bValid()) { if ((palDC.ptransCurrent() != NULL) && (palDC.ptransOld() != NULL)) { XLATEMEMOBJ xlo(palSurf, palDC);
if (xlo.bValid()) { ECLIPOBJ co(dco.prgnEffRao(), dco.erclWindow());
//
// Check the destination which is reduced by clipping.
//
if (!co.erclExclude().bEmpty()) { //
// Exclude the pointer.
//
DEVEXCLUDEOBJ dxo(dco,&co.erclExclude(),&co);
//
// Inc the target surface uniqueness
//
INC_SURF_UNIQ(pSurf);
if (!pdo.bMetaDriver()) { //
// Dispatch the call. Give it no mask.
//
bReturn = (*PPFNGET(pdo, CopyBits, pSurf->flags())) ( pSurf->pSurfobj(), pSurf->pSurfobj(), &co, xlo.pxlo(), (RECTL *) &co.erclExclude(), (POINTL *) &co.erclExclude()); } else { //
// Dispatch to DDML.
//
bReturn = MulUpdateColors( pSurf->pSurfobj(), &co, xlo.pxlo()); } } else bReturn = TRUE; } } else bReturn = TRUE; // Nothing to update
} else { bReturn = dco.bFullScreen(); } } }
return(bReturn); }
/******************************Public*Routine******************************\
* RealizeDefaultPalette * * Take away colors that have been realized by other Windows. Reset it to * state where no colors have been taken. Return number of colors * * History: * 07-Jan-1993 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
extern "C" ULONG GreRealizeDefaultPalette( HDC hdcScreen, BOOL bClearDefaultPalette) {
DCOBJ dco(hdcScreen);
if (dco.bValid()) { PDEVOBJ po(dco.hdev());
//
// Block out the GreRealizePalette code. Also protect us from
// dynamic mode changes while we grunge in the surface palette.
//
DEVLOCKOBJ dlo(po);
SEMOBJ semo(ghsemPalette);
if (po.bIsPalManaged()) { XEPALOBJ palSurf(po.ppalSurf()); ASSERTGDI(palSurf.bIsPalManaged(), "GreRealizeDefaultPalette");
//
// Now map back to static colors if necesary. Win3.1 does not do this but we do
// just in case naughty app died and left the palette hosed.
//
//
if (palSurf.bIsNoStatic() || palSurf.bIsNoStatic256()) { GreSetSystemPaletteUse(hdcScreen, SYSPAL_STATIC); }
//
// Get rid of the PC_FOREGROUND flag from the non-reserved entries.
//
ULONG ulTemp = palSurf.ulNumReserved() >> 1; ULONG ulMax = palSurf.cEntries() - ulTemp;
for (; ulTemp < ulMax; ulTemp++) { palSurf.apalColorGet()[ulTemp].pal.peFlags &= (~PC_FOREGROUND); }
if (bClearDefaultPalette) { hForePalette = NULL; }
palSurf.vUpdateTime();
//
// Mark the brushes dirty.
//
dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES); } } else { WARNING("ERROR User called RealizeDefaultPalette with bad hdc\n"); }
//
// What should this return value be ?
//
return(0); }
/******************************Public*Routine******************************\
* UnrealizeObject * * Resets a logical palette. * * History: * 16-May-1993 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
BOOL GreUnrealizeObject(HANDLE hpal) { BOOL bReturn = FALSE;
EPALOBJ pal((HPALETTE) hpal);
if (pal.bValid()) {
//
// You must grab the palette semaphore to access the translates.
//
SEMOBJ semo(ghsemPalette);
if (pal.ptransFore() != NULL) { pal.ptransFore()->iUniq = 0; }
if (pal.ptransCurrent() != NULL) { pal.ptransCurrent()->iUniq = 0; }
bReturn = TRUE; }
return(bReturn); }
/******************************Public*Routine******************************\
* GreRealizePalette * * Re-written to be Win3.1 compatible. * * History: * 22-Nov-1992 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
extern "C" DWORD GreRealizePalette(HDC hdc) { ULONG nTransChanged = 0; ULONG nPhysChanged = 0;
DCOBJ dco(hdc);
if (dco.bValid()) { PDEVOBJ po(dco.hdev());
//
// Lock the screen semaphore so that we don't get flipped into
// full screen after checking the bit. This also protects us
// from dynamic mode changes that change the 'bIsPalManaged'
// status.
//
DEVLOCKOBJ dlo(po);
XEPALOBJ palSurf(po.ppalSurf()); XEPALOBJ palDC(dco.ppal());
HPALETTE hpalDC = palDC.hpal(); HDC hdcNext, hdcTemp;
if (po.bIsPalManaged()) { ASSERTGDI(palSurf.bIsPalManaged(), "GreRealizePalette");
//
// Access to the ptrans and the fields of the hpal are protected by
// this semaphore.
//
SEMOBJ semo(ghsemPalette);
if ((SAMEHANDLE(hpalDC,hForePalette)) || ((dco.pdc->iGraphicsMode() == GM_COMPATIBLE) && (SAMEINDEX(hpalDC, hForePalette)) && (hForePID == W32GetCurrentProcess()))) { //
// Check for early out.
//
if (palDC.bIsPalDefault()) { //
// Do nothing.
//
PAL_DEBUG(2,"DC has default palette quick out\n");
} else { if ((palDC.ptransFore() != NULL) && (palDC.ptransFore() == palDC.ptransCurrent()) && (palDC.ptransFore()->iUniq == palSurf.ulTime())) { //
// Everything is valid.
//
PAL_DEBUG(2,"ptransCurrent == ptransFore quick out\n"); } else { MLOCKFAST mlo;
//
// Run down the list and exclusive lock all the handles.
//
{ hdcNext = palDC.hdcHead();
while (hdcNext != (HDC) 0) { MDCOBJ dcoLock(hdcNext);
if (!dcoLock.bLocked()) { WARNING1("GreRealizePalette failed because a DC the hpal is in is busy\n"); break; }
dcoLock.ulDirty(dco.ulDirty() | DIRTY_BRUSHES); hdcNext = dcoLock.pdc->hdcNext(); dcoLock.vDontUnlockDC(); } }
if (hdcNext == (HDC) 0) { //
// Get rid of the old mapping, it is useless now.
//
if (palDC.ptransOld()) { if (palDC.ptransOld() != palDC.ptransFore()) VFREEMEM(palDC.ptransOld());
palDC.ptransOld(NULL); }
//
// Check if we have stale translates.
// UnrealizeObject and SetPaletteEntries can cause it.
//
if ((palDC.ptransFore()) && (palDC.ptransFore()->iUniq == 0)) { if (palDC.ptransCurrent() != palDC.ptransFore()) VFREEMEM(palDC.ptransFore());
palDC.ptransFore(NULL); }
//
// Check if we need a new foreground realization.
//
if (palDC.ptransFore() == NULL) { //
// Need to force ourselves in for the first time.
//
PAL_DEBUG(2,"Creating a foreground realization\n");
palDC.ptransFore(ptransMatchAPal(dco.pdc,palSurf, palDC, TRUE, &nPhysChanged, &nTransChanged));
if (palDC.ptransFore() == NULL) { WARNING("RealizePalette failed initial foreground realize\n"); } } else { //
// Foreground Realize already done and isn't stale.
// Force the foreground mapping into the physical palette.
//
PAL_DEBUG(2,"Forcing a foreground realization in to palette\n");
vMatchAPal(dco.pdc,palSurf, palDC, &nPhysChanged, &nTransChanged); }
palDC.ptransOld(palDC.ptransCurrent()); palDC.ptransCurrent(palDC.ptransFore()); } else { WARNING("GreRealizePalette failed to lock down all DC's in linked list\n"); }
//
// Unlock all the DC we have locked.
//
{ hdcTemp = palDC.hdcHead();
while (hdcTemp != hdcNext) { MDCOBJ dcoUnlock(hdcTemp); ASSERTGDI(dcoUnlock.bLocked(), "ERROR couldn't re-lock to unlock"); DEC_EXCLUSIVE_REF_CNT(dcoUnlock.pdc); hdcTemp = dcoUnlock.pdc->hdcNext(); } } }
} } else { //
// We are a background palette.
//
if (!palDC.bIsPalDefault()) {
//
// Check for the quick out.
//
if ((palDC.ptransCurrent() != NULL) && (palDC.ptransCurrent()->iUniq == palSurf.ulTime())) { //
// Well it's good enough. Nothing has changed that
// would give us any better mapping.
//
PAL_DEBUG(2,"ptransCurrent not foreground but good enough\n"); } else { MLOCKFAST mlo;
//
// Run down the list and exclusive lock all the handles.
//
{ hdcNext = palDC.hdcHead();
while (hdcNext != (HDC) 0) { MDCOBJ dcoLock(hdcNext);
if (!dcoLock.bLocked()) { WARNING1("GreRealizePalette failed because a DC the hpal is in is busy\n"); break; }
dcoLock.ulDirty(dco.ulDirty() | DIRTY_BRUSHES); hdcNext = dcoLock.pdc->hdcNext(); dcoLock.vDontUnlockDC(); } }
if (hdcNext == (HDC) 0) { //
// We have work to do, get rid of the old translate.
//
if (palDC.ptransOld()) { if (palDC.ptransOld() != palDC.ptransFore()) VFREEMEM(palDC.ptransOld());
palDC.ptransOld(NULL); }
//
// Check if we have stale translates.
// UnrealizeObject and SetPaletteEntries can cause it.
//
if ((palDC.ptransFore()) && (palDC.ptransFore()->iUniq == 0)) { if (palDC.ptransCurrent() != palDC.ptransFore()) { VFREEMEM(palDC.ptransFore()); }
palDC.ptransFore(NULL); }
//
// Check for initial foreground realization.
//
PAL_DEBUG(2,"Realizing in the background\n");
if (palDC.ptransFore() == NULL) { //
// Create a scratch pad to establish a foreground realize.
//
PAL_DEBUG(2,"Making ptransFore in the background\n");
PALMEMOBJ palTemp;
if (palTemp.bCreatePalette(PAL_INDEXED, palSurf.cEntries(), NULL, 0, 0, 0, PAL_MANAGED)) { ULONG ulTemp = 0; ASSERTGDI(palTemp.cEntries() == 256, "ERROR palTemp invalid");
palTemp.vCopyEntriesFrom(palSurf); palTemp.ulNumReserved(palSurf.ulNumReserved()); palTemp.flPalSet(palSurf.flPal()); palTemp.vComputeCallTables();
PAL_DEBUG(2,"Need to make a foreground realize first\n");
//
// Need to map ourselves for the first time. This actually doesn't
// change the current surface palette but instead computes the
// translate vector that would result if it was to be mapped in now.
//
palDC.ptransFore(ptransMatchAPal(dco.pdc,palTemp, palDC, TRUE, &ulTemp, &ulTemp)); }
#if DBG
if (palDC.ptransFore() == NULL) { WARNING("RealizePalette failed initial foreground realize\n"); } #endif
}
//
// Save the Current mapping into Old.
//
palDC.ptransOld(palDC.ptransCurrent());
if (palDC.ptransFore() == NULL) { //
// The Current can't be set if the Fore
// is NULL so we're done.
//
palDC.ptransCurrent(NULL); } else { //
// Get the new Current mapping.
//
PAL_DEBUG(2,"Making ptransCurrent\n");
palDC.ptransCurrent(ptransMatchAPal(dco.pdc,palSurf, palDC, FALSE, &nPhysChanged, &nTransChanged));
if (palDC.ptransCurrent() == NULL) { //
// Well we can't have the foreground set
// and the current being NULL so just
// make it foreground for this memory
// failure case.
//
palDC.ptransCurrent(palDC.ptransFore()); WARNING("ptransCurrent failed allocation in RealizePalette"); } } }
//
// Unlock all the DC we have locked.
//
{ hdcTemp = palDC.hdcHead();
while (hdcTemp != hdcNext) { MDCOBJ dcoUnlock(hdcTemp); ASSERTGDI(dcoUnlock.bLocked(), "ERROR couldn't re-lock to unlock"); DEC_EXCLUSIVE_REF_CNT(dcoUnlock.pdc); hdcTemp = dcoUnlock.pdc->hdcNext(); } } } } } }
//
// Check if the device needs to be notified.
//
if (nPhysChanged) { //
// Lock the screen semaphore so that we don't get flipped into
// full screen after checking the bit.
//
GreAcquireSemaphoreEx(po.hsemDevLock(), SEMORDER_DEVLOCK, NULL); GreEnterMonitoredSection(po.ppdev, WD_DEVLOCK);
{ SEMOBJ so(po.hsemPointer());
if (!po.bDisabled()) { po.pfnSetPalette()( po.dhpdevParent(), (PALOBJ *) &palSurf, 0, 0, palSurf.cEntries()); } }
GreExitMonitoredSection(po.ppdev, WD_DEVLOCK); GreReleaseSemaphoreEx(po.hsemDevLock());
//
// mark palsurf if it is a halftone palette
//
if (palSurf.cEntries() == 256) { ULONG ulIndex; for (ulIndex=0;ulIndex<256;ulIndex++) { if ( (palSurf.ulEntryGet(ulIndex) & 0xffffff) != (aPalHalftone[ulIndex].ul & 0xffffff) ) { break; } }
if (ulIndex == 256) { palSurf.flPal(PAL_HT); } else { FLONG fl = palSurf.flPal(); fl &= ~PAL_HT; palSurf.flPalSet(fl); } } } }
return(nTransChanged | (nPhysChanged << 16)); }
/******************************Public*Routine******************************\
* IsDCCurrentPalette * * Returns TRUE if the palette is the foreground palette. * * History: * 18-May-1993 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
extern "C" BOOL IsDCCurrentPalette(HDC hdc) { BOOL bReturn = FALSE;
DCOBJ dco(hdc);
if (dco.bValid()) { if ((SAMEHANDLE(dco.hpal(), (HPAL)hForePalette)) || ((dco.pdc->iGraphicsMode() == GM_COMPATIBLE) && (SAMEINDEX(dco.hpal(), hForePalette)) && (hForePID == W32GetCurrentProcess()))) { bReturn = TRUE; } }
return(bReturn); }
/******************************Public*Routine******************************\
* GreSelectPalette * * API function for selecting palette into the DC. * * Returns previous hpal if successful, (HPALETTE) 0 for failure. * * History: * 17-Nov-1990 -by- Patrick Haluptzok patrickh * Wrote it. \**************************************************************************/
extern "C" HPALETTE GreSelectPalette( HDC hdc, HPALETTE hpalNew, BOOL bForceBackground) {
//
// The palette semaphore serializes access to the reference count and
// the linked list of DC's a palette is selected into. We don't want
// 2 people trying to select at the same time. We must hold this between
// the setting of the hsem and the incrementing of the reference count.
//
SEMOBJ semo(ghsemPalette);
//
// Validate and lock down the DC and new palette.
//
DCOBJ dco(hdc); EPALOBJ palNew(hpalNew);
#if DBG
if (DbgPal >= 2) { DbgPrint("GreSelectPalette %p\n",palNew.ppalGet()); } #endif
if ((!dco.bLocked()) || (!palNew.bValid())|| (!palNew.bIsPalDC())) { //
// Error code logged by failed lock.
//
WARNING1("GreSelectPalette failed, invalid palette or DC\n"); return((HPALETTE)NULL); }
if (!bForceBackground) { hForePID = W32GetCurrentProcess(); hForePalette = hpalNew; }
HPAL hpalOld = (HPAL) dco.hpal();
if (SAMEHANDLE(hpalOld,(HPAL)hpalNew)) { return((HPALETTE)hpalOld); }
PDEVOBJ po(dco.hdev()); XEPALOBJ palOld(dco.ppal());
//
// Check that we aren't trying to select the palette into a
// device incompatible with a type we are already selected into.
// We need to be able to translate from the DC hpal to the surface hpal
// to do Animate, ect. So we can only be selected into one
// surface with a PAL_MANAGED hpal because we only maintain one
// translate table in the DC hpal.
//
if (!palNew.bIsPalDefault()) { if (!palNew.bSet_hdev(dco.hdev())) { WARNING("GreSelectPalette failed hsemDisplay check\n"); return((HPALETTE)NULL); } }
//
// Grab the multi-lock semaphore to run the DC link list.
//
MLOCKFAST mlo;
//
// Take care of the old hpal. Remove from linked list. Decrement cRef.
// Remove the hdc from the linked list of DC's associated with palette.
//
palOld.vRemoveFromList(dco);
//
// Set the new palette in so the old hpal is truly gone.
//
dco.pdc->hpal((HPAL)hpalNew); dco.pdc->ppal(palNew.ppalGet()); dco.ulDirty(dco.ulDirty() | DIRTY_BRUSHES);
//
// Associate the palette with the bitmap for use when converting DDBs
// to DIBs for dynamic mode changes. We don't associate the default
// palette because the normal usage pattern is:
//
// hpalOld = SelectPalette(hdc, hpal);
// RealizePalette(hdc);
// BitBlt(hdc);
// SelectPalette(hdc, hpalOld);
//
if ((dco.bHasSurface()) && (!palNew.bIsPalDefault())) { dco.pSurface()->hpalHint(hpalNew); }
//
// Take care of the new hpal.
//
palNew.vAddToList(dco);
return((HPALETTE)hpalOld); }
/******************************Public*Routine******************************\
* ulMagicFind - look for given magic color in default palette * * Arguments: * * clrMagic - COLORREF of color to search for * * Return Value: * * Index if found, 0xffffffff if not found. * * History: * * 15-Nov-1995 -by- Mark Enstrom [marke] * \**************************************************************************/
ULONG ulMagicFind( PALETTEENTRY peMagic ) { XEPALOBJ xePalDefault(ppalDefault); return(xePalDefault.ulGetMatchFromPalentry(peMagic)); }
/******************************Public*Routine******************************\
* bSetMagicColor - set the specified magic color in both the device * palette and the default palette * * Arguments: * * hdev - hdev * Index - magic color index (8,9,246,247) * palSurf - surface palette * palDC - logical palette * palColor - magic color * * Return Value: * * Status * * History: * * 15-Nov-1995 -by- Mark Enstrom [marke] * \**************************************************************************/
extern PPALETTE gppalHalftone;
BOOL bSetMagicColor( XEPALOBJ palSurf, ULONG ulIndex, PAL_ULONG PalEntry ) { BOOL bRet = FALSE;
ASSERTGDI(((ulIndex == 8) || (ulIndex == 9) || (ulIndex == 246) || (ulIndex == 247)), "bSetMagicColor Error, wrong palette index");
//
// make sure there are 20 reserved entries, and the static
// colors are in use
//
if ( (palSurf.ulNumReserved() == 20) && (!palSurf.bIsNoStatic()) && (!palSurf.bIsNoStatic256()) ) { //
// set the entrie in the surface palette
//
PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED; palSurf.ulEntrySet(ulIndex,PalEntry.ul);
//
// update the palette time stamp
//
palSurf.vUpdateTime();
//
// set colors in the defaukt halftone palette for multimon system
//
if (gppalHalftone) { XEPALOBJ palHalftone(gppalHalftone); palHalftone.ulEntrySet(ulIndex,PalEntry.ul); }
//
// offset to upper half of default palette if needed
//
if (ulIndex > 10) { ulIndex = ulIndex - 236; }
PalEntry.pal.peFlags = 0;
//
// set colors in the default Logical palette.
//
logDefaultPal.palPalEntry[ulIndex] = PalEntry.pal;
//
// set colors in the default palette and default log palette
//
XEPALOBJ palDefault(ppalDefault); palDefault.ulEntrySet(ulIndex,PalEntry.ul);
bRet = TRUE; }
return(bRet); }
/******************************Public*Routine******************************\
* vResetSurfacePalette - copy the magic colors from the default palette * to the surface palette, and call the driver to set the palette * * NOTE: The devlock and pointer semaphore must already be held! * * Arguments: * * po - PDEV object * palSurf - surface palette * * Return Value: * * Status * * History: * * 21-Mar-1996 -by- J. Andrew Goossen [andrewgo] * \**************************************************************************/
VOID vResetSurfacePalette( HDEV hdev ) { PDEVOBJ po(hdev);
if (po.bIsPalManaged()) { XEPALOBJ palSurf(po.ppalSurf());
ASSERTGDI(palSurf.bValid(), "Invalid surface palette");
if ( (palSurf.ulNumReserved() == 20) && (!palSurf.bIsNoStatic()) && (!palSurf.bIsNoStatic256()) ) { PAL_ULONG PalEntry;
XEPALOBJ palDefault(ppalDefault);
//
// set the entries in the surface palette
//
PalEntry.pal = palDefault.palentryGet(8); PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED; palSurf.ulEntrySet(8,PalEntry.ul);
PalEntry.pal = palDefault.palentryGet(9); PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED; palSurf.ulEntrySet(9,PalEntry.ul);
PalEntry.pal = palDefault.palentryGet(246 - 236); PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED; palSurf.ulEntrySet(246,PalEntry.ul);
PalEntry.pal = palDefault.palentryGet(247 - 236); PalEntry.pal.peFlags = PC_FOREGROUND | PC_USED; palSurf.ulEntrySet(247,PalEntry.ul); }
if (!po.bDisabled()) { (*PPFNDRV(po,SetPalette))( po.dhpdev(), (PALOBJ *) &palSurf, 0, 0, palSurf.cEntries()); } } }
/******************************Public*Routine******************************\
* * GreSetMagicColor win95 compatible: set surface and default palette * "magic" entries. This changes the default palette, * and will affect bitmaps that think they have the * correct 20 default colors already... * * Arguments: * * hdc - DC, specifies device surface * Index - magic index, 1 of 8,9,246,247 * peMagic - new color * * Return Value: * * Status * * History: * * 10-Nov-1995 -by- Mark Enstrom [marke] * \**************************************************************************/
BOOL NtGdiSetMagicColors( HDC hdc, PALETTEENTRY peMagic, ULONG Index ) { return(GreSetMagicColors(hdc,peMagic,Index)); }
BOOL GreSetMagicColors( HDC hdc, PALETTEENTRY peMagic, ULONG Index ) { DCOBJ dco(hdc); BOOL bRet = FALSE; BOOL bPaletteChange = FALSE; BOOL bChildDriver = FALSE;
if (dco.bValid()) { if ( (Index == 8) || (Index == 9) || (Index == 246) || (Index == 247) ) { PAL_ULONG PalEntry;
PalEntry.pal = peMagic;
//
// must be RGB or PALETTERGB
//
if ( ((PalEntry.ul & 0xff000000) == 0) || ((PalEntry.ul & 0xff000000) == 0x02000000) ) { PDEVOBJ po(dco.hdev()); BOOL bSetColor = FALSE;
//
// Lock the screen semaphore so that we don't get flipped into
// full screen after checking the bit. Plus it also protects
// us from a dynamic mode change, which can change the
// bIsPalManaged status.
//
DEVLOCKOBJ dlo(po);
if (po.bIsPalManaged()) { bSetColor = TRUE; } else if (po.bMetaDriver()) { //
// If this is meta-driver, check if there is any palette device
//
PVDEV pvdev = (VDEV*) po.dhpdev(); PDISPSURF pds = pvdev->pds; LONG csurf = pvdev->cSurfaces; do { po.vInit(pds->hdev); if (po.bIsPalManaged()) { bSetColor = TRUE; bChildDriver = TRUE; break; } pds = pds->pdsNext; } while (--csurf); }
if (bSetColor) { XEPALOBJ palSurf(po.ppalSurf());
//
// palette sem scope
//
{ SEMOBJ semPalette(ghsemPalette);
//
// look for color
//
ULONG ulMagicIndex = ulMagicFind(PalEntry.pal);
if (ulMagicIndex != 0xffffffff) { //
// found exact match
//
if (ulMagicIndex >= 10) { //
// the returned index must be adjusted for surface palette
//
ulMagicIndex += 236; }
if (ulMagicIndex == Index) { if (bChildDriver) { // If this is child of meta driver, we still need to call
// driver to update palette. (in the ppalDefault, doesn't
// mean in the child surface palette).
//
// set magic color
//
bPaletteChange = bSetMagicColor(palSurf,Index,PalEntry); bRet = bPaletteChange; } else { //
// already set
//
bRet = TRUE; } } else { //
// make sure RGB is not a non-magic VGA color,
// if there is a match, it can only be a magic
// color
//
if ( (ulMagicIndex == 8) || (ulMagicIndex == 9) || (ulMagicIndex == 246) || (ulMagicIndex == 247) ) { //
// set magic color
//
bPaletteChange = bSetMagicColor(palSurf,Index,PalEntry); bRet = bPaletteChange; } else { //
// bad rgb, restore Index with
// default color
//
if (Index == 8) { PalEntry.ul = 0x00C0DCC0; } else if (Index == 9) { PalEntry.ul = 0x00F0CAA6; } else if (Index == 246) { PalEntry.ul = 0x00F0FBFF; } else { PalEntry.ul = 0x00A4A0A0; }
bPaletteChange = bSetMagicColor(palSurf,Index,PalEntry); bRet = FALSE; } } } else { //
// set magic color
//
bPaletteChange = bSetMagicColor(palSurf,Index,PalEntry); bRet = bPaletteChange; } }
if (bPaletteChange) { SEMOBJ so(po.hsemPointer());
if (!po.bDisabled()) { po.pfnSetPalette()( po.dhpdevParent(), (PALOBJ *) &palSurf, 0, 0, palSurf.cEntries()); } } } } } }
return(bRet); }
|