955 lines
27 KiB
C++
955 lines
27 KiB
C++
|
/******************************Module*Header*******************************\
|
||
|
* Module Name: palette.cxx
|
||
|
*
|
||
|
* Palette processing functions
|
||
|
*
|
||
|
* Adapted from tk.c
|
||
|
*
|
||
|
* Copyright (c) 1996 Microsoft Corporation
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <windows.h>
|
||
|
|
||
|
#include "mtk.h"
|
||
|
#include "palette.hxx"
|
||
|
|
||
|
#if(WINVER < 0x0400)
|
||
|
// Ordinarily not defined for versions before 4.00.
|
||
|
#define COLOR_3DDKSHADOW 21
|
||
|
#define COLOR_3DLIGHT 22
|
||
|
#define COLOR_INFOTEXT 23
|
||
|
#define COLOR_INFOBK 24
|
||
|
#endif
|
||
|
|
||
|
#define TKASSERT(x) SS_ASSERT( x, "palette processing failure\n" )
|
||
|
|
||
|
/******************************************************************************/
|
||
|
|
||
|
// Fixed palette support.
|
||
|
|
||
|
#define BLACK PALETTERGB(0,0,0)
|
||
|
#define WHITE PALETTERGB(255,255,255)
|
||
|
#define MAX_STATIC_COLORS (COLOR_INFOBK - COLOR_SCROLLBAR + 1)
|
||
|
static int gNumStaticColors = MAX_STATIC_COLORS;
|
||
|
|
||
|
// TRUE if static system color settings have been replaced with B&W settings.
|
||
|
|
||
|
// TRUE if original static colors saved
|
||
|
//static BOOL tkStaticColorsSaved = FALSE;
|
||
|
|
||
|
// saved system static colors (initialize with default colors)
|
||
|
static COLORREF gacrSave[MAX_STATIC_COLORS];
|
||
|
|
||
|
// new B&W system static colors
|
||
|
static COLORREF gacrBlackAndWhite[] = {
|
||
|
WHITE, // COLOR_SCROLLBAR
|
||
|
BLACK, // COLOR_BACKGROUND
|
||
|
BLACK, // COLOR_ACTIVECAPTION
|
||
|
WHITE, // COLOR_INACTIVECAPTION
|
||
|
WHITE, // COLOR_MENU
|
||
|
WHITE, // COLOR_WINDOW
|
||
|
BLACK, // COLOR_WINDOWFRAME
|
||
|
BLACK, // COLOR_MENUTEXT
|
||
|
BLACK, // COLOR_WINDOWTEXT
|
||
|
WHITE, // COLOR_CAPTIONTEXT
|
||
|
WHITE, // COLOR_ACTIVEBORDER
|
||
|
WHITE, // COLOR_INACTIVEBORDER
|
||
|
WHITE, // COLOR_APPWORKSPACE
|
||
|
BLACK, // COLOR_HIGHLIGHT
|
||
|
WHITE, // COLOR_HIGHLIGHTTEXT
|
||
|
WHITE, // COLOR_BTNFACE
|
||
|
BLACK, // COLOR_BTNSHADOW
|
||
|
BLACK, // COLOR_GRAYTEXT
|
||
|
BLACK, // COLOR_BTNTEXT
|
||
|
BLACK, // COLOR_INACTIVECAPTIONTEXT
|
||
|
BLACK, // COLOR_BTNHIGHLIGHT
|
||
|
BLACK, // COLOR_3DDKSHADOW
|
||
|
WHITE, // COLOR_3DLIGHT
|
||
|
BLACK, // COLOR_INFOTEXT
|
||
|
WHITE // COLOR_INFOBK
|
||
|
};
|
||
|
static INT gaiStaticIndex[] = {
|
||
|
COLOR_SCROLLBAR ,
|
||
|
COLOR_BACKGROUND ,
|
||
|
COLOR_ACTIVECAPTION ,
|
||
|
COLOR_INACTIVECAPTION ,
|
||
|
COLOR_MENU ,
|
||
|
COLOR_WINDOW ,
|
||
|
COLOR_WINDOWFRAME ,
|
||
|
COLOR_MENUTEXT ,
|
||
|
COLOR_WINDOWTEXT ,
|
||
|
COLOR_CAPTIONTEXT ,
|
||
|
COLOR_ACTIVEBORDER ,
|
||
|
COLOR_INACTIVEBORDER ,
|
||
|
COLOR_APPWORKSPACE ,
|
||
|
COLOR_HIGHLIGHT ,
|
||
|
COLOR_HIGHLIGHTTEXT ,
|
||
|
COLOR_BTNFACE ,
|
||
|
COLOR_BTNSHADOW ,
|
||
|
COLOR_GRAYTEXT ,
|
||
|
COLOR_BTNTEXT ,
|
||
|
COLOR_INACTIVECAPTIONTEXT,
|
||
|
COLOR_BTNHIGHLIGHT ,
|
||
|
COLOR_3DDKSHADOW ,
|
||
|
COLOR_3DLIGHT ,
|
||
|
COLOR_INFOTEXT ,
|
||
|
COLOR_INFOBK
|
||
|
};
|
||
|
|
||
|
#define RESTORE_FROM_REGISTRY 1
|
||
|
#if RESTORE_FROM_REGISTRY
|
||
|
// Registry names for the system colors.
|
||
|
static CHAR *gaszSysClrNames[] = {
|
||
|
"Scrollbar", // COLOR_SCROLLBAR 0
|
||
|
"Background", // COLOR_BACKGROUND 1 (also COLOR_DESKTOP)
|
||
|
"ActiveTitle", // COLOR_ACTIVECAPTION 2
|
||
|
"InactiveTitle", // COLOR_INACTIVECAPTION 3
|
||
|
"Menu", // COLOR_MENU 4
|
||
|
"Window", // COLOR_WINDOW 5
|
||
|
"WindowFrame", // COLOR_WINDOWFRAME 6
|
||
|
"MenuText", // COLOR_MENUTEXT 7
|
||
|
"WindowText", // COLOR_WINDOWTEXT 8
|
||
|
"TitleText", // COLOR_CAPTIONTEXT 9
|
||
|
"ActiveBorder", // COLOR_ACTIVEBORDER 10
|
||
|
"InactiveBorder", // COLOR_INACTIVEBORDER 11
|
||
|
"AppWorkspace", // COLOR_APPWORKSPACE 12
|
||
|
"Hilight", // COLOR_HIGHLIGHT 13
|
||
|
"HilightText", // COLOR_HIGHLIGHTTEXT 14
|
||
|
"ButtonFace", // COLOR_BTNFACE 15 (also COLOR_3DFACE)
|
||
|
"ButtonShadow", // COLOR_BTNSHADOW 16 (also COLOR_3DSHADOW)
|
||
|
"GrayText", // COLOR_GRAYTEXT 17
|
||
|
"ButtonText", // COLOR_BTNTEXT 18
|
||
|
"InactiveTitleText", // COLOR_INACTIVECAPTIONTEXT 19
|
||
|
"ButtonHilight", // COLOR_BTNHIGHLIGHT 20 (also COLOR_3DHILIGHT)
|
||
|
"ButtonDkShadow", // COLOR_3DDKSHADOW 21
|
||
|
"ButtonLight", // COLOR_3DLIGHT 22
|
||
|
"InfoText", // COLOR_INFOTEXT 23
|
||
|
"InfoWindow" // COLOR_INFOBK 24
|
||
|
};
|
||
|
|
||
|
static BOOL GetRegistrySysColors(COLORREF *, int);
|
||
|
#endif
|
||
|
|
||
|
unsigned char ss_ComponentFromIndex(int i, int nbits, int shift );
|
||
|
static int ss_PixelFormatDescriptorFromDc( HDC hdc, PIXELFORMATDESCRIPTOR *Pfd );
|
||
|
|
||
|
LONG
|
||
|
NullPaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
|
||
|
|
||
|
/******************************************************************************/
|
||
|
|
||
|
#if RESTORE_FROM_REGISTRY
|
||
|
/******************************Public*Routine******************************\
|
||
|
* GetRegistrySysColors
|
||
|
*
|
||
|
* Reads the Control Panel's color settings from the registry and stores
|
||
|
* those values in pcr. If we fail to get any value, then the corresponding
|
||
|
* entry in pcr is not modified.
|
||
|
*
|
||
|
* History:
|
||
|
* 12-Apr-1995 -by- Gilman Wong [gilmanw]
|
||
|
* Wrote it.
|
||
|
\**************************************************************************/
|
||
|
|
||
|
static BOOL GetRegistrySysColors(COLORREF *pcr, int nColors)
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
long lRet;
|
||
|
HKEY hkSysColors = (HKEY) NULL;
|
||
|
int i;
|
||
|
DWORD dwDataType;
|
||
|
char achColor[64];
|
||
|
DWORD cjColor;
|
||
|
|
||
|
TKASSERT(nColors <= gNumStaticColors);
|
||
|
|
||
|
// Open the key for the system color settings.
|
||
|
|
||
|
lRet = RegOpenKeyExA(HKEY_CURRENT_USER,
|
||
|
"Control Panel\\Colors",
|
||
|
0,
|
||
|
KEY_QUERY_VALUE,
|
||
|
&hkSysColors);
|
||
|
|
||
|
if ( lRet != ERROR_SUCCESS )
|
||
|
{
|
||
|
goto GetRegistrySysColors_exit;
|
||
|
}
|
||
|
|
||
|
// Read each system color value. The names are stored in the global
|
||
|
// array of char *, gaszSysClrNames.
|
||
|
|
||
|
for (i = 0; i < nColors; i++)
|
||
|
{
|
||
|
cjColor = sizeof(achColor);
|
||
|
lRet = RegQueryValueExA(hkSysColors,
|
||
|
(LPSTR) gaszSysClrNames[i],
|
||
|
(LPDWORD) NULL,
|
||
|
&dwDataType,
|
||
|
(LPBYTE) achColor,
|
||
|
&cjColor);
|
||
|
|
||
|
TKASSERT(lRet != ERROR_MORE_DATA);
|
||
|
|
||
|
if ( lRet == ERROR_SUCCESS && dwDataType == REG_SZ )
|
||
|
{
|
||
|
DWORD r, g, b;
|
||
|
|
||
|
sscanf(achColor, "%ld %ld %ld", &r, &g, &b);
|
||
|
pcr[i] = RGB(r, g, b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bRet = TRUE;
|
||
|
|
||
|
GetRegistrySysColors_exit:
|
||
|
if (hkSysColors)
|
||
|
RegCloseKey(hkSysColors);
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* GrabStaticEntries
|
||
|
*
|
||
|
* Support routine for Realize to manage the static system color
|
||
|
* usage.
|
||
|
*
|
||
|
* This function will save the current static system color usage state.
|
||
|
* It will fail if:
|
||
|
*
|
||
|
* 1. TK is not in "sys color in use state but system palette is in
|
||
|
* SYSPAL_NOSTATIC mode. This means that another app still possesses
|
||
|
* the static system colors. If this happens <TBD>
|
||
|
*
|
||
|
* Side effect:
|
||
|
* If system colors are changed, then WM_SYSCOLORCHANGE message is
|
||
|
* broadcast to all top level windows.
|
||
|
*
|
||
|
* Returns:
|
||
|
* TRUE if successful, FALSE otherwise (see above).
|
||
|
*
|
||
|
* History:
|
||
|
* 26-Apr-1994 -by- Gilman Wong [gilmanw]
|
||
|
* Wrote it.
|
||
|
\**************************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
SS_PAL::GrabStaticEntries()
|
||
|
{
|
||
|
int i;
|
||
|
BOOL bRet = FALSE;
|
||
|
|
||
|
// Do nothing if sys colors already in use.
|
||
|
|
||
|
if ( !bSystemColorsInUse )
|
||
|
{
|
||
|
// Take possession only if no other app has the static colors.
|
||
|
// How can we tell? If the return from SetSystemPaletteUse is
|
||
|
// SYSPAL_STATIC, then no other app has the statics. If it is
|
||
|
// SYSPAL_NOSTATIC, someone else has them and we must fail.
|
||
|
//
|
||
|
// SetSystemPaletteUse is properly synchronized internally
|
||
|
// so that it is atomic.
|
||
|
//
|
||
|
// Because we are relying on SetSystemPaletteUse to synchronize TK,
|
||
|
// it is important to observe the following order for grabbing and
|
||
|
// releasing:
|
||
|
//
|
||
|
// Grab call SetSystemPaletteUse and check for SYSPAL_STATIC
|
||
|
// save sys color settings
|
||
|
// set new sys color settings
|
||
|
//
|
||
|
// Release restore sys color settings
|
||
|
// call SetSystemPaletteUse
|
||
|
|
||
|
//mf: ! potential pitfall here, if a 'bad' app has not released the static
|
||
|
// colors on deactivation.
|
||
|
if ( SetSystemPaletteUse( hdc, SYSPAL_NOSTATIC ) == SYSPAL_STATIC )
|
||
|
{
|
||
|
// Save current sys color settings.
|
||
|
|
||
|
for (i = COLOR_SCROLLBAR; i <= COLOR_BTNHIGHLIGHT; i++)
|
||
|
gacrSave[i - COLOR_SCROLLBAR] = GetSysColor(i);
|
||
|
|
||
|
bSystemColorsInUse = TRUE;
|
||
|
|
||
|
// Set b&w sys color settings.
|
||
|
|
||
|
SetSysColors(gNumStaticColors, gaiStaticIndex, gacrBlackAndWhite);
|
||
|
|
||
|
// Inform all other top-level windows of the system color change.
|
||
|
|
||
|
PostMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
|
||
|
|
||
|
bRet = TRUE;
|
||
|
} else {
|
||
|
// handle case where can't get sys colors
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
bRet = TRUE;
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* ReleaseStaticEntries
|
||
|
*
|
||
|
* Support routine for Realize to manage the static system color
|
||
|
* usage.
|
||
|
*
|
||
|
* This function will reset the current static system color usage state.
|
||
|
* It will fail if:
|
||
|
*
|
||
|
* 1. TK is not in a "sys colors in use" state. If we are in this case,
|
||
|
* then the static system colors do not need to be released.
|
||
|
*
|
||
|
* Side effect:
|
||
|
* If system colors are changed, then WM_SYSCOLORCHANGE message is
|
||
|
* broadcast to all top level windows.
|
||
|
*
|
||
|
* Returns:
|
||
|
* TRUE if successful, FALSE otherwise (see above).
|
||
|
*
|
||
|
* History:
|
||
|
* 21-Jul-1994 -by- Gilman Wong [gilmanw]
|
||
|
* Wrote it.
|
||
|
\**************************************************************************/
|
||
|
|
||
|
BOOL
|
||
|
SS_PAL::ReleaseStaticEntries()
|
||
|
{
|
||
|
BOOL bRet = FALSE;
|
||
|
|
||
|
// Do nothing if sys colors not in use.
|
||
|
|
||
|
if ( bSystemColorsInUse )
|
||
|
{
|
||
|
#if RESTORE_FROM_REGISTRY
|
||
|
// Replace saved system colors with registry values. We do it now
|
||
|
// rather than earlier because someone may have changed registry while
|
||
|
// TK app was running in the foreground (very unlikely, but it could
|
||
|
// happen).
|
||
|
//
|
||
|
// Also, we still try to save current setting in GrabStaticEntries so
|
||
|
// that if for some reason we fail to grab one or more of the colors
|
||
|
// from the registry, we can still fall back on what we grabbed via
|
||
|
// GetSysColors (even though there is a chance its the wrong color).
|
||
|
|
||
|
GetRegistrySysColors(gacrSave, gNumStaticColors);
|
||
|
#endif
|
||
|
|
||
|
// Do this now, since SetSysColors() generates WM_SYSCOLORCHANGE,
|
||
|
// which can cause this routine to be re-entered
|
||
|
bSystemColorsInUse = FALSE;
|
||
|
|
||
|
// Return the system palette to SYSPAL_STATIC.
|
||
|
|
||
|
SetSystemPaletteUse( hdc, SYSPAL_STATIC );
|
||
|
|
||
|
// Restore the saved system color settings.
|
||
|
|
||
|
SetSysColors(gNumStaticColors, gaiStaticIndex, gacrSave);
|
||
|
|
||
|
// Inform all other top-level windows of the system color change.
|
||
|
|
||
|
PostMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
|
||
|
|
||
|
// Reset the "sys colors in use" state and return success.
|
||
|
|
||
|
bSystemColorsInUse = FALSE;
|
||
|
bRet = TRUE;
|
||
|
}
|
||
|
|
||
|
return bRet;
|
||
|
}
|
||
|
|
||
|
// Gamma correction factor * 10
|
||
|
#define GAMMA_CORRECTION 14
|
||
|
|
||
|
// Maximum color distance with 8-bit components
|
||
|
#define MAX_COL_DIST (3*256*256L)
|
||
|
|
||
|
// Number of static colors
|
||
|
#define STATIC_COLORS 20
|
||
|
|
||
|
// Flags used when matching colors
|
||
|
#define EXACT_MATCH 1
|
||
|
#define COLOR_USED 1
|
||
|
|
||
|
// Conversion tables for n bits to eight bits
|
||
|
|
||
|
#if GAMMA_CORRECTION == 10
|
||
|
// These tables are corrected for a gamma of 1.0
|
||
|
static unsigned char abThreeToEight[8] =
|
||
|
{
|
||
|
0, 0111 >> 1, 0222 >> 1, 0333 >> 1, 0444 >> 1, 0555 >> 1, 0666 >> 1, 0377
|
||
|
};
|
||
|
static unsigned char abTwoToEight[4] =
|
||
|
{
|
||
|
0, 0x55, 0xaa, 0xff
|
||
|
};
|
||
|
static unsigned char abOneToEight[2] =
|
||
|
{
|
||
|
0, 255
|
||
|
};
|
||
|
#else
|
||
|
// These tables are corrected for a gamma of 1.4
|
||
|
static unsigned char abThreeToEight[8] =
|
||
|
{
|
||
|
0, 63, 104, 139, 171, 200, 229, 255
|
||
|
};
|
||
|
static unsigned char abTwoToEight[4] =
|
||
|
{
|
||
|
0, 116, 191, 255
|
||
|
};
|
||
|
static unsigned char abOneToEight[2] =
|
||
|
{
|
||
|
0, 255
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
// Table which indicates which colors in a 3-3-2 palette should be
|
||
|
// replaced with the system default colors
|
||
|
#if GAMMA_CORRECTION == 10
|
||
|
static int aiDefaultOverride[STATIC_COLORS] =
|
||
|
{
|
||
|
0, 4, 32, 36, 128, 132, 160, 173, 181, 245,
|
||
|
247, 164, 156, 7, 56, 63, 192, 199, 248, 255
|
||
|
};
|
||
|
#else
|
||
|
static int aiDefaultOverride[STATIC_COLORS] =
|
||
|
{
|
||
|
0, 3, 24, 27, 64, 67, 88, 173, 181, 236,
|
||
|
247, 164, 91, 7, 56, 63, 192, 199, 248, 255
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
unsigned char
|
||
|
ss_ComponentFromIndex(int i, int nbits, int shift)
|
||
|
{
|
||
|
unsigned char val;
|
||
|
|
||
|
TKASSERT(nbits >= 1 && nbits <= 3);
|
||
|
|
||
|
val = i >> shift;
|
||
|
switch (nbits)
|
||
|
{
|
||
|
case 1:
|
||
|
return abOneToEight[val & 1];
|
||
|
|
||
|
case 2:
|
||
|
return abTwoToEight[val & 3];
|
||
|
|
||
|
case 3:
|
||
|
return abThreeToEight[val & 7];
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// System default colors
|
||
|
static PALETTEENTRY apeDefaultPalEntry[STATIC_COLORS] =
|
||
|
{
|
||
|
{ 0, 0, 0, 0 },
|
||
|
{ 0x80,0, 0, 0 },
|
||
|
{ 0, 0x80,0, 0 },
|
||
|
{ 0x80,0x80,0, 0 },
|
||
|
{ 0, 0, 0x80, 0 },
|
||
|
{ 0x80,0, 0x80, 0 },
|
||
|
{ 0, 0x80,0x80, 0 },
|
||
|
{ 0xC0,0xC0,0xC0, 0 },
|
||
|
|
||
|
{ 192, 220, 192, 0 },
|
||
|
{ 166, 202, 240, 0 },
|
||
|
{ 255, 251, 240, 0 },
|
||
|
{ 160, 160, 164, 0 },
|
||
|
|
||
|
{ 0x80,0x80,0x80, 0 },
|
||
|
{ 0xFF,0, 0, 0 },
|
||
|
{ 0, 0xFF,0, 0 },
|
||
|
{ 0xFF,0xFF,0, 0 },
|
||
|
{ 0, 0, 0xFF, 0 },
|
||
|
{ 0xFF,0, 0xFF, 0 },
|
||
|
{ 0, 0xFF,0xFF, 0 },
|
||
|
{ 0xFF,0xFF,0xFF, 0 }
|
||
|
};
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
*
|
||
|
* UpdateStaticMapping
|
||
|
*
|
||
|
* Computes the best match between the current system static colors
|
||
|
* and a 3-3-2 palette
|
||
|
*
|
||
|
* History:
|
||
|
* Tue Aug 01 18:18:12 1995 -by- Drew Bliss [drewb]
|
||
|
* Created
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
static void
|
||
|
UpdateStaticMapping(PALETTEENTRY *pe332Palette)
|
||
|
{
|
||
|
HPALETTE hpalStock;
|
||
|
int iStatic, i332;
|
||
|
int iMinDist, iDist;
|
||
|
int iDelta;
|
||
|
int iMinEntry;
|
||
|
PALETTEENTRY *peStatic, *pe332;
|
||
|
|
||
|
hpalStock = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
|
||
|
|
||
|
// The system should always have one of these
|
||
|
TKASSERT(hpalStock != NULL);
|
||
|
// Make sure there's the correct number of entries
|
||
|
TKASSERT(GetPaletteEntries(hpalStock, 0, 0, NULL) == STATIC_COLORS);
|
||
|
|
||
|
// Get the current static colors
|
||
|
GetPaletteEntries(hpalStock, 0, STATIC_COLORS, apeDefaultPalEntry);
|
||
|
|
||
|
// Zero the flags in the static colors because they are used later
|
||
|
peStatic = apeDefaultPalEntry;
|
||
|
for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
|
||
|
{
|
||
|
peStatic->peFlags = 0;
|
||
|
peStatic++;
|
||
|
}
|
||
|
|
||
|
// Zero the flags in the incoming palette because they are used later
|
||
|
pe332 = pe332Palette;
|
||
|
for (i332 = 0; i332 < 256; i332++)
|
||
|
{
|
||
|
pe332->peFlags = 0;
|
||
|
pe332++;
|
||
|
}
|
||
|
|
||
|
// Try to match each static color exactly
|
||
|
// This saves time by avoiding the least-squares match for each
|
||
|
// exact match
|
||
|
peStatic = apeDefaultPalEntry;
|
||
|
for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
|
||
|
{
|
||
|
pe332 = pe332Palette;
|
||
|
for (i332 = 0; i332 < 256; i332++)
|
||
|
{
|
||
|
if (peStatic->peRed == pe332->peRed &&
|
||
|
peStatic->peGreen == pe332->peGreen &&
|
||
|
peStatic->peBlue == pe332->peBlue)
|
||
|
{
|
||
|
TKASSERT(pe332->peFlags != COLOR_USED);
|
||
|
|
||
|
peStatic->peFlags = EXACT_MATCH;
|
||
|
pe332->peFlags = COLOR_USED;
|
||
|
aiDefaultOverride[iStatic] = i332;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
pe332++;
|
||
|
}
|
||
|
|
||
|
peStatic++;
|
||
|
}
|
||
|
|
||
|
// Match each static color as closely as possible to an entry
|
||
|
// in the 332 palette by minimized the square of the distance
|
||
|
peStatic = apeDefaultPalEntry;
|
||
|
for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
|
||
|
{
|
||
|
// Skip colors already matched exactly
|
||
|
if (peStatic->peFlags == EXACT_MATCH)
|
||
|
{
|
||
|
peStatic++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
iMinDist = MAX_COL_DIST+1;
|
||
|
#if DBG
|
||
|
iMinEntry = -1;
|
||
|
#endif
|
||
|
|
||
|
pe332 = pe332Palette;
|
||
|
for (i332 = 0; i332 < 256; i332++)
|
||
|
{
|
||
|
// Skip colors already used
|
||
|
if (pe332->peFlags == COLOR_USED)
|
||
|
{
|
||
|
pe332++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Compute Euclidean distance squared
|
||
|
iDelta = pe332->peRed-peStatic->peRed;
|
||
|
iDist = iDelta*iDelta;
|
||
|
iDelta = pe332->peGreen-peStatic->peGreen;
|
||
|
iDist += iDelta*iDelta;
|
||
|
iDelta = pe332->peBlue-peStatic->peBlue;
|
||
|
iDist += iDelta*iDelta;
|
||
|
|
||
|
if (iDist < iMinDist)
|
||
|
{
|
||
|
iMinDist = iDist;
|
||
|
iMinEntry = i332;
|
||
|
}
|
||
|
|
||
|
pe332++;
|
||
|
}
|
||
|
|
||
|
TKASSERT(iMinEntry != -1);
|
||
|
|
||
|
// Remember the best match
|
||
|
aiDefaultOverride[iStatic] = iMinEntry;
|
||
|
pe332Palette[iMinEntry].peFlags = COLOR_USED;
|
||
|
|
||
|
peStatic++;
|
||
|
}
|
||
|
|
||
|
// Zero the flags in the static colors because they may have been
|
||
|
// set. We want them to be zero so the colors can be remapped
|
||
|
peStatic = apeDefaultPalEntry;
|
||
|
for (iStatic = 0; iStatic < STATIC_COLORS; iStatic++)
|
||
|
{
|
||
|
peStatic->peFlags = 0;
|
||
|
peStatic++;
|
||
|
}
|
||
|
|
||
|
// Reset the 332 flags because we may have set them
|
||
|
pe332 = pe332Palette;
|
||
|
for (i332 = 0; i332 < 256; i332++)
|
||
|
{
|
||
|
pe332->peFlags = PC_NOCOLLAPSE;
|
||
|
pe332++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* FlushPalette
|
||
|
*
|
||
|
* Because of Win 3.1 compatibility, GDI palette mapping always starts
|
||
|
* at zero and stops at the first exact match. So if there are duplicates,
|
||
|
* the higher colors aren't mapped to--which is often a problem if we
|
||
|
* are trying to make to any of the upper 10 static colors. To work around
|
||
|
* this, we flush the palette to all black.
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
void
|
||
|
SS_PAL::Flush()
|
||
|
{
|
||
|
LOGPALETTE *pPal;
|
||
|
HPALETTE hpalBlack, hpalOld;
|
||
|
int i;
|
||
|
|
||
|
if( nEntries == 256 )
|
||
|
{
|
||
|
pPal = (LOGPALETTE *) LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,
|
||
|
sizeof(LOGPALETTE) + nEntries * sizeof(PALETTEENTRY));
|
||
|
|
||
|
if (pPal)
|
||
|
{
|
||
|
pPal->palVersion = 0x300;
|
||
|
pPal->palNumEntries = nEntries;
|
||
|
|
||
|
// Mark everything PC_NOCOLLAPSE and PC_RESERVED to force every
|
||
|
// thing into the palette. Colors are already black because
|
||
|
// we zero initialized during memory allocation.
|
||
|
|
||
|
for (i = 0; i < nEntries; i++)
|
||
|
{
|
||
|
pPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE | PC_RESERVED;
|
||
|
}
|
||
|
|
||
|
hpalBlack = CreatePalette(pPal);
|
||
|
LocalFree(pPal);
|
||
|
|
||
|
hpalOld = SelectPalette(hdc, hpalBlack, FALSE);
|
||
|
RealizePalette(hdc);
|
||
|
|
||
|
SelectPalette(hdc, hpalOld, FALSE);
|
||
|
DeleteObject(hpalBlack);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* Realize
|
||
|
*
|
||
|
* Select the given palette in background or foreground mode (as specified
|
||
|
* by the bForceBackground flag), and realize the palette.
|
||
|
*
|
||
|
* If static system color usage is set, the system colors are replaced.
|
||
|
*
|
||
|
* History:
|
||
|
* 26-Apr-1994 -by- Gilman Wong [gilmanw]
|
||
|
* Wrote it.
|
||
|
\**************************************************************************/
|
||
|
|
||
|
//mf: ! this grabbing of colors n stuff should only be done by the top
|
||
|
// level window - ? but what if it's not a GL window ?
|
||
|
|
||
|
long
|
||
|
SS_PAL::Realize( HWND hwndArg, HDC hdcArg, BOOL bForceBackground )
|
||
|
{
|
||
|
// cache:
|
||
|
hwnd = hwndArg;
|
||
|
hdc = hdcArg;
|
||
|
|
||
|
if( bTakeOver ) {
|
||
|
// Easy case
|
||
|
SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
|
||
|
SelectPalette(hdc, hPal, bForceBackground );
|
||
|
RealizePalette(hdc);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// Else general purpose 'tk' method
|
||
|
|
||
|
if( bFlush ) {
|
||
|
Flush();
|
||
|
bFlush = FALSE;
|
||
|
}
|
||
|
|
||
|
return Realize( bForceBackground );
|
||
|
}
|
||
|
|
||
|
long
|
||
|
SS_PAL::Realize( BOOL bForceBackground )
|
||
|
{
|
||
|
long Result = -1;
|
||
|
BOOL bHaveSysPal = TRUE;
|
||
|
|
||
|
SS_DBGLEVEL2( SS_LEVEL_INFO, "SS_PAL::Realize: %d for %d\n", bForceBackground, hwnd );
|
||
|
|
||
|
// If static system color usage is set, prepare to take over the
|
||
|
// system palette.
|
||
|
|
||
|
if( bUseStatic )
|
||
|
{
|
||
|
// If foreground, take over the static colors. If background, release
|
||
|
// the static colors.
|
||
|
|
||
|
if ( !bForceBackground )
|
||
|
{
|
||
|
// If GrabStaticEntries succeeds, then it is OK to take over the
|
||
|
// static colors. If not <mf:TBD>
|
||
|
|
||
|
bHaveSysPal = GrabStaticEntries();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// If we are currently using the system colors (bSystemColorsInUse)
|
||
|
// and Realize was called with bForceBackground set, we
|
||
|
// are being deactivated and must release the static system colors.
|
||
|
|
||
|
ReleaseStaticEntries();
|
||
|
}
|
||
|
|
||
|
// Rerealize the palette.
|
||
|
//
|
||
|
// If set to TRUE, bForceBackground will force the palette to be
|
||
|
// realized as a background palette, regardless of focus. This
|
||
|
// will happen anyway if the TK window does not have the keyboard focus.
|
||
|
|
||
|
if ( (bForceBackground || bHaveSysPal) &&
|
||
|
UnrealizeObject( hPal ) &&
|
||
|
NULL != SelectPalette( hdc, hPal, bForceBackground ) )
|
||
|
{
|
||
|
Result = RealizePalette( hdc );
|
||
|
}
|
||
|
//mf: ?? klugey fix for rude apps
|
||
|
// If some rude app still has the system colors and we're in the
|
||
|
// foreground, make the best of it.
|
||
|
if( !bForceBackground && !bHaveSysPal ) {
|
||
|
if( UnrealizeObject( hPal ) &&
|
||
|
NULL != SelectPalette( hdc, hPal, TRUE ) )
|
||
|
{
|
||
|
Result = RealizePalette( hdc );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if ( NULL != SelectPalette( hdc, hPal, FALSE ) )
|
||
|
{
|
||
|
Result = RealizePalette( hdc );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return( Result );
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* SS_PAL constructor
|
||
|
*
|
||
|
* This creates the palette, but does not select or realize it
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
SS_PAL::SS_PAL( HDC hdcArg, PIXELFORMATDESCRIPTOR *ppfd, BOOL bTakeOverPalette )
|
||
|
: hdc( hdcArg ), pfd( *ppfd ), bTakeOver( bTakeOverPalette )
|
||
|
{
|
||
|
hwnd = 0;
|
||
|
hPal = 0;
|
||
|
bUseStatic = FALSE;
|
||
|
bSystemColorsInUse = FALSE;
|
||
|
// bTakeOver : mf: for now, when this is set, it means
|
||
|
// the screen saver is running in full screen mode - implying that
|
||
|
// interaction with other apps not necessary
|
||
|
|
||
|
if( bTakeOver ) {
|
||
|
//mf: !!! bFlush should be per-window, not per SS_PAL !!
|
||
|
//mf: hmmm, not so sure about that...
|
||
|
bFlush = FALSE;
|
||
|
bUseStatic = TRUE;
|
||
|
} else {
|
||
|
bFlush = TRUE;
|
||
|
bUseStatic = ppfd->dwFlags & PFD_NEED_SYSTEM_PALETTE;
|
||
|
}
|
||
|
|
||
|
if( bUseStatic )
|
||
|
// save current static palette usage so we can restore it
|
||
|
uiOldStaticUse = GetSystemPaletteUse( hdc );
|
||
|
|
||
|
paletteManageProc = NullPaletteManageProc;
|
||
|
|
||
|
// Now create the palette and return
|
||
|
hPal = MakeRGBPalette();
|
||
|
SS_ASSERT( hPal, "SS_PAL constructor failure\n" );
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* SS_PAL destructor
|
||
|
|
||
|
\**************************************************************************/
|
||
|
|
||
|
SS_PAL::~SS_PAL()
|
||
|
{
|
||
|
if( bUseStatic )
|
||
|
{
|
||
|
if( uiOldStaticUse )
|
||
|
//mf: ! make sure hdc is valid !!!
|
||
|
SetSystemPaletteUse(hdc, uiOldStaticUse);
|
||
|
|
||
|
SS_DBGINFO( "SS_PAL destructor: broadcasting WM_SYSCOLORCHANGE\n" );
|
||
|
PostMessage(HWND_BROADCAST, WM_SYSCOLORCHANGE, 0, 0);
|
||
|
}
|
||
|
if( hPal ) {
|
||
|
SelectPalette( hdc, (HPALETTE) GetStockObject(DEFAULT_PALETTE), TRUE );
|
||
|
DeleteObject( hPal );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* ReCreateRGBPalette
|
||
|
*
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
void
|
||
|
SS_PAL::ReCreateRGBPalette()
|
||
|
{
|
||
|
if( bTakeOver )
|
||
|
return;
|
||
|
|
||
|
HPALETTE hPalTmp = hPal;
|
||
|
hPal = MakeRGBPalette();
|
||
|
if( hPal ) {
|
||
|
DeleteObject( hPalTmp );
|
||
|
bFlush = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/******************************Public*Routine******************************\
|
||
|
* MakeRGBPalette
|
||
|
*
|
||
|
* Creates an HPALETTE with values required for a logical rgb palette.
|
||
|
* If bUseStatic is TRUE, the static system
|
||
|
* colors will be overridden. Otherwise, the PALETTEENTRY array will be
|
||
|
* fixed up to contain the default static system colors.
|
||
|
*
|
||
|
\**************************************************************************/
|
||
|
|
||
|
HPALETTE
|
||
|
SS_PAL::MakeRGBPalette()
|
||
|
{
|
||
|
LOGPALETTE *pPal;
|
||
|
HPALETTE hpal;
|
||
|
int count, i;
|
||
|
PIXELFORMATDESCRIPTOR *ppfd = &pfd;
|
||
|
|
||
|
count = 1 << ppfd->cColorBits;
|
||
|
nEntries = count;
|
||
|
pPal = (PLOGPALETTE)LocalAlloc(LMEM_FIXED, sizeof(LOGPALETTE) +
|
||
|
count * sizeof(PALETTEENTRY));
|
||
|
if( !pPal )
|
||
|
return (HPALETTE) 0;
|
||
|
|
||
|
pPal->palVersion = 0x300;
|
||
|
pPal->palNumEntries = count;
|
||
|
|
||
|
PALETTEENTRY *pEntry = pPal->palPalEntry;
|
||
|
|
||
|
for ( i = 0; i < count ; i++, pEntry++ )
|
||
|
{
|
||
|
pEntry->peRed = ss_ComponentFromIndex(i, ppfd->cRedBits,
|
||
|
ppfd->cRedShift);
|
||
|
pEntry->peGreen = ss_ComponentFromIndex(i, ppfd->cGreenBits,
|
||
|
ppfd->cGreenShift);
|
||
|
pEntry->peBlue = ss_ComponentFromIndex(i, ppfd->cBlueBits,
|
||
|
ppfd->cBlueShift);
|
||
|
pEntry->peFlags = PC_NOCOLLAPSE;
|
||
|
}
|
||
|
|
||
|
if( count == 256 )
|
||
|
{
|
||
|
// If app set static system color usage for fixed palette support,
|
||
|
// setup to take over the static colors. Otherwise, fixup the
|
||
|
// static system colors.
|
||
|
|
||
|
if ( bUseStatic )
|
||
|
{
|
||
|
// Black and white already exist as the only remaining static
|
||
|
// colors. Let those remap. All others should be put into
|
||
|
// the palette (i.e., set PC_NOCOLLAPSE).
|
||
|
|
||
|
pPal->palPalEntry[0].peFlags = 0;
|
||
|
pPal->palPalEntry[255].peFlags = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// The defaultOverride array is computed assuming a 332
|
||
|
// palette where red has zero shift, etc.
|
||
|
|
||
|
if ( (3 == ppfd->cRedBits) && (0 == ppfd->cRedShift) &&
|
||
|
(3 == ppfd->cGreenBits) && (3 == ppfd->cGreenShift) &&
|
||
|
(2 == ppfd->cBlueBits) && (6 == ppfd->cBlueShift) )
|
||
|
{
|
||
|
pEntry = pPal->palPalEntry;
|
||
|
UpdateStaticMapping( pEntry );
|
||
|
|
||
|
for ( i = 0 ; i < STATIC_COLORS ; i++)
|
||
|
{
|
||
|
pEntry[aiDefaultOverride[i]] = apeDefaultPalEntry[i];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
hpal = CreatePalette(pPal);
|
||
|
LocalFree(pPal);
|
||
|
return hpal;
|
||
|
}
|
||
|
|
||
|
LONG
|
||
|
NullPaletteManageProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|