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.
 
 
 
 
 
 

3376 lines
97 KiB

/******************************Module*Header*******************************\
* Module Name: palobj.cxx
*
* Palette user object functions
*
* Created: 07-Nov-1990 21:30:19
* Author: Patrick Haluptzok patrickh
*
* Copyright (c) 1990-1999 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
extern "C" BOOL bInitPALOBJ();
#pragma alloc_text(INIT, bInitPALOBJ)
#define MAX_PAL_ERROR (3 * (256*256))
// ulXlatePalUnique is used for the uniquess of the xlates and palettes.
ULONG ulXlatePalUnique = 3;
// gpRGBXlate is a global RGBXlate for the rainbow palette
PBYTE gpRGBXlate = NULL;
UINT *pArrayOfSquares;
UINT aArrayOfSquares[511];
typedef BYTE FAR *PIMAP;
typedef struct {BYTE r,g,b,x;} RGBX;
BOOL MakeITable(PIMAP lpITable, RGBX FAR *prgb, int nColors);
/******************************Public*Data*********************************\
* Default Monochrome Palette
*
* History:
* 16-Nov-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
ULONG gaulMono[2] =
{
0,
0xFFFFFF
};
/******************************Public*Data*********************************\
* Default Logical Palette
*
* Default Palette Data Structure, Taken straight from Win 3.1
* This is the default palette, the stock palette.
* This contains the 20 default colors.
* This is the default logical palette put in every DC when it is created.
*
* History:
* 16-Nov-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
PAL_LOGPALETTE logDefaultPal =
{
0x300, // version number
20, // number of entries
{
{ 0, 0, 0, 0 }, // 0
{ 0x80,0, 0, 0 }, // 1
{ 0, 0x80,0, 0 }, // 2
{ 0x80,0x80,0, 0 }, // 3
{ 0, 0, 0x80,0 }, // 4
{ 0x80,0, 0x80,0 }, // 5
{ 0, 0x80,0x80,0 }, // 6
{ 0xC0,0xC0,0xC0,0 }, // 7
{ 192, 220, 192, 0 }, // 8
{ 166, 202, 240, 0 }, // 9
{ 255, 251, 240, 0 }, // 10
{ 160, 160, 164, 0 }, // 11
{ 0x80,0x80,0x80,0 }, // 12
{ 0xFF,0, 0, 0 }, // 13
{ 0, 0xFF,0, 0 }, // 14
{ 0xFF,0xFF,0, 0 }, // 15
{ 0, 0, 0xFF,0 }, // 16
{ 0xFF,0, 0xFF,0 }, // 17
{ 0, 0xFF,0xFF,0 }, // 18
{ 0xFF,0xFF,0xFF,0 } // 19
}
};
/******************************Public*Data**********************************\
*
* This is the same as color table as logDefaultPal except
* entries for magic colors. These are 0x0 to prevent a match.
* We now only match magic colors exactly, otherwise nearest-match
* to this palette
*
\**************************************************************************/
PAL_ULONG aPalDefaultVGA[20] =
{
{ 0, 0, 0, 0 }, // 0
{ 0x80,0, 0, 0 }, // 1
{ 0, 0x80,0, 0 }, // 2
{ 0x80,0x80,0, 0 }, // 3
{ 0, 0, 0x80,0 }, // 4
{ 0x80,0, 0x80,0 }, // 5
{ 0, 0x80,0x80,0 }, // 6
{ 0xC0,0xC0,0xC0,0 }, // 7
{ 000, 000, 000, 0 }, // 8
{ 000, 000, 000, 0 }, // 9
{ 000, 000, 000, 0 }, // 10
{ 000, 000, 000, 0 }, // 11
{ 0x80,0x80,0x80,0 }, // 12
{ 0xFF,0, 0, 0 }, // 13
{ 0, 0xFF,0, 0 }, // 14
{ 0xFF,0xFF,0, 0 }, // 15
{ 0, 0, 0xFF,0 }, // 16
{ 0xFF,0, 0xFF,0 }, // 17
{ 0, 0xFF,0xFF,0 }, // 18
{ 0xFF,0xFF,0xFF,0 } // 19
};
/******************************Public*Data*********************************\
* This is the default 16 color palette which matches the VGA palette
* exactly.
*
* History:
* 05-Nov-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
PAL_ULONG aPalVGA[16] =
{
{ 0, 0, 0, 0 }, // 0
{ 0x80,0, 0, 0 }, // 1
{ 0, 0x80,0, 0 }, // 2
{ 0x80,0x80,0, 0 }, // 3
{ 0, 0, 0x80,0 }, // 4
{ 0x80,0, 0x80,0 }, // 5
{ 0, 0x80,0x80,0 }, // 6
{ 0x80,0x80,0x80,0 }, // 7
{ 0xC0,0xC0,0xC0,0 }, // 8
{ 0xFF,0, 0, 0 }, // 9
{ 0, 0xFF,0, 0 }, // 10
{ 0xFF,0xFF,0, 0 }, // 11
{ 0, 0, 0xFF,0 }, // 12
{ 0xFF,0, 0xFF,0 }, // 13
{ 0, 0xFF,0xFF,0 }, // 14
{ 0xFF,0xFF,0xFF,0 } // 15
};
/******************************Public*Routine******************************\
*
* win95 halftone palette
*
* History:
*
* 11/27/1996 Mark Enstrom [marke]
*
* 03-Feb-1999 Wed 01:47:31 updated -by- Daniel Chou (danielc)
* Even though this is the one copy from win95, it is wrong for halftone
* to be use correctly, it missing high luminance green color, I added
* this back, and the low r/b/m/c luminance color (20% of that color) are
* patch into gray color. All window system halftone does not use any
* gray color in 256 color mode any more.
*
* Index 10: 0x04:0x04:0x04 --> 0x00:0x00:0x33
* Index 11: 0x08:0x08:0x08 --> 0x33:0x00:0x00
* Index 12: 0x0c:0x0c:0x0c --> 0x33:0x00:0x33
* Index 13: 0x11:0x11:0x11 --> 0x00:0x33:0x33
* Index 39: 0x33:0x00:0x00 --> 0x33:0xFF:0x00
* Index 60: 0x00:0x00:0x33 --> 0x00:0xFF:0x33
* Index 61: 0x33:0x00:0x33 --> 0x33:0x00:0xFF
* Index 66: 0x00:0x33:0x33 --> 0x00:0x33:0xFF
*
\**************************************************************************/
PAL_ULONG aPalHalftone[256] =
{
{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x00,0x80,0x00,0x00},{0x80,0x80,0x00,0x00},
{0x00,0x00,0x80,0x00},{0x80,0x00,0x80,0x00},{0x00,0x80,0x80,0x00},{0xc0,0xc0,0xc0,0x00},
{0xc0,0xdc,0xc0,0x00},{0xa6,0xca,0xf0,0x00},{0x00,0x00,0x33,0x04},{0x33,0x00,0x00,0x04},
{0x33,0x00,0x33,0x04},{0x00,0x33,0x33,0x04},{0x16,0x16,0x16,0x04},{0x1c,0x1c,0x1c,0x04},
//1
{0x22,0x22,0x22,0x04},{0x29,0x29,0x29,0x04},{0x55,0x55,0x55,0x04},{0x4d,0x4d,0x4d,0x04},
{0x42,0x42,0x42,0x04},{0x39,0x39,0x39,0x04},{0xFF,0x7C,0x80,0x04},{0xFF,0x50,0x50,0x04},
{0xD6,0x00,0x93,0x04},{0xCC,0xEC,0xFF,0x04},{0xEF,0xD6,0xC6,0x04},{0xE7,0xE7,0xD6,0x04},
{0xAD,0xA9,0x90,0x04},{0x33,0xFF,0x00,0x04},{0x66,0x00,0x00,0x04},{0x99,0x00,0x00,0x04},
//2
{0xcc,0x00,0x00,0x04},{0x00,0x33,0x00,0x04},{0x33,0x33,0x00,0x04},{0x66,0x33,0x00,0x04},
{0x99,0x33,0x00,0x04},{0xcc,0x33,0x00,0x04},{0xff,0x33,0x00,0x04},{0x00,0x66,0x00,0x04},
{0x33,0x66,0x00,0x04},{0x66,0x66,0x00,0x04},{0x99,0x66,0x00,0x04},{0xcc,0x66,0x00,0x04},
{0xff,0x66,0x00,0x04},{0x00,0x99,0x00,0x04},{0x33,0x99,0x00,0x04},{0x66,0x99,0x00,0x04},
//3
{0x99,0x99,0x00,0x04},{0xcc,0x99,0x00,0x04},{0xff,0x99,0x00,0x04},{0x00,0xcc,0x00,0x04},
{0x33,0xcc,0x00,0x04},{0x66,0xcc,0x00,0x04},{0x99,0xcc,0x00,0x04},{0xcc,0xcc,0x00,0x04},
{0xff,0xcc,0x00,0x04},{0x66,0xff,0x00,0x04},{0x99,0xff,0x00,0x04},{0xcc,0xff,0x00,0x04},
{0x00,0xFF,0x33,0x04},{0x33,0x00,0xFF,0x04},{0x66,0x00,0x33,0x04},{0x99,0x00,0x33,0x04},
//4
{0xcc,0x00,0x33,0x04},{0xff,0x00,0x33,0x04},{0x00,0x33,0xFF,0x04},{0x33,0x33,0x33,0x04},
{0x66,0x33,0x33,0x04},{0x99,0x33,0x33,0x04},{0xcc,0x33,0x33,0x04},{0xff,0x33,0x33,0x04},
{0x00,0x66,0x33,0x04},{0x33,0x66,0x33,0x04},{0x66,0x66,0x33,0x04},{0x99,0x66,0x33,0x04},
{0xcc,0x66,0x33,0x04},{0xff,0x66,0x33,0x04},{0x00,0x99,0x33,0x04},{0x33,0x99,0x33,0x04},
//5
{0x66,0x99,0x33,0x04},{0x99,0x99,0x33,0x04},{0xcc,0x99,0x33,0x04},{0xff,0x99,0x33,0x04},
{0x00,0xcc,0x33,0x04},{0x33,0xcc,0x33,0x04},{0x66,0xcc,0x33,0x04},{0x99,0xcc,0x33,0x04},
{0xcc,0xcc,0x33,0x04},{0xff,0xcc,0x33,0x04},{0x33,0xff,0x33,0x04},{0x66,0xff,0x33,0x04},
{0x99,0xff,0x33,0x04},{0xcc,0xff,0x33,0x04},{0xff,0xff,0x33,0x04},{0x00,0x00,0x66,0x04},
//6
{0x33,0x00,0x66,0x04},{0x66,0x00,0x66,0x04},{0x99,0x00,0x66,0x04},{0xcc,0x00,0x66,0x04},
{0xff,0x00,0x66,0x04},{0x00,0x33,0x66,0x04},{0x33,0x33,0x66,0x04},{0x66,0x33,0x66,0x04},
{0x99,0x33,0x66,0x04},{0xcc,0x33,0x66,0x04},{0xff,0x33,0x66,0x04},{0x00,0x66,0x66,0x04},
{0x33,0x66,0x66,0x04},{0x66,0x66,0x66,0x04},{0x99,0x66,0x66,0x04},{0xcc,0x66,0x66,0x04},
//7
{0x00,0x99,0x66,0x04},{0x33,0x99,0x66,0x04},{0x66,0x99,0x66,0x04},{0x99,0x99,0x66,0x04},
{0xcc,0x99,0x66,0x04},{0xff,0x99,0x66,0x04},{0x00,0xcc,0x66,0x04},{0x33,0xcc,0x66,0x04},
{0x99,0xcc,0x66,0x04},{0xcc,0xcc,0x66,0x04},{0xff,0xcc,0x66,0x04},{0x00,0xff,0x66,0x04},
{0x33,0xff,0x66,0x04},{0x99,0xff,0x66,0x04},{0xcc,0xff,0x66,0x04},{0xff,0x00,0xcc,0x04},
//8
{0xcc,0x00,0xff,0x04},{0x00,0x99,0x99,0x04},{0x99,0x33,0x99,0x04},{0x99,0x00,0x99,0x04},
{0xcc,0x00,0x99,0x04},{0x00,0x00,0x99,0x04},{0x33,0x33,0x99,0x04},{0x66,0x00,0x99,0x04},
{0xcc,0x33,0x99,0x04},{0xff,0x00,0x99,0x04},{0x00,0x66,0x99,0x04},{0x33,0x66,0x99,0x04},
{0x66,0x33,0x99,0x04},{0x99,0x66,0x99,0x04},{0xcc,0x66,0x99,0x04},{0xff,0x33,0x99,0x04},
//9
{0x33,0x99,0x99,0x04},{0x66,0x99,0x99,0x04},{0x99,0x99,0x99,0x04},{0xcc,0x99,0x99,0x04},
{0xff,0x99,0x99,0x04},{0x00,0xcc,0x99,0x04},{0x33,0xcc,0x99,0x04},{0x66,0xcc,0x66,0x04},
{0x99,0xcc,0x99,0x04},{0xcc,0xcc,0x99,0x04},{0xff,0xcc,0x99,0x04},{0x00,0xff,0x99,0x04},
{0x33,0xff,0x99,0x04},{0x66,0xcc,0x99,0x04},{0x99,0xff,0x99,0x04},{0xcc,0xff,0x99,0x04},
//a
{0xff,0xff,0x99,0x04},{0x00,0x00,0xcc,0x04},{0x33,0x00,0x99,0x04},{0x66,0x00,0xcc,0x04},
{0x99,0x00,0xcc,0x04},{0xcc,0x00,0xcc,0x04},{0x00,0x33,0x99,0x04},{0x33,0x33,0xcc,0x04},
{0x66,0x33,0xcc,0x04},{0x99,0x33,0xcc,0x04},{0xcc,0x33,0xcc,0x04},{0xff,0x33,0xcc,0x04},
{0x00,0x66,0xcc,0x04},{0x33,0x66,0xcc,0x04},{0x66,0x66,0x99,0x04},{0x99,0x66,0xcc,0x04},
//b
{0xcc,0x66,0xcc,0x04},{0xff,0x66,0x99,0x04},{0x00,0x99,0xcc,0x04},{0x33,0x99,0xcc,0x04},
{0x66,0x99,0xcc,0x04},{0x99,0x99,0xcc,0x04},{0xcc,0x99,0xcc,0x04},{0xff,0x99,0xcc,0x04},
{0x00,0xcc,0xcc,0x04},{0x33,0xcc,0xcc,0x04},{0x66,0xcc,0xcc,0x04},{0x99,0xcc,0xcc,0x04},
{0xcc,0xcc,0xcc,0x04},{0xff,0xcc,0xcc,0x04},{0x00,0xff,0xcc,0x04},{0x33,0xff,0xcc,0x04},
//c
{0x66,0xff,0x99,0x04},{0x99,0xff,0xcc,0x04},{0xcc,0xff,0xcc,0x04},{0xff,0xff,0xcc,0x04},
{0x33,0x00,0xcc,0x04},{0x66,0x00,0xff,0x04},{0x99,0x00,0xff,0x04},{0x00,0x33,0xcc,0x04},
{0x33,0x33,0xff,0x04},{0x66,0x33,0xff,0x04},{0x99,0x33,0xff,0x04},{0xcc,0x33,0xff,0x04},
{0xff,0x33,0xff,0x04},{0x00,0x66,0xff,0x04},{0x33,0x66,0xff,0x04},{0x66,0x66,0xcc,0x04},
//d
{0x99,0x66,0xff,0x04},{0xcc,0x66,0xff,0x04},{0xff,0x66,0xcc,0x04},{0x00,0x99,0xff,0x04},
{0x33,0x99,0xff,0x04},{0x66,0x99,0xff,0x04},{0x99,0x99,0xff,0x04},{0xcc,0x99,0xff,0x04},
{0xff,0x99,0xff,0x04},{0x00,0xcc,0xff,0x04},{0x33,0xcc,0xff,0x04},{0x66,0xcc,0xff,0x04},
{0x99,0xcc,0xff,0x04},{0xcc,0xcc,0xff,0x04},{0xff,0xcc,0xff,0x04},{0x33,0xff,0xff,0x04},
//e
{0x66,0xff,0xcc,0x04},{0x99,0xff,0xff,0x04},{0xcc,0xff,0xff,0x04},{0xff,0x66,0x66,0x04},
{0x66,0xff,0x66,0x04},{0xff,0xff,0x66,0x04},{0x66,0x66,0xff,0x04},{0xff,0x66,0xff,0x04},
{0x66,0xff,0xff,0x04},{0xA5,0x00,0x21,0x04},{0x5f,0x5f,0x5f,0x04},{0x77,0x77,0x77,0x04},
{0x86,0x86,0x86,0x04},{0x96,0x96,0x96,0x04},{0xcb,0xcb,0xcb,0x04},{0xb2,0xb2,0xb2,0x04},
//f
{0xd7,0xd7,0xd7,0x04},{0xdd,0xdd,0xdd,0x04},{0xe3,0xe3,0xe3,0x04},{0xea,0xea,0xea,0x04},
{0xf1,0xf1,0xf1,0x04},{0xf8,0xf8,0xf8,0x04},{0xff,0xfb,0xf0,0x00},{0xa0,0xa0,0xa4,0x00},
{0x80,0x80,0x80,0x00},{0xff,0x00,0x00,0x00},{0x00,0xff,0x00,0x00},{0xff,0xff,0x00,0x00},
{0x00,0x00,0xff,0x00},{0xff,0x00,0xff,0x00},{0x00,0xff,0xff,0x00},{0xff,0xff,0xff,0x00}
};
// ppalDefault is the pointer to the default palette info
// We lock the default palette down at creation and never unlock
// it so that multiple apps can access the default palette simultaneously.
PPALETTE ppalDefault = (PPALETTE) NULL;
PPALETTE gppalRGB = (PPALETTE) NULL;
// ppalDefaultSurface8bpp is the pointer to the default 8bpp surface palette.
// This is used for dynamic mode changes when converting a Device Dependent
// Bitmap, which has no color table, to a Device Indepdent Bitmap, which
// has a color table -- this is what we use for the color table.
// We lock the default palette down at creation and never unlock
// it so that multiple surface can access the default palette simultaneously.
PPALETTE ppalDefaultSurface8bpp = (PPALETTE) NULL;
// This is the global palette for the monochrome bitmaps.
HPALETTE hpalMono = (HPALETTE) 0;
PPALETTE ppalMono = (PPALETTE) NULL;
/******************************Public*Routine******************************\
* RGB_ERROR
*
* Returns a measure of error between two RGB entries.
*
* History:
* 14-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
inline ULONG RGB_ERROR(PALETTEENTRY palDst, PALETTEENTRY palSrc)
{
INT lTemp, lTemp1;
lTemp = ((INT) (UINT) (palDst.peRed)) -
((INT) (UINT) (palSrc.peRed));
lTemp1 = lTemp * lTemp;
lTemp = ((INT) (UINT) (palDst.peGreen)) -
((INT) (UINT) (palSrc.peGreen));
lTemp1 += lTemp * lTemp;
lTemp = ((INT) (UINT) (palDst.peBlue)) -
((INT) (UINT) (palSrc.peBlue));
lTemp1 += lTemp * lTemp;
return((ULONG) lTemp1);
}
/******************************Public*Routine******************************\
* BOOL XEPALOBJ::bSwap(ppalSrc)
*
* This is for swapping palettes, necesary for ResizePalette.
*
* History:
* Sun 21-Jun-1992 -by- Patrick Haluptzok [patrickh]
* Make it a Safe swap under MLOCK.
*
* Fri 18-Jan-1991 -by- Patrick Haluptzok [patrickh]
* Wrote it.
\**************************************************************************/
BOOL
XEPALOBJ::bSwap(
PPALETTE *pppalSrc,
ULONG cShareCountDst,
ULONG cShareCountSrc
)
{
PPALETTE ppalSrc = *pppalSrc;
BOOL bRet;
bRet = HmgSwapLockedHandleContents((HOBJ)ppal->hGet(),
cShareCountDst,
(HOBJ)ppalSrc->hGet(),
cShareCountSrc,
PAL_TYPE);
//
// swap user pointers to palette objects
//
if (bRet)
{
*pppalSrc = ppal;
ppal = ppalSrc;
}
return(bRet);
}
/******************************Public*Routine******************************\
* XEPALOBJ::ulBitfieldToRGB
*
* Converts an index into an RGB for Bitfield palettes.
*
* History:
* Tue 31-Mar-1992 -by- Patrick Haluptzok [patrickh]
* Does better mapping.
*
* 08-Nov-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
ULONG XEPALOBJ::ulBitfieldToRGB(ULONG ulIndex)
{
ASSERTGDI(bIsBitfields(), "Error ulBitfieldToRGB not bitfields");
ULONG ulRed = (ulIndex & flRed()) >> cRedRight();
if (cRedMiddle() < 8)
{
ulRed = ulRed << (8 - cRedMiddle());
ulRed = ulRed | (ulRed >> cRedMiddle());
}
ULONG ulGre = (ulIndex & flGre()) >> cGreRight();
if (cGreMiddle() < 8)
{
ulGre = ulGre << (8 - cGreMiddle());
ulGre = ulGre | (ulGre >> cGreMiddle());
}
ulGre = ulGre << 8;
ULONG ulBlu = (ulIndex & flBlu()) >> cBluRight();
if (cBluMiddle() < 8)
{
ulBlu = ulBlu << (8 - cBluMiddle());
ulBlu = ulBlu | (ulBlu >> cBluMiddle());
}
ulBlu = ulBlu << 16;
return(ulRed | ulBlu | ulGre);
}
/******************************Public*Routine******************************\
* XEPALOBJ::ulIndexToRGB
*
* Converts an index to an RGB for a palette.
*
* History:
* 05-Dec-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
ULONG XEPALOBJ::ulIndexToRGB(ULONG ulIndex)
{
if (bIsIndexed())
{
if (cEntries() > ulIndex)
ulIndex = (ulEntryGet(ulIndex) & 0xFFFFFF);
else
ulIndex = 0;
}
else if (bIsBitfields())
{
ulIndex = ulBitfieldToRGB(ulIndex);
}
else if (bIsBGR())
{
BGR_ULONG palOld;
PAL_ULONG palNew;
palOld.ul = ulIndex;
palNew.pal.peRed = palOld.rgb.rgbRed;
palNew.pal.peGreen = palOld.rgb.rgbGreen;
palNew.pal.peBlue = palOld.rgb.rgbBlue;
palNew.pal.peFlags = 0;
ulIndex = palNew.ul;
}
else
{
// 0 out the flags.
ASSERTGDI(bIsRGB(), "ERROR another type not accounted for\n");
ulIndex &= 0xFFFFFF;
}
return(ulIndex);
}
/******************************Public*Routine******************************\
* ParseBits
*
* This routine computes how much the left and right shifts are for
* PAL_BITFIELDS 16 and 32 bit masks.
*
* History:
* 09-Nov-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID ParseBits(FLONG flag, ULONG *pcRight, ULONG *pcLeft, ULONG *pcMiddle, ULONG cForColor)
{
ULONG ulRight = 0;
ULONG ulMiddle;
ASSERTGDI(flag != 0, "ERROR flag");
while((flag & 1) == 0)
{
flag >>= 1;
ulRight++;
}
ulMiddle = ulRight;
do
{
flag >>= 1;
ulMiddle++;
} while(flag & 1);
*pcMiddle = ulMiddle = ulMiddle - ulRight;
*pcRight = (ulMiddle > 8) ? (ulRight + ulMiddle - 8) : (ulRight);
*pcLeft = (ulMiddle > 8) ? (cForColor) : (cForColor + (8 - ulMiddle));
}
/******************************Public*Routine******************************\
* PALMEMOBJ::bCreatePalette
*
* Constructor for creating palettes.
*
* Returns: True for success, False for error.
*
* History:
* 18-Feb-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL
PALMEMOBJ::bCreatePalette(
ULONG iMode, // The mode the palette is.
ULONG cColors, // Number of RGB's if indexed palette.
ULONG *pulColors, // Pointer to RGB's if indexed.
FLONG flRedd, // Mask for Red if bitfields
FLONG flGreen, // Mask for Green if bitfields
FLONG flBlue, // Mask for Blue if bitfields
ULONG iType) // The type it will be, fixed, free, managed, DC.
{
ASSERTGDI(bKeep == FALSE, "ERROR bCreatePalette bKeep is not False");
ASSERTGDI(ppal == (PPALETTE) NULL, "ERROR bCreatePalette ppal is NULL");
PAL_ULONG palul;
BOOL bDataStatus = TRUE;
// This data may be coming accross the DDI from a newer driver or from a
// journal file or from a app, so we must validate everything, make sure
// only valid iType flags are set for the iMode.
// Validate the iMode, calculate the size needed into palul.
palul.ul = sizeof(PALETTE);
switch(iMode)
{
case PAL_BITFIELDS:
// Bitfields palette is always fixed, we ASSERT values that should
// be correct to detect bad code in testing, but still assign correct
// values so that corrupt journal files don't create bad palettes.
ASSERTGDI(iType & PAL_FIXED, "ERROR bCreatePalette PAL_BITFIELDS");
ASSERTGDI(cColors == 0, "ERROR GDI EngCreatePalette PAL_BITFIELDS");
iType = iType & (PAL_FIXED | PAL_HT | PAL_DC);
cColors = 0;
// We need to check these so we don't fault ourselves.
if ((flRedd == 0) || (flBlue == 0) || (flGreen == 0))
{
WARNING1("ERROR bCreatePalette 0 flags for PAL_BITFIELDS\n");
return(FALSE);
}
palul.ul += sizeof(P_BITFIELDS);
break;
case PAL_BGR:
case PAL_RGB:
case PAL_CMYK:
// RGB and CMYK palette is always fixed.
ASSERTGDI(iType & PAL_FIXED, "bCreatePalette PAL_RGB/PAL_CMYK: iType not PAL_FIXED");
ASSERTGDI((iType & ~(PAL_FIXED | PAL_DC | PAL_HT)) == 0, "bCreatePal PAL_RGB/PAL_CMYK: extra flags in iType ");
ASSERTGDI(cColors == 0, "bCreatePalette PAL_RGB/PAL_CMYK: cColors not 0");
iType = (iType & (PAL_DC | PAL_HT)) | PAL_FIXED;
cColors = 0;
if (iMode != PAL_CMYK)
{
if (iMode == PAL_RGB)
{
flRedd = 0x0000FF;
flGreen = 0x00FF00;
flBlue = 0xFF0000;
}
else if (iMode == PAL_BGR)
{
flRedd = 0xFF0000;
flGreen = 0x00FF00;
flBlue = 0x0000FF;
}
palul.ul += sizeof(P_BITFIELDS);
}
break;
case PAL_INDEXED:
palul.ul += (sizeof(PAL_ULONG) * cColors);
// ASSERT for valid flags to detect bad code, mask off invalid flags so in
// retail we work fine with journal files, bad drivers.
ASSERTGDI((iType & ~(PAL_MONOCHROME | PAL_DC | PAL_FREE | PAL_FIXED | PAL_MANAGED | PAL_HT)) == 0,
"ERROR bCreatePal PAL_INDEXED iType");
iType = iType & (PAL_MONOCHROME | PAL_DC | PAL_FREE | PAL_FIXED | PAL_MANAGED | PAL_HT);
if (cColors == 0)
{
RIP("ERROR PAL_INDEXED bCreatePalette cColors 0\n");
return(FALSE);
}
break;
default:
RIP("bCreatePalette theses modes are not supported at this time\n");
return(FALSE);
}
// Allocate the palette.
PPALETTE ppalTemp;
ppal = ppalTemp = (PPALETTE) ALLOCOBJ(palul.ul, PAL_TYPE, FALSE);
if (ppalTemp == (PPALETTE)NULL)
{
WARNING("bCreatePalette failed memory allocation\n");
return(FALSE);
}
//
// Initialize the palette.
//
ppalTemp->flPal = iMode | iType;
ppalTemp->cEntries = cColors;
ppalTemp->ulTime = ulGetNewUniqueness(ulXlatePalUnique);
ppalTemp->hdcHead = (HDC) 0;
ppalTemp->hSelected.ppal = (PPALETTE) NULL;
ppalTemp->cRefRegular = 0;
ppalTemp->cRefhpal = 0;
ppalTemp->ptransFore = NULL;
ppalTemp->ptransCurrent = NULL;
ppalTemp->ptransOld = NULL;
ppalTemp->ulRGBTime = 0;
ppalTemp->pRGBXlate = NULL;
ppalTemp->ppalColor = ppalTemp;
ppalTemp->apalColor = &ppalTemp->apalColorTable[0];
switch(iMode)
{
case PAL_BITFIELDS:
case PAL_RGB:
case PAL_BGR:
{
// It won't kill us if any of these flags are 0, but it is
// definitely an error on someones behalf.
ASSERTGDI(flRedd != 0, "ERROR flGre");
ASSERTGDI(flGreen != 0, "ERROR flGre");
ASSERTGDI(flBlue != 0, "ERROR flBlu");
// Save away the Masks
flRed(flRedd);
flGre(flGreen);
flBlu(flBlue);
if ((flRedd == 0x0000ff) &&
(flGreen == 0x00ff00) &&
(flBlue == 0xff0000))
{
ppalTemp->flPal |= PAL_RGB;
}
else if ((flRedd == 0xf800) &&
(flGreen == 0x07e0) &&
(flBlue == 0x001f))
{
ppalTemp->flPal |= PAL_RGB16_565;
}
else if ((flRedd == 0x7c00) &&
(flGreen == 0x03e0) &&
(flBlue == 0x001f))
{
ppalTemp->flPal |= PAL_RGB16_555;
}
// Let ParseBits calculate the left and right shifts we need.
ParseBits(flRedd, &cRedRight(), &cRedLeft(), &cRedMiddle(), 0);
ParseBits(flGreen, &cGreRight(), &cGreLeft(), &cGreMiddle(), 8);
ParseBits(flBlue, &cBluRight(), &cBluLeft(), &cBluMiddle(), 16);
}
break;
case PAL_INDEXED:
{
UINT uiTemp;
PAL_ULONG *ppalstruc = apalColorGet();
if (pulColors != (PULONG) NULL)
{
//
// Copy the palette values in.
// Make sure only valid entries are copied.
//
__try
{
for (uiTemp = 0; uiTemp < cColors; uiTemp++)
{
palul.ul = *(pulColors++);
(ppalstruc++)->pal = palul.pal;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// SetLastError(GetExceptionCode());
bDataStatus = FALSE;
}
}
else
{
// Initialize the palette with 0's.
for (uiTemp = 0; uiTemp < cColors; uiTemp++)
(ppalstruc++)->ul = 0;
}
}
} // switch
// Now that all the other appropriate fields have been computed, compute
// the call tables.
XEPALOBJ pal(ppalTemp);
pal.vComputeCallTables();
// Add it to the handle table.
if (bDataStatus)
{
if (HmgInsertObject(ppalTemp,
HMGR_MAKE_PUBLIC | HMGR_ALLOC_ALT_LOCK,
PAL_TYPE) != (HOBJ) 0)
{
return(TRUE);
}
WARNING("bCreatePalette failed HmgInsertObject\n");
}
else
{
WARNING("bCreatePalette failed Copying user data\n");
}
// Clean up the allocated memory.
FREEOBJ(ppalTemp, PAL_TYPE);
ppal = NULL;
return(FALSE);
}
PALETTEENTRY apalMono[2] =
{
{ 0, 0, 0, 0 },
{ 0xFF,0xFF,0xFF,0 }
};
PALETTEENTRY apal3BPP[8] =
{
{0, 0, 0, 0 },
{0, 0, 0xFF, 0 },
{0, 0xFF,0, 0 },
{0, 0xFF,0xFF, 0 },
{0xFF,0, 0, 0 },
{0xFF,0, 0xFF, 0 },
{0xFF,0xFF,0, 0 },
{0xFF,0xFF,0xFF, 0 }
};
PALETTEENTRY apalVGA[16] =
{
{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 },
{0x80,0x80,0x80, 0 },
{0xC0,0xC0,0xC0, 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 }
};
#define COLOR_SWAP_BC 0x01
#define COLOR_SWAP_AB 0x02
#define COLOR_SWAP_AC 0x04
/******************************Member*Function*****************************\
* PALMEMOBJ::bCreateHTPalette
*
* Constructor for creating halftone palettes.
*
* Returns: True for success, False for error.
*
* History:
* 04-Jun-1993 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL PALMEMOBJ::bCreateHTPalette(LONG iFormatHT, GDIINFO *pGdiInfo)
{
if ((iFormatHT == HT_FORMAT_32BPP) ||
(iFormatHT == HT_FORMAT_24BPP) ||
(iFormatHT == HT_FORMAT_16BPP)) {
// 32BPP halftone use lower 3 bytes as RGB, same as 24bpp, but with extra
// pad byte at end, the order can be any of PRIMARY_ORDER_xxx
ULONG ulPrimaryOrder = pGdiInfo->ulPrimaryOrder;
ULONG ulR;
ULONG ulG;
ULONG ulB;
ULONG ulTmp;
if (iFormatHT == HT_FORMAT_16BPP) {
//
// 16BPP_555 for now, we should also do 16bpp_565
ulR = 0x00007c00;
ulG = 0x000003e0;
ulB = 0x0000001f;
} else {
ulR = 0x00FF0000;
ulG = 0x0000FF00;
ulB = 0x000000FF;
}
if (ulPrimaryOrder & COLOR_SWAP_BC) {
ulTmp = ulG;
ulG = ulB;
ulB = ulTmp;
}
if (ulPrimaryOrder & COLOR_SWAP_AB) {
ulTmp = ulR;
ulR = ulG;
ulG = ulTmp;
} else if (ulPrimaryOrder & COLOR_SWAP_AC) {
ulTmp = ulR;
ulR = ulB;
ulB = ulTmp;
}
if (!bCreatePalette(PAL_BITFIELDS, 0, (PULONG)NULL,
ulR, ulG, ulB, PAL_FIXED|PAL_HT)) {
return(FALSE);
}
#if 0
} else if (iFormatHT == HT_FORMAT_24BPP) {
// 24BPP halftone always does BGR
if (!bCreatePalette(PAL_BGR, 0, (PULONG)NULL,
0x0,0x0,0x0,PAL_FIXED|PAL_HT))
{
return(FALSE);
}
} else if (iFormatHT == HT_FORMAT_16BPP) {
// 16BPP halftone always does 555 for red, green, and blue.
if (!bCreatePalette(PAL_BITFIELDS, 0, (PULONG)NULL,
0x7c00,0x3e0,0x1f,PAL_FIXED|PAL_HT))
{
return(FALSE);
}
#endif
}
else
{
ULONG cEntries;
BOOL bAlloc = FALSE;
PPALETTEENTRY ppalentry;
PALETTEENTRY apalentry[8];
switch(iFormatHT)
{
case HT_FORMAT_1BPP:
cEntries = 2;
ppalentry = &apalMono[0];
if (pGdiInfo->flHTFlags & HT_FLAG_OUTPUT_CMY)
{
ppalentry = &apalentry[0];
*((ULONG *)&apalentry[0]) = 0x0FFFFFF;
*((ULONG *)&apalentry[1]) = 0;
}
break;
case HT_FORMAT_4BPP_IRGB:
cEntries = 16;
ppalentry = &apalVGA[0];
break;
default:
WARNING("unsupported halftone format, use default VGA format\n");
case HT_FORMAT_4BPP:
{
cEntries = 8;
ppalentry = &apalentry[0];
RtlCopyMemory(apalentry, apal3BPP, sizeof(PALETTEENTRY) * 8);
ULONG ulPrimaryOrder = pGdiInfo->ulPrimaryOrder;
BYTE jTmp;
int i;
if (ulPrimaryOrder & COLOR_SWAP_BC)
{
for (i = 1; i < 7; i++)
{
// Swap Green and Blue entries.
jTmp = apalentry[i].peGreen;
apalentry[i].peGreen = apalentry[i].peBlue;
apalentry[i].peBlue = jTmp;
}
}
if (ulPrimaryOrder & COLOR_SWAP_AB)
{
for (i = 1; i < 7; i++)
{
// Swap Red and Green.
jTmp = apalentry[i].peRed;
apalentry[i].peRed = apalentry[i].peGreen;
apalentry[i].peGreen = jTmp;
}
}
else if (ulPrimaryOrder & COLOR_SWAP_AC)
{
for (i = 1; i < 7; i++)
{
// Swap Red and Blue entries.
jTmp = apalentry[i].peRed;
apalentry[i].peRed = apalentry[i].peBlue;
apalentry[i].peBlue = jTmp;
}
}
if (pGdiInfo->flHTFlags & HT_FLAG_OUTPUT_CMY)
{
// Substrative device.
for (int i = 0; i < 8; i++)
*((ULONG *)&apalentry[i]) ^= 0x0FFFFFF;
}
}
break;
case HT_FORMAT_8BPP:
// Query the palette entries from Daniel's halftone library.
// Query the number of entries on the first call. Get the
// color entries on the second.
PCOLORINFO pci = &pGdiInfo->ciDevice;
cEntries = HT_Get8BPPMaskPalette((LPPALETTEENTRY)NULL,
(BOOL)(pGdiInfo->flHTFlags &
HT_FLAG_USE_8BPP_BITMASK),
(BYTE)((pGdiInfo->flHTFlags &
HT_FLAG_8BPP_CMY332_MASK)
>> 24),
(UDECI4)pci->RedGamma,
(UDECI4)pci->GreenGamma,
(UDECI4)pci->BlueGamma);
ppalentry = (PPALETTEENTRY)
PALLOCNOZ (sizeof(PALETTEENTRY) * cEntries, 'laPG');
if (ppalentry == (PPALETTEENTRY)NULL)
return(FALSE);
if (pGdiInfo->flHTFlags & HT_FLAG_INVERT_8BPP_BITMASK_IDX) {
HT_SET_BITMASKPAL2RGB(ppalentry);
} else {
ppalentry->peRed =
ppalentry->peGreen =
ppalentry->peBlue =
ppalentry->peFlags = 0;
}
HT_Get8BPPMaskPalette(ppalentry,
(BOOL)(pGdiInfo->flHTFlags &
HT_FLAG_USE_8BPP_BITMASK),
(BYTE)((pGdiInfo->flHTFlags &
HT_FLAG_8BPP_CMY332_MASK) >> 24),
(UDECI4)pci->RedGamma,
(UDECI4)pci->GreenGamma,
(UDECI4)pci->BlueGamma);
bAlloc = TRUE;
break;
}
if (!bCreatePalette(PAL_INDEXED, cEntries,
(PULONG)ppalentry,0,0,0,PAL_FREE|PAL_HT))
{
if (bAlloc)
VFREEMEM(ppalentry);
return(FALSE);
}
if (bAlloc)
{
// 8bpp case. halftone palette is not the same as the device palette.
VFREEMEM(ppalentry);
}
}
return(TRUE);
}
/******************************Public*Routine******************************\
* PALMEMOBJ destructor
*
* destructor for palette memory objects
*
* History:
* 07-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
PALMEMOBJ::~PALMEMOBJ()
{
PVOID pvRemove;
if (ppal != (PPALETTE) NULL)
{
if (bKeep)
{
DEC_SHARE_REF_CNT(ppal);
}
else
{
if (ppal != ppalColor())
{
//
// Remove a reference to the palette who owns the color
// table.
//
XEPALOBJ palColor(ppalColor());
palColor.vUnrefPalette();
}
if (ppal->pRGBXlate != NULL)
{
if (ppal->pRGBXlate != gpRGBXlate)
VFREEMEM(ppal->pRGBXlate);
ppal->pRGBXlate = NULL;
}
pvRemove = HmgRemoveObject((HOBJ)ppal->hGet(), 0, 1, TRUE, PAL_TYPE);
ASSERTGDI(pvRemove != NULL, "Remove failed. Havoc will result.");
FREEOBJ(ppal,PAL_TYPE);
}
ppal = (PPALETTE) NULL; // prevent ~PALOBJ from doing anything
}
}
/******************************Public*Routine******************************\
* ulGetNearestFromPalentryNoExactMatchFirst
*
* Given a palette entry finds the index of the closest matching entry.
*
* History:
* 02-Sep-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
*
* 16-Jan-1993 -by- Michael Abrash [mikeab]
* Checked for exact match first.
\**************************************************************************/
ULONG XEPALOBJ::ulGetNearestFromPalentryNoExactMatchFirst(
CONST PALETTEENTRY palentry)
{
if (!bIsIndexed())
{
return(ulGetMatchFromPalentry(palentry));
}
//
// We should only be called when there wouldn't be an exact match.
// We don't need to check BGR, RGB, bitfields, or explicit
// index, because those always produce an exact match.
// We assume the palette is non-explicitly indexed at this point.
//
ASSERTGDI(bIsIndexed(), "ERROR ulGetNearestFromPalentry not indexed");
ASSERTGDI(cEntries() != 0, "ERROR ulGetNearestFromPalentry cEntries is 0");
PALETTEENTRY *ppalTemp, *ppalMax, *ppalBase;
PALETTEENTRY *ppalBest;
if (ppal == ppalDefault)
{
ppalTemp = &aPalDefaultVGA[0].pal;
}
else
{
ppalTemp = &ppal->apalColor[0].pal;
}
//
// last palette entry.
//
ppalBase = ppalTemp;
ppalMax = ppalTemp + cEntries();
#if defined(_X86_)
ULONG ulRed = palentry.peRed;
ULONG ulGre = palentry.peGreen;
ULONG ulBlu = palentry.peBlue;
_asm
{
;eax is a work buffer
mov ebx, ulBlu
mov ecx,ppalTemp
mov edx,MAX_PAL_ERROR
mov esi,ppalMax
;edi is used to accum ulErrTemp
jmp Begin_Loop
align 16
Check_For_Done:
add ecx, 4
cmp ecx, esi
jz short Done
Begin_Loop:
mov edi, edx // Put best error so far in
movzx eax, BYTE PTR [ecx+2] // Get the blue byte from log pal
sub eax, ebx // Subtract out the blue component
sub edi, DWORD PTR [aArrayOfSquares+1020+eax*4] // Sub the square of the
// the red diff from the best so far
jbe short Check_For_Done // If it's 0 or below jump to done
movzx eax, BYTE PTR [ecx+1] // Get green byte from log pal
sub eax, ulGre // Subtract out the green component
sub edi, DWORD PTR [aArrayOfSquares+1020+eax*4] // Sub the square of the
// blue diff with the best so far.
jbe short Check_For_Done // If it's 0 or below jump to done
movzx eax, BYTE PTR [ecx] // Put red byte from log pal
sub eax, ulRed // Subtract out red component
sub edi, DWORD PTR [aArrayOfSquares+1020+eax*4] // Sub square of diff
jbe short Check_For_Done // If it's 0 or below jump to done
// New_Best:
mov ppalBest, ecx // Remember our best entry so far
sub edx,edi // Subtract out what remains to
// get our new best error.
jnz Check_For_Done // If it's 0 error we are done.
Done:
}
#else
#if defined(_MIPS_)
ppalBest = ppalSearchNearestEntry(ppalTemp,
palentry,
cEntries(),
pArrayOfSquares);
#else
ULONG ulError; // The least error for ppalBest
ULONG ulErrTemp;
ulError = MAX_PAL_ERROR;
do
{
if ((ulErrTemp =
pArrayOfSquares[ppalTemp->peRed - palentry.peRed] +
pArrayOfSquares[ppalTemp->peGreen - palentry.peGreen] +
pArrayOfSquares[ppalTemp->peBlue - palentry.peBlue]) < ulError)
{
ppalBest = ppalTemp;
if ((ulError = ulErrTemp) == 0)
{
break;
}
}
} while (++ppalTemp < ppalMax);
#endif // #if defined(_MIPS_)
#endif // #if defined(_X86_)
ASSERTGDI( ((ULONG)(ppalBest - ppalBase) < cEntries()), "index too big ulGetNearestFromPalentry");
// Sundown safe truncation
return (ULONG)(ppalBest - ppalBase);
}
/******************************Public*Routine******************************\
* ulIndexedGetMatchFromPalentry
*
* Given a PALETTEENTRY, finds the index of the matching entry in the
* specified palette, or returns 0xFFFFFFFF if there's no exact match.
*
* Note: This function does not use any semaphoring, nor does it expect the
* calling code to have done so. Palettes belong to DCs, and DCs are unique
* on a per-process basis; therefore, the only risk is that a multithreaded
* app acting on a palette-managed DC (because non-palette-managed palettes
* can never change) might have one thread change the palette while another
* thread is creating a brush or doing something similar that reads the
* palette. In that case, the app's in trouble anyway, because unless it
* does its own synchronization (and if it does, there's no issue here at all),
* then it can't be sure which palette will be in effect for the brush, and
* it would get indeterminate results even if we did protect the palette
* while we did this.
*
* History:
* Sun 27-Dec-1992 -by- Michael Abrash [mikeab]
* Wrote it.
\**************************************************************************/
ULONG FASTCALL ulIndexedGetMatchFromPalentry(PALETTE* ppal, ULONG ulRGB)
{
ULONG ulIndex;
PAL_ULONG palentryTemp, *ppalTemp, *ppalMax;
XEPALOBJ pal(ppal);
//
// make a copy we can access as a ULONG
//
palentryTemp.ul = ulRGB;
ASSERTGDI(pal.cEntries() != 0, "ERROR ulGetNearestFromPalentry cEntries==0");
if (palentryTemp.pal.peFlags == PC_EXPLICIT)
{
//
// This is an explicit index, so we can just use it directly.
// Explicit indices are limited to 8 bits, so mask off high three bytes,
// then keep within the number of palette entries, if necessary
//
ulIndex = palentryTemp.ul & 0x000000FF;
if (ulIndex >= pal.cEntries())
{
ulIndex = ulIndex % pal.cEntries();
}
return(ulIndex);
}
//
// We only care about the RGB fields from now on
//
palentryTemp.ul &= 0x00FFFFFF;
//
// Scan through the palette until we either find an exact match or have
// rejected all the palette entries
//
ppalTemp = pal.apalColorGet(); // point to the first palette entry
ppalMax = ppalTemp + pal.cEntries(); // last palette entry
while (ppalTemp != ppalMax)
{
//
// Does the current palette entry match the color we're searching for?
//
if ((ppalTemp->ul & 0x00FFFFFF) == palentryTemp.ul)
{
//
// Yes, we've found an exact match.
//
goto ExactMatch;
}
ppalTemp++;
}
//
// We didn't find an exact match.
//
return(0xFFFFFFFF);
//
// We've found an exact match.
//
ExactMatch:
//Sundown safe truncation
return(ULONG)(ppalTemp - pal.apalColorGet());
}
/******************************Public*Routine******************************\
* ulIndexedGetNearestFromPalentry
*
* For an indexed palette, finds the index of the matching entry in the
* specified palette by first doing an exact search, then doing a nearest
* search.
*
* Note that this routine isn't in-line because it is sometimes the target
* of indirect calls.
\**************************************************************************/
ULONG FASTCALL ulIndexedGetNearestFromPalentry(PALETTE* ppal, ULONG ulRGB)
{
ULONG ul = ulIndexedGetMatchFromPalentry(ppal, ulRGB);
if (ul == 0xffffffff)
{
XEPALOBJ pal(ppal);
ul = pal.ulGetNearestFromPalentryNoExactMatchFirst(*((PALETTEENTRY*) &ulRGB));
}
return(ul);
}
/******************************Public*Routine******************************\
* ulRGBToBitfield
*
* Converts an RGB into an index for Bitfield palettes.
*
* History:
* 08-Nov-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
ULONG FASTCALL ulRGBToBitfield(PALETTE* ppal, ULONG ulRGB)
{
XEPALOBJ pal(ppal);
ASSERTGDI(pal.bIsBitfields(), "Error ulRGBToBitfield not bitfields");
return((((ulRGB >> pal.cRedLeft()) << pal.cRedRight()) & pal.flRed()) |
(((ulRGB >> pal.cGreLeft()) << pal.cGreRight()) & pal.flGre()) |
(((ulRGB >> pal.cBluLeft()) << pal.cBluRight()) & pal.flBlu()));
}
/******************************Public*Routine******************************\
* ulRGBTo565
*
* Converts an RGB into an index for 5-6-5 bitfield palettes.
\**************************************************************************/
ULONG FASTCALL ulRGBTo565(PALETTE* ppal, ULONG ulRGB)
{
ASSERTGDI((((XEPALOBJ) ppal).bIsBitfields()) &&
(((XEPALOBJ) ppal).flRed() == 0xf800) &&
(((XEPALOBJ) ppal).flGre() == 0x07e0) &&
(((XEPALOBJ) ppal).flBlu() == 0x001f), "Error not 5-6-5");
return(((ulRGB >> 19) & 0x001f) |
((ulRGB >> 5) & 0x07e0) |
((ulRGB << 8) & 0xf800));
}
/******************************Public*Routine******************************\
* ulRGBTo555
*
* Converts an RGB into an index for 5-5-5 bitfield palettes.
\**************************************************************************/
ULONG FASTCALL ulRGBTo555(PALETTE* ppal, ULONG ulRGB)
{
ASSERTGDI((((XEPALOBJ) ppal).bIsBitfields()) &&
(((XEPALOBJ) ppal).flRed() == 0x7c00) &&
(((XEPALOBJ) ppal).flGre() == 0x03e0) &&
(((XEPALOBJ) ppal).flBlu() == 0x001f), "Error not 5-5-5");
return(((ulRGB >> 19) & 0x001f) |
((ulRGB >> 6) & 0x03e0) |
((ulRGB << 7) & 0x7c00));
}
/******************************Public*Routine******************************\
* ulRGBToBGR
*
* Converts an RGB into an index for BGR palettes.
\**************************************************************************/
ULONG FASTCALL ulRGBToBGR(PALETTE* ppal, ULONG ulRGB)
{
ASSERTGDI(((XEPALOBJ) ppal).bIsBGR(), "Error not BGR");
return(((ulRGB & 0x0000ff) << 16) |
((ulRGB & 0x00ff00)) |
((ulRGB & 0xff0000) >> 16));
}
/******************************Public*Routine******************************\
* ulRGBToRGB
*
* Converts an RGB into an index for RGB palettes.
\**************************************************************************/
ULONG FASTCALL ulRGBToRGB(PALETTE* ppal, ULONG ulRGB)
{
ASSERTGDI(((XEPALOBJ) ppal).bIsRGB(), "Error not RGB");
return(ulRGB & 0xffffff);
}
/******************************Public*Routine******************************\
* ulRawToRaw
*
* No Converts, just pass through original data
\**************************************************************************/
ULONG FASTCALL ulRawToRaw(PALETTE* ppal, ULONG ulRGB)
{
UNREFERENCED_PARAMETER(ppal);
return(ulRGB);
}
/******************************Public*Routine******************************\
* vComputeCallTables
*
* Updates the pfnGetMatchFromPalentry and pfnGetNearestFromPalentry
* function pointers to reflect the current palette settings.
\**************************************************************************/
VOID XEPALOBJ::vComputeCallTables()
{
PFN_GetFromPalentry pfnGetMatchFromPalentry;
PFN_GetFromPalentry pfnGetNearestFromPalentry;
if (bIsIndexed())
{
pfnGetMatchFromPalentry = ulIndexedGetMatchFromPalentry;
pfnGetNearestFromPalentry = ulIndexedGetNearestFromPalentry;
}
else
{
if (bIsBitfields())
{
if ((flBlu() == 0x001f) &&
(flGre() == 0x07e0) &&
(flRed() == 0xf800))
{
pfnGetMatchFromPalentry = ulRGBTo565;
}
else if ((flBlu() == 0x001f) &&
(flGre() == 0x03e0) &&
(flRed() == 0x7c00))
{
pfnGetMatchFromPalentry = ulRGBTo555;
}
else
{
pfnGetMatchFromPalentry = ulRGBToBitfield;
}
}
else if (bIsBGR())
{
pfnGetMatchFromPalentry = ulRGBToBGR;
}
else if (bIsCMYK())
{
//
// In CMYK color case, Palette index == CMYK color data.
//
pfnGetMatchFromPalentry = ulRawToRaw;
}
else
{
ASSERTGDI(bIsRGB(), "ERROR invalid type in palette");
pfnGetMatchFromPalentry = ulRGBToRGB;
}
//
// For non-indexed palettes, an exact match can always be found,
// so GetMatch and GetNearest can be the same function:
//
pfnGetNearestFromPalentry = pfnGetMatchFromPalentry;
}
ppal->pfnGetMatchFromPalentry = pfnGetMatchFromPalentry;
ppal->pfnGetNearestFromPalentry = pfnGetNearestFromPalentry;
}
/******************************Public*Routine******************************\
* XEPALOBJ::ulGetEntries
*
* This function copies the requested palette entries out.
*
* History:
* 18-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
extern "C" ULONG PALOBJ_cGetColors(
PALOBJ *ppo,
ULONG iStart,
ULONG cEntry,
ULONG *ppalentry
)
{
XEPALOBJ *ppal = (XEPALOBJ *)ppo;
//
// Get color data from PALOBJ
//
ULONG ulRet = ppal->ulGetEntries(iStart, cEntry, (PPALETTEENTRY)ppalentry,FALSE);
//
// Correct GammaRamp if nessesary.
//
if (ppal->bNeedGammaCorrection())
{
//
// Correct color based on GammaRamp table
//
ppal->CorrectColors((PPALETTEENTRY)ppalentry,ulRet);
}
return (ulRet);
}
ULONG XEPALOBJ::ulGetEntries(ULONG iStart, ULONG cEntry,
PPALETTEENTRY ppalentry, BOOL bZeroFlags)
{
// See if the number of entries in the palette is being requested.
if (ppalentry == (PPALETTEENTRY) NULL)
return(ppal->cEntries);
// Make sure the start index is valid, this checks RGB case also.
if (iStart >= ppal->cEntries)
return(0);
// Make sure we don't ask for more than we have
if (cEntry > (ppal->cEntries - iStart))
cEntry = ppal->cEntries - iStart;
// Copy them to the buffer
PPALETTEENTRY ppalstruc = (PPALETTEENTRY) &(ppal->apalColor[iStart]);
RtlCopyMemory(ppalentry, ppalstruc, cEntry*sizeof(PALETTEENTRY));
if (bZeroFlags)
{
ppalstruc = ppalentry + cEntry;
while (ppalentry < ppalstruc)
{
ppalentry->peFlags = 0;
ppalentry++;
}
}
return(cEntry);
}
/******************************Public*Routine******************************\
* XEPALOBJ::ulSetEntries
*
* This function copies the requested palette entries into the palette
*
* History:
* 18-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
ULONG XEPALOBJ::ulSetEntries(ULONG iStart, ULONG cEntry, CONST PALETTEENTRY *ppalentry)
{
ASSERTGDI(bIsPalDC(), "ERROR: ulSetEntries called on non-DC palette");
// Make sure they aren't trying to change the default or halftone palette.
// Make sure they aren't trying to pass us NULL.
// Make sure the start index is valid, this checks the RGB case also.
if ((ppal == ppalDefault) ||
bIsHTPal() ||
(ppalentry == (PPALETTEENTRY) NULL) ||
(iStart >= ppal->cEntries))
{
return(0);
}
// Make sure we don't try to copy off the end of the buffer
if (iStart + cEntry > ppal->cEntries)
cEntry = ppal->cEntries - iStart;
// Let's not update the palette time if we don't have to.
if (cEntry == 0)
return(0);
// Copy the new values in
PPALETTEENTRY ppalstruc = (PPALETTEENTRY) &(ppal->apalColor[iStart]);
PBYTE pjFore = NULL;
PBYTE pjCurrent = NULL;
// Mark the foreground translate dirty so we get a new realization done
// in the next RealizePaletette.
if (ptransFore() != NULL)
{
ptransFore()->iUniq = 0;
pjFore = &(ptransFore()->ajVector[iStart]);
}
if (ptransCurrent() != NULL)
{
ptransCurrent()->iUniq = 0;
pjCurrent = &(ptransCurrent()->ajVector[iStart]);
}
// Hold the orginal values in temporary vars.
ULONG ulReturn = cEntry;
while(cEntry--)
{
*ppalstruc = *ppalentry;
if (pjFore)
{
*pjFore = 0;
pjFore++;
}
if (pjCurrent)
{
*pjCurrent = 0;
pjCurrent++;
}
ppalentry++;
ppalstruc++;
}
// Set in the new palette time.
vUpdateTime();
// Mark foreground translate and current translate invalid so they get rerealized.
return(ulReturn);
}
/******************************Public*Routine******************************\
* XEPALOBJ::vUnrefPalette()
*
* Palettes are referenced when put into a surface. If the reference count
* is one when vUnreference is called it mean the last surface using the
* palette is being deleted so the palette should be deleted. Otherwise the
* reference count should just be decremented.
*
* History:
* 09-Nov-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vUnrefPalette()
{
if (ppal != (PPALETTE) NULL)
{
ASSERTGDI(!bIsPalDC(), "ERROR should not be called on DC palette");
if (HmgRemoveObject((HOBJ)ppal->hGet(), 0, 1, FALSE, PAL_TYPE))
{
if (bIsPalManaged() && ppalOriginal())
{
//
// We have to delete the original palette.
//
PVOID ppalOld = HmgRemoveObject((HOBJ)ppalOriginal()->hGet(), 0, 0, FALSE, PAL_TYPE);
ASSERTGDI(ppalOld != NULL, "ERROR it failed to remove object handle");
FREEOBJ(ppalOriginal(), PAL_TYPE);
}
if (ppal != ppalColor())
{
//
// Remove a reference to the palette who owns the color
// table.
//
XEPALOBJ palColor(ppalColor());
palColor.vUnrefPalette();
}
if (ppal->pRGBXlate != NULL)
{
if (ppal->pRGBXlate != gpRGBXlate)
VFREEMEM(ppal->pRGBXlate);
ppal->pRGBXlate = NULL;
}
ASSERTGDI(ppal != ppalMono, "ERROR mono palette went to 0");
FREEOBJ(ppal, PAL_TYPE);
}
else
{
//
// Just decrement the reference count.
//
DEC_SHARE_REF_CNT(ppal);
}
ppal = (PPALETTE) NULL;
}
}
/******************************Public*Routine******************************\
* bDeletePalette
*
* This attempts to delete a palette. It will fail if the palette
* is currently selected into more than one DC or is busy.
*
* History:
* Wed 04-Sep-1991 -by- Patrick Haluptzok [patrickh]
* Simplified and renamed.
*
* 27-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL bDeletePalette(HPAL hpal, BOOL bCleanup, CLEANUPTYPE cutype)
{
//
// Need to grab the palette semaphore so this guy can't get selected in
// anymore. Only once we know he isn't selected anywhere and we hold the
// semaphore so he can't be selected anywhere can we delete the translates.
// This is because to access the translates you must either hold the palette
// semaphore or have a lock on a DC that the palette is selected in.
// Grab the semaphore so ResizePalette doesn't change the palette out from
// under you.
//
SEMOBJ semo(ghsemPalette);
EPALOBJ palobj((HPALETTE)hpal);
return(palobj.bDeletePalette(bCleanup,cutype));
}
/******************************Public*Routine******************************\
* XEPALOBJ::bDeletePalette()
*
* This attempts to delete a palette. It will fail if the palette
* is currently selected into more than one DC or is busy.
*
* History:
* 27-Nov-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL XEPALOBJ::bDeletePalette(BOOL bCleanup, CLEANUPTYPE cutype)
{
BOOL bReturn = TRUE;
if ((ppal != ppalDefault) &&
(ppal != (PPALETTE) NULL) &&
(ppal != ppalMono))
{
if (ppal->pRGBXlate != NULL)
{
if (ppal->pRGBXlate != gpRGBXlate)
VFREEMEM(ppal->pRGBXlate);
ppal->pRGBXlate = NULL;
}
if (bIsPalDC())
{
if (ppal->cRefhpal != 0)
{
WARNING("bDelete failed palette is selected into a DC\n");
return(FALSE);
}
vMakeNoXlate();
}
ASSERTGDI(HmgQueryLock((HOBJ)ppal->hGet()) == 0, "bDeletePalette cLock != 0");
//
// Need to make sure we are not being used in a palette API somewhere.
//
if (HmgRemoveObject((HOBJ)ppal->hGet(), 0, 1, FALSE, PAL_TYPE))
{
if (cutype != CLEANUP_SESSION)
{
if (bIsPalManaged() && ppalOriginal())
{
//
// We have to delete the original palette.
//
PVOID ppalOld = HmgRemoveObject((HOBJ)ppalOriginal()->hGet(), 0, 0, FALSE, PAL_TYPE);
ASSERTGDI(ppalOld != NULL, "ERROR it failed to remove object handle");
FREEOBJ(ppalOriginal(), PAL_TYPE);
}
if (ppal != ppalColor())
{
//
// Remove a reference to the palette who owns the color
// table.
//
XEPALOBJ palColor(ppalColor());
palColor.vUnrefPalette();
}
}
FREEOBJ(ppal, PAL_TYPE);
ppal = (PPALETTE) NULL;
}
else
{
//
// force deletion of palette at cleanup time
//
if (bCleanup)
{
WARNING ("DRIVER is leaking palette, we force cleanup here\n");
if (cutype != CLEANUP_SESSION)
{
//
// HmgFree will call FREEOBJ after the handle manager entry is freed
//
if (bIsPalManaged() && ppalOriginal())
{
//
// We have to delete the original palette.
//
PVOID ppalOld = HmgRemoveObject((HOBJ)ppalOriginal()->hGet(), 0, 0, FALSE, PAL_TYPE);
ASSERTGDI(ppalOld != NULL, "ERROR it failed to remove object handle");
FREEOBJ(ppalOriginal(), PAL_TYPE);
}
if (ppal != ppalColor())
{
//
// Remove a reference to the palette who owns the color
// table.
//
XEPALOBJ palColor(ppalColor());
palColor.vUnrefPalette();
}
}
HmgFree((HOBJ)ppal->hGet());
ppal = (PPALETTE) NULL;
bReturn = TRUE;
}
else
{
#if DBG
DbgPrint("The count is %lu\n", HmgQueryLock((HOBJ)ppal->hGet()));
#endif
WARNING("App error, trying to delete palette that's in use\n");
bReturn = FALSE;
}
}
}
return(bReturn);
}
/******************************Public*Routine******************************\
* XEPALOBJ::vCopy_rgbquad
*
* copies in rgbquad values, used by CreateDIBitmap
*
* History:
* 10-Dec-1990 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vCopy_rgbquad(RGBQUAD *prgbquad, ULONG iStart, ULONG cEntries)
{
ASSERTGDI(iStart < ppal->cEntries,"vCopy_rgbquad iStart > cEntries\n");
PPALETTEENTRY ppalstruc = (PPALETTEENTRY) &ppal->apalColor[iStart];
if (iStart + cEntries > ppal->cEntries)
cEntries = ppal->cEntries - iStart;
#if defined(_X86_)
_asm
{
mov ecx, cEntries
mov esi, prgbquad
mov edi, ppalstruc
shr ecx, 1
jz Done_Unroll
Begin_Loop:
mov eax, [esi]
mov edx, [esi+4]
bswap eax
bswap edx
shr eax, 8
shr edx, 8
mov [edi], eax
mov [edi+4], edx
add esi, 8
add edi, 8
dec ecx
jnz Begin_Loop
Done_Unroll:
test cEntries, 1
jz Done
mov eax, [esi]
bswap eax
shr eax, 8
mov [edi], eax
Done:
}
#else
while(cEntries--)
{
ppalstruc->peFlags = 0;
ppalstruc->peBlue = prgbquad->rgbBlue;
ppalstruc->peRed = prgbquad->rgbRed;
ppalstruc->peGreen = prgbquad->rgbGreen;
ppalstruc++;
prgbquad++;
}
#endif
vUpdateTime();
}
/******************************Public*Routine******************************\
* XEPALOBJ::vCopy_cmykquad
*
* copies in cmykquad values, used by CreateDIBitmap
*
* History:
* 24-Mar-1997 -by- Hideyuki Nagase hideyukn
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vCopy_cmykquad(ULONG *pcmykquad, ULONG iStart, ULONG cEntries)
{
ASSERTGDI(iStart < ppal->cEntries,"vCopy_cmykquad iStart > cEntries\n");
PULONG ppalCMYK = (PULONG) &ppal->apalColor[iStart];
if (iStart + cEntries > ppal->cEntries)
cEntries = ppal->cEntries - iStart;
RtlCopyMemory(ppalCMYK,pcmykquad,cEntries*sizeof(ULONG));
vUpdateTime();
}
/******************************Public*Routine******************************\
* BOOL XEPALOBJ::bSet_hdev
*
* Attempts to set the hdev owner of a DC palette.
*
* Returns: True if successful, False for failure.
*
* This operation must be protected by the palette semaphore.
*
* History:
* 08-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
BOOL XEPALOBJ::bSet_hdev(HDEV hdevNew)
{
ASSERTGDI(ppal->flPal & PAL_DC, "bSet_() passed invalid palette type\n");
ASSERTGDI(hdevNew != (HDEV) 0, "ERROR hdev is 0");
if (hdev() != hdevNew)
{
if (ppal->cRefhpal == 0)
{
// It is not selected into a DC yet so it is safe to delete xlates
// without holding the DEVLOCK for the device. because no output
// can be occuring now.
vMakeNoXlate();
hdev(hdevNew);
}
else
return(FALSE);
}
return(TRUE);
}
/******************************Member*Function*****************************\
* BOOL XEPALOBJ::bEqualEntries
*
* Return TRUE if the given two palettes have same color entries.
*
* History:
* 04-Jun-1993 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL XEPALOBJ::bEqualEntries(XEPALOBJ pal)
{
if (!pal.bValid())
return(FALSE);
if (cEntries() == pal.cEntries())
{
if (flPal() & PAL_INDEXED)
{
if (!(pal.flPal() & PAL_INDEXED))
return(FALSE);
ULONG ulTemp, ulSource, ulDest;
ULONG cComp = cEntries();
for (ulTemp = 0; ulTemp < cComp; ulTemp++)
{
ulSource = apalColorGet()[ulTemp].ul;
ulDest = pal.apalColorGet()[ulTemp].ul;
if ((ulSource ^ ulDest) << 8)
{
return(FALSE);
}
}
return(TRUE);
}
else if (flPal() & PAL_BITFIELDS)
{
if (!(pal.flPal() & PAL_BITFIELDS))
return(FALSE);
return(!memcmp(apalColorGet(), pal.apalColorGet(),
sizeof(PALETTEENTRY) * 3));
}
else if (flPal() & PAL_RGB)
{
if (pal.flPal() & PAL_RGB)
return(TRUE);
else
return(FALSE);
}
else if (flPal() & PAL_BGR)
{
if (pal.flPal() & PAL_BGR)
return(TRUE);
else
return(FALSE);
}
else
RIP("There is another type we didn't know about");
}
return(FALSE);
}
/******************************Public*Routine******************************\
* bInitPALOBJ
*
* Initialize the PALOBJ component
*
* History:
* 10-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
extern "C" BOOL bInitPALOBJ()
{
INT iTemp;
pArrayOfSquares = &(aArrayOfSquares[255]);
for (iTemp = 0; iTemp < 256; iTemp++)
{
pArrayOfSquares[iTemp] =
pArrayOfSquares[-(iTemp)] = iTemp * iTemp;
}
if ((ghsemPalette = GreCreateSemaphore()) == NULL)
return(FALSE);
// Now initialize 20 color default DC palette
if (!bSetStockObject(GreCreatePalette((LOGPALETTE *) &logDefaultPal),DEFAULT_PALETTE))
{
return(FALSE);
}
{
EPALOBJ palDefault((HPALETTE) STOCKOBJ_PAL);
ASSERTGDI(palDefault.bValid(), "ERROR invalid default palette");
palDefault.vSetPID(OBJECT_OWNER_PUBLIC);
ppalDefault = palDefault.ppalGet();
dclevelDefault.hpal = STOCKOBJ_PAL;
dclevelDefault.ppal = ppalDefault;
// Now initialize default surface palette for 8bpp displays
PALMEMOBJ palDefaultSurface8bpp;
if (!palDefaultSurface8bpp.bCreatePalette(PAL_INDEXED,
256,
NULL,
0,
0,
0,
PAL_FREE))
{
return(FALSE);
}
ppalDefaultSurface8bpp = palDefaultSurface8bpp.ppalGet();
// Copy the 20 default colours. The middle entries will be black
PALETTEENTRY palEntry;
ULONG ulReturn;
ULONG ulNumReserved = palDefault.cEntries() >> 1;
for (ulReturn = 0; ulReturn < ulNumReserved; ulReturn++)
{
palEntry = palDefault.palentryGet(ulReturn);
palDefaultSurface8bpp.palentrySet(ulReturn, palEntry);
}
ULONG ulCurrentPal = 256;
ULONG ulCurrentDef = 20;
for (ulReturn = 0; ulReturn < ulNumReserved; ulReturn++)
{
ulCurrentPal--;
ulCurrentDef--;
palEntry = palDefault.palentryGet(ulCurrentDef);
palDefaultSurface8bpp.palentrySet(ulCurrentPal, palEntry);
}
// Leave a reference count of 1 so that it never gets deleted
palDefaultSurface8bpp.ppalSet(NULL);
}
// Now initialize default monochrome surface palette.
PALMEMOBJ palMono;
if (!palMono.bCreatePalette(PAL_INDEXED, 2, gaulMono,
0, 0, 0, PAL_FIXED | PAL_MONOCHROME))
{
WARNING("GDI failed mono palette create\n");
return(FALSE);
}
palMono.vKeepIt();
hpalMono = palMono.hpal();
ppalMono = palMono.ppalGet();
//
// Now initialize default RGB palette for gradient fill source
//
PALMEMOBJ palRGB;
if (!palRGB.bCreatePalette(
PAL_BGR,
0,
NULL,
0,
0,
0,
PAL_FIXED))
{
WARNING("GDI failed RGB palette create\n");
return(FALSE);
}
gppalRGB = palRGB.ppalGet();
// Leave a reference count of 1 so that it never gets deleted
palRGB.ppalSet(NULL);
return(TRUE);
}
/******************************Public*Routine******************************\
* ULONG XEPALOBJ::ulAnimatePalette
*
* This function changes the requested palette entries in the palette.
*
* History:
* 16-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
ULONG XEPALOBJ::ulAnimatePalette(ULONG iStart, ULONG cEntry, CONST PALETTEENTRY *ppalSrc)
{
ASSERTGDI(bIsPalDC(), "ERROR this is not a DC palette");
// Make sure they aren't trying to change the default palette.
// Make sure they aren't trying to pass us NULL.
// Make sure the start index is valid, this checks the RGB case also.
if ((ppal == ppalDefault) ||
(ppalSrc == (PPALETTEENTRY) NULL) ||
(iStart >= ppal->cEntries))
{
return(0);
}
// Make sure we don't try to copy off the end of the buffer
if (iStart + cEntry > ppal->cEntries)
cEntry = ppal->cEntries - iStart;
// Let's not update the palette if we don't have to.
if (cEntry == 0)
return(0);
// Save the Original values
ULONG ulReturn = 0;
ULONG ulTemp = cEntry;
// Copy the new values in
PAL_ULONG *ppalLogical = (PAL_ULONG *) &(ppal->apalColor[iStart]);
PAL_ULONG palentry, palPhys;
TRANSLATE *ptransCurrent = NULL;
PBYTE pjCurrent = NULL;
XEPALOBJ palSurf;
// Grab the SEMOBJ so you can access the translates, and can look at cEntries.
{
SEMOBJ semo(ghsemPalette);
if (cRefhpal())
{
PDEVOBJ po(hdev());
ASSERTGDI(po.bValid(), "ERROR invalid pdev");
if (po.bIsPalManaged())
{
palSurf.ppalSet(po.ppalSurf());
ASSERTGDI(palSurf.bValid(), "ERROR GDI ulAnimatePalette dc");
ASSERTGDI(palSurf.bIsPalManaged(), "ERROR pdev palmanaged but not palette ???");
if (ppal->ptransCurrent != NULL)
{
ptransCurrent = ppal->ptransCurrent;
pjCurrent = &(ppal->ptransCurrent->ajVector[iStart]);
}
}
}
while(ulTemp--)
{
palentry.pal = *ppalSrc;
if (ppalLogical->pal.peFlags & PC_RESERVED)
{
ppalLogical->ul = palentry.ul;
ulReturn++;
if (pjCurrent != NULL)
{
palPhys.ul = palSurf.ulEntryGet((ULONG) *pjCurrent);
if (palPhys.pal.peFlags & PC_RESERVED)
{
palentry.pal.peFlags = palPhys.pal.peFlags;
palSurf.ulEntrySet(*pjCurrent, palentry.ul);
}
}
}
if (pjCurrent != NULL)
pjCurrent++;
ppalSrc++;
ppalLogical++;
}
// Release the palette semaphore, we are done accessing protected stuff.
}
// Don't set in a new time, Animate doesn't do that.
if (pjCurrent)
{
PDEVOBJ po(hdev());
// 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);
// Make sure we're still a palettized device -- a dynamic mode change
// may have occured between the time we released the palette semaphore
// and acquired the devlock.
if (po.bIsPalManaged())
{
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());
}
return(ulReturn);
}
/******************************Public*Routine******************************\
* VOID XEPALOBJ::vMakeNoXlate()
*
* deletes the pxlate if it exists
*
* History:
* 19-Jan-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vMakeNoXlate()
{
ASSERTGDI(bIsPalDC(), "ERROR trying to delete pxlate from non-dc palette");
// Caller should grab the DEVLOCK to ensure the engine
// isn't in the middle of blt before calling.
if (ppal->ptransOld)
{
if (ppal->ptransOld != ppal->ptransFore)
VFREEMEM(ppal->ptransOld);
ppal->ptransOld = NULL;
}
if (ppal->ptransCurrent)
{
if (ppal->ptransCurrent != ppal->ptransFore)
VFREEMEM(ppal->ptransCurrent);
ppal->ptransCurrent = NULL;
}
if (ppal->ptransFore)
{
VFREEMEM(ppal->ptransFore);
ppal->ptransFore = NULL;
}
}
/******************************Public*Routine******************************\
* vAddToList
*
* Add DC to linked list of DC's attached to palette. The MLOCKOBJ must be
* grabbed before calling this function.
*
* History:
* 16-Dec-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vAddToList(XDCOBJ& dco)
{
ASSERTGDI(dco.bLocked(), "ERROR 14939");
ASSERTGDI(bValid(), "ERROR dj945kd");
ASSERTGDI(bIsPalDC(), "ERROR 234343");
if (!bIsPalDefault())
{
// Well it's a new live hpal. Add the DC to it's linked list
// and inc it's cRef count.
vInc_cRef();
dco.pdc->hdcNext(hdcHead());
hdcHead(dco.hdc());
dco.pdc->hdcPrev((HDC) 0);
if (dco.pdc->hdcNext() != (HDC) 0)
{
MDCOBJA dcoNext(dco.pdc->hdcNext());
dcoNext.pdc->hdcPrev(dco.hdc());
}
}
else
{
dco.pdc->hdcNext((HDC) 0);
dco.pdc->hdcPrev((HDC) 0);
}
}
/******************************Public*Routine******************************\
* vRemoveFromList
*
* Remove DC from linked list of DC's. MLOCKOBJ must be grabbed before call.
*
* History:
* 16-Dec-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vRemoveFromList(XDCOBJ& dco)
{
ASSERTGDI(dco.bLocked(), "ERROR 1");
ASSERTGDI(bIsPalDC(), "ERROR 2");
// 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.
if (!bIsPalDefault())
{
// Remove this DC from the linked list.
if (dco.pdc->hdcNext() != (HDC) 0)
{
MDCOBJA dcoNext(dco.pdc->hdcNext());
dcoNext.pdc->hdcPrev(dco.pdc->hdcPrev());
}
if (dco.pdc->hdcPrev() == (HDC) 0)
{
// New head of hdc list for hpal
hdcHead(dco.pdc->hdcNext());
}
else
{
MDCOBJA dcoPrev(dco.pdc->hdcPrev());
dcoPrev.pdc->hdcNext(dco.pdc->hdcNext());
}
// Decrement the reference count correctly.
vDec_cRef();
}
dco.pdc->hdcPrev((HDC) 0);
dco.pdc->hdcNext((HDC) 0);
}
/******************************Public*Routine******************************\
* vFill_triples
*
* For GetDIBits we need to copy a palette out to triples.
*
* History:
* 08-May-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vFill_triples(
RGBTRIPLE *prgb, // array of quads to fill
ULONG iStart, // first index in palette to copy out
ULONG cEntry) // max # of entries to copy out
{
PALETTEENTRY palentry;
RGBTRIPLE rgbtrip;
cEntry = MIN((iStart + cEntry), cEntries());
ASSERTGDI(cEntries() != 0, "ERROR cEntries");
ASSERTGDI(!bIsBitfields(), "ERROR bIsBitfields");
ASSERTGDI(!bIsRGB(), "ERROR bIsRGB");
ASSERTGDI(!bIsBGR(), "ERROR bIsBGR");
while (iStart < cEntry)
{
palentry = palentryGet(iStart);
rgbtrip.rgbtRed = palentry.peRed;
rgbtrip.rgbtBlue = palentry.peBlue;
rgbtrip.rgbtGreen = palentry.peGreen;
*prgb++ = rgbtrip;
iStart++;
}
}
/******************************Public*Routine******************************\
* vFill_rgbquads
*
* For GetDIBits we need to copy a palette out to rgbquads
*
* History:
* 08-May-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vFill_rgbquads(
RGBQUAD *prgb, // array of quads to fill
ULONG iStart, // first index in palette to copy out
ULONG cEntry) // max # of entries to copy out
{
if (bIsBGR())
{
((PDWORD) prgb)[0] = 0x00FF0000;
((PDWORD) prgb)[1] = 0x0000FF00;
((PDWORD) prgb)[2] = 0x000000FF;
}
else if (bIsBitfields() && cEntry == 3)
{
((PDWORD) prgb)[0] = flRed();
((PDWORD) prgb)[1] = flGre();
((PDWORD) prgb)[2] = flBlu();
}
else if (bIsRGB())
{
((PDWORD) prgb)[0] = 0x000000FF;
((PDWORD) prgb)[1] = 0x0000FF00;
((PDWORD) prgb)[2] = 0x00FF0000;
}
else
{
PALETTEENTRY palentry;
RGBQUAD rgbquad;
cEntry = MIN((iStart + cEntry), cEntries());
while (iStart < cEntry)
{
palentry = palentryGet(iStart);
rgbquad.rgbRed = palentry.peRed;
rgbquad.rgbBlue = palentry.peBlue;
rgbquad.rgbGreen = palentry.peGreen;
rgbquad.rgbReserved = 0;
*prgb++ = rgbquad;
iStart++;
}
}
}
/******************************Public*Routine******************************\
* vGetEntriesFrom
*
* This is for the DIB_PAL_COLORS case of CreateDIBitmap.
* This uses the array of ushorts in bmiColors and the DC palette to
* initialize the surface palette. You need to create a palette that
* represents the essence of a DC palette. That means if DC palette
* has a PC_EXPLICIT in it, reach down into the surface palette for the
* palette entry.
*
* History:
* Thu 03-Feb-1994 -by- Patrick Haluptzok [patrickh]
* Chicago compatability, grab the colors out of the VGA palette if the
* system palette is not available.
*
* 09-May-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vGetEntriesFrom(XEPALOBJ palDC, XEPALOBJ palSurf, PUSHORT pusIndices, ULONG cEntry)
{
//
// We assume if the palette was invalid (which indicates it was a compatible
// bitmap on a palette managed device) then the caller has passed the
// PDEV surface palette instead which is valid.
//
ASSERTGDI(palDC.bValid(), "ERROR palDC not valid");
ASSERTGDI(palSurf.bValid(), "ERROR palSurf not valid");
ASSERTGDI(palDC.cEntries() != 0, "ERROR 0 entry palDC");
ASSERTGDI(cEntry <= cEntries(), "ERROR bGetEntriesFrom cEntry too big");
PAL_ULONG palentry;
ULONG cEntryDC;
ULONG cEntrySurf;
cEntryDC = palDC.cEntries();
//
// We need the PDEV palette for the screen if this is a compatible
// bitmap on a palette managed device which is indicated by have a
// NULL ppalSurf.
//
cEntrySurf = palSurf.bIsPalManaged() ? palSurf.cEntries() : 0;
while (cEntry--)
{
palentry.ul = (ULONG) pusIndices[cEntry];
if (palentry.ul >= cEntryDC)
palentry.ul = palentry.ul % cEntryDC;
palentry.pal = palDC.palentryGet(palentry.ul);
if (palentry.pal.peFlags == PC_EXPLICIT)
{
if (cEntrySurf)
{
// Grab the RGB out of the system palette.
palentry.ul = palentry.ul & 0x0000FFFF;
if (palentry.ul >= cEntrySurf)
palentry.ul = palentry.ul % cEntrySurf;
palentry.pal = palSurf.palentryGet(palentry.ul);
}
else
{
// Get color entries from the VGA palette. This
// is Chicago compatible.
palentry.ul = palentry.ul & 0x0000F;
palentry.pal = apalVGA[palentry.ul];
}
}
//
// Always 0 out the flags.
//
palentry.pal.peFlags = 0;
palentrySet(cEntry, palentry.pal);
}
}
/******************************Public*Routine******************************\
* XEPALOBJ::vInitMono
*
* This initializes a monochrome palette.
*
* History:
* 24-Jun-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vInitMono()
{
PAL_ULONG palentry;
palentry.ul = 0;
palentrySet(0, palentry.pal);
palentry.ul = 0x00FFFFFF;
palentrySet(1, palentry.pal);
}
/******************************Public*Routine******************************\
* XEPALOBJ::vInitVGA
*
* This initializes a 16 color palette to be just like the VGA.
*
* History:
* Wed 02-Oct-1991 -by- Patrick Haluptzok [patrickh]
* Re-did to be Win3.0 compatible.
*
* 22-Jun-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vInitVGA()
{
ULONG ulIndex;
for (ulIndex = 0; ulIndex < 16; ulIndex++)
{
palentrySet(ulIndex, aPalVGA[ulIndex].pal);
}
}
/******************************Public*Routine******************************\
* XEPALOBJ::vInit256Rainbow
*
* This initializes a 256 color palette with the default colors at the ends
* and a rainbow in the middle.
*
* History:
* 22-Jun-1991 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vInit256Rainbow()
{
ULONG ulIndex;
PAL_ULONG palentry;
PBYTE gTmp;
// Generate 256 (= 8*8*4) RGB combinations to fill
// in the palette.
BYTE red, green, blue;
red = green = blue = 0;
for (ulIndex = 0; ulIndex < 256; ulIndex++)
{
palentry.pal.peRed = red;
palentry.pal.peGreen = green;
palentry.pal.peBlue = blue;
palentry.pal.peFlags = 0;
palentrySet(ulIndex, palentry.pal);
if (!(red += 32))
if (!(green += 32))
blue += 64;
}
vInit256Default();
if (gpRGBXlate == NULL)
{
gTmp = (PBYTE)PALLOCNOZ(32768,'bgrG');
if (gTmp)
{
//
// use InterlockedCompareExchangePointer to set
// gpRGBXlate, so that another thread won't
// try to do this at the same time
//
MakeITable(gTmp,(RGBX *)ppal->apalColor,256);
if (InterlockedCompareExchangePointer((PVOID *)&gpRGBXlate,
gTmp,
NULL) != NULL)
{
//
// if we failed the InterlockedCompareExchangePointer,
// it means gpRGBXlate is already set by another thread
// free the temp buffer here
//
if (gTmp)
{
VFREEMEM(gTmp);
}
}
}
else
{
WARNING("Failed to allocate memory in XEPALOBJ::vInit256Rainbow\n");
// set this to NULL to be safe
ppal->pRGBXlate = NULL;
return;
}
}
ppal->ulRGBTime = ulTime();
ASSERTGDI(gpRGBXlate, "gpRGBXlate == NULL!\n");
ppal->pRGBXlate = gpRGBXlate;
}
/******************************Public*Routine******************************\
* XEPALOBJ::vInit256Default
*
* Initialize 256 color palette with the default colors.
*
* History:
* 02-Mar-1993 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID XEPALOBJ::vInit256Default()
{
// Fill in 20 reserved colors at beginning and end.
UINT uiIndex;
for (uiIndex = 0; uiIndex < 10; uiIndex++)
{
palentrySet(uiIndex, logDefaultPal.palPalEntry[uiIndex]);
palentrySet((ULONG)(255 - uiIndex), logDefaultPal.palPalEntry[19 - uiIndex]);
}
}
/**************************************************************************\
* XEPALOBJ::pGetRGBXlate
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 2/19/1997 Mark Enstrom [marke]
*
\**************************************************************************/
PRGB555XLATE
XEPALOBJ::pGetRGBXlate()
{
//
// palette semaphore?
//
PRGB555XLATE prgb555 = NULL;
if (ppal != NULL)
{
prgb555 = ppal->pRGBXlate;
if (
(prgb555 == NULL) ||
(ppal->ulRGBTime != ulTime())
)
{
if (bGenColorXlate555())
{
prgb555 = ppal->pRGBXlate;
}
else
{
prgb555 = NULL;
}
}
}
else
{
WARNING("XEPALOBJ::pGetRGBXlate called with NULL ppal\n");
}
return(prgb555);
}
/**************************************************************************\
* XEPALOBJ::bGenColorXlate555
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 2/12/1997 Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
XEPALOBJ::bGenColorXlate555()
{
BOOL bRet = FALSE;
//
// allocate rgb555 xlate table if needed
//
if ((ppal->pRGBXlate == NULL) || (ppal->pRGBXlate == gpRGBXlate))
{
ppal->pRGBXlate = (PRGB555XLATE)PALLOCNOZ(32768,'bgrG');
}
if (ppal->pRGBXlate)
{
MakeITable((PIMAP)ppal->pRGBXlate,(RGBX *)apalColorGet(),cEntries());
bRet = TRUE;
ppal->ulRGBTime = ulTime();
}
return(bRet);
}
/******************************Public*Routine******************************\
* ColorMatch
*
* Direct from Win3.1 to you. This function returns the best index to use
* when realizing a palette. It also returns the error incurred with using
* that index.
*
* Converted from Win3.1 colormat.asm - the ColorMatch function
*
* The only difference is we return a 32-bit error difference, and a 32-bit
* index. They compress both into 16-bit ax,dx.
*
* History:
* 11-May-1993 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
ULONG ColorMatch(XEPALOBJ palSurf, PAL_ULONG palRGB, ULONG *pulError)
{
if (palRGB.pal.peFlags & PC_EXPLICIT)
{
// Return the low word index.
palRGB.ul &= 0x0000FFFF;
// This is an error case Win3.1 does not test for, but we do.
if (palRGB.ul >= palSurf.cEntries())
{
palRGB.ul = 0;
}
*pulError = 0;
return(palRGB.ul);
}
if (palRGB.pal.peFlags & PC_RESERVED)
{
*pulError = 0x0FFFFFFF;
return(0);
}
ULONG ulTemp, ulError, ulBestIndex, ulBestError;
PAL_ULONG palTemp;
ulBestIndex = 0;
ulBestError = 0x0FFFFFFF;
for (ulTemp = 0; ulTemp < palSurf.cEntries(); ulTemp++)
{
palTemp.ul = palSurf.ulEntryGet(ulTemp);
if (palTemp.pal.peFlags & PC_USED)
{
if (!(palTemp.pal.peFlags & PC_RESERVED))
{
ulError = RGB_ERROR(palTemp.pal, palRGB.pal);
if (ulError < ulBestError)
{
ulBestIndex = ulTemp;
ulBestError = ulError;
}
if (ulBestError == 0)
break;
}
}
}
if (palRGB.pal.peFlags & PC_NOCOLLAPSE)
{
// He doesn't really want to match, so give it a big error.
*pulError = 0x0FFFFFFF;
}
else
*pulError = ulBestError;
return(ulBestIndex);
}
/******************************Public*Routine******************************\
* ptransMatchAPal
*
* Direct from Win3.1 to you. Builds a foreground translate just like Windows
* does.
*
* History:
* 12-May-1993 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
PTRANSLATE
ptransMatchAPal(
PDC pdc,
XEPALOBJ palSurf,
XEPALOBJ palDC,
BOOL bForeground,
ULONG *pulnPhysChanged,
ULONG *pulnTransChanged
)
{
ASSERTGDI(palDC.bValid(), "ERROR invalid DC pal");
ASSERTGDI(palSurf.bValid(), "ERROR invalid Surface pal");
ASSERTGDI(!palDC.bIsPalDefault(), "ERROR ptransMapIn default palette");
ASSERTGDI(palSurf.cEntries() == 256, "Error: dinky palette in");
ASSERTGDI(palDC.bIsPalDC(), "Error: palDC is not a DC");
ASSERTGDI(*pulnPhysChanged == 0, "ERROR 1349456 ptransMapIn");
ASSERTGDI(*pulnTransChanged == 0, "ERROR not 0");
//
// Determine how many entries are reserved
//
ULONG ulReserved;
if (palSurf.bIsNoStatic())
{
ulReserved = 1;
}
else if (palSurf.bIsNoStatic256())
{
ulReserved = 0;
}
else
{
ulReserved = palSurf.ulNumReserved() >> 1;
}
ULONG ulStartFill = ulReserved;
ULONG ulMaxInsert = 256 - ulReserved;
PAL_ULONG palLog, palPhys;
ULONG ulTemp;
ULONG iInsertIndex, iLogPal;
ULONG nPhysChanged = 0;
ULONG nTransChanged = 0;
//
// We allocate the vector that converts logical palette indices to physical
// palette indices. Note we subtract out the extra ULONG at compile time
// rather than run-time.
//
PTRANSLATE pTrans = (PTRANSLATE)
PALLOCNOZ((sizeof(TRANSLATE) - sizeof(BYTE)) +
(palDC.cEntries() * sizeof(BYTE)), 'laPG');
if (pTrans == NULL)
{
WARNING("Allocation for pTransMapIn failed\n");
return(NULL);
}
nTransChanged = palDC.cEntries();
if (bForeground)
{
//
// This is a foreground realize. Clear all PC_FOREGROUND and PC_RESERVED
// flags in the non-reserved entries of the surface palette.
//
//
// Update the time because we are removing foreground entries.
//
palSurf.vUpdateTime();
//
// match_fore_pal:
//
for (ulTemp = ulReserved; ulTemp < ulMaxInsert; ulTemp++)
{
palPhys.ul = palSurf.ulEntryGet(ulTemp);
// WINBUG #2621 5-4-2000 bhouse Foreground realization does not match Win9X
// We now clear PC_USED thus allowing us to match Win9X palette realization
// behavior. Note, we really should not clear PC_USED if we are in a WOW
// thread but have decided it is not necessary to maintain WOW compat.
palPhys.pal.peFlags &= (~(PC_FOREGROUND | PC_RESERVED | PC_USED));
palSurf.ulEntrySet(ulTemp, palPhys.ul);
}
}
BYTE fNotOverwritable = PC_FOREGROUND | PC_USED;
//
// match_back_loop:
//
for (iLogPal = 0; iLogPal < palDC.cEntries(); iLogPal++)
{
palLog.ul = palDC.ulEntryGet(iLogPal);
iInsertIndex = ColorMatch(palSurf, palLog, &ulTemp);
if (ulTemp == 0)
{
//
// Awesome, nothing to change.
//
if (!(palLog.pal.peFlags & PC_EXPLICIT))
{
//
// Mark it used if not PC_EXPLICIT log pal entry.
//
palPhys.ul = palSurf.ulEntryGet(iInsertIndex);
palPhys.pal.peFlags |= (PC_USED | PC_FOREGROUND);
palSurf.ulEntrySet(iInsertIndex, palPhys.ul);
}
}
else
{
//
// imperfect_match:
//
if (ulStartFill || palSurf.bIsNoStatic256())
{
//
// There is room to jam in an entry.
//
// look_for_overwrite:
//
look_for_overwriteable_loop:
for (ulTemp = ulStartFill; ulTemp < ulMaxInsert; ulTemp++)
{
palPhys.ul = palSurf.ulEntryGet(ulTemp);
if (!(palPhys.pal.peFlags & fNotOverwritable))
{
//
// replace_opening:
//
iInsertIndex = ulStartFill = ulTemp; // New start point for search.
palLog.pal.peFlags |= (PC_USED | PC_FOREGROUND);
palSurf.ulEntrySet(ulTemp, palLog.ul);
nPhysChanged++;
goto entry_back_matched;
}
}
if (fNotOverwritable & PC_USED)
{
//
// Can't be so picky, kick out used entries.
//
fNotOverwritable &= (~PC_USED);
ulStartFill = ulReserved;
goto look_for_overwriteable_loop;
}
else
{
//
// all_filled_for_back:
//
ulStartFill = 0;
}
}
}
entry_back_matched:
pTrans->ajVector[iLogPal] = (BYTE) iInsertIndex;
}
//
// finished_back_match
//
palDC.vUpdateTime();
pTrans->iUniq = palSurf.ulTime();
*pulnPhysChanged = nPhysChanged;
*pulnTransChanged = nTransChanged;
return(pTrans);
}
/******************************Public*Routine******************************\
* vMatchAPal
*
* This maps the foreground realization into the palette.
*
* History:
* 23-Nov-1992 -by- Patrick Haluptzok patrickh
* Wrote it.
\**************************************************************************/
VOID
vMatchAPal(
PDC pdc,
XEPALOBJ palSurf,
XEPALOBJ palDC,
ULONG *pulnPhysChanged,
ULONG *pulnTransChanged
)
{
ASSERTGDI(palDC.bValid(), "ERROR invalid DC pal");
ASSERTGDI(palSurf.bValid(), "ERROR invalid Surface pal");
ASSERTGDI(!palDC.bIsPalDefault(), "ERROR ptransMapIn default palette");
ASSERTGDI(palSurf.cEntries() == 256, "Error: dinky palette in");
ASSERTGDI(palDC.bIsPalDC(), "Error: palDC is not a DC");
ASSERTGDI(*pulnPhysChanged == 0, "ERROR 1349456 ptransMapIn");
ASSERTGDI(*pulnTransChanged == 0, "ERROR not 0");
//
// Determine how many entries are reserved
//
ULONG ulReserved;
if (palSurf.bIsNoStatic())
{
ulReserved = 1;
}
else if (palSurf.bIsNoStatic256())
{
ulReserved = 0;
}
else
{
ulReserved = palSurf.ulNumReserved() >> 1;
}
ULONG ulMaxInsert = 256 - ulReserved;
PAL_ULONG palLog, palPhys;
ULONG iLogPal;
ULONG nPhysChanged = 0;
ULONG nTransChanged = 0;
PTRANSLATE pTransFore = palDC.ptransFore();
PTRANSLATE pTransCur = palDC.ptransCurrent();
ASSERTGDI(pTransFore != NULL, "ERROR this NULL");
//
// un_use_palette_loop: Remove all foreground and reserved flags.
//
for (iLogPal = ulReserved; iLogPal < ulMaxInsert; iLogPal++)
{
palPhys.ul = palSurf.ulEntryGet(iLogPal);
palPhys.pal.peFlags &= (~(PC_FOREGROUND | PC_RESERVED));
palSurf.ulEntrySet(iLogPal, palPhys.ul);
}
for (iLogPal = 0; iLogPal < palDC.cEntries(); iLogPal++)
{
//
// slam_foreground_palette_loop
//
if ((pTransCur == NULL) ||
(pTransCur->ajVector[iLogPal] != pTransFore->ajVector[iLogPal]))
{
nTransChanged++;
}
//
// fore_no_trans_change:
//
palPhys.ul = palSurf.ulEntryGet(pTransFore->ajVector[iLogPal]);
if (!(palPhys.pal.peFlags & PC_FOREGROUND))
{
//
// Index is not foreground, we have to at least mark it.
//
palLog.ul = palDC.ulEntryGet(iLogPal);
if (!(palLog.pal.peFlags & PC_EXPLICIT))
{
//
// Not explicit, we better make sure it's the same entry.
//
if ((palLog.pal.peRed != palPhys.pal.peRed) ||
(palLog.pal.peGreen != palPhys.pal.peGreen) ||
(palLog.pal.peBlue != palPhys.pal.peBlue) ||
((palLog.pal.peFlags & PC_RESERVED) != (palPhys.pal.peFlags & PC_RESERVED)))
{
//
// Not the same as logical palette, stick it in the palette.
//
palLog.pal.peFlags &= PC_RESERVED;
palPhys.ul = palLog.ul;
nPhysChanged++;
}
}
//
// fore_entry_slammed
//
palPhys.pal.peFlags |= (PC_FOREGROUND | PC_USED);
palSurf.ulEntrySet((ULONG) pTransFore->ajVector[iLogPal], palPhys.ul);
}
}
//
// Increment the palette's time, we changed removed the foreground flags.
//
palSurf.vUpdateTime();
palDC.vUpdateTime();
pTransFore->iUniq = palSurf.ulTime();
*pulnPhysChanged = nPhysChanged;
*pulnTransChanged = nTransChanged;
}