[WIN32K]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 5 May 2012 21:39:35 +0000 (21:39 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 5 May 2012 21:39:35 +0000 (21:39 +0000)
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

reactos/win32ss/gdi/ntgdi/brush.h
reactos/win32ss/gdi/ntgdi/dib.h
reactos/win32ss/gdi/ntgdi/dibobj.c
reactos/win32ss/gdi/ntgdi/palette.c
reactos/win32ss/gdi/ntgdi/palette.h

index 055f491..cf88361 100644 (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;
index a63f464..4e4cb2d 100644 (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
index deedecd..07e1e26 100644 (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*
index fd23672..20ea68d 100644 (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)
index 1c2cedf..1ac39e6 100644 (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(