📄 color.c
字号:
/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: color.c 28434 2007-08-20 19:50:07Z cfinck $ */
#include <w32k.h>
#define NDEBUG
#include <debug.h>
// FIXME: Use PXLATEOBJ logicalToSystem instead of int *mapping
int COLOR_gapStart = 256;
int COLOR_gapEnd = -1;
int COLOR_gapFilled = 0;
int COLOR_max = 256;
#ifndef NO_MAPPING
static HPALETTE hPrimaryPalette = 0; // used for WM_PALETTECHANGED
#endif
//static HPALETTE hLastRealizedPalette = 0; // UnrealizeObject() needs it
static UINT SystemPaletteUse = SYSPAL_NOSTATIC; /* the program need save the pallete and restore it */
const PALETTEENTRY COLOR_sysPalTemplate[NB_RESERVED_COLORS] =
{
// first 10 entries in the system palette
// red green blue flags
{ 0x00, 0x00, 0x00, PC_SYS_USED },
{ 0x80, 0x00, 0x00, PC_SYS_USED },
{ 0x00, 0x80, 0x00, PC_SYS_USED },
{ 0x80, 0x80, 0x00, PC_SYS_USED },
{ 0x00, 0x00, 0x80, PC_SYS_USED },
{ 0x80, 0x00, 0x80, PC_SYS_USED },
{ 0x00, 0x80, 0x80, PC_SYS_USED },
{ 0xc0, 0xc0, 0xc0, PC_SYS_USED },
{ 0xc0, 0xdc, 0xc0, PC_SYS_USED },
{ 0xd4, 0xd0, 0xc7, PC_SYS_USED },
// ... c_min/2 dynamic colorcells
// ... gap (for sparse palettes)
// ... c_min/2 dynamic colorcells
{ 0xff, 0xfb, 0xf0, PC_SYS_USED },
{ 0x3a, 0x6e, 0xa5, PC_SYS_USED },
{ 0x80, 0x80, 0x80, PC_SYS_USED },
{ 0xff, 0x00, 0x00, PC_SYS_USED },
{ 0x00, 0xff, 0x00, PC_SYS_USED },
{ 0xff, 0xff, 0x00, PC_SYS_USED },
{ 0x00, 0x00, 0xff, PC_SYS_USED },
{ 0xff, 0x00, 0xff, PC_SYS_USED },
{ 0x00, 0xff, 0xff, PC_SYS_USED },
{ 0xff, 0xff, 0xff, PC_SYS_USED } // last 10
};
const PALETTEENTRY* FASTCALL COLOR_GetSystemPaletteTemplate(void)
{
return (const PALETTEENTRY*)&COLOR_sysPalTemplate;
}
BOOL STDCALL NtGdiAnimatePalette(HPALETTE hPal, UINT StartIndex,
UINT NumEntries, CONST PPALETTEENTRY PaletteColors)
{
if( hPal != NtGdiGetStockObject(DEFAULT_PALETTE) )
{
PPALGDI palPtr;
UINT pal_entries;
HDC hDC;
PDC dc;
PWINDOW_OBJECT Wnd;
const PALETTEENTRY *pptr = PaletteColors;
palPtr = (PPALGDI)PALETTE_LockPalette(hPal);
if (!palPtr) return FALSE;
pal_entries = palPtr->NumColors;
if (StartIndex >= pal_entries)
{
PALETTE_UnlockPalette(palPtr);
return FALSE;
}
if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++) {
/* According to MSDN, only animate PC_RESERVED colours */
if (palPtr->IndexedColors[StartIndex].peFlags & PC_RESERVED) {
memcpy( &palPtr->IndexedColors[StartIndex], pptr,
sizeof(PALETTEENTRY) );
PALETTE_ValidateFlags(&palPtr->IndexedColors[StartIndex], 1);
}
}
PALETTE_UnlockPalette(palPtr);
/* Immediately apply the new palette if current window uses it */
Wnd = UserGetDesktopWindow();
hDC = (HDC)UserGetWindowDC(Wnd);
dc = DC_LockDc(hDC);
if (NULL != dc)
{
if (dc->w.hPalette == hPal)
{
DC_UnlockDc(dc);
NtGdiRealizePalette(hDC);
}
else
DC_UnlockDc(dc);
}
UserReleaseDC(Wnd,hDC, FALSE);
}
return TRUE;
}
HPALETTE STDCALL NtGdiCreateHalftonePalette(HDC hDC)
{
int i, r, g, b;
struct {
WORD Version;
WORD NumberOfEntries;
PALETTEENTRY aEntries[256];
} Palette;
Palette.Version = 0x300;
Palette.NumberOfEntries = 256;
if (NtGdiGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries) == 0)
{
/* from wine, more that 256 color math */
Palette.NumberOfEntries = 20;
for (i = 0; i < Palette.NumberOfEntries; i++)
{
Palette.aEntries[i].peRed=0xff;
Palette.aEntries[i].peGreen=0xff;
Palette.aEntries[i].peBlue=0xff;
Palette.aEntries[i].peFlags=0x00;
}
Palette.aEntries[0].peRed=0x00;
Palette.aEntries[0].peBlue=0x00;
Palette.aEntries[0].peGreen=0x00;
/* the first 6 */
for (i=1; i <= 6; i++)
{
Palette.aEntries[i].peRed=(i%2)?0x80:0;
Palette.aEntries[i].peGreen=(i==2)?0x80:(i==3)?0x80:(i==6)?0x80:0;
Palette.aEntries[i].peBlue=(i>3)?0x80:0;
}
for (i=7; i <= 12; i++)
{
switch(i)
{
case 7:
Palette.aEntries[i].peRed=0xc0;
Palette.aEntries[i].peBlue=0xc0;
Palette.aEntries[i].peGreen=0xc0;
break;
case 8:
Palette.aEntries[i].peRed=0xc0;
Palette.aEntries[i].peGreen=0xdc;
Palette.aEntries[i].peBlue=0xc0;
break;
case 9:
Palette.aEntries[i].peRed=0xa6;
Palette.aEntries[i].peGreen=0xca;
Palette.aEntries[i].peBlue=0xf0;
break;
case 10:
Palette.aEntries[i].peRed=0xff;
Palette.aEntries[i].peGreen=0xfb;
Palette.aEntries[i].peBlue=0xf0;
break;
case 11:
Palette.aEntries[i].peRed=0xa0;
Palette.aEntries[i].peGreen=0xa0;
Palette.aEntries[i].peBlue=0xa4;
break;
case 12:
Palette.aEntries[i].peRed=0x80;
Palette.aEntries[i].peGreen=0x80;
Palette.aEntries[i].peBlue=0x80;
}
}
for (i=13; i <= 18; i++)
{
Palette.aEntries[i].peRed=(i%2)?0xff:0;
Palette.aEntries[i].peGreen=(i==14)?0xff:(i==15)?0xff:(i==18)?0xff:0;
Palette.aEntries[i].peBlue=(i>15)?0xff:0x00;
}
}
else
{
/* 256 color table */
for (r = 0; r < 6; r++)
for (g = 0; g < 6; g++)
for (b = 0; b < 6; b++)
{
i = r + g*6 + b*36 + 10;
Palette.aEntries[i].peRed = r * 51;
Palette.aEntries[i].peGreen = g * 51;
Palette.aEntries[i].peBlue = b * 51;
}
for (i = 216; i < 246; i++)
{
int v = (i - 216) << 3;
Palette.aEntries[i].peRed = v;
Palette.aEntries[i].peGreen = v;
Palette.aEntries[i].peBlue = v;
}
}
return NtGdiCreatePalette((LOGPALETTE *)&Palette);
}
HPALETTE STDCALL NtGdiCreatePalette(CONST PLOGPALETTE palette)
{
PPALGDI PalGDI;
HPALETTE NewPalette = PALETTE_AllocPalette(
PAL_INDEXED,
palette->palNumEntries,
(PULONG)palette->palPalEntry,
0, 0, 0);
if (NewPalette == NULL)
{
return NULL;
}
PalGDI = (PPALGDI) PALETTE_LockPalette(NewPalette);
if (PalGDI != NULL)
{
PALETTE_ValidateFlags(PalGDI->IndexedColors, PalGDI->NumColors);
PalGDI->logicalToSystem = NULL;
PALETTE_UnlockPalette(PalGDI);
}
else
{
/* FIXME - Handle PalGDI == NULL!!!! */
DPRINT1("waring PalGDI is NULL \n");
}
return NewPalette;
}
BOOL STDCALL NtGdiGetColorAdjustment(HDC hDC,
LPCOLORADJUSTMENT ca)
{
UNIMPLEMENTED;
return FALSE;
}
unsigned short GetNumberOfBits(unsigned int dwMask)
{
unsigned short wBits;
for (wBits = 0; dwMask; dwMask = dwMask & (dwMask - 1))
wBits++;
return wBits;
}
COLORREF STDCALL NtGdiGetNearestColor(HDC hDC, COLORREF Color)
{
COLORREF nearest = CLR_INVALID;
PDC dc;
PPALGDI palGDI;
LONG RBits, GBits, BBits;
dc = DC_LockDc(hDC);
if (NULL != dc)
{
HPALETTE hpal = dc->w.hPalette;
palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
if (!palGDI)
{
DC_UnlockDc(dc);
return nearest;
}
switch (palGDI->Mode)
{
case PAL_INDEXED:
nearest = COLOR_LookupNearestColor(palGDI->IndexedColors,
palGDI->NumColors, Color);
break;
case PAL_BGR:
case PAL_RGB:
nearest = Color;
break;
case PAL_BITFIELDS:
RBits = 8 - GetNumberOfBits(palGDI->RedMask);
GBits = 8 - GetNumberOfBits(palGDI->GreenMask);
BBits = 8 - GetNumberOfBits(palGDI->BlueMask);
nearest = RGB(
(GetRValue(Color) >> RBits) << RBits,
(GetGValue(Color) >> GBits) << GBits,
(GetBValue(Color) >> BBits) << BBits);
break;
}
PALETTE_UnlockPalette(palGDI);
DC_UnlockDc(dc);
}
return nearest;
}
UINT STDCALL NtGdiGetNearestPaletteIndex(HPALETTE hpal,
COLORREF Color)
{
PPALGDI palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
UINT index = 0;
if (NULL != palGDI)
{
/* Return closest match for the given RGB color */
index = COLOR_PaletteLookupPixel(palGDI->IndexedColors, palGDI->NumColors, NULL, Color, FALSE);
PALETTE_UnlockPalette(palGDI);
}
return index;
}
UINT STDCALL NtGdiGetPaletteEntries(HPALETTE hpal,
UINT StartIndex,
UINT Entries,
LPPALETTEENTRY pe)
{
PPALGDI palGDI;
UINT numEntries;
palGDI = (PPALGDI) PALETTE_LockPalette(hpal);
if (NULL == palGDI)
{
return 0;
}
numEntries = palGDI->NumColors;
if (numEntries < StartIndex + Entries)
{
Entries = numEntries - StartIndex;
}
if (NULL != pe)
{
if (numEntries <= StartIndex)
{
PALETTE_UnlockPalette(palGDI);
return 0;
}
memcpy(pe, palGDI->IndexedColors + StartIndex, Entries * sizeof(PALETTEENTRY));
for (numEntries = 0; numEntries < Entries; numEntries++)
{
if (pe[numEntries].peFlags & 0xF0)
{
pe[numEntries].peFlags = 0;
}
}
}
PALETTE_UnlockPalette(palGDI);
return Entries;
}
UINT STDCALL NtGdiGetSystemPaletteEntries(HDC hDC,
UINT StartIndex,
UINT Entries,
LPPALETTEENTRY pe)
{
PPALGDI palGDI = NULL;
PDC dc = NULL;
UINT EntriesSize = 0;
UINT Ret = 0;
if (Entries == 0)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
}
_SEH_TRY
{
if (pe != NULL)
{
EntriesSize = Entries * sizeof(pe[0]);
if (Entries != EntriesSize / sizeof(pe[0]))
{
/* Integer overflow! */
SetLastWin32Error(ERROR_INVALID_PARAMETER);
_SEH_LEAVE;
}
ProbeForWrite(pe,
EntriesSize,
sizeof(UINT));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -