From f7ffbe4581ee4f358b6f39a1376573cd27286eaa Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 8 Nov 2006 19:57:30 +0100 Subject: [PATCH] =?utf8?q?gdi32:=20Remove=20call=20to=20CreateCompatibleDC?= =?utf8?q?()=20from=20GetDIBits()=20implementation.=20Based=20on=20a=20pat?= =?utf8?q?ch=20by=20Alex=20Villac=C3=ADs=20Lasso.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- 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 1a638c790b7..d720ae451a9 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -279,6 +279,8 @@ HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp ) 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 handle, void *obj ) 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 07bd8ed41ae..a3d559c6aaa 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -387,11 +387,27 @@ UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUA { 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, UINT startpos, UINT entries, RGBQUAD *col 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 (HDC16 hdc, const BITMAPINFO *bmi, UINT16 us 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, CONST BITMAPINFO *bmi, UINT usage, { 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 1dbae75476f..0d3f1d0483e 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 8503e088b50..9701a005f6f 100644 --- a/dlls/gdi32/tests/bitmap.c +++ b/dlls/gdi32/tests/bitmap.c @@ -1096,10 +1096,7 @@ static void test_GetDIBits_selected_DIB(UINT bpp) 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++) -- 2.11.4.GIT