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

522 lines
16 KiB

/**************************************************************************\
*
* Copyright (c) 1999-2000 Microsoft Corporation
*
* Abstract:
*
* Object which maps one palette to another.
*
* It only maps colors which match exactly - its purpose is to deal
* with, e.g., the halftone palette which has identical colors on different
* platforms, but colors may be in different positions.
*
* Revision History:
*
* 12/09/1999 ericvan
* Created it.
* 01/20/2000 agodfrey
* Moved it from Imaging\Api. Renamed it to EpPaletteMap.
* Replaced the halftoning function pointer with 'isVGAOnly'.
*
\**************************************************************************/
#include "precomp.hpp"
//#define GDIPLUS_WIN9X_HALFTONE_MAP
#if defined(GDIPLUS_WIN9X_HALFTONE_MAP)
// The first array maps from our halftone color palette to the Windows 9x
// halftone color palette, while the second array does the reverse. Negative
// values indicate an unmatched color:
//
// -1 no exact match (Win9x is missing 4 of our halftone colors)
// -2 magic color
INT HTToWin9xPaletteMap[256] = {
0, 1, 2, 3, 4, 5, 6, 7,
-2, -2, -2, -2, 248, 249, 250, 251,
252, 253, 254, 255, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 60, 95, 133, 161, 252, 33, 66,
101, 166, 199, -1, 39, 72, 107, 138,
172, 205, 45, 78, 112, 129, 178, 211,
51, 84, 118, 149, 184, 217, 250, -1,
123, 155, 190, 254, 29, 61, 96, 162,
196, -1, 34, 67, 102, 134, 167, 200,
40, 73, 108, 139, 173, 206, 46, 79,
113, 144, 179, 212, 52, 85, 119, 150,
185, 218, -1, 90, 124, 156, 191, 223,
30, 62, 97, 135, 163, 197, 35, 68,
103, 140, 168, 201, 41, 74, 109, 174,
207, 230, 47, 80, 114, 145, 180, 213,
53, 86, 151, 157, 186, 219, 57, 91,
228, 192, 224, 232, 31, 63, 98, 131,
164, 198, 36, 69, 104, 130, 169, 202,
42, 75, 110, 141, 175, 208, 48, 81,
115, 146, 181, 214, 54, 87, 120, 152,
187, 220, 58, 92, 125, 158, 193, 225,
32, 64, 99, 132, 165, 128, 37, 70,
105, 136, 170, 203, 43, 76, 111, 142,
176, 209, 49, 82, 116, 147, 182, 215,
55, 88, 121, 153, 188, 221, 59, 93,
126, 159, 194, 226, 249, 65, 100, 137,
127, 253, 38, 71, 106, 143, 171, 204,
44, 77, 227, 177, 210, 231, 50, 83,
117, 148, 183, 216, 56, 89, 122, 154,
189, 222, 251, 94, 229, 160, 195, 255
};
INT HTFromWin9xPaletteMap[256] = {
0, 1, 2, 3, 4, 5, 6, 7,
-2, -2, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, 76, 112, 148,
184, 46, 82, 118, 154, 190, 226, 52,
88, 124, 160, 196, 232, 58, 94, 130,
166, 202, 238, 64, 100, 136, 172, 208,
244, 142, 178, 214, 41, 77, 113, 149,
185, 221, 47, 83, 119, 155, 191, 227,
53, 89, 125, 161, 197, 233, 59, 95,
131, 167, 203, 239, 65, 101, 137, 173,
209, 245, 107, 143, 179, 215, 251, 42,
78, 114, 150, 186, 222, 48, 84, 120,
156, 192, 228, 54, 90, 126, 162, 198,
60, 96, 132, 168, 204, 240, 66, 102,
174, 210, 246, 72, 108, 180, 216, 224,
189, 61, 157, 151, 187, 43, 85, 115,
193, 223, 55, 91, 121, 163, 199, 229,
97, 133, 169, 205, 241, 67, 103, 138,
175, 211, 247, 73, 109, 139, 181, 217,
253, 44, 79, 116, 152, 188, 49, 86,
122, 158, 194, 230, 56, 92, 127, 164,
200, 235, 62, 98, 134, 170, 206, 242,
68, 104, 140, 176, 212, 248, 74, 110,
145, 182, 218, 254, 80, 117, 153, 50,
87, 123, 159, 195, 231, 57, 93, 128,
165, 201, 236, 63, 99, 135, 171, 207,
243, 69, 105, 141, 177, 213, 249, 111,
146, 183, 219, 234, 144, 252, 129, 237,
147, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -2, -2,
12, 13, 14, 15, 16, 17, 18, 19
};
#endif
BYTE
GetNearestColorIndex(
GpColor color,
ColorPalette *palette
)
{
INT i;
BYTE nearestIndex = 0;
INT nearestDistance = INT_MAX;
// Note: This does not optimize for the exact match case because it's
// assumed we already did this check first.
for (i = 0; i < (INT) palette->Count; i++)
{
// Compute the distance (squared) between colors:
GpColor palColor = GpColor(palette->Entries[i]);
INT r = (INT) color.GetRed() - (INT) palColor.GetRed();
INT g = (INT) color.GetGreen() - (INT) palColor.GetGreen();
INT b = (INT) color.GetBlue() - (INT) palColor.GetBlue();
INT distance = (r * r) + (g * g) + (b * b);
if (distance < nearestDistance)
{
nearestDistance = distance;
nearestIndex = static_cast<BYTE>(i);
if (nearestDistance == 0)
{
break;
}
}
}
return nearestIndex;
}
VOID
EpPaletteMap::CreateFromColorPalette(
ColorPalette *palette
)
{
INT i;
INT matchCount = 0;
#if defined(GDIPLUS_WIN9X_HALFTONE_MAP)
// Check for the Win9x halftone palette:
PALETTEENTRY *palEntry = Win9xHalftonePalette.palPalEntry;
for (i = 0; i < 256; i++, palEntry++)
{
// Ignore magic or unmatched colors:
if (HTFromWin9xPaletteMap[i] >= 0)
{
GpColor palColor(palette->Entries[i]);
if ((palColor.GetRed() != palEntry->peRed) ||
(palColor.GetGreen() != palEntry->peGreen) ||
(palColor.GetBlue() != palEntry->peBlue))
{
break;
}
}
}
if (i == 256) // --- Win9x halftone palette ---
{
matchCount = 212;
for (i = 0; i < 256; i++)
{
INT win9xIndex = HTToWin9xPaletteMap[i];
if (win9xIndex >= 0)
{
translate[i] = static_cast<BYTE>(win9xIndex);
}
else
{
GpColor halftoneColor;
if (win9xIndex == -1)
{
halftoneColor =
GpColor(HTColorPalette.palPalEntry[i].peRed,
HTColorPalette.palPalEntry[i].peGreen,
HTColorPalette.palPalEntry[i].peBlue);
}
else
{
ASSERT(win9xIndex == -2);
ASSERT((i >= 8) && (i <= 11));
COLORREF systemColor = Globals::SystemColors[i + 8];
halftoneColor = GpColor(GetRValue(systemColor),
GetGValue(systemColor),
GetBValue(systemColor));
}
translate[i] = GetNearestColorIndex(halftoneColor,
palette);
}
}
}
else // --- Any other palette ---
#endif
{
for (i = 0; i < 256; i++)
{
GpColor color;
if ((i > 11) || (i < 8))
{
color = GpColor(HTColorPalette.palPalEntry[i].peRed,
HTColorPalette.palPalEntry[i].peGreen,
HTColorPalette.palPalEntry[i].peBlue);
}
else
{
COLORREF systemColor = Globals::SystemColors[i + 8];
color = GpColor(GetRValue(systemColor),
GetGValue(systemColor),
GetBValue(systemColor));
}
// First look for exact matches:
INT j;
for (j = 0; j < (INT) palette->Count; j++)
{
if (GpColor(palette->Entries[j]).IsEqual(color))
{
// We found an exact match:
translate[i] = static_cast<BYTE>(j);
if (i >= 40)
{
matchCount++;
}
break;
}
}
// If we didn't find an exact match, look for the nearest:
if (j == (INT) palette->Count)
{
translate[i] = GetNearestColorIndex(color,
palette);
}
}
}
uniqueness = 0;
// See comments in UpdateTranslate to see why we look for 212 colors.
isVGAOnly = (matchCount >= 212) ? FALSE : TRUE;
}
EpPaletteMap::EpPaletteMap(HDC hdc, ColorPalette **palette, BOOL isDib8)
{
// isDib8 is TRUE when the caller has already determined that the HDC
// bitmap is an 8 bpp DIB section. If the caller hasn't determined, we
// check here:
if (!isDib8 && (GetDCType(hdc) == OBJ_MEMDC))
{
HBITMAP hbm = (HBITMAP) GetCurrentObject(hdc, OBJ_BITMAP);
if (hbm)
{
DIBSECTION dibInfo;
INT infoSize = GetObjectA(hbm, sizeof(dibInfo), &dibInfo);
// Comment below copied from GpGraphics::GetFromGdiBitmap:
//
// WinNT/Win95 differences in GetObject:
//
// WinNT always returns the number of bytes filled, either
// sizeof(BITMAP) or sizeof(DIBSECTION).
//
// Win95 always returns the original requested size (filling the
// remainder with NULLs). So if it is a DIBSECTION, we expect
// dibInfo.dsBmih.biSize != 0; otherwise it is a BITMAP.
if ((infoSize == sizeof(DIBSECTION)) &&
(Globals::IsNt || dibInfo.dsBmih.biSize))
{
if (dibInfo.dsBmih.biBitCount == 8)
{
isDib8 = TRUE;
}
}
}
}
// If we've got an 8 bpp DIB section, extract its color table and create
// the palette map from this. Otherwise, call UpdateTranslate which will
// handle screen and compatible bitmaps.
if (isDib8)
{
// Get the color table from the DIBSection
RGBQUAD colorTable[256];
GetDIBColorTable(hdc, 0, 256, colorTable);
// Create a GDI+ ColorPalette object from it
// Note: the reason we use "255" here is because
// ColorPalette object already has 1 allocation for ARGB
ColorPalette *newPalette =
static_cast<ColorPalette *>(
GpMalloc(sizeof(ColorPalette) + 255 * sizeof(ARGB)));
if (newPalette)
{
newPalette->Flags = 0;
newPalette->Count = 256;
for (int i = 0; i < 256; i++)
{
newPalette->Entries[i] =
MAKEARGB(255,
colorTable[i].rgbRed,
colorTable[i].rgbGreen,
colorTable[i].rgbBlue);
}
CreateFromColorPalette(newPalette);
if (palette)
{
*palette = newPalette;
}
else
{
GpFree(newPalette);
}
SetValid(TRUE);
return;
}
SetValid(FALSE);
}
else
{
UpdateTranslate(hdc, palette);
}
}
EpPaletteMap::~EpPaletteMap()
{
SetValid(FALSE); // so we don't use a deleted object
}
VOID EpPaletteMap::UpdateTranslate(HDC hdc, ColorPalette **palette)
{
SetValid(FALSE);
HPALETTE hSysPal = NULL;
struct
{
LOGPALETTE logpalette;
PALETTEENTRY palEntries[256];
} pal;
pal.logpalette.palVersion = 0x0300;
// <SystemPalette>
// !!! [agodfrey] On Win9x, GetSystemPaletteEntries(hdc, 0, 256, NULL)
// doesn't do what MSDN says it does. It seems to return the number
// of entries in the logical palette of the DC instead. So we have
// to make it up ourselves.
pal.logpalette.palNumEntries = (1 << (GetDeviceCaps(hdc, BITSPIXEL) *
GetDeviceCaps(hdc, PLANES)));
GetSystemPaletteEntries(hdc, 0, 256, &pal.logpalette.palPalEntry[0]);
hSysPal = CreatePalette(&pal.logpalette);
if (hSysPal == NULL)
{
return;
}
if (palette)
{
// system palette is required for ScanDci case.
if (*palette == NULL)
{
*palette = (ColorPalette*)GpMalloc(sizeof(ColorPalette)+sizeof(ARGB)*256);
if (*palette == NULL)
{
goto exit;
}
}
(*palette)->Count = pal.logpalette.palNumEntries;
for (INT j=0; j<pal.logpalette.palNumEntries; j++)
{
(*palette)->Entries[j] = GpColor::MakeARGB(0xFF,
pal.logpalette.palPalEntry[j].peRed,
pal.logpalette.palPalEntry[j].peGreen,
pal.logpalette.palPalEntry[j].peBlue);
}
}
{
GpMemset(translate, 0, 256);
INT matchCount;
INT i;
PALETTEENTRY * halftonePalEntry = HTColorPalette.palPalEntry;
COLORREF halftoneColor;
COLORREF sysColor;
COLORREF matchedColor;
UINT matchingIndex;
// Create a translation table for the 216 halftone colors, and count
// how many exact matches we get.
for (i = 0, matchCount = 0; i < 256; i++, halftonePalEntry++)
{
if ((i > 11) || (i < 8))
{
halftoneColor = PALETTERGB(halftonePalEntry->peRed,
halftonePalEntry->peGreen,
halftonePalEntry->peBlue);
}
else // it is one of the magic 4 changeable system colors
{
halftoneColor = Globals::SystemColors[i + 8] | 0x02000000;
}
// See if the color is actually available in the system palette.
matchedColor = ::GetNearestColor(hdc, halftoneColor) | 0x02000000;
// Find the index of the matching color in the system palette
matchingIndex = ::GetNearestPaletteIndex(hSysPal, matchedColor);
if (matchingIndex == CLR_INVALID)
{
goto exit;
}
// We should never match to an entry outside of the device palette.
ASSERT(matchingIndex < pal.logpalette.palNumEntries);
translate[i] = static_cast<BYTE>(matchingIndex);
sysColor = PALETTERGB(pal.logpalette.palPalEntry[matchingIndex].peRed,
pal.logpalette.palPalEntry[matchingIndex].peGreen,
pal.logpalette.palPalEntry[matchingIndex].peBlue);
// see if we got an exact match
if ((i >= 40) && (sysColor == halftoneColor))
{
matchCount++;
}
}
// If we matched enough colors, we'll do 216-color halftoning.
// Otherwise, we'll have to halftone with the VGA colors.
// The palette returned from CreateHalftonePalette() on Win9x has
// only 212 of the required 216 halftone colors. (On NT it has all 216).
// The 4 colors missing from the Win9x halftone palette are:
// 0x00, 0x33, 0xFF
// 0x00, 0xFF, 0x33
// 0x33, 0x00, 0xFF
// 0x33, 0xFF, 0x00
// We require that all 212 colors be available because our GetNearestColor
// API assumes that all 216 colors are there if we're doing 216-color
// halftoning.
SetValid(TRUE);
if (matchCount >= 212)
{
isVGAOnly = FALSE;
}
else
{
isVGAOnly = TRUE;
}
}
exit:
DeleteObject(hSysPal);
return;
}