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

Based on a patch by Alex Villacís Lasso.
This commit is contained in:
Alexandre Julliard 2006-11-08 19:57:30 +01:00
parent 68817c10ee
commit f7ffbe4581
4 changed files with 120 additions and 32 deletions

View File

@ -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 );
}

View File

@ -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)

View File

@ -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 */

View File

@ -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++)