diff --git a/reactos/win32ss/gdi/ntgdi/brush.h b/reactos/win32ss/gdi/ntgdi/brush.h index 055f4915d04..cf88361d064 100644 --- a/reactos/win32ss/gdi/ntgdi/brush.h +++ b/reactos/win32ss/gdi/ntgdi/brush.h @@ -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; diff --git a/reactos/win32ss/gdi/ntgdi/dib.h b/reactos/win32ss/gdi/ntgdi/dib.h index a63f464806b..4e4cb2d1f96 100644 --- a/reactos/win32ss/gdi/ntgdi/dib.h +++ b/reactos/win32ss/gdi/ntgdi/dib.h @@ -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 diff --git a/reactos/win32ss/gdi/ntgdi/dibobj.c b/reactos/win32ss/gdi/ntgdi/dibobj.c index deedecd0c1e..07e1e26111d 100644 --- a/reactos/win32ss/gdi/ntgdi/dibobj.c +++ b/reactos/win32ss/gdi/ntgdi/dibobj.c @@ -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* diff --git a/reactos/win32ss/gdi/ntgdi/palette.c b/reactos/win32ss/gdi/ntgdi/palette.c index fd23672eb87..20ea68d1d9c 100644 --- a/reactos/win32ss/gdi/ntgdi/palette.c +++ b/reactos/win32ss/gdi/ntgdi/palette.c @@ -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) diff --git a/reactos/win32ss/gdi/ntgdi/palette.h b/reactos/win32ss/gdi/ntgdi/palette.h index 1c2cedfb618..1ac39e6bd76 100644 --- a/reactos/win32ss/gdi/ntgdi/palette.h +++ b/reactos/win32ss/gdi/ntgdi/palette.h @@ -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(