Alexandre Julliard : gdi32: Remove call to CreateCompatibleDC() from GetDIBits() implementation.

Alexandre Julliard julliard at wine.codeweavers.com
Wed Nov 8 14:12:14 CST 2006


Module: wine
Branch: master
Commit: f7ffbe4581ee4f358b6f39a1376573cd27286eaa
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f7ffbe4581ee4f358b6f39a1376573cd27286eaa

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed Nov  8 19:57:30 2006 +0100

gdi32: Remove call to CreateCompatibleDC() from GetDIBits() implementation.
Based on a patch by Alex Villacís Lasso.

---

 dlls/gdi32/bitmap.c       |    3 +
 dlls/gdi32/dib.c          |  142 ++++++++++++++++++++++++++++++++++++---------
 dlls/gdi32/gdi_private.h  |    2 +
 dlls/gdi32/tests/bitmap.c |    5 +-
 4 files changed, 120 insertions(+), 32 deletions(-)

diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c
index 1a638c7..d720ae4 100644
--- a/dlls/gdi32/bitmap.c
+++ b/dlls/gdi32/bitmap.c
@@ -279,6 +279,8 @@ HBITMAP WINAPI CreateBitmapIndirect( con
     bmpobj->funcs = NULL;
     bmpobj->dib = NULL;
     bmpobj->segptr_bits = 0;
+    bmpobj->color_table = NULL;
+    bmpobj->nb_colors = 0;
 
     if (bm.bmBits)
         SetBitmapBits( hbitmap, bm.bmHeight * bm.bmWidthBytes, bm.bmBits );
@@ -628,6 +630,7 @@ static BOOL BITMAP_DeleteObject( HGDIOBJ
 
             for (i = 0; i < count; i++) FreeSelector16(sel + (i << __AHSHIFT));
         }
+        HeapFree(GetProcessHeap(), 0, bmp->color_table);
     }
     return GDI_FreeObject( handle, obj );
 }
diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c
index 07bd8ed..a3d559c 100644
--- a/dlls/gdi32/dib.c
+++ b/dlls/gdi32/dib.c
@@ -387,11 +387,27 @@ UINT WINAPI SetDIBColorTable( HDC hdc, U
 {
     DC * dc;
     UINT result = 0;
+    BITMAPOBJ * bitmap;
 
-    if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
+    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
+
+    if ((bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC )))
+    {
+        /* Check if currently selected bitmap is a DIB */
+        if (bitmap->color_table)
+        {
+            if (startpos < bitmap->nb_colors)
+            {
+                if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
+                memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
+                result = entries;
+            }
+        }
+        GDI_ReleaseObj( dc->hBitmap );
+    }
 
     if (dc->funcs->pSetDIBColorTable)
-        result = dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
+        dc->funcs->pSetDIBColorTable(dc->physDev, startpos, entries, colors);
 
     GDI_ReleaseObj( hdc );
     return result;
@@ -406,11 +422,28 @@ UINT WINAPI GetDIBColorTable( HDC hdc, U
     DC * dc;
     UINT result = 0;
 
-    if (!(dc = DC_GetDCUpdate( hdc ))) return 0;
+    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
 
     if (dc->funcs->pGetDIBColorTable)
         result = dc->funcs->pGetDIBColorTable(dc->physDev, startpos, entries, colors);
-
+    else
+    {
+        BITMAPOBJ *bitmap = GDI_GetObjPtr( dc->hBitmap, BITMAP_MAGIC );
+        if (bitmap)
+        {
+            /* Check if currently selected bitmap is a DIB */
+            if (bitmap->color_table)
+            {
+                if (startpos < bitmap->nb_colors)
+                {
+                    if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
+                    memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
+                    result = entries;
+                }
+            }
+            GDI_ReleaseObj( dc->hBitmap );
+        }
+    }
     GDI_ReleaseObj( hdc );
     return result;
 }
@@ -533,7 +566,6 @@ INT WINAPI GetDIBits(
     DC * dc;
     BITMAPOBJ * bmp;
     int i;
-    HDC memdc;
     int bitmap_type;
     BOOL core_header;
     LONG width;
@@ -553,16 +585,13 @@ INT WINAPI GetDIBits(
         return 0;
     }
     core_header = (bitmap_type == 0);
-    memdc = CreateCompatibleDC(hdc);
     if (!(dc = DC_GetDCUpdate( hdc )))
     {
-        DeleteDC(memdc);
         return 0;
     }
     if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
     {
         GDI_ReleaseObj( hdc );
-        DeleteDC(memdc);
 	return 0;
     }
 
@@ -580,34 +609,25 @@ INT WINAPI GetDIBits(
 	   same color depth then get the color map from it */
 	if (bmp->dib && bmp->dib->dsBm.bmBitsPixel == bpp) {
             if(coloruse == DIB_RGB_COLORS) {
-                HBITMAP oldbm = SelectObject(memdc, hbitmap);
-                unsigned int colors = 1 << bpp;
+                unsigned int colors = min( bmp->nb_colors, 1 << bpp );
 
                 if (core_header)
                 {
-                    /* Convert the color table (RGBQUAD to RGBTRIPLE) */		    
-                    RGBQUAD* buffer = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD));
+                    /* Convert the color table (RGBQUAD to RGBTRIPLE) */
+                    RGBTRIPLE* index = rgbTriples;
 
-                    if (buffer)
+                    for (i=0; i < colors; i++, index++)
                     {
-                        RGBTRIPLE* index = rgbTriples;
-                        GetDIBColorTable(memdc, 0, colors, buffer);
-
-                        for (i=0; i < colors; i++, index++)
-                        {
-                            index->rgbtRed   = buffer[i].rgbRed;
-                            index->rgbtGreen = buffer[i].rgbGreen;
-                            index->rgbtBlue  = buffer[i].rgbBlue;
-                        }
-
-                        HeapFree(GetProcessHeap(), 0, buffer);
+                        index->rgbtRed   = bmp->color_table[i].rgbRed;
+                        index->rgbtGreen = bmp->color_table[i].rgbGreen;
+                        index->rgbtBlue  = bmp->color_table[i].rgbBlue;
                     }
                 }
                 else
                 {
-                    GetDIBColorTable(memdc, 0, colors, colorPtr);
+                    if (colors != 1 << bpp) info->bmiHeader.biClrUsed = colors;
+                    memcpy(colorPtr, bmp->color_table, colors * sizeof(RGBQUAD));
                 }
-                SelectObject(memdc, oldbm);
             }
             else {
                 WORD *index = colorPtr;
@@ -623,7 +643,6 @@ INT WINAPI GetDIBits(
                 if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC ))) {
                     GDI_ReleaseObj( hdc );
                     GDI_ReleaseObj( hbitmap );
-                    DeleteDC(memdc);
                     return 0;
                 }
                 palEntry = palette->logpalette.palPalEntry;
@@ -1019,7 +1038,6 @@ INT WINAPI GetDIBits(
 
     GDI_ReleaseObj( hdc );
     GDI_ReleaseObj( hbitmap );
-    DeleteDC(memdc);
     return lines;
 }
 
@@ -1126,6 +1144,72 @@ HBITMAP16 WINAPI CreateDIBSection16 (HDC
     return HBITMAP_16(hbitmap);
 }
 
+/* Copy/synthetize RGB palette from BITMAPINFO. Ripped from dlls/winex11.drv/dib.c */
+static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
+{
+    RGBQUAD *colorTable;
+    unsigned int colors;
+    int i;
+    BOOL core_info = info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER);
+
+    if (core_info)
+    {
+        colors = 1 << ((const BITMAPCOREINFO*) info)->bmciHeader.bcBitCount;
+    }
+    else
+    {
+        colors = info->bmiHeader.biClrUsed;
+        if (!colors) colors = 1 << info->bmiHeader.biBitCount;
+    }
+
+    if (colors > 256) {
+        ERR("called with >256 colors!\n");
+        return;
+    }
+
+    if (!(colorTable = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
+
+    if(coloruse == DIB_RGB_COLORS)
+    {
+        if (core_info)
+        {
+           /* Convert RGBTRIPLEs to RGBQUADs */
+           for (i=0; i < colors; i++)
+           {
+               colorTable[i].rgbRed   = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtRed;
+               colorTable[i].rgbGreen = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtGreen;
+               colorTable[i].rgbBlue  = ((const BITMAPCOREINFO*) info)->bmciColors[i].rgbtBlue;
+               colorTable[i].rgbReserved = 0;
+           }
+        }
+        else
+        {
+            memcpy(colorTable, (const BYTE*) info + (WORD) info->bmiHeader.biSize, colors * sizeof(RGBQUAD));
+        }
+    }
+    else
+    {
+        PALETTEOBJ *palette;
+        const WORD *index = (const WORD*) ((const BYTE*) info + (WORD) info->bmiHeader.biSize);
+
+        if ((palette = GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC )))
+        {
+            UINT entries = palette->logpalette.palNumEntries;
+            for (i = 0; i < colors; i++, index++)
+            {
+                PALETTEENTRY *entry = &palette->logpalette.palPalEntry[*index % entries];
+                colorTable[i].rgbRed = entry->peRed;
+                colorTable[i].rgbGreen = entry->peGreen;
+                colorTable[i].rgbBlue = entry->peBlue;
+                colorTable[i].rgbReserved = 0;
+            }
+            GDI_ReleaseObj( dc->hPalette );
+        }
+    }
+    bmp->color_table = colorTable;
+    bmp->nb_colors = colors;
+}
+
 /***********************************************************************
  *           CreateDIBSection    (GDI32.@)
  */
@@ -1260,6 +1344,8 @@ HBITMAP WINAPI CreateDIBSection(HDC hdc,
     {
         bmp->dib = dib;
         bmp->funcs = dc->funcs;
+        /* create local copy of DIB palette */
+        if (bpp <= 8) DIB_CopyColorTable( dc, bmp, usage, bmi );
         GDI_ReleaseObj( ret );
 
         if (dc->funcs->pCreateDIBSection)
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index 1dbae75..0d3f1d0 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -324,6 +324,8 @@ typedef struct tagBITMAPOBJ
     /* For device-independent bitmaps: */
     DIBSECTION         *dib;
     SEGPTR              segptr_bits;  /* segptr to DIB bits */
+    RGBQUAD            *color_table;  /* DIB color table if <= 8bpp */
+    UINT                nb_colors;    /* number of colors in table */
 } BITMAPOBJ;
 
 /* bidi.c */
diff --git a/dlls/gdi32/tests/bitmap.c b/dlls/gdi32/tests/bitmap.c
index 8503e08..9701a00 100644
--- a/dlls/gdi32/tests/bitmap.c
+++ b/dlls/gdi32/tests/bitmap.c
@@ -1096,10 +1096,7 @@ static void test_GetDIBits_selected_DIB(
             break;
         }
     }
-    todo_wine
-    {
-        ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB color table\n");
-    }
+    ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB color table\n");
 
     equalContents = TRUE;
     for (i=0; i < dib_size / sizeof(DWORD); i++)




More information about the wine-cvs mailing list