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