Implement CreateDIBPalette(), replacing BuildDIBPalette.
It creates a palette without a handle and handles DIB_PAL_COLORS as well as DIB_RGB_COLORS. Additionally it now handles DIB_PAL_BRUSHHACK, which is used for DIB brushes, when DIB_PAL_COLORS is passed to CreateDIBPatternBrush(). The palette is not created directly, but instead the indices into the DC palette are put into the palette and the real palette is created, when the brush is realized. The latter is not yet handled.

svn path=/trunk/; revision=56518
This commit is contained in:
Timo Kreuzer 2012-05-05 21:39:35 +00:00
parent 7afed148ab
commit 2962518823
5 changed files with 178 additions and 185 deletions

View file

@ -56,8 +56,8 @@ typedef struct _EBRUSHOBJ
// DWORD dwUnknown30;
SURFACE * psurfTrg;
struct _PALETTE * ppalSurf;
// PALETTE * ppalDC;
// PALETTE * ppal3;
struct _PALETTE * ppalDC;
struct _PALETTE * ppalDIB;
// DWORD dwUnknown44;
BRUSH * pbrush;
FLONG flattrs;

View file

@ -9,3 +9,5 @@ HPALETTE FASTCALL DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi);
HPALETTE FASTCALL BuildDIBPalette (CONST BITMAPINFO *bmi);
BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig);
#define DIB_PAL_BRUSHHACK 3

View file

@ -103,6 +103,157 @@ static const RGBQUAD DefLogPaletteTriples[20] = /* Copy of Default Logical Pal
{ 0xff, 0xff, 0xff }
};
PPALETTE
NTAPI
CreateDIBPalette(
_In_ const BITMAPINFO *pbmi,
_In_ PDC pdc,
_In_ ULONG iUsage)
{
PPALETTE ppal;
ULONG i, cColors;
/* Check if the colors are indexed */
if (pbmi->bmiHeader.biBitCount <= 8)
{
/* We create a "full" palette */
cColors = 1 << pbmi->bmiHeader.biBitCount;
/* Allocate the palette */
ppal = PALETTE_AllocPalette(PAL_INDEXED,
cColors,
NULL,
0,
0,
0);
/* Check if the BITMAPINFO specifies how many colors to use */
if (pbmi->bmiHeader.biClrUsed != 0)
{
/* This is how many colors we can actually process */
cColors = min(cColors, pbmi->bmiHeader.biClrUsed);
}
/* Check how to use the colors */
if (iUsage == DIB_PAL_COLORS)
{
COLORREF crColor;
/* The colors are an array of WORD indices into the DC palette */
PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
/* Use the DCs palette or, if no DC is given, the default one */
PPALETTE ppalDC = pdc ? pdc->dclevel.ppal : gppalDefault;
/* Loop all color indices in the DIB */
for (i = 0; i < cColors; i++)
{
/* Get the RGB value from the DC palette, indexed by the DIB
color table value */
crColor = PALETTE_ulGetRGBColorFromIndex(ppalDC, pwColors[i]);
PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
}
}
else if (iUsage == DIB_PAL_BRUSHHACK)
{
/* The colors are an array of WORD indices into the DC palette */
PWORD pwColors = (PWORD)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
/* Loop all color indices in the DIB */
for (i = 0; i < cColors; i++)
{
/* Set the index directly as the RGB color, the real palette
containing RGB values will be calculated when the brush is
realized */
PALETTE_vSetRGBColorForIndex(ppal, i, pwColors[i]);
}
/* Mark the palette as a brush hack palette */
ppal->flFlags |= PAL_BRUSHHACK;
}
else if (iUsage == 2)
{
// FIXME: this one is undocumented
ASSERT(FALSE);
}
else // if (iUsage == DIB_RGB_COLORS)
{
/* The colors are an array of RGBQUAD values */
RGBQUAD *prgb = (RGBQUAD*)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
// FIXME: do we need to handle PALETTEINDEX / PALETTERGB macro?
/* Loop all color indices in the DIB */
for (i = 0; i < cColors; i++)
{
/* Get the color value and translate it to a COLORREF */
RGBQUAD rgb = prgb[i];
COLORREF crColor = RGB(rgb.rgbRed, rgb.rgbGreen, rgb.rgbBlue);
/* Set the RGB value in the palette */
PALETTE_vSetRGBColorForIndex(ppal, i, crColor);
}
}
}
else
{
/* This is a bitfield / RGB palette */
ULONG flRedMask, flGreenMask, flBlueMask;
/* Check if the DIB contains bitfield values */
if (pbmi->bmiHeader.biCompression == BI_BITFIELDS)
{
/* Check if we have a v4/v5 header */
if (pbmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
{
/* The masks are dedicated fields in the header */
PBITMAPV4HEADER pbmV4Header = (PBITMAPV4HEADER)&pbmi->bmiHeader;
flRedMask = pbmV4Header->bV4RedMask;
flGreenMask = pbmV4Header->bV4GreenMask;
flBlueMask = pbmV4Header->bV4BlueMask;
}
else
{
/* The masks are the first 3 values in the DIB color table */
PDWORD pdwColors = (PVOID)((PCHAR)pbmi + pbmi->bmiHeader.biSize);
flRedMask = pdwColors[0];
flGreenMask = pdwColors[1];
flBlueMask = pdwColors[2];
}
}
else
{
/* Check what bit depth we have. Note: optimization flags are
calculated in PALETTE_AllocPalette() */
if (pbmi->bmiHeader.biBitCount == 16)
{
/* This is an RGB 555 palette */
flRedMask = 0x7C00;
flGreenMask = 0x03E0;
flBlueMask = 0x001F;
}
else
{
/* This is an RGB 888 palette */
flRedMask = 0xFF0000;
flGreenMask = 0x00FF00;
flBlueMask = 0x0000FF;
}
}
/* Allocate the bitfield palette */
ppal = PALETTE_AllocPalette(PAL_BITFIELDS,
0,
NULL,
flRedMask,
flGreenMask,
flBlueMask);
}
/* We're done, return the palette */
return ppal;
}
UINT
APIENTRY
@ -251,7 +402,6 @@ IntSetDIBits(
RECT rcDst;
POINTL ptSrc;
EXLATEOBJ exlo;
HPALETTE hpalDIB = 0;
PPALETTE ppalDIB = 0;
SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
@ -280,18 +430,10 @@ IntSetDIBits(
}
/* Create a palette for the DIB */
hpalDIB = BuildDIBPalette(bmi);
if (!hpalDIB)
{
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
goto cleanup;
}
/* Lock the DIB palette */
ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
ppalDIB = CreateDIBPalette(bmi, DC, ColorUse);
if (!ppalDIB)
{
EngSetLastError(ERROR_INVALID_HANDLE);
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
goto cleanup;
}
@ -323,7 +465,6 @@ IntSetDIBits(
cleanup:
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
if (hpalDIB) GreDeleteObject(hpalDIB);
if(psurfSrc) SURFACE_ShareUnlockSurface(psurfSrc);
if(psurfDst) SURFACE_ShareUnlockSurface(psurfDst);
GreDeleteObject(SourceBitmap);
@ -364,7 +505,6 @@ NtGdiSetDIBitsToDeviceInternal(
SIZEL SourceSize;
EXLATEOBJ exlo;
PPALETTE ppalDIB = NULL;
HPALETTE hpalDIB = NULL;
LPBITMAPINFO pbmiSafe;
if (!Bits) return 0;
@ -455,23 +595,14 @@ NtGdiSetDIBitsToDeviceInternal(
ASSERT(pSurf->ppal);
/* Create a palette for the DIB */
hpalDIB = BuildDIBPalette(bmi);
if (!hpalDIB)
ppalDIB = CreateDIBPalette(bmi, pDC, ColorUse);
if (!ppalDIB)
{
EngSetLastError(ERROR_NO_SYSTEM_RESOURCES);
Status = STATUS_NO_MEMORY;
goto Exit;
}
/* Lock the DIB palette */
ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
if (!ppalDIB)
{
EngSetLastError(ERROR_INVALID_HANDLE);
Status = STATUS_UNSUCCESSFUL;
goto Exit;
}
/* Initialize EXLATEOBJ */
EXLATEOBJ_vInitialize(&exlo,
ppalDIB,
@ -509,7 +640,6 @@ Exit:
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
if (hpalDIB) GreDeleteObject(hpalDIB);
DC_UnlockDc(pDC);
Exit2:
ExFreePool(pbmiSafe);
@ -1118,15 +1248,7 @@ NtGdiStretchDIBitsInternal(
}
/* Create a palette for the DIB */
hpalDIB = BuildDIBPalette(pbmi);
if (!hpalDIB)
{
bResult = FALSE;
goto cleanup;
}
/* Lock the DIB palette */
ppalDIB = PALETTE_ShareLockPalette(hpalDIB);
ppalDIB = CreateDIBPalette(pbmi, pdc, dwUsage);
if (!ppalDIB)
{
bResult = FALSE;
@ -1162,7 +1284,6 @@ NtGdiStretchDIBitsInternal(
EXLATEOBJ_vCleanup(&exlo);
cleanup:
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
if (hpalDIB) GreDeleteObject(hpalDIB);
if (psurfTmp) SURFACE_ShareUnlockSurface(psurfTmp);
if (hbmTmp) GreDeleteObject(hbmTmp);
if (pdc) DC_UnlockDc(pdc);
@ -1439,7 +1560,7 @@ DIB_CreateDIBSection(
HBITMAP res = 0;
SURFACE *bmp = NULL;
void *mapBits = NULL;
HPALETTE hpal ;
PPALETTE ppalDIB;
// Fill BITMAP32 structure with DIB data
CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
@ -1534,33 +1655,6 @@ DIB_CreateDIBSection(
// hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
hSecure = (HANDLE)0x1; // HACK OF UNIMPLEMENTED KERNEL STUFF !!!!
if (usage == DIB_PAL_COLORS)
{
if(dc)
{
PPALETTE ppalDc;
ppalDc = PALETTE_ShareLockPalette(dc->dclevel.hpal);
hpal = DIB_MapPaletteColors(ppalDc, bmi);
PALETTE_ShareUnlockPalette(ppalDc);
}
else
{
/* For DIB Brushes */
DPRINT1("FIXME: Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
/* HACK */
hpal = (HPALETTE) 0xFFFFFFFF;
}
}
else
{
hpal = BuildDIBPalette(bmi);
}
if(!hpal)
{
DPRINT1("Error: Could not create a palette for the DIB.\n");
goto cleanup;
}
// Create Device Dependent Bitmap and add DIB pointer
//Size.cx = bm.bmWidth;
@ -1598,19 +1692,12 @@ DIB_CreateDIBSection(
bmp->flags = API_BITMAP;
bmp->biClrImportant = bi->biClrImportant;
/* HACK */
if(hpal != (HPALETTE)0xFFFFFFFF)
/* Create a palette for the DIB */
ppalDIB = CreateDIBPalette(bmi, dc, usage);
if (ppalDIB)
{
PPALETTE ppal = PALETTE_ShareLockPalette(hpal);
if (ppal)
{
if (bmp->ppal) PALETTE_ShareUnlockPalette(bmp->ppal);
bmp->ppal = ppal;
}
/* Lazy delete hpal, it will be freed at surface release */
GreDeleteObject(hpal);
if (bmp->ppal) PALETTE_ShareUnlockPalette(bmp->ppal);
bmp->ppal = ppalDIB;
}
// Clean up in case of errors
@ -1774,112 +1861,6 @@ DIB_MapPaletteColors(PPALETTE ppalDc, CONST BITMAPINFO* lpbmi)
return hpal;
}
HPALETTE
FASTCALL
BuildDIBPalette(CONST BITMAPINFO *bmi)
{
WORD bits;
ULONG ColorCount;
HPALETTE hpal;
PPALETTE ppal;
ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
ULONG paletteType, i;
// Determine Bits Per Pixel
bits = bmi->bmiHeader.biBitCount;
// Determine paletteType from Bits Per Pixel
if (bits <= 8)
{
paletteType = PAL_INDEXED;
RedMask = GreenMask = BlueMask = 0;
}
else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
{
paletteType = PAL_BITFIELDS;
if (bmi->bmiHeader.biSize >= sizeof(BITMAPV4HEADER))
{
PBITMAPV4HEADER pV4Header = (PBITMAPV4HEADER)&bmi->bmiHeader;
RedMask = pV4Header->bV4RedMask;
GreenMask = pV4Header->bV4GreenMask;
BlueMask = pV4Header->bV4BlueMask;
}
else
{
RedMask = pdwColors[0];
GreenMask = pdwColors[1];
BlueMask = pdwColors[2];
}
}
else
{
paletteType = PAL_BITFIELDS;
switch (bits)
{
case 16:
paletteType |= PAL_RGB16_555;
RedMask = 0x7C00;
GreenMask = 0x03E0;
BlueMask = 0x001F;
break;
case 24:
case 32:
paletteType |= PAL_BGR;
RedMask = 0xFF0000;
GreenMask = 0x00FF00;
BlueMask = 0x0000FF;
break;
}
}
if (bmi->bmiHeader.biClrUsed == 0)
{
ColorCount = 1 << bmi->bmiHeader.biBitCount;
}
else
{
ColorCount = bmi->bmiHeader.biClrUsed;
}
if (paletteType == PAL_INDEXED)
{
RGBQUAD* pColors = (RGBQUAD*)((PBYTE)bmi + bmi->bmiHeader.biSize);
/* Allocate a palette */
ppal = PALETTE_AllocPalWithHandle(PAL_INDEXED,
ColorCount,
NULL,
0, 0, 0);
if (!ppal) return NULL;
/* Copy all colors */
for (i = 0; i < ColorCount; i++)
{
ppal->IndexedColors[i].peRed = pColors[i].rgbRed;
ppal->IndexedColors[i].peGreen = pColors[i].rgbGreen;
ppal->IndexedColors[i].peBlue = pColors[i].rgbBlue;
ppal->IndexedColors[i].peFlags = 0;
}
/* Get palette handle and unlock the palette */
hpal = ppal->BaseObject.hHmgr;
PALETTE_UnlockPalette(ppal);
}
else
{
ppal = PALETTE_AllocPalWithHandle(paletteType, 0,
NULL,
RedMask, GreenMask, BlueMask);
hpal = ppal->BaseObject.hHmgr;
PALETTE_UnlockPalette(ppal);
}
return hpal;
}
/* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
* or does nothing if it's already a BITMAPINFO (or V4 or V5) */
BITMAPINFO*

View file

@ -151,7 +151,7 @@ NTAPI
PALETTE_AllocPalette(
_In_ ULONG iMode,
_In_ ULONG cColors,
_In_ PULONG pulColors,
_In_opt_ PULONG pulColors,
_In_ FLONG flRed,
_In_ FLONG flGreen,
_In_ FLONG flBlue)

View file

@ -62,7 +62,7 @@ NTAPI
PALETTE_AllocPalette(
_In_ ULONG iMode,
_In_ ULONG cColors,
_In_ PULONG pulColors,
_In_opt_ PULONG pulColors,
_In_ FLONG flRed,
_In_ FLONG flGreen,
_In_ FLONG flBlue);
@ -140,6 +140,16 @@ PALETTE_ulGetRGBColorFromIndex(PPALETTE ppal, ULONG ulIndex)
ppal->IndexedColors[ulIndex].peBlue);
}
FORCEINLINE
VOID
PALETTE_vSetRGBColorForIndex(PPALETTE ppal, ULONG ulIndex, COLORREF crColor)
{
if (ulIndex >= ppal->NumColors) return;
ppal->IndexedColors[ulIndex].peRed = GetRValue(crColor);
ppal->IndexedColors[ulIndex].peGreen = GetGValue(crColor);
ppal->IndexedColors[ulIndex].peBlue = GetBValue(crColor);
}
HPALETTE
NTAPI
GreCreatePaletteInternal(